1
0
Fork 0

(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
rubidium 2008-09-07 22:04:39 +00:00
parent 09cf61b466
commit 52154a3f64
12 changed files with 122 additions and 87 deletions

View File

@ -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)

View File

@ -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();

View File

@ -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);
}
}
}
}

View File

@ -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 */

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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 #

View File

@ -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 ),

View File

@ -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);
}
}

View File

@ -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()
};

View File

@ -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 */

View File

@ -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)