From 52154a3f64b628aa1207a82099ce681266f4d62e Mon Sep 17 00:00:00 2001 From: rubidium Date: Sun, 7 Sep 2008 22:04:39 +0000 Subject: [PATCH] (svn r14268) [0.6] -Backport from trunk: - Fix: Properly update the current timetable's travel/wait times instead of only doing it for one vehicle in the shared order chain and only when some bit has not been set [FS#2236] (r14192) - Fix: Sprite payload skipping would not skip enough bytes in a very small subset of compressed sprites (r14191) - Fix: After applying NewGRF settings, all rail and road types were available as the engine availability check was performed too early (r14182) - Fix: Close all related vehicle lists when closing a station window (and not only the train list) (r14180) - Fix: RemoveOrderFromAllVehicles() did not mark enough windows dirty (r14179) - Fix: Incorrect cargo weights (r14144) - Fix: GetSlopeZ() gets a virtual coordinate, not a tile (r14139) - Fix: Close the 'manage vehicles' dropdown once the number of vehicles in the list reaches 0 [FS#2249] (r14133) - Fix: [strgen] Changing order of parameters {X:...} did not work for strings including some {StringY} (r14111) - Fix: Desync due to bubbles in toyland (r14110) - Fix: Make NewGRF action 0x06's changes persistent over the several loading stages [FS#1986] (r14102) --- src/engine.cpp | 7 ++++ src/newgrf.cpp | 84 ++++++++++++++++++++++++----------------- src/order_cmd.cpp | 6 ++- src/sprite.h | 1 + src/spritecache.cpp | 48 ++++++++++++++--------- src/station_gui.cpp | 8 ++-- src/strgen/strgen.cpp | 10 ++--- src/table/cargo_const.h | 10 ++--- src/timetable_cmd.cpp | 15 ++++---- src/vehicle.cpp | 16 +++----- src/vehicle_gui.cpp | 2 + src/viewport.cpp | 2 +- 12 files changed, 122 insertions(+), 87 deletions(-) diff --git a/src/engine.cpp b/src/engine.cpp index d9c3c76857..6a1504d41b 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -173,6 +173,13 @@ void StartupEngines() e->player_avail = 0; } } + + /* Update the bitmasks for the vehicle lists */ + Player *p; + FOR_ALL_PLAYERS(p) { + p->avail_railtypes = GetPlayerRailtypes(p->index); + p->avail_roadtypes = GetPlayerRoadtypes(p->index); + } } static void AcceptEnginePreview(EngineID eid, PlayerID player) diff --git a/src/newgrf.cpp b/src/newgrf.cpp index 943ca63a68..0be6f67f88 100644 --- a/src/newgrf.cpp +++ b/src/newgrf.cpp @@ -80,9 +80,6 @@ static byte _misc_grf_features = 0; /* 32 * 8 = 256 flags. Apparently TTDPatch uses this many.. */ static uint32 _ttdpatch_flags[8]; -/* Used by Action 0x06 to preload a pseudo sprite and modify its content */ -static byte *_preload_sprite = NULL; - /* Indicates which are the newgrf features currently loaded ingame */ GRFLoadedFeatures _loaded_newgrf_features; @@ -123,6 +120,26 @@ static uint32 _grm_engines[TOTAL_NUM_ENGINES]; /* Contains the GRF ID of the owner of a cargo if it has been reserved */ static uint32 _grm_cargos[NUM_CARGO * 2]; +struct GRFLocation { + uint32 grfid; + uint32 nfoline; + + GRFLocation(uint32 grfid, uint32 nfoline) : grfid(grfid), nfoline(nfoline) { } + + bool operator<(const GRFLocation &other) const + { + return this->grfid < other.grfid || (this->grfid == other.grfid && this->nfoline < other.nfoline); + } + + bool operator==(const GRFLocation &other) const + { + return this->grfid == other.grfid && this->nfoline == other.nfoline; + } +}; + +typedef std::map GRFLineToSpriteOverride; +GRFLineToSpriteOverride _grf_line_to_action6_sprite_override; + /** DEBUG() function dedicated to newGRF debugging messages * Function is essentialy the same as DEBUG(grf, severity, ...) with the * addition of file:line information when parsing grf files. @@ -3619,11 +3636,12 @@ static void CfgApply(byte *buf, int len) uint32 pos = FioGetPos(); uint16 num = FioReadWord(); uint8 type = FioReadByte(); + byte *preload_sprite = NULL; /* Check if the sprite is a pseudo sprite. We can't operate on real sprites. */ if (type == 0xFF) { - _preload_sprite = MallocT(num); - FioReadBlock(_preload_sprite, num); + preload_sprite = MallocT(num); + FioReadBlock(preload_sprite, num); } /* Reset the file position to the start of the next sprite */ @@ -3631,9 +3649,19 @@ static void CfgApply(byte *buf, int len) if (type != 0xFF) { grfmsg(2, "CfgApply: Ignoring (next sprite is real, unsupported)"); + free(preload_sprite); return; } + GRFLocation location(_cur_grfconfig->grfid, _nfo_line + 1); + GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location); + if (it != _grf_line_to_action6_sprite_override.end()) { + free(preload_sprite); + preload_sprite = _grf_line_to_action6_sprite_override[location]; + } else { + _grf_line_to_action6_sprite_override[location] = preload_sprite; + } + /* Now perform the Action 0x06 on our data. */ buf++; @@ -3677,12 +3705,12 @@ static void CfgApply(byte *buf, int len) if (i == 0) carry = false; if (add_value) { - uint new_value = _preload_sprite[offset + i] + GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0); - _preload_sprite[offset + i] = GB(new_value, 0, 8); + uint new_value = preload_sprite[offset + i] + GB(value, (i % 4) * 8, 8) + (carry ? 1 : 0); + preload_sprite[offset + i] = GB(new_value, 0, 8); /* Check if the addition overflowed */ carry = new_value >= 256; } else { - _preload_sprite[offset + i] = GB(value, (i % 4) * 8, 8); + preload_sprite[offset + i] = GB(value, (i % 4) * 8, 8); } } } @@ -5645,17 +5673,20 @@ static void DecodeSpecialSprite(uint num, GrfLoadingStage stage) /* 0x13 */ { NULL, NULL, NULL, NULL, NULL, TranslateGRFStrings, }, }; - byte* buf; + bool preloaded_sprite = true; + GRFLocation location(_cur_grfconfig->grfid, _nfo_line); + byte *buf; - if (_preload_sprite == NULL) { + GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.find(location); + if (it == _grf_line_to_action6_sprite_override.end()) { /* No preloaded sprite to work with; allocate and read the * pseudo sprite content. */ buf = MallocT(num); FioReadBlock(buf, num); + preloaded_sprite = false; } else { /* Use the preloaded sprite data. */ - buf = _preload_sprite; - _preload_sprite = NULL; + buf = _grf_line_to_action6_sprite_override[location]; grfmsg(7, "DecodeSpecialSprite: Using preloaded pseudo sprite data"); /* Skip the real (original) content of this action. */ @@ -5678,7 +5709,7 @@ static void DecodeSpecialSprite(uint num, GrfLoadingStage stage) grfmsg(7, "DecodeSpecialSprite: Handling action 0x%02X in stage %d", action, stage); handlers[action][stage](buf, num); } - free(buf); + if (!preloaded_sprite) free(buf); } @@ -5752,23 +5783,7 @@ void LoadNewGRFFile(GRFConfig *config, uint file_index, GrfLoadingStage stage) if (_skip_sprites == 0) grfmsg(7, "LoadNewGRFFile: Skipping unexpected sprite"); FioSkipBytes(7); - num -= 8; - - if (type & 2) { - FioSkipBytes(num); - } else { - while (num > 0) { - int8 i = FioReadByte(); - if (i >= 0) { - num -= i; - FioSkipBytes(i); - } else { - i = -(i >> 3); - num -= i; - FioReadByte(); - } - } - } + SkipSpriteData(type, num - 8); } if (_skip_sprites > 0) _skip_sprites--; @@ -5822,12 +5837,11 @@ extern void InitGRFTownGeneratorNames(); static void AfterLoadGRFs() { - /* Update the bitmasks for the vehicle lists */ - Player *p; - FOR_ALL_PLAYERS(p) { - p->avail_railtypes = GetPlayerRailtypes(p->index); - p->avail_roadtypes = GetPlayerRoadtypes(p->index); + /* Free the action 6 override sprites. */ + for (GRFLineToSpriteOverride::iterator it = _grf_line_to_action6_sprite_override.begin(); it != _grf_line_to_action6_sprite_override.end(); it++) { + free((*it).second); } + _grf_line_to_action6_sprite_override.clear(); /* Pre-calculate all refit masks after loading GRF files. */ CalculateRefitMasks(); diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index 2085fb1f94..05c4ceff50 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -1185,7 +1185,11 @@ void RemoveOrderFromAllVehicles(OrderType type, DestinationID destination) } /* Only invalidate once, and if needed */ - if (invalidate) InvalidateWindow(WC_VEHICLE_ORDERS, v->index); + if (invalidate) { + for (const Vehicle *w = GetFirstVehicleFromSharedList(v); w != NULL; w = w->next_shared) { + InvalidateVehicleOrder(w); + } + } } } diff --git a/src/sprite.h b/src/sprite.h index 11054c6a44..a97e6eb75d 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -56,5 +56,6 @@ struct DrawBuildingsTileStruct { /** Iterate through all DrawTileSeqStructs in DrawTileSprites. */ #define foreach_draw_tile_seq(idx, list) for (idx = list; ((byte) idx->delta_x) != 0x80; idx++) +void SkipSpriteData(byte type, uint16 num); #endif /* SPRITE_H */ diff --git a/src/spritecache.cpp b/src/spritecache.cpp index a1677ad585..002866c1bb 100644 --- a/src/spritecache.cpp +++ b/src/spritecache.cpp @@ -72,6 +72,35 @@ static int _compact_cache_counter; static void CompactSpriteCache(); +/** + * Skip the given amount of sprite graphics data. + * @param type the type of sprite (compressed etc) + * @param num the amount of sprites to skip + */ +void SkipSpriteData(byte type, uint16 num) +{ + if (type & 2) { + FioSkipBytes(num); + } else { + while (num > 0) { + int8 i = FioReadByte(); + if (i >= 0) { + int size = (i == 0) ? 0x80 : i; + num -= size; + FioSkipBytes(size); + } else { + i = -(i >> 3); + num -= i; + FioReadByte(); + } + } + } +} + +/** + * Read the sprite header data and then skip the real payload. + * @return true if the sprite is a pseudo sprite. + */ static bool ReadSpriteHeaderSkipData() { uint16 num = FioReadWord(); @@ -88,24 +117,7 @@ static bool ReadSpriteHeaderSkipData() } FioSkipBytes(7); - num -= 8; - if (num == 0) return true; - - if (type & 2) { - FioSkipBytes(num); - } else { - while (num > 0) { - int8 i = FioReadByte(); - if (i >= 0) { - num -= i; - FioSkipBytes(i); - } else { - i = -(i >> 3); - num -= i; - FioReadByte(); - } - } - } + SkipSpriteData(type, num - 8); return true; } diff --git a/src/station_gui.cpp b/src/station_gui.cpp index 5dad18a43c..b604139c2a 100644 --- a/src/station_gui.cpp +++ b/src/station_gui.cpp @@ -955,10 +955,10 @@ static void StationViewWndProc(Window *w, WindowEvent *e) WindowNumber wno = (w->window_number << 16) | VLW_STATION_LIST | GetStation(w->window_number)->owner; - DeleteWindowById(WC_TRAINS_LIST, wno); - DeleteWindowById(WC_ROADVEH_LIST, wno); - DeleteWindowById(WC_SHIPS_LIST, wno); - DeleteWindowById(WC_AIRCRAFT_LIST, wno); + DeleteWindowById(WC_TRAINS_LIST, wno | (VEH_TRAIN << 11)); + DeleteWindowById(WC_ROADVEH_LIST, wno | (VEH_ROAD << 11)); + DeleteWindowById(WC_SHIPS_LIST, wno | (VEH_SHIP << 11)); + DeleteWindowById(WC_AIRCRAFT_LIST, wno | (VEH_AIRCRAFT << 11)); break; } diff --git a/src/strgen/strgen.cpp b/src/strgen/strgen.cpp index d05f0e796a..df0d281473 100644 --- a/src/strgen/strgen.cpp +++ b/src/strgen/strgen.cpp @@ -462,11 +462,11 @@ static const CmdStruct _cmd_structs[] = { {"REV", EmitSingleChar, SCC_REVISION, 0, 0}, // openttd revision string {"SHORTCARGO", EmitSingleChar, SCC_CARGO_SHORT, 2, 0}, // short cargo description, only ### tons, or ### litres - {"STRING1", EmitSingleChar, SCC_STRING1, 1, C_CASE}, // included string that consumes ONE argument - {"STRING2", EmitSingleChar, SCC_STRING2, 2, C_CASE}, // included string that consumes TWO arguments - {"STRING3", EmitSingleChar, SCC_STRING3, 3, C_CASE}, // included string that consumes THREE arguments - {"STRING4", EmitSingleChar, SCC_STRING4, 4, C_CASE}, // included string that consumes FOUR arguments - {"STRING5", EmitSingleChar, SCC_STRING5, 5, C_CASE}, // included string that consumes FIVE arguments + {"STRING1", EmitSingleChar, SCC_STRING1, 2, C_CASE}, // included string that consumes the string id and ONE argument + {"STRING2", EmitSingleChar, SCC_STRING2, 3, C_CASE}, // included string that consumes the string id and TWO arguments + {"STRING3", EmitSingleChar, SCC_STRING3, 4, C_CASE}, // included string that consumes the string id and THREE arguments + {"STRING4", EmitSingleChar, SCC_STRING4, 5, C_CASE}, // included string that consumes the string id and FOUR arguments + {"STRING5", EmitSingleChar, SCC_STRING5, 6, C_CASE}, // included string that consumes the string id and FIVE arguments {"STATIONFEATURES", EmitSingleChar, SCC_STATION_FEATURES, 1, 0}, // station features string, icons of the features {"INDUSTRY", EmitSingleChar, SCC_INDUSTRY_NAME, 1, 0}, // industry, takes an industry # diff --git a/src/table/cargo_const.h b/src/table/cargo_const.h index f87e0090cb..98c90ff9cf 100644 --- a/src/table/cargo_const.h +++ b/src/table/cargo_const.h @@ -43,7 +43,7 @@ static const CargoSpec _default_cargo[] = { STR_0022_WHEAT, STR_0042_WHEAT, STR_TONS, STR_QUANTITY_WHEAT, STR_ABBREV_WHEAT, SPR_CARGO_GRAIN, CC_BULK ), - MK( 6, 'MAIZ', 191, 6, 4322, 4, 40, true, TE_NONE, + MK( 6, 'MAIZ', 191, 16, 4322, 4, 40, true, TE_NONE, STR_001B_MAIZE, STR_003B_MAIZE, STR_TONS, STR_QUANTITY_MAIZE, STR_ABBREV_MAIZE, SPR_CARGO_GRAIN, CC_BULK ), @@ -85,19 +85,19 @@ static const CargoSpec _default_cargo[] = { STR_001E_FOOD, STR_003E_FOOD, STR_TONS, STR_QUANTITY_FOOD, STR_ABBREV_FOOD, SPR_CARGO_FOOD, CC_EXPRESS | CC_REFRIGERATED), - MK( 13, 'FRUT', 208, 6, 4209, 0, 15, true, TE_NONE, + MK( 13, 'FRUT', 208, 16, 4209, 0, 15, true, TE_NONE, STR_001C_FRUIT, STR_003C_FRUIT, STR_TONS, STR_QUANTITY_FRUIT, STR_ABBREV_FRUIT, SPR_CARGO_FRUIT, CC_BULK | CC_REFRIGERATED), - MK( 14, 'CORE', 184, 6, 4892, 12, 255, true, TE_NONE, + MK( 14, 'CORE', 184, 16, 4892, 12, 255, true, TE_NONE, STR_001A_COPPER_ORE, STR_003A_COPPER_ORE, STR_TONS, STR_QUANTITY_COPPER_ORE, STR_ABBREV_COPPER_ORE, SPR_CARGO_COPPER_ORE, CC_BULK ), - MK( 15, 'WATR', 10, 6, 4664, 20, 80, true, TE_WATER, + MK( 15, 'WATR', 10, 16, 4664, 20, 80, true, TE_WATER, STR_0021_WATER, STR_0041_WATER, STR_LITERS, STR_QUANTITY_WATER, STR_ABBREV_WATER, SPR_CARGO_WATERCOLA, CC_LIQUID ), - MK( 16, 'RUBR', 32, 6, 4437, 2, 20, true, TE_NONE, + MK( 16, 'RUBR', 32, 16, 4437, 2, 20, true, TE_NONE, STR_0023_RUBBER, STR_0043_RUBBER, STR_LITERS, STR_QUANTITY_RUBBER, STR_ABBREV_RUBBER, SPR_CARGO_RUBBER, CC_LIQUID ), diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp index 9d2769a327..f3f5eb65dc 100644 --- a/src/timetable_cmd.cpp +++ b/src/timetable_cmd.cpp @@ -24,15 +24,14 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 time order->wait_time = time; } - if (v->cur_order_index == order_number && HasBit(v->current_order.flags, OF_PART_OF_ORDERS)) { - if (is_journey) { - v->current_order.travel_time = time; - } else { - v->current_order.wait_time = time; - } - } - for (v = GetFirstVehicleFromSharedList(v); v != NULL; v = v->next_shared) { + if (v->cur_order_index == order_number && HasBit(v->current_order.flags, OF_PART_OF_ORDERS)) { + if (is_journey) { + v->current_order.travel_time = time; + } else { + v->current_order.wait_time = time; + } + } InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index); } } diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 4e5167bdd2..7c82fc72d2 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1349,12 +1349,6 @@ static const BubbleMovement * const _bubble_movement[] = { static void BubbleTick(Vehicle *v) { - /* - * Warning: those effects can NOT use Random(), and have to use - * InteractiveRandom(), because somehow someone forgot to save - * spritenum to the savegame, and so it will cause desyncs in - * multiplayer!! (that is: in ToyLand) - */ uint et; const BubbleMovement *b; @@ -1372,7 +1366,7 @@ static void BubbleTick(Vehicle *v) return; } if (v->u.special.animation_substate != 0) { - v->spritenum = GB(InteractiveRandom(), 0, 2) + 1; + v->spritenum = GB(Random(), 0, 2) + 1; } else { v->spritenum = 6; } @@ -1390,7 +1384,7 @@ static void BubbleTick(Vehicle *v) } if (b->y == 4 && b->x == 1) { - if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) { + if (v->z_pos > 180 || Chance16I(1, 96, Random())) { v->spritenum = 5; SndPlayVehicleFx(SND_2F_POP, v); } @@ -3047,8 +3041,10 @@ static const SaveLoad _special_desc[] = { SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, animation_state), SLE_UINT16), SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleSpecial, animation_substate), SLE_UINT8), - /* reserve extra space in savegame here. (currently 16 bytes) */ - SLE_CONDNULL(16, 2, SL_MAX_VERSION), + SLE_CONDVAR(Vehicle, spritenum, SLE_UINT8, 2, SL_MAX_VERSION), + + /* reserve extra space in savegame here. (currently 15 bytes) */ + SLE_CONDNULL(15, 2, SL_MAX_VERSION), SLE_END() }; diff --git a/src/vehicle_gui.cpp b/src/vehicle_gui.cpp index 86cc859e2a..cd41cf772c 100644 --- a/src/vehicle_gui.cpp +++ b/src/vehicle_gui.cpp @@ -939,6 +939,8 @@ static void DrawVehicleListWindow(Window *w) SortVehicleList(vl); SetVScrollCount(w, vl->l.list_length); + if (vl->l.list_length == 0) HideDropDownMenu(w); + /* draw the widgets */ switch (window_type) { case VLW_SHARED_ORDERS: /* Shared Orders */ diff --git a/src/viewport.cpp b/src/viewport.cpp index ad9141b89b..b9cfa92cf1 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2162,7 +2162,7 @@ void PlaceObject() bool ScrollWindowTo(int x , int y, Window *w, bool instant) { /* The slope cannot be acquired outside of the map, so make sure we are always within the map. */ - Point pt = MapXYZToViewport(w->viewport, x, y, GetSlopeZ(Clamp(x, 0, MapSizeX()), Clamp(y, 0, MapSizeY()))); + Point pt = MapXYZToViewport(w->viewport, x, y, GetSlopeZ(Clamp(x, 0, MapSizeX() * TILE_SIZE), Clamp(y, 0, MapSizeY() * TILE_SIZE))); WP(w, vp_d).follow_vehicle = INVALID_VEHICLE; if (WP(w, vp_d).dest_scrollpos_x == pt.x && WP(w, vp_d).dest_scrollpos_y == pt.y)