mirror of https://github.com/OpenTTD/OpenTTD
(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)release/0.6
parent
09cf61b466
commit
52154a3f64
|
@ -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)
|
||||
|
|
|
@ -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<GRFLocation, byte*> 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<byte>(num);
|
||||
FioReadBlock(_preload_sprite, num);
|
||||
preload_sprite = MallocT<byte>(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<byte>(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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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 #
|
||||
|
|
|
@ -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 ),
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
};
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue