diff --git a/src/graph_gui.cpp b/src/graph_gui.cpp index 5c4446c419..2e9027b1b3 100644 --- a/src/graph_gui.cpp +++ b/src/graph_gui.cpp @@ -199,25 +199,33 @@ protected: byte colours[GRAPH_MAX_DATASETS]; OverflowSafeInt64 cost[GRAPH_MAX_DATASETS][GRAPH_NUM_MONTHS]; ///< Stored costs for the last #GRAPH_NUM_MONTHS months - int64 GetHighestValue(int initial_highest_value) const + /** + * Get the highest value of the graph's data. Excluded data is ignored to allow showing smaller values in + * better detail when disabling higher ones. + * @return Highest value of the graph (ignoring disabled data). + */ + int64 GetHighestValue() const { - OverflowSafeInt64 highest_value = initial_highest_value; + OverflowSafeInt64 highest_value = 0; for (int i = 0; i < this->num_dataset; i++) { - if (!HasBit(this->excluded_data, i)) { - for (int j = 0; j < this->num_on_x_axis; j++) { - OverflowSafeInt64 datapoint = this->cost[i][j]; + if (HasBit(this->excluded_data, i)) continue; + for (int j = 0; j < this->num_on_x_axis; j++) { + OverflowSafeInt64 datapoint = this->cost[i][j]; - if (datapoint != INVALID_DATAPOINT) { - /* For now, if the graph has negative values the scaling is - * symmetrical about the x axis, so take the absolute value - * of each data point. */ - highest_value = max(highest_value, abs(datapoint)); - } + if (datapoint != INVALID_DATAPOINT) { + /* For now, if the graph has negative values the scaling is + * symmetrical about the x axis, so take the absolute value + * of each data point. */ + highest_value = max(highest_value, abs(datapoint)); } } } + /* Prevent showing the highest value too close to the graph upper limit. */ + highest_value = (11 * highest_value) / 10; + /* Avoid using zero as the highest value. */ + if (highest_value == 0) highest_value = GRAPH_NUM_LINES_Y - 1; /* Round up highest_value so that it will divide cleanly into the number of * axis labels used. */ int round_val = highest_value % (GRAPH_NUM_LINES_Y - 1); @@ -274,13 +282,7 @@ protected: r.left += 9; r.right -= 5; - /* Start of with a highest_value of twice the height of the graph in pixels. - * It's a bit arbitrary, but it makes the cargo payment graph look a little - * nicer, and prevents division by zero when calculating where the datapoint - * should be drawn. */ - highest_value = r.bottom - r.top + 1; - if (!this->has_negative_values) highest_value *= 2; - highest_value = GetHighestValue(highest_value); + highest_value = GetHighestValue(); /* Get width for Y labels */ int label_width = GetYLabelWidth(highest_value); diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 86086dddb4..31bca03b6d 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -1454,6 +1454,61 @@ static ChangeInfoResult BridgeChangeInfo(uint brid, int numinfo, int prop, ByteR return ret; } +static ChangeInfoResult IgnoreTownHouseProperty(int prop, ByteReader *buf) +{ + ChangeInfoResult ret = CIR_SUCCESS; + + switch (prop) { + case 0x09: + case 0x0B: + case 0x0C: + case 0x0D: + case 0x0E: + case 0x0F: + case 0x11: + case 0x14: + case 0x15: + case 0x16: + case 0x18: + case 0x19: + case 0x1A: + case 0x1B: + case 0x1C: + case 0x1D: + case 0x1F: + buf->ReadByte(); + break; + + case 0x0A: + case 0x10: + case 0x12: + case 0x13: + case 0x21: + case 0x22: + buf->ReadWord(); + break; + + case 0x1E: + buf->ReadDWord(); + break; + + case 0x17: + for (uint j = 0; j < 4; j++) buf->ReadByte(); + break; + + case 0x20: { + byte count = buf->ReadByte(); + for (byte j = 0; j < count; j++) buf->ReadByte(); + ret = CIR_UNHANDLED; + } break; + + default: + ret = CIR_UNKNOWN; + break; + } + return ret; +} + static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, ByteReader *buf) { ChangeInfoResult ret = CIR_SUCCESS; @@ -1472,8 +1527,10 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, Byt HouseSpec *housespec = _cur_grffile->housespec[hid + i]; if (prop != 0x08 && housespec == NULL) { - grfmsg(2, "TownHouseChangeInfo: Attempt to modify undefined house %u. Ignoring.", hid + i); - return CIR_INVALID_ID; + /* If the house property 08 is not yet set, ignore this property */ + ChangeInfoResult cir = IgnoreTownHouseProperty(prop, buf); + if (cir > ret) ret = cir; + continue; } switch (prop) { @@ -2060,6 +2117,34 @@ static ChangeInfoResult SoundEffectChangeInfo(uint sid, int numinfo, int prop, B return ret; } +static ChangeInfoResult IgnoreIndustryTileProperty(int prop, ByteReader *buf) +{ + ChangeInfoResult ret = CIR_SUCCESS; + + switch (prop) { + case 0x09: + case 0x0D: + case 0x0E: + case 0x10: + case 0x11: + case 0x12: + buf->ReadByte(); + break; + + case 0x0A: + case 0x0B: + case 0x0C: + case 0x0F: + buf->ReadWord(); + break; + + default: + ret = CIR_UNKNOWN; + break; + } + return ret; +} + static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int prop, ByteReader *buf) { ChangeInfoResult ret = CIR_SUCCESS; @@ -2078,8 +2163,9 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr IndustryTileSpec *tsp = _cur_grffile->indtspec[indtid + i]; if (prop != 0x08 && tsp == NULL) { - grfmsg(2, "IndustryTilesChangeInfo: Attempt to modify undefined industry tile %u. Ignoring.", indtid + i); - return CIR_INVALID_ID; + ChangeInfoResult cir = IgnoreIndustryTileProperty(prop, buf); + if (cir > ret) ret = cir; + continue; } switch (prop) { @@ -2168,6 +2254,83 @@ static ChangeInfoResult IndustrytilesChangeInfo(uint indtid, int numinfo, int pr return ret; } +static ChangeInfoResult IgnoreIndustryProperty(int prop, ByteReader *buf) +{ + ChangeInfoResult ret = CIR_SUCCESS; + + switch (prop) { + case 0x09: + case 0x0B: + case 0x0F: + case 0x12: + case 0x13: + case 0x14: + case 0x17: + case 0x18: + case 0x19: + case 0x21: + case 0x22: + buf->ReadByte(); + break; + + case 0x0C: + case 0x0D: + case 0x0E: + case 0x10: + case 0x1B: + case 0x1F: + case 0x24: + buf->ReadWord(); + break; + + case 0x1A: + case 0x1C: + case 0x1D: + case 0x1E: + case 0x20: + case 0x23: + buf->ReadDWord(); + break; + + case 0x0A: { + byte num_table = buf->ReadByte(); + for (byte j = 0; j < num_table; j++) { + for (uint k = 0;; k++) { + byte x = buf->ReadByte(); + if (x == 0xFE && k == 0) { + buf->ReadByte(); + buf->ReadByte(); + break; + } + + byte y = buf->ReadByte(); + if (x == 0 && y == 0x80) break; + + byte gfx = buf->ReadByte(); + if (gfx == 0xFE) buf->ReadWord(); + } + } + } break; + + case 0x11: + case 0x16: + for (byte j = 0; j < 3; j++) buf->ReadByte(); + break; + + case 0x15: { + byte number_of_sounds = buf->ReadByte(); + for (uint8 j = 0; j < number_of_sounds; j++) { + buf->ReadByte(); + } + } break; + + default: + ret = CIR_UNKNOWN; + break; + } + return ret; +} + /** * Validate the industry layout; e.g. to prevent duplicate tiles. * @param layout the layout to check @@ -2207,8 +2370,9 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop, IndustrySpec *indsp = _cur_grffile->industryspec[indid + i]; if (prop != 0x08 && indsp == NULL) { - grfmsg(2, "IndustriesChangeInfo: Attempt to modify undefined industry %u. Ignoring.", indid + i); - return CIR_INVALID_ID; + ChangeInfoResult cir = IgnoreIndustryProperty(prop, buf); + if (cir > ret) ret = cir; + continue; } switch (prop) { diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index 4a9ed1a886..f7317b44db 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -1737,7 +1737,7 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (flags & DC_EXEC) { RoadVehicle *front = v->First(); RoadVehUpdateCache(front); - SetWindowDirty(WC_VEHICLE_DETAILS, front->index); + InvalidateWindowData(WC_VEHICLE_DETAILS, front->index); SetWindowDirty(WC_VEHICLE_DEPOT, front->tile); InvalidateWindowClassesData(WC_ROADVEH_LIST, 0); } else { diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index c559702e77..55af88d2bd 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -1398,6 +1398,40 @@ struct VehicleDetailsWindow : Window { this->tab = TDW_TAB_CARGO; } + virtual void OnInvalidateData(int data) + { + const Vehicle *v = Vehicle::Get(this->window_number); + if (v->type == VEH_ROAD) { + const NWidgetBase *nwid_info = this->GetWidget(VLD_WIDGET_MIDDLE_DETAILS); + uint aimed_height = this->GetRoadVehDetailsHeight(v); + /* If the number of articulated parts changes, the size of the window must change too. */ + if (aimed_height != nwid_info->current_y) { + this->ReInit(); + } + } + } + + /** + * Gets the desired height for the road vehicle details panel. + * @param v Road vehicle being shown. + * @return Desired height in pixels. + */ + uint GetRoadVehDetailsHeight(const Vehicle *v) + { + uint desired_height; + if (RoadVehicle::From(v)->HasArticulatedPart()) { + /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */ + desired_height = WD_FRAMERECT_TOP + 15 + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM; + /* Add space for the cargo amount for each part. */ + for (const Vehicle *u = v; u != NULL; u = u->Next()) { + if (u->cargo_cap != 0) desired_height += FONT_HEIGHT_NORMAL + 1; + } + } else { + desired_height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM; + } + return desired_height; + } + virtual void UpdateWidgetSize(int widget, Dimension *size, const Dimension &padding, Dimension *fill, Dimension *resize) { switch (widget) { @@ -1425,16 +1459,7 @@ struct VehicleDetailsWindow : Window { const Vehicle *v = Vehicle::Get(this->window_number); switch (v->type) { case VEH_ROAD: - if (RoadVehicle::From(v)->HasArticulatedPart()) { - /* An articulated RV has its text drawn under the sprite instead of after it, hence 15 pixels extra. */ - size->height = WD_FRAMERECT_TOP + 15 + 3 * FONT_HEIGHT_NORMAL + 2 + WD_FRAMERECT_BOTTOM; - /* Add space for the cargo amount for each part. */ - for (const Vehicle *u = v; u != NULL; u = u->Next()) { - if (u->cargo_cap != 0) size->height += FONT_HEIGHT_NORMAL + 1; - } - } else { - size->height = WD_FRAMERECT_TOP + 4 * FONT_HEIGHT_NORMAL + 3 + WD_FRAMERECT_BOTTOM; - } + size->height = this->GetRoadVehDetailsHeight(v); break; case VEH_SHIP: