# HG changeset patch # User richk # Date 1208705248 0 # Node ID b3c58f3df92bb074d88cac8823b2701c1f29220f # Parent e9066a148720509340c979b07fea77eecf57c1fe (svn r12806) [NewGRF_ports] -Sync: with trunk r12773:12805. diff -r e9066a148720 -r b3c58f3df92b projects/openttd_vs80.vcproj --- a/projects/openttd_vs80.vcproj Fri Apr 18 21:20:03 2008 +0000 +++ b/projects/openttd_vs80.vcproj Sun Apr 20 15:27:28 2008 +0000 @@ -460,6 +460,10 @@ > + + @@ -544,6 +548,10 @@ > + + @@ -816,6 +824,10 @@ > + + @@ -968,6 +980,14 @@ > + + + + diff -r e9066a148720 -r b3c58f3df92b projects/openttd_vs90.vcproj --- a/projects/openttd_vs90.vcproj Fri Apr 18 21:20:03 2008 +0000 +++ b/projects/openttd_vs90.vcproj Sun Apr 20 15:27:28 2008 +0000 @@ -457,6 +457,10 @@ > + + @@ -541,6 +545,10 @@ > + + @@ -809,6 +817,10 @@ > + + @@ -961,6 +973,14 @@ > + + + + diff -r e9066a148720 -r b3c58f3df92b source.list --- a/source.list Fri Apr 18 21:20:03 2008 +0000 +++ b/source.list Sun Apr 20 15:27:28 2008 +0000 @@ -1,6 +1,7 @@ # Source Files airport.cpp core/alloc_func.cpp +animated_tile.cpp articulated_vehicles.cpp autoreplace_cmd.cpp aystar.cpp @@ -22,6 +23,7 @@ driver.cpp widgets/dropdown.cpp economy.cpp +effectvehicle.cpp elrail.cpp engine.cpp fileio.cpp @@ -125,6 +127,7 @@ airport.h core/alloc_func.hpp core/alloc_type.hpp +animated_tile_func.h articulated_vehicles.h autoreplace_base.h autoreplace_func.h @@ -163,6 +166,8 @@ widgets/dropdown_type.h economy_func.h economy_type.h +effectvehicle_func.h +effectvehicle_base.h core/endian_func.hpp engine_func.h engine_type.h diff -r e9066a148720 -r b3c58f3df92b src/aircraft_cmd.cpp --- a/src/aircraft_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/aircraft_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -36,6 +36,7 @@ #include "player_func.h" #include "settings_type.h" #include "order_func.h" +#include "effectvehicle_func.h" #include "table/strings.h" #include "table/sprites.h" @@ -2211,7 +2212,7 @@ if (v->breakdown_ctr <= 2) { HandleBrokenAircraft(v); } else { - v->breakdown_ctr--; + if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--; } } diff -r e9066a148720 -r b3c58f3df92b src/autoreplace_cmd.cpp --- a/src/autoreplace_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/autoreplace_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -1,5 +1,7 @@ /* $Id$ */ +/** @file autoreplace_cmd.cpp Deals with autoreplace execution but not the setup */ + #include "stdafx.h" #include "openttd.h" #include "roadveh.h" @@ -117,31 +119,26 @@ return CT_NO_REFIT; // We failed to find a cargo type on the old vehicle and we will not refit the new one } -/* Replaces a vehicle (used to be called autorenew) +/** Replaces a vehicle (used to be called autorenew) * This function is only called from MaybeReplaceVehicle() * Must be called with _current_player set to the owner of the vehicle * @param w Vehicle to replace * @param flags is the flags to use when calling DoCommand(). Mainly DC_EXEC counts + * @param p The vehicle owner (faster than refinding the pointer) + * @param new_engine_type The EngineID to replace to * @return value is cost of the replacement or CMD_ERROR */ -static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost) +static CommandCost ReplaceVehicle(Vehicle **w, byte flags, Money total_cost, const Player *p, EngineID new_engine_type) { CommandCost cost; CommandCost sell_value; Vehicle *old_v = *w; - const Player *p = GetPlayer(old_v->owner); - EngineID new_engine_type; const UnitID cached_unitnumber = old_v->unitnumber; bool new_front = false; Vehicle *new_v = NULL; char *vehicle_name = NULL; CargoID replacement_cargo_type; - /* Check if there is a autoreplacement set for the vehicle */ - new_engine_type = EngineReplacementForPlayer(p, old_v->engine_type, old_v->group_id); - /* if not, just renew to the same type */ - if (new_engine_type == INVALID_ENGINE) new_engine_type = old_v->engine_type; - replacement_cargo_type = GetNewCargoTypeForReplace(old_v, new_engine_type); /* check if we can't refit to the needed type, so no replace takes place to prevent the vehicle from altering cargo type */ @@ -292,21 +289,103 @@ return cost; } +/** Removes wagons from a train until it get a certain length + * @param v The vehicle + * @param old_total_length The wanted max length + * @return The profit from selling the wagons + */ +static CommandCost WagonRemoval(Vehicle *v, uint16 old_total_length) +{ + if (v->type != VEH_TRAIN) return CommandCost(); + Vehicle *front = v; + + CommandCost cost = CommandCost(); + + while (front->u.rail.cached_total_length > old_total_length) { + /* the train is too long. We will remove cars one by one from the start of the train until it's short enough */ + while (v != NULL && RailVehInfo(v->engine_type)->railveh_type != RAILVEH_WAGON) { + /* We move backwards in the train until we find a wagon */ + v = GetNextVehicle(v); + } + + if (v == NULL) { + /* We sold all the wagons and the train is still not short enough */ + SetDParam(0, front->unitnumber); + AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, front->index, 0); + return cost; + } + + /* We found a wagon we can sell */ + Vehicle *temp = v; + v = GetNextVehicle(v); + DoCommand(0, (INVALID_VEHICLE << 16) | temp->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); // remove the wagon from the train + MoveVehicleCargo(front, temp); // move the cargo back on the train + cost.AddCost(DoCommand(0, temp->index, 0, DC_EXEC, CMD_SELL_RAIL_WAGON)); // sell the wagon + } + return cost; +} + +/** Get the EngineID of the replacement for a vehicle + * @param v The vehicle to find a replacement for + * @param p The vehicle's owner (it's faster to forward the pointer than refinding it) + * @return the EngineID of the replacement. INVALID_ENGINE if no buildable replacement is found + */ +static EngineID GetNewEngineType(const Vehicle *v, const Player *p) +{ + if (v->type == VEH_TRAIN && IsRearDualheaded(v)) { + /* we build the rear ends of multiheaded trains with the front ones */ + return INVALID_ENGINE; + } + + EngineID e = EngineReplacementForPlayer(p, v->engine_type, v->group_id); + + if (e != INVALID_ENGINE && IsEngineBuildable(e, v->type, _current_player)) { + return e; + } + + if (v->NeedsAutorenewing(p) && // replace if engine is too old + IsEngineBuildable(v->engine_type, v->type, _current_player)) { // engine can still be build + return v->engine_type; + } + + return INVALID_ENGINE; +} + /** replaces a vehicle if it's set for autoreplace or is too old * (used to be called autorenew) * @param v The vehicle to replace * if the vehicle is a train, v needs to be the front engine - * @param check Checks if the replace is valid. No action is done at all - * @param display_costs If set, a cost animation is shown (only if check is false) - * @return CMD_ERROR if something went wrong. Otherwise the price of the replace + * @param flags + * @param display_costs If set, a cost animation is shown (only if DC_EXEC is set) + * This bool also takes autorenew money into consideration + * @return the costs, the success bool and sometimes an error message */ -CommandCost MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs) +CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs) { Vehicle *w; const Player *p = GetPlayer(v->owner); - byte flags = 0; - CommandCost cost, temp_cost; - bool stopped; + CommandCost cost; + bool stopped = false; + + /* We only want "real" vehicle types. */ + assert(IsPlayerBuildableVehicleType(v)); + + /* Ensure that this bool is cleared. */ + assert(!v->leave_depot_instantly); + + /* We can't sell if the current player don't own the vehicle. */ + assert(v->owner == _current_player); + + if (!v->IsInDepot()) { + /* The vehicle should be inside the depot */ + switch (v->type) { + default: NOT_REACHED(); + case VEH_TRAIN: return_cmd_error(STR_881A_TRAINS_CAN_ONLY_BE_ALTERED); break; + case VEH_ROAD: return_cmd_error(STR_9013_MUST_BE_STOPPED_INSIDE); break; + case VEH_SHIP: return_cmd_error(STR_980B_SHIP_MUST_BE_STOPPED_IN); break; + case VEH_AIRCRAFT: return_cmd_error(STR_A01B_AIRCRAFT_MUST_BE_STOPPED); break; + } + } /* Remember the length in case we need to trim train later on * If it's not a train, the value is unused @@ -317,38 +396,22 @@ -1 ); - - _current_player = v->owner; - - assert(IsPlayerBuildableVehicleType(v)); - - assert(v->vehstatus & VS_STOPPED); // the vehicle should have been stopped in VehicleEnteredDepotThisTick() if needed + if (!(v->vehstatus & VS_STOPPED)) { + /* The vehicle is moving so we better stop it before we might alter consist or sell it */ + v->vehstatus |= VS_STOPPED; + /* Remember that we stopped the vehicle */ + stopped = true; + } - /* Remember the flag v->leave_depot_instantly because if we replace the vehicle, the vehicle holding this flag will be sold - * If it is set, then we only stopped the vehicle to replace it (if needed) and we will need to start it again. - * We also need to reset the flag since it should remain false except from when the vehicle enters a depot until autoreplace is handled in the same tick */ - stopped = v->leave_depot_instantly; - v->leave_depot_instantly = false; - - for (;;) { + { cost = CommandCost(EXPENSES_NEW_VEHICLES); w = v; do { - if (w->type == VEH_TRAIN && IsRearDualheaded(w)) { - /* we build the rear ends of multiheaded trains with the front ones */ - continue; - } - - // check if the vehicle should be replaced - if (!w->NeedsAutorenewing(p) || // replace if engine is too old - w->max_age == 0) { // rail cars got a max age of 0 - if (!EngineHasReplacementForPlayer(p, w->engine_type, w->group_id)) continue; - } + EngineID new_engine = GetNewEngineType(w, p); + if (new_engine == INVALID_ENGINE) continue; /* Now replace the vehicle */ - temp_cost = ReplaceVehicle(&w, flags, cost.GetCost()); - - if (CmdFailed(temp_cost)) break; // replace failed for some reason. Leave the vehicle alone + cost.AddCost(ReplaceVehicle(&w, flags, cost.GetCost(), p, new_engine)); if (flags & DC_EXEC && (w->type != VEH_TRAIN || w->u.rail.first_engine == INVALID_ENGINE)) { @@ -358,11 +421,26 @@ */ v = w; } - cost.AddCost(temp_cost); } while (w->type == VEH_TRAIN && (w = GetNextVehicle(w)) != NULL); - if (!(flags & DC_EXEC) && (p->player_money < (cost.GetCost() + p->engine_renew_money) || cost.GetCost() == 0)) { - if (!check && p->player_money < (cost.GetCost() + p->engine_renew_money) && ( _local_player == v->owner ) && cost.GetCost() != 0) { + if (flags & DC_QUERY_COST || cost.GetCost() == 0) { + /* We didn't do anything during the replace so we will just exit here */ + if (stopped) v->vehstatus &= ~VS_STOPPED; + return cost; + } + + if (display_costs && !(flags & DC_EXEC)) { + /* We want to ensure that we will not get below p->engine_renew_money. + * We will not actually pay this amount. It's for display and checks only. */ + cost.AddCost((Money)p->engine_renew_money); + if (CmdSucceeded(cost) && GetAvailableMoneyForCommand() < cost.GetCost()) { + /* We don't have enough money so we will set cost to failed */ + cost.AddCost(CMD_ERROR); + } + } + + if (display_costs && CmdFailed(cost)) { + if (GetAvailableMoneyForCommand() < cost.GetCost() && IsLocalPlayer()) { StringID message; SetDParam(0, v->unitnumber); switch (v->type) { @@ -376,50 +454,22 @@ AddNewsItem(message, NM_SMALL, NF_VIEWPORT|NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0); } - if (stopped) v->vehstatus &= ~VS_STOPPED; - if (display_costs) _current_player = OWNER_NONE; - return CMD_ERROR; - } - - if (flags & DC_EXEC) { - break; // we are done replacing since the loop ran once with DC_EXEC - } else if (check) { - /* It's a test only and we know that we can do this - * NOTE: payment for wagon removal is NOT included in this price */ - return cost; - } - // now we redo the loop, but this time we actually do stuff since we know that we can do it - flags |= DC_EXEC; - } - - /* If setting is on to try not to exceed the old length of the train with the replacement */ - if (v->type == VEH_TRAIN && p->renew_keep_length) { - Vehicle *temp; - w = v; - - while (v->u.rail.cached_total_length > old_total_length) { - // the train is too long. We will remove cars one by one from the start of the train until it's short enough - while (w != NULL && RailVehInfo(w->engine_type)->railveh_type != RAILVEH_WAGON) { - w = GetNextVehicle(w); - } - if (w == NULL) { - // we failed to make the train short enough - SetDParam(0, v->unitnumber); - AddNewsItem(STR_TRAIN_TOO_LONG_AFTER_REPLACEMENT, NM_SMALL, NF_VIEWPORT | NF_VEHICLE, NT_ADVICE, DNC_NONE, v->index, 0); - break; - } - temp = w; - w = GetNextVehicle(w); - DoCommand(0, (INVALID_VEHICLE << 16) | temp->index, 0, DC_EXEC, CMD_MOVE_RAIL_VEHICLE); - MoveVehicleCargo(v, temp); - cost.AddCost(DoCommand(0, temp->index, 0, DC_EXEC, CMD_SELL_RAIL_WAGON)); } } + if (flags & DC_EXEC && CmdSucceeded(cost)) { + if (v->type == VEH_TRAIN && p->renew_keep_length) { + /* Remove wagons until the wanted length is reached */ + cost.AddCost(WagonRemoval(v, old_total_length)); + } + + if (display_costs && IsLocalPlayer()) { + ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost()); + } + } + + /* Start the vehicle if we stopped it earlier */ if (stopped) v->vehstatus &= ~VS_STOPPED; - if (display_costs) { - if (IsLocalPlayer()) ShowCostOrIncomeAnimation(v->x_pos, v->y_pos, v->z_pos, cost.GetCost()); - _current_player = OWNER_NONE; - } + return cost; } diff -r e9066a148720 -r b3c58f3df92b src/core/alloc_func.cpp --- a/src/core/alloc_func.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/core/alloc_func.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -9,7 +9,7 @@ * Function to exit with an error message after malloc() or calloc() have failed * @param size number of bytes we tried to allocate */ -void MallocError(size_t size) +void NORETURN MallocError(size_t size) { error("Out of memory. Cannot allocate %i bytes", size); } @@ -18,7 +18,7 @@ * Function to exit with an error message after realloc() have failed * @param size number of bytes we tried to allocate */ -void ReallocError(size_t size) +void NORETURN ReallocError(size_t size) { error("Out of memory. Cannot reallocate %i bytes", size); } diff -r e9066a148720 -r b3c58f3df92b src/core/alloc_func.hpp --- a/src/core/alloc_func.hpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/core/alloc_func.hpp Sun Apr 20 15:27:28 2008 +0000 @@ -11,8 +11,8 @@ * duplicated in each object file making the final * binary needlessly large. */ -void MallocError(size_t size); -void ReallocError(size_t size); +void NORETURN MallocError(size_t size); +void NORETURN ReallocError(size_t size); /** * Simplified allocation function that allocates the specified number of diff -r e9066a148720 -r b3c58f3df92b src/disaster_cmd.cpp --- a/src/disaster_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/disaster_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -39,6 +39,7 @@ #include "vehicle_func.h" #include "vehicle_base.h" #include "sound_func.h" +#include "effectvehicle_func.h" #include "table/strings.h" #include "table/sprites.h" diff -r e9066a148720 -r b3c58f3df92b src/economy.cpp --- a/src/economy.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/economy.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -26,6 +26,7 @@ #include "newgrf_callbacks.h" #include "newgrf_industries.h" #include "newgrf_industrytiles.h" +#include "newgrf_station.h" #include "unmovable.h" #include "cargotype.h" #include "player_face.h" @@ -1691,6 +1692,8 @@ st->time_since_load = 0; st->last_vehicle_type = v->type; + StationAnimationTrigger(st, st->xy, STAT_ANIM_CARGO_TAKEN, v->cargo_type); + unloading_time += cap; result |= 2; diff -r e9066a148720 -r b3c58f3df92b src/engine_func.h --- a/src/engine_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/engine_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -1,6 +1,6 @@ /* $Id$ */ -/** @file engine.h */ +/** @file engine_func.h */ #ifndef ENGINE_H #define ENGINE_H diff -r e9066a148720 -r b3c58f3df92b src/functions.h --- a/src/functions.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/functions.h Sun Apr 20 15:27:28 2008 +0000 @@ -22,21 +22,11 @@ bool CheckOwnership(Owner owner); bool CheckTileOwnership(TileIndex tile); -/* texteff.cpp */ -void AddAnimatedTile(TileIndex tile); -void DeleteAnimatedTile(TileIndex tile); -void AnimateAnimatedTiles(); -void InitializeAnimatedTiles(); - /* misc_cmd.cpp */ void PlaceTreesRandomly(); void InitializeLandscapeVariables(bool only_constants); -/* misc.cpp */ -bool IsCustomName(StringID id); -char *CopyFromOldName(StringID id); - /* misc functions */ /** * Mark a tile given by its coordinate dirty for repaint. @@ -68,14 +58,10 @@ void RedrawAutosave(); -StringID RemapOldStringID(StringID s); - void UpdateViewportSignPos(ViewportSign *sign, int left, int top, StringID str); - /* callback from drivers that is called if the game size changes dynamically */ void GameSizeChanged(); -const char *GetCurrentLocale(const char *param); int ttd_main(int argc, char* argv[]); void HandleExitGameRequest(); diff -r e9066a148720 -r b3c58f3df92b src/gfx.cpp --- a/src/gfx.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/gfx.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -17,6 +17,7 @@ #include "strings_func.h" #include "core/math_func.hpp" #include "settings_type.h" +#include "core/alloc_func.hpp" #include "table/palettes.h" #include "table/sprites.h" @@ -64,8 +65,12 @@ static const byte *_color_remap_ptr; static byte _string_colorremap[3]; -#define DIRTY_BYTES_PER_LINE (MAX_SCREEN_WIDTH / 64) -static byte _dirty_blocks[DIRTY_BYTES_PER_LINE * MAX_SCREEN_HEIGHT / 8]; +enum { + DIRTY_BLOCK_HEIGHT = 8, + DIRTY_BLOCK_WIDTH = 64, +}; +static uint _dirty_bytes_per_line = 0; +static byte *_dirty_blocks = NULL; void GfxScroll(int left, int top, int width, int height, int xo, int yo) { @@ -930,6 +935,9 @@ void ScreenSizeChanged() { + _dirty_bytes_per_line = (_screen.width + DIRTY_BLOCK_WIDTH - 1) / DIRTY_BLOCK_WIDTH; + _dirty_blocks = ReallocT(_dirty_blocks, _dirty_bytes_per_line * ((_screen.height + DIRTY_BLOCK_HEIGHT - 1) / DIRTY_BLOCK_HEIGHT)); + /* check the dirty rect */ if (_invalid_rect.right >= _screen.width) _invalid_rect.right = _screen.width; if (_invalid_rect.bottom >= _screen.height) _invalid_rect.bottom = _screen.height; @@ -1033,8 +1041,8 @@ void DrawDirtyBlocks() { byte *b = _dirty_blocks; - const int w = Align(_screen.width, 64); - const int h = Align(_screen.height, 8); + const int w = Align(_screen.width, DIRTY_BLOCK_WIDTH); + const int h = Align(_screen.height, DIRTY_BLOCK_HEIGHT); int x; int y; @@ -1047,7 +1055,7 @@ if (*b != 0) { int left; int top; - int right = x + 64; + int right = x + DIRTY_BLOCK_WIDTH; int bottom = y; byte *p = b; int h2; @@ -1055,12 +1063,12 @@ /* First try coalescing downwards */ do { *p = 0; - p += DIRTY_BYTES_PER_LINE; - bottom += 8; + p += _dirty_bytes_per_line; + bottom += DIRTY_BLOCK_HEIGHT; } while (bottom != h && *p != 0); /* Try coalescing to the right too. */ - h2 = (bottom - y) >> 3; + h2 = (bottom - y) / DIRTY_BLOCK_HEIGHT; assert(h2 > 0); p = b; @@ -1070,18 +1078,18 @@ /* Check if a full line of dirty flags is set. */ do { if (!*p2) goto no_more_coalesc; - p2 += DIRTY_BYTES_PER_LINE; + p2 += _dirty_bytes_per_line; } while (--h != 0); /* Wohoo, can combine it one step to the right! * Do that, and clear the bits. */ - right += 64; + right += DIRTY_BLOCK_WIDTH; h = h2; p2 = p; do { *p2 = 0; - p2 += DIRTY_BYTES_PER_LINE; + p2 += _dirty_bytes_per_line; } while (--h != 0); } no_more_coalesc: @@ -1099,8 +1107,8 @@ } } - } while (b++, (x += 64) != w); - } while (b += -(w >> 6) + DIRTY_BYTES_PER_LINE, (y += 8) != h); + } while (b++, (x += DIRTY_BLOCK_WIDTH) != w); + } while (b += -(w / DIRTY_BLOCK_WIDTH) + _dirty_bytes_per_line, (y += DIRTY_BLOCK_HEIGHT) != h); _invalid_rect.left = w; _invalid_rect.top = h; @@ -1147,13 +1155,13 @@ if (right > _invalid_rect.right ) _invalid_rect.right = right; if (bottom > _invalid_rect.bottom) _invalid_rect.bottom = bottom; - left >>= 6; - top >>= 3; + left /= DIRTY_BLOCK_WIDTH; + top /= DIRTY_BLOCK_HEIGHT; - b = _dirty_blocks + top * DIRTY_BYTES_PER_LINE + left; + b = _dirty_blocks + top * _dirty_bytes_per_line + left; - width = ((right - 1) >> 6) - left + 1; - height = ((bottom - 1) >> 3) - top + 1; + width = ((right - 1) / DIRTY_BLOCK_WIDTH) - left + 1; + height = ((bottom - 1) / DIRTY_BLOCK_HEIGHT) - top + 1; assert(width > 0 && height > 0); @@ -1162,7 +1170,7 @@ do b[--i] = 0xFF; while (i); - b += DIRTY_BYTES_PER_LINE; + b += _dirty_bytes_per_line; } while (--height != 0); } diff -r e9066a148720 -r b3c58f3df92b src/industry_cmd.cpp --- a/src/industry_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/industry_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -39,6 +39,8 @@ #include "sound_func.h" #include "station_base.h" #include "oldpool_func.h" +#include "animated_tile_func.h" +#include "effectvehicle_func.h" #include "table/strings.h" #include "table/sprites.h" @@ -620,7 +622,7 @@ } } -static void CreateIndustryEffectSmoke(TileIndex tile) +static void CreateChimneySmoke(TileIndex tile) { uint x = TileX(tile) * TILE_SIZE; uint y = TileY(tile) * TILE_SIZE; @@ -657,7 +659,7 @@ switch (gfx) { case GFX_POWERPLANT_CHIMNEY: - CreateIndustryEffectSmoke(tile); + CreateChimneySmoke(tile); break; case GFX_OILRIG_1: @@ -684,10 +686,10 @@ { int dir; Vehicle *v; - static const int8 _tileloop_ind_case_161[12] = { - 11, 0, -4, -14, - -4, -10, -4, 1, - 49, 59, 60, 65, + static const int8 _bubble_spawn_location[3][4] = { + { 11, 0, -4, -14 }, + { -4, -10, -4, 1 }, + { 49, 59, 60, 65 }, }; SndPlayTileFx(SND_2E_EXTRACT_AND_POP, tile); @@ -695,13 +697,13 @@ dir = Random() & 3; v = CreateEffectVehicleAbove( - TileX(tile) * TILE_SIZE + _tileloop_ind_case_161[dir + 0], - TileY(tile) * TILE_SIZE + _tileloop_ind_case_161[dir + 4], - _tileloop_ind_case_161[dir + 8], + TileX(tile) * TILE_SIZE + _bubble_spawn_location[0][dir], + TileY(tile) * TILE_SIZE + _bubble_spawn_location[1][dir], + _bubble_spawn_location[2][dir], EV_BUBBLE ); - if (v != NULL) v->u.special.animation_substate = dir; + if (v != NULL) v->u.effect.animation_substate = dir; } static void TileLoop_Industry(TileIndex tile) diff -r e9066a148720 -r b3c58f3df92b src/industry_gui.cpp --- a/src/industry_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/industry_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -631,7 +631,7 @@ WP(w, indview_d).editbox_line = 0; WP(w, indview_d).clicked_line = 0; WP(w, indview_d).clicked_button = 0; - AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY); + InitializeWindowViewport(w, 3, 17, 254, 86, GetIndustry(w->window_number)->xy + TileDiffXY(1, 1), ZOOM_LVL_INDUSTRY); } } diff -r e9066a148720 -r b3c58f3df92b src/landscape.cpp --- a/src/landscape.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/landscape.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -24,6 +24,7 @@ #include "vehicle_func.h" #include "settings_type.h" #include "water.h" +#include "effectvehicle_func.h" #include "table/sprites.h" diff -r e9066a148720 -r b3c58f3df92b src/main_gui.cpp --- a/src/main_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/main_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -412,7 +412,7 @@ int height = _screen.height; Window *w = AllocateWindow(0, 0, width, height, MainWindowWndProc, WC_MAIN_WINDOW, NULL); - AssignWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT); + InitializeWindowViewport(w, 0, 0, width, height, TileXY(32, 32), ZOOM_LVL_VIEWPORT); /* XXX: these are not done */ switch (_game_mode) { @@ -449,7 +449,7 @@ { _cur_resolution[0] = _screen.width; _cur_resolution[1] = _screen.height; + ScreenSizeChanged(); RelocateAllWindows(_screen.width, _screen.height); - ScreenSizeChanged(); MarkWholeScreenDirty(); } diff -r e9066a148720 -r b3c58f3df92b src/misc.cpp --- a/src/misc.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/misc.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -23,14 +23,13 @@ #include "date_func.h" #include "vehicle_func.h" #include "texteff.hpp" -#include "string_func.h" #include "gfx_func.h" #include "core/alloc_type.hpp" +#include "animated_tile_func.h" #include "table/strings.h" #include "table/sprites.h" -char _name_array[512][32]; extern TileIndex _cur_tileloop_tile; void InitializeVehicles(); @@ -49,10 +48,10 @@ void InitializeSigns(); void InitializeStations(); void InitializeCargoPackets(); -static void InitializeNameMgr(); void InitializePlayers(); void InitializeCheats(); void InitializeNPF(); +void InitializeOldNames(); void InitializeGame(int mode, uint size_x, uint size_y) { @@ -93,7 +92,7 @@ InitializeIndustries(); InitializeBuildingCounts(); - InitializeNameMgr(); + InitializeOldNames(); InitializeVehiclesGuiList(); InitializeTrains(); InitializeNPF(); @@ -111,60 +110,6 @@ ResetObjectToPlace(); } -bool IsCustomName(StringID id) -{ - return GB(id, 11, 5) == 15; -} - - -static void InitializeNameMgr() -{ - memset(_name_array, 0, sizeof(_name_array)); -} - -/* Copy and convert old custom names to UTF-8 */ -char *CopyFromOldName(StringID id) -{ - if (!IsCustomName(id)) return NULL; - - if (CheckSavegameVersion(37)) { - /* Old names were 32 characters long, so 128 characters should be - * plenty to allow for expansion when converted to UTF-8. */ - char tmp[128]; - const char *strfrom = _name_array[GB(id, 0, 9)]; - char *strto = tmp; - - for (; *strfrom != '\0'; strfrom++) { - WChar c = (byte)*strfrom; - - /* Map from non-ISO8859-15 characters to UTF-8. */ - switch (c) { - case 0xA4: c = 0x20AC; break; // Euro - case 0xA6: c = 0x0160; break; // S with caron - case 0xA8: c = 0x0161; break; // s with caron - case 0xB4: c = 0x017D; break; // Z with caron - case 0xB8: c = 0x017E; break; // z with caron - case 0xBC: c = 0x0152; break; // OE ligature - case 0xBD: c = 0x0153; break; // oe ligature - case 0xBE: c = 0x0178; break; // Y with diaresis - default: break; - } - - /* Check character will fit into our buffer. */ - if (strto + Utf8CharLen(c) > lastof(tmp)) break; - - strto += Utf8Encode(strto, c); - } - - /* Terminate the new string and copy it back to the name array */ - *strto = '\0'; - - return strdup(tmp); - } else { - /* Name will already be in UTF-8. */ - return strdup(_name_array[GB(id, 0, 9)]); - } -} /* Calculate constants that depend on the landscape type. */ void InitializeLandscapeVariables(bool only_constants) @@ -177,15 +122,6 @@ } } -static void Load_NAME() -{ - int index; - - while ((index = SlIterateArray()) != -1) { - SlArray(_name_array[index], SlGetFieldLength(), SLE_UINT8); - } -} - static const SaveLoadGlobVarList _date_desc[] = { SLEG_CONDVAR(_date, SLE_FILE_U16 | SLE_VAR_I32, 0, 30), SLEG_CONDVAR(_date, SLE_INT32, 31, SL_MAX_VERSION), @@ -469,7 +405,6 @@ { 'MAPE', Save_MAP6, Load_MAP6, CH_RIFF }, { 'MAP7', Save_MAP7, Load_MAP7, CH_RIFF }, - { 'NAME', NULL, Load_NAME, CH_ARRAY}, { 'DATE', SaveLoad_DATE, SaveLoad_DATE, CH_RIFF}, { 'VIEW', SaveLoad_VIEW, SaveLoad_VIEW, CH_RIFF | CH_LAST}, }; diff -r e9066a148720 -r b3c58f3df92b src/network/core/packet.cpp --- a/src/network/core/packet.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/network/core/packet.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -11,10 +11,6 @@ #include "packet.h" - -/* Do not want to include functions.h and all required headers */ -extern void NORETURN CDECL error(const char *str, ...); - /** * Create a packet that is used to read from a network socket * @param cs the socket handler associated with the socket we are reading from diff -r e9066a148720 -r b3c58f3df92b src/newgrf.cpp --- a/src/newgrf.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -1127,19 +1127,17 @@ statspec->blocked = grf_load_byte(&buf); break; - case 0x16: // @todo Animation info - grf_load_word(&buf); - ret = true; - break; - - case 0x17: // @todo Animation speed - grf_load_byte(&buf); - ret = true; - break; - - case 0x18: // @todo Animation triggers - grf_load_word(&buf); - ret = true; + case 0x16: // Animation info + statspec->anim_frames = grf_load_byte(&buf); + statspec->anim_status = grf_load_byte(&buf); + break; + + case 0x17: // Animation speed + statspec->anim_speed = grf_load_byte(&buf); + break; + + case 0x18: // Animation triggers + statspec->anim_triggers = grf_load_word(&buf); break; default: diff -r e9066a148720 -r b3c58f3df92b src/newgrf_callbacks.h --- a/src/newgrf_callbacks.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_callbacks.h Sun Apr 20 15:27:28 2008 +0000 @@ -173,13 +173,13 @@ /* There are no callbacks 0x3E - 0x13F */ /** Called for periodically starting or stopping the animation. */ - CBID_STATION_ANIM_START_STOP = 0x140, // not implemented + CBID_STATION_ANIM_START_STOP = 0x140, /** Called to determine station tile next animation frame. */ - CBID_STATION_ANIM_NEXT_FRAME = 0x141, // not implemented + CBID_STATION_ANIM_NEXT_FRAME = 0x141, /** Called to indicate how long the current animation frame should last. */ - CBID_STATION_ANIMATION_SPEED = 0x142, // not implemented + CBID_STATION_ANIMATION_SPEED = 0x142, /** Called to determine whether a town building can be destroyed. */ CBID_HOUSE_DENY_DESTRUCTION = 0x143, diff -r e9066a148720 -r b3c58f3df92b src/newgrf_fsmports.cpp --- a/src/newgrf_fsmports.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_fsmports.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -21,6 +21,7 @@ #include "cargotype.h" #include "town_map.h" #include "newgrf_town.h" +#include "date_func.h" #include "player_func.h" #include "gfx_func.h" #include "strings_func.h" diff -r e9066a148720 -r b3c58f3df92b src/newgrf_house.cpp --- a/src/newgrf_house.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_house.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -21,6 +21,8 @@ #include "transparency.h" #include "functions.h" #include "player_func.h" +#include "animated_tile_func.h" +#include "date_func.h" #include "table/strings.h" #include "table/sprites.h" diff -r e9066a148720 -r b3c58f3df92b src/newgrf_industrytiles.cpp --- a/src/newgrf_industrytiles.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_industrytiles.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -23,6 +23,7 @@ #include "functions.h" #include "town.h" #include "command_func.h" +#include "animated_tile_func.h" #include "table/sprites.h" #include "table/strings.h" diff -r e9066a148720 -r b3c58f3df92b src/newgrf_station.cpp --- a/src/newgrf_station.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_station.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -22,6 +22,8 @@ #include "gfx_func.h" #include "date_func.h" #include "player_func.h" +#include "animated_tile_func.h" +#include "functions.h" #include "table/sprites.h" #include "table/strings.h" @@ -741,8 +743,12 @@ free(st->speclist); st->num_specs = 0; st->speclist = NULL; + st->cached_anim_triggers = 0; + return; } } + + StationUpdateAnimTriggers(st); } /** Draw representation of a station tile for GUI purposes. @@ -854,3 +860,178 @@ HasBit(statspec->pylons, GetStationGfx(tile)) || !HasBit(statspec->wires, GetStationGfx(tile)); } + +void AnimateStationTile(TileIndex tile) +{ + const StationSpec *ss = GetStationSpec(tile); + if (ss == NULL) return; + + const Station *st = GetStationByTile(tile); + + uint8 animation_speed = ss->anim_speed; + + if (HasBit(ss->callbackmask, CBM_STATION_ANIMATION_SPEED)) { + uint16 callback = GetStationCallback(CBID_STATION_ANIMATION_SPEED, 0, 0, ss, st, tile); + if (callback != CALLBACK_FAILED) animation_speed = Clamp(callback & 0xFF, 0, 16); + } + + if (_tick_counter % (1 << animation_speed) != 0) return; + + uint8 frame = GetStationAnimationFrame(tile); + uint8 num_frames = ss->anim_frames; + + bool frame_set_by_callback = false; + + if (HasBit(ss->callbackmask, CBM_STATION_ANIMATION_NEXT_FRAME)) { + uint32 param = HasBit(ss->flags, 2) ? Random() : 0; + uint16 callback = GetStationCallback(CBID_STATION_ANIM_NEXT_FRAME, param, 0, ss, st, tile); + + if (callback != CALLBACK_FAILED) { + frame_set_by_callback = true; + + switch (callback & 0xFF) { + case 0xFF: + DeleteAnimatedTile(tile); + break; + + case 0xFE: + frame_set_by_callback = false; + break; + + default: + frame = callback & 0xFF; + break; + } + } + } + + if (!frame_set_by_callback) { + if (frame < num_frames) { + frame++; + } else if (frame == num_frames && HasBit(ss->anim_status, 0)) { + /* This animation loops, so start again from the beginning */ + frame = 0; + } else { + /* This animation doesn't loop, so stay here */ + DeleteAnimatedTile(tile); + } + } + + SetStationAnimationFrame(tile, frame); + MarkTileDirtyByTile(tile); +} + + +static void ChangeStationAnimationFrame(const StationSpec *ss, const Station *st, TileIndex tile, uint16 random_bits, StatAnimTrigger trigger, CargoID cargo_type) +{ + uint16 callback = GetStationCallback(CBID_STATION_ANIM_START_STOP, (random_bits << 16) | Random(), (uint8)trigger | (cargo_type << 8), ss, st, tile); + if (callback == CALLBACK_FAILED) return; + + switch (callback & 0xFF) { + case 0xFD: /* Do nothing. */ break; + case 0xFE: AddAnimatedTile(tile); break; + case 0xFF: DeleteAnimatedTile(tile); break; + default: + SetStationAnimationFrame(tile, callback); + AddAnimatedTile(tile); + break; + } +} + +enum TriggerArea { + TA_TILE, + TA_PLATFORM, + TA_WHOLE, +}; + +struct TileArea { + TileIndex tile; + uint8 w; + uint8 h; + + TileArea(const Station *st, TileIndex tile, TriggerArea ta) + { + switch (ta) { + default: NOT_REACHED(); + + case TA_TILE: + this->tile = tile; + this->w = 1; + this->h = 1; + break; + + case TA_PLATFORM: { + TileIndex start, end; + Axis axis = GetRailStationAxis(tile); + TileIndexDiff delta = TileOffsByDiagDir(AxisToDiagDir(axis)); + + for (end = tile; IsRailwayStationTile(end + delta) && IsCompatibleTrainStationTile(tile, end + delta); end += delta) { /* Nothing */ } + for (start = tile; IsRailwayStationTile(start - delta) && IsCompatibleTrainStationTile(tile, start - delta); start -= delta) { /* Nothing */ } + + this->tile = start; + this->w = TileX(end) - TileX(start) + 1; + this->h = TileY(end) - TileY(start) + 1; + break; + } + + case TA_WHOLE: + this->tile = st->train_tile; + this->w = st->trainst_w + 1; + this->h = st->trainst_h + 1; + break; + } + } +}; + +void StationAnimationTrigger(const Station *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type) +{ + /* List of coverage areas for each animation trigger */ + static const TriggerArea tas[] = { + TA_TILE, TA_WHOLE, TA_WHOLE, TA_PLATFORM, TA_PLATFORM, TA_PLATFORM, TA_WHOLE + }; + + /* Get Station if it wasn't supplied */ + if (st == NULL) st = GetStationByTile(tile); + + /* Check the cached animation trigger bitmask to see if we need + * to bother with any further processing. */ + if (!HasBit(st->cached_anim_triggers, trigger)) return; + + uint16 random_bits = Random(); + TileArea area = TileArea(st, tile, tas[trigger]); + + for (uint y = 0; y < area.h; y++) { + for (uint x = 0; x < area.w; x++) { + if (st->TileBelongsToRailStation(area.tile)) { + const StationSpec *ss = GetStationSpec(area.tile); + if (ss != NULL && HasBit(ss->anim_triggers, trigger)) { + CargoID cargo; + if (cargo_type == CT_INVALID) { + cargo = CT_INVALID; + } else { + cargo = GetReverseCargoTranslation(cargo_type, ss->grffile); + } + ChangeStationAnimationFrame(ss, st, area.tile, random_bits, trigger, cargo); + } + } + area.tile += TileDiffXY(1, 0); + } + area.tile += TileDiffXY(-area.w, 1); + } +} + +/** + * Update the cached animation trigger bitmask for a station. + * @param st Station to update. + */ +void StationUpdateAnimTriggers(Station *st) +{ + st->cached_anim_triggers = 0; + + /* Combine animation trigger bitmask for all station specs + * of this station. */ + for (uint i = 0; i < st->num_specs; i++) { + const StationSpec *ss = st->speclist[i].spec; + if (ss != NULL) st->cached_anim_triggers |= ss->anim_triggers; + } +} diff -r e9066a148720 -r b3c58f3df92b src/newgrf_station.h --- a/src/newgrf_station.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/newgrf_station.h Sun Apr 20 15:27:28 2008 +0000 @@ -83,6 +83,11 @@ StationLayout **layouts; bool copied_layouts; + uint8 anim_frames; + uint8 anim_status; + uint8 anim_speed; + uint16 anim_triggers; + /** * NUM_CARGO real cargo plus three pseudo cargo sprite groups. * Used for obtaining the sprite offset of custom sprites, and for @@ -132,4 +137,18 @@ /* Draw representation of a station tile for GUI purposes. */ bool DrawStationTile(int x, int y, RailType railtype, Axis axis, StationClassID sclass, uint station); +enum StatAnimTrigger { + STAT_ANIM_BUILT, + STAT_ANIM_NEW_CARGO, + STAT_ANIM_CARGO_TAKEN, + STAT_ANIM_TRAIN_ARRIVES, + STAT_ANIM_TRAIN_DEPARTS, + STAT_ANIM_TRAIN_LOADS, + STAT_ANIM_250_TICKS, +}; + +void AnimateStationTile(TileIndex tile); +void StationAnimationTrigger(const Station *st, TileIndex tile, StatAnimTrigger trigger, CargoID cargo_type = CT_INVALID); +void StationUpdateAnimTriggers(Station *st); + #endif /* NEWGRF_STATION_H */ diff -r e9066a148720 -r b3c58f3df92b src/news_func.h --- a/src/news_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/news_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -14,10 +14,9 @@ void InitNewsItemStructs(); extern NewsItem _statusbar_news_item; -extern uint32 _news_display_opt; extern bool _news_ticker_sound; -extern const char *_news_display_name[NT_END]; +extern NewsTypeData _news_type_data[NT_END]; /** * Delete a news item type about a vehicle diff -r e9066a148720 -r b3c58f3df92b src/news_gui.cpp --- a/src/news_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/news_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -53,7 +53,6 @@ #define INVALID_NEWS 255 NewsItem _statusbar_news_item; -uint32 _news_display_opt; bool _news_ticker_sound; static NewsItem _news_items[MAX_NEWS]; ///< The news FIFO queue static NewsID _current_news = INVALID_NEWS; ///< points to news item that should be shown next @@ -335,25 +334,24 @@ /** - * Maximum age of news items. - * Don't show item if it's older than x days, corresponds with NewsType in news_type.h - * @see NewsType + * Per-NewsType data */ -static const byte _news_items_age[NT_END] = { - 60, ///< NT_ARRIVAL_PLAYER - 60, ///< NT_ARRIVAL_OTHER - 90, ///< NT_ACCIDENT - 60, ///< NT_COMPANY_INFO - 90, ///< NT_OPENCLOSE - 30, ///< NT_ECONOMY - 30, ///< NT_INDUSTRY_PLAYER - 30, ///< NT_INDUSTRY_OTHER - 30, ///< NT_INDUSTRY_NOBODY - 150, ///< NT_ADVICE - 30, ///< NT_NEW_VEHICLES - 90, ///< NT_ACCEPTANCE - 180, ///< NT_SUBSIDIES - 60 ///< NT_GENERAL +NewsTypeData _news_type_data[NT_END] = { + /* name, age, sound, display */ + { "arrival_player", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_PLAYER + { "arrival_other", 60, SND_1D_APPLAUSE, ND_FULL }, ///< NT_ARRIVAL_OTHER + { "accident", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCIDENT + { "company_info", 60, SND_BEGIN, ND_FULL }, ///< NT_COMPANY_INFO + { "openclose", 90, SND_BEGIN, ND_FULL }, ///< NT_OPENCLOSE + { "economy", 30, SND_BEGIN, ND_FULL }, ///< NT_ECONOMY + { "production_player", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_PLAYER + { "production_other", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_OTHER + { "production_nobody", 30, SND_BEGIN, ND_FULL }, ///< NT_INDUSTRY_NOBODY + { "advice", 150, SND_BEGIN, ND_FULL }, ///< NT_ADVICE + { "new_vehicles", 30, SND_1E_OOOOH, ND_FULL }, ///< NT_NEW_VEHICLES + { "acceptance", 90, SND_BEGIN, ND_FULL }, ///< NT_ACCEPTANCE + { "subsidies", 180, SND_BEGIN, ND_FULL }, ///< NT_SUBSIDIES + { "general", 60, SND_BEGIN, ND_FULL }, ///< NT_GENERAL }; @@ -401,63 +399,6 @@ NewsWindowProc }; -static const SoundFx _news_sounds[NT_END] = { - SND_1D_APPLAUSE, ///< NT_ARRIVAL_PLAYER - SND_1D_APPLAUSE, ///< NT_ARRIVAL_OTHER - SND_BEGIN, ///< NT_ACCIDENT - SND_BEGIN, ///< NT_COMPANY_INFO - SND_BEGIN, ///< NT_OPENCLOSE - SND_BEGIN, ///< NT_ECONOMY - SND_BEGIN, ///< NT_INDUSTRY_PLAYER - SND_BEGIN, ///< NT_INDUSTRY_OTHER - SND_BEGIN, ///< NT_INDUSTRY_NOBODY - SND_BEGIN, ///< NT_ADVICE - SND_1E_OOOOH, ///< NT_NEW_VEHICLES - SND_BEGIN, ///< NT_ACCEPTANCE - SND_BEGIN, ///< NT_SUBSIDIES - SND_BEGIN, ///< NT_GENERAL -}; - -const char *_news_display_name[NT_END] = { - "arrival_player", - "arrival_other", - "accident", - "company_info", - "openclose", - "economy", - "production_player", - "production_other", - "production_nobody", - "advice", - "new_vehicles", - "acceptance", - "subsidies", - "general", -}; - -/** - * Get the value of an item of the news-display settings. This is - * a little tricky since on/off/summary must use 2 bits to store the value - * @param item the item whose value is requested - * @return return the found value which is between 0-2 - */ -static inline byte GetNewsDisplayValue(byte item) -{ - assert(item < NT_END && GB(_news_display_opt, item * 2, 2) <= 2); - return GB(_news_display_opt, item * 2, 2); -} - -/** - * Set the value of an item in the news-display settings. This is - * a little tricky since on/off/summary must use 2 bits to store the value - * @param item the item whose value is being set - * @param val new value - */ -static inline void SetNewsDisplayValue(byte item, byte val) -{ - assert(item < NT_END && val <= 2); - SB(_news_display_opt, item * 2, 2, val); -} /** Open up an own newspaper window for the news item */ static void ShowNewspaper(NewsItem *ni) @@ -465,7 +406,7 @@ ni->flags &= ~NF_FORCE_BIG; ni->duration = 555; - SoundFx sound = _news_sounds[ni->type]; + SoundFx sound = _news_type_data[ni->type].sound; if (sound != 0) SndPlayFx(sound); int top = _screen.height; @@ -476,7 +417,7 @@ _news_type13_desc.top = top; w = AllocateWindowDesc(&_news_type13_desc); if (ni->flags & NF_VIEWPORT) { - AssignWindowViewport(w, 2, 58, 0x1AA, 0x6E, + InitializeWindowViewport(w, 2, 58, 426, 110, ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); } break; @@ -485,7 +426,7 @@ _news_type2_desc.top = top; w = AllocateWindowDesc(&_news_type2_desc); if (ni->flags & NF_VIEWPORT) { - AssignWindowViewport(w, 2, 58, 0x1AA, 0x46, + InitializeWindowViewport(w, 2, 58, 426, 70, ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); } break; @@ -494,7 +435,7 @@ _news_type0_desc.top = top; w = AllocateWindowDesc(&_news_type0_desc); if (ni->flags & NF_VIEWPORT) { - AssignWindowViewport(w, 3, 17, 0x112, 0x2F, + InitializeWindowViewport(w, 3, 17, 274, 47, ni->data_a | (ni->flags & NF_VEHICLE ? 0x80000000 : 0), ZOOM_LVL_NEWS); } break; @@ -553,11 +494,11 @@ NewsItem *ni = &_news_items[_current_news]; /* check the date, don't show too old items */ - if (_date - _news_items_age[ni->type] > ni->date) return; + if (_date - _news_type_data[ni->type].age > ni->date) return; - switch (GetNewsDisplayValue(ni->type)) { + switch (_news_type_data[ni->type].display) { default: NOT_REACHED(); - case 0: { // Off - show nothing only a small reminder in the status bar + case ND_OFF: { // Off - show nothing only a small reminder in the status bar Window *w = FindWindowById(WC_STATUS_BAR, 0); if (w != NULL) { @@ -567,14 +508,14 @@ break; } - case 1: // Summary - show ticker, but if forced big, cascade to full + case ND_SUMMARY: // Summary - show ticker, but if forced big, cascade to full if (!(ni->flags & NF_FORCE_BIG)) { ShowTicker(ni); break; } /* Fallthrough */ - case 2: // Full - show newspaper + case ND_FULL: // Full - show newspaper ShowNewspaper(ni); break; } @@ -803,33 +744,30 @@ /* WP(w, def_d).data_1 stores state of the ALL on/off/summary button */ switch (e->event) { case WE_CREATE: { - uint32 val = _news_display_opt; - uint32 all_val; + NewsDisplay all_val; /* Set up the initial disabled buttons in the case of 'off' or 'full' */ - all_val = val & 0x3; - for (int i = 0; i < NT_END; i++, val >>= 2) { - SetMessageButtonStates(w, val & 0x3, i); + all_val = _news_type_data[0].display; + for (int i = 0; i < NT_END; i++) { + SetMessageButtonStates(w, _news_type_data[i].display, i); /* If the value doesn't match the ALL-button value, set the ALL-button value to 'off' */ - if ((val & 0x3) != all_val) all_val = 0; + if (_news_type_data[i].display != all_val) all_val = ND_OFF; } /* If all values are the same value, the ALL-button will take over this value */ WP(w, def_d).data_1 = all_val; } break; case WE_PAINT: { - uint32 val = _news_display_opt; - if (_news_ticker_sound) w->LowerWidget(WIDGET_NEWSOPT_SOUNDTICKER); w->widget[WIDGET_NEWSOPT_DROP_SUMMARY].data = message_opt[WP(w, def_d).data_1]; DrawWindowWidgets(w); /* Draw the string of each setting on each button. */ - for (int i = 0, y = 26; i < NT_END; i++, y += 12, val >>= 2) { + for (int i = 0, y = 26; i < NT_END; i++, y += 12) { /* 51 comes from 13 + 89 (left and right of the button)+1, shiefted by one as to get division, * which will give centered position */ - DrawStringCentered(51, y + 1, message_opt[val & 0x3], TC_BLACK); + DrawStringCentered(51, y + 1, message_opt[_news_type_data[i].display], TC_BLACK); } } break; @@ -849,10 +787,10 @@ int wid = e->we.click.widget - WIDGET_NEWSOPT_START_OPTION; if (wid >= 0 && wid < (NB_WIDG_PER_SETTING * NT_END)) { int element = wid / NB_WIDG_PER_SETTING; - byte val = (GetNewsDisplayValue(element) + ((wid % NB_WIDG_PER_SETTING) ? 1 : -1)) % 3; + byte val = (_news_type_data[element].display + ((wid % NB_WIDG_PER_SETTING) ? 1 : -1)) % 3; SetMessageButtonStates(w, val, element); - SetNewsDisplayValue(element, val); + _news_type_data[element].display = (NewsDisplay)val; SetWindowDirty(w); } } break; @@ -864,7 +802,7 @@ for (int i = 0; i < NT_END; i++) { SetMessageButtonStates(w, e->we.dropdown.index, i); - SetNewsDisplayValue(i, e->we.dropdown.index); + _news_type_data[i].display = (NewsDisplay)e->we.dropdown.index; } SetWindowDirty(w); break; diff -r e9066a148720 -r b3c58f3df92b src/news_type.h --- a/src/news_type.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/news_type.h Sun Apr 20 15:27:28 2008 +0000 @@ -8,6 +8,7 @@ #include "window_type.h" #include "date_type.h" #include "strings_type.h" +#include "sound_type.h" /** * Type of news. @@ -75,6 +76,25 @@ NB_BNEWCOMPANY = (4 << 4), ///< A new company has been started }; +/** + * News display options + */ +enum NewsDisplay { + ND_OFF, ///< Only show a reminder in the status bar + ND_SUMMARY, ///< Show ticker + ND_FULL, ///< Show newspaper +}; + +/** + * Per-NewsType data + */ +struct NewsTypeData { + const char *const name; ///< Name + const byte age; ///< Maximum age of news items (in days) + const SoundFx sound; ///< Sound + NewsDisplay display; ///< Display mode (off, summary, full) +}; + struct NewsItem { StringID string_id; ///< Message text (sometimes also used for storing other info) uint16 duration; ///< Remaining time for showing this news message diff -r e9066a148720 -r b3c58f3df92b src/oldloader.cpp --- a/src/oldloader.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/oldloader.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -24,6 +24,8 @@ #include "date_func.h" #include "vehicle_func.h" #include "variables.h" +#include "strings_func.h" +#include "effectvehicle_base.h" #include "table/strings.h" @@ -84,6 +86,12 @@ OC_TILE = OC_VAR_U32 | OC_FILE_U16, + /** + * Dereference the pointer once before writing to it, + * so we do not have to use big static arrays. + */ + OC_DEREFERENCE_POINTER = 1 << 31, + OC_END = 0 ///< End of the whole chunk, all 32bits set to zero }; @@ -201,10 +209,10 @@ byte *base_ptr = (byte*)base; while (chunk->type != OC_END) { - byte* ptr = (byte*)chunk->ptr; - uint i; + byte *ptr = (byte*)chunk->ptr; + if ((chunk->type & OC_DEREFERENCE_POINTER) != 0) ptr = *(byte**)ptr; - for (i = 0; i < chunk->amount; i++) { + for (uint i = 0; i < chunk->amount; i++) { if (ls->failed) return false; /* Handle simple types */ @@ -391,10 +399,10 @@ extern TileIndex *_animated_tile_list; extern uint _animated_tile_count; -extern char _name_array[512][32]; +extern char *_old_name_array; static byte _old_vehicle_multiplier; -static uint8 _old_map3[OLD_MAP_SIZE * 2]; +static uint8 *_old_map3; static bool _new_ttdpatch_format; static uint32 _old_town_index; static uint16 _old_string_id; @@ -1079,9 +1087,9 @@ OCL_END() }; -static const OldChunks vehicle_special_chunk[] = { - OCL_SVAR( OC_UINT16, VehicleSpecial, animation_state ), - OCL_SVAR( OC_UINT8, VehicleSpecial, animation_substate ), +static const OldChunks vehicle_effect_chunk[] = { + OCL_SVAR( OC_UINT16, VehicleEffect, animation_state ), + OCL_SVAR( OC_UINT8, VehicleEffect, animation_substate ), OCL_NULL( 7 ), // Junk @@ -1116,7 +1124,7 @@ case VEH_ROAD : res = LoadChunk(ls, &v->u.road, vehicle_road_chunk); break; case VEH_SHIP : res = LoadChunk(ls, &v->u.ship, vehicle_ship_chunk); break; case VEH_AIRCRAFT: res = LoadChunk(ls, &v->u.air, vehicle_air_chunk); break; - case VEH_SPECIAL : res = LoadChunk(ls, &v->u.special, vehicle_special_chunk); break; + case VEH_EFFECT : res = LoadChunk(ls, &v->u.effect, vehicle_effect_chunk); break; case VEH_DISASTER: res = LoadChunk(ls, &v->u.disaster, vehicle_disaster_chunk); break; } @@ -1229,7 +1237,7 @@ case 0x11 /*VEH_ROAD */: v = new (_current_vehicle_id) RoadVehicle(); break; case 0x12 /*VEH_SHIP */: v = new (_current_vehicle_id) Ship(); break; case 0x13 /*VEH_AIRCRAFT*/: v = new (_current_vehicle_id) Aircraft(); break; - case 0x14 /*VEH_SPECIAL */: v = new (_current_vehicle_id) SpecialVehicle(); break; + case 0x14 /*VEH_EFFECT */: v = new (_current_vehicle_id) EffectVehicle(); break; case 0x15 /*VEH_DISASTER*/: v = new (_current_vehicle_id) DisasterVehicle(); break; } if (!LoadChunk(ls, v, vehicle_chunk)) return false; @@ -1263,7 +1271,7 @@ v->name = CopyFromOldName(_old_string_id); /* Vehicle-subtype is different in TTD(Patch) */ - if (v->type == VEH_SPECIAL) v->subtype = v->subtype >> 1; + if (v->type == VEH_EFFECT) v->subtype = v->subtype >> 1; if (_cargo_count != 0) { CargoPacket *cp = new CargoPacket((_cargo_source == 0xFF) ? INVALID_STATION : _cargo_source, _cargo_count); @@ -1521,7 +1529,7 @@ OCL_ASSERT( 0x6F0F2 ), - OCL_VAR ( OC_UINT8, 32 * 500, &_name_array[0] ), + OCL_VAR ( OC_UINT8 | OC_DEREFERENCE_POINTER, 32 * 500, &_old_name_array ), OCL_NULL( 0x2000 ), ///< Old hash-table, no longer in use @@ -1601,8 +1609,10 @@ DEBUG(oldloader, 3, "Reading main chunk..."); /* Load the biggest chunk */ + _old_map3 = MallocT(OLD_MAP_SIZE * 2); if (!LoadChunk(ls, NULL, main_chunk)) { DEBUG(oldloader, 0, "Loading failed"); + free(_old_map3); return false; } DEBUG(oldloader, 3, "Done, converting game data..."); @@ -1669,6 +1679,8 @@ DEBUG(oldloader, 3, "Finished converting game data"); DEBUG(oldloader, 1, "TTD(Patch) savegame successfully converted"); + free(_old_map3); + return true; } diff -r e9066a148720 -r b3c58f3df92b src/openttd.cpp --- a/src/openttd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/openttd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -59,6 +59,8 @@ #include "date_func.h" #include "vehicle_func.h" #include "cheat_func.h" +#include "animated_tile_func.h" +#include "functions.h" #include "newgrf.h" #include "newgrf_config.h" @@ -92,6 +94,8 @@ void DoPaletteAnimations(); void MusicLoop(); void ResetMusic(); +void ResetOldNames(); +void ProcessAsyncSaveFinish(); extern void SetDifficultyLevel(int mode, GameOptions *gm_opt); extern Player* DoStartupNewPlayer(bool is_ai); @@ -259,8 +263,8 @@ return; } - res[0] = Clamp(strtoul(s, NULL, 0), 64, MAX_SCREEN_WIDTH); - res[1] = Clamp(strtoul(t + 1, NULL, 0), 64, MAX_SCREEN_HEIGHT); + res[0] = max(strtoul(s, NULL, 0), 64UL); + res[1] = max(strtoul(t + 1, NULL, 0), 64UL); } static void InitializeDynamicVariables() @@ -639,39 +643,6 @@ } } - -/** Mutex so that only one thread can communicate with the main program - * at any given time */ -static ThreadMsg _message = MSG_OTTD_NO_MESSAGE; - -static inline void OTTD_ReleaseMutex() {_message = MSG_OTTD_NO_MESSAGE;} -static inline ThreadMsg OTTD_PollThreadEvent() {return _message;} - -/** Called by running thread to execute some action in the main game. - * It will stall as long as the mutex is not freed (handled) by the game */ -void OTTD_SendThreadMessage(ThreadMsg msg) -{ - if (_exit_game) return; - while (_message != MSG_OTTD_NO_MESSAGE) CSleep(10); - - _message = msg; -} - - -/** Handle the user-messages sent to us - * @param message message sent - */ -static void ProcessSentMessage(ThreadMsg message) -{ - switch (message) { - case MSG_OTTD_SAVETHREAD_DONE: SaveFileDone(); break; - case MSG_OTTD_SAVETHREAD_ERROR: SaveFileError(); break; - default: NOT_REACHED(); - } - - OTTD_ReleaseMutex(); // release mutex so that other threads, messages can be handled -} - static void ShowScreenshotResult(bool b) { if (b) { @@ -1089,9 +1060,7 @@ void GameLoop() { - ThreadMsg message; - - if ((message = OTTD_PollThreadEvent()) != 0) ProcessSentMessage(message); + ProcessAsyncSaveFinish(); /* autosave game? */ if (_do_autosave) { @@ -1413,6 +1382,9 @@ } } + /* From this point the old names array is cleared. */ + ResetOldNames(); + /* convert road side to my format. */ if (_opt.road_side) _opt.road_side = 1; diff -r e9066a148720 -r b3c58f3df92b src/openttd.h --- a/src/openttd.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/openttd.h Sun Apr 20 15:27:28 2008 +0000 @@ -1,4 +1,5 @@ /* $Id$ */ + /** @file openttd.h */ #ifndef OPENTTD_H @@ -97,11 +98,6 @@ extern byte _savegame_sort_order; -enum { - MAX_SCREEN_WIDTH = 2048, - MAX_SCREEN_HEIGHT = 1200, -}; - /* In certain windows you navigate with the arrow keys. Do not scroll the * gameview when here. Bitencoded variable that only allows scrolling if all * elements are zero */ @@ -113,17 +109,6 @@ }; extern byte _no_scroll; -/** To have a concurrently running thread interface with the main program, use - * the OTTD_SendThreadMessage() function. Actions to perform upon the message are handled - * in the ProcessSentMessage() function */ -enum ThreadMsg { - MSG_OTTD_NO_MESSAGE, - MSG_OTTD_SAVETHREAD_DONE, - MSG_OTTD_SAVETHREAD_ERROR, -}; - -void OTTD_SendThreadMessage(ThreadMsg msg); - extern byte _game_mode; extern bool _exit_game; extern int8 _pause_game; diff -r e9066a148720 -r b3c58f3df92b src/rail_cmd.cpp --- a/src/rail_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/rail_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -43,6 +43,7 @@ #include "tunnelbridge.h" #include "station_map.h" #include "water_map.h" +#include "functions.h" #include "table/sprites.h" #include "table/strings.h" diff -r e9066a148720 -r b3c58f3df92b src/road_cmd.cpp --- a/src/road_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/road_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -36,6 +36,8 @@ #include "road_func.h" #include "tunnelbridge.h" #include "cheat_func.h" +#include "functions.h" +#include "effectvehicle_func.h" #include "table/sprites.h" #include "table/strings.h" diff -r e9066a148720 -r b3c58f3df92b src/roadveh_cmd.cpp --- a/src/roadveh_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/roadveh_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -42,6 +42,7 @@ #include "order_func.h" #include "depot_base.h" #include "depot_func.h" +#include "effectvehicle_func.h" #include "table/strings.h" @@ -704,7 +705,7 @@ if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); - if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2; + if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2; } } @@ -1844,7 +1845,7 @@ HandleBrokenRoadVeh(v); return; } - v->breakdown_ctr--; + if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--; } if (v->vehstatus & VS_STOPPED) return; diff -r e9066a148720 -r b3c58f3df92b src/saveload.cpp --- a/src/saveload.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/saveload.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -87,6 +87,32 @@ throw std::exception(); } +typedef void (*AsyncSaveFinishProc)(); +static AsyncSaveFinishProc _async_save_finish = NULL; + +/** + * Called by save thread to tell we finished saving. + */ +static void SetAsyncSaveFinish(AsyncSaveFinishProc proc) +{ + if (_exit_game) return; + while (_async_save_finish != NULL) CSleep(10); + + _async_save_finish = proc; +} + +/** + * Handle async save finishes. + */ +void ProcessAsyncSaveFinish() +{ + if (_async_save_finish == NULL) return; + + _async_save_finish(); + + _async_save_finish = NULL; +} + /** * Fill the input buffer by reading from the file with the given reader */ @@ -1248,6 +1274,7 @@ /* these define the chunks */ extern const ChunkHandler _misc_chunk_handlers[]; +extern const ChunkHandler _name_chunk_handlers[]; extern const ChunkHandler _cheat_chunk_handlers[] ; extern const ChunkHandler _setting_chunk_handlers[]; extern const ChunkHandler _player_chunk_handlers[]; @@ -1268,6 +1295,7 @@ static const ChunkHandler * const _chunk_handlers[] = { _misc_chunk_handlers, + _name_chunk_handlers, _cheat_chunk_handlers, _setting_chunk_handlers, _veh_chunk_handlers, @@ -1455,7 +1483,7 @@ /** Update the gui accordingly when starting saving * and set locks on saveload. Also turn off fast-forward cause with that * saving takes Aaaaages */ -void SaveFileStart() +static void SaveFileStart() { _ts.ff_state = _fast_forward; _fast_forward = 0; @@ -1467,7 +1495,7 @@ /** Update the gui accordingly when saving is done and release locks * on saveload */ -void SaveFileDone() +static void SaveFileDone() { _fast_forward = _ts.ff_state; if (_cursor.sprite == SPR_CURSOR_ZZZ) SetMouseCursor(SPR_CURSOR_MOUSE, PAL_NONE); @@ -1494,7 +1522,7 @@ } /** Show a gui message when saving has failed */ -void SaveFileError() +static void SaveFileError() { SetDParamStr(0, GetSaveLoadErrorString()); ShowErrorMessage(STR_012D, STR_NULL, 0, 0); @@ -1543,7 +1571,7 @@ GetSavegameFormat("memory")->uninit_write(); // clean the memorypool fclose(_sl.fh); - if (threaded) OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_DONE); + if (threaded) SetAsyncSaveFinish(SaveFileDone); return SL_OK; } @@ -1555,7 +1583,7 @@ fprintf(stderr, GetSaveLoadErrorString()); if (threaded) { - OTTD_SendThreadMessage(MSG_OTTD_SAVETHREAD_ERROR); + SetAsyncSaveFinish(SaveFileError); } else { SaveFileError(); } diff -r e9066a148720 -r b3c58f3df92b src/saveload.h --- a/src/saveload.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/saveload.h Sun Apr 20 15:27:28 2008 +0000 @@ -321,7 +321,4 @@ void SlObject(void *object, const SaveLoad *sld); bool SlObjectMember(void *object, const SaveLoad *sld); -void SaveFileStart(); -void SaveFileDone(); -void SaveFileError(); #endif /* SAVELOAD_H */ diff -r e9066a148720 -r b3c58f3df92b src/settings.cpp --- a/src/settings.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/settings.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -1654,20 +1654,18 @@ #undef NO #undef CR -static uint NewsDisplayLoadConfig(IniFile *ini, const char *grpname) +static void NewsDisplayLoadConfig(IniFile *ini, const char *grpname) { IniGroup *group = ini_getgroup(ini, grpname, -1); IniItem *item; - /* By default, set everything to full (0xAAAAAAAA = 1010101010101010) */ - uint res = 0xAAAAAAAA; - /* If no group exists, return everything full */ - if (group == NULL) return res; + /* If no group exists, return */ + if (group == NULL) return; for (item = group->item; item != NULL; item = item->next) { int news_item = -1; for (int i = 0; i < NT_END; i++) { - if (strcasecmp(item->name, _news_display_name[i]) == 0) { + if (strcasecmp(item->name, _news_type_data[i].name) == 0) { news_item = i; break; } @@ -1678,18 +1676,16 @@ } if (strcasecmp(item->value, "full") == 0) { - SB(res, news_item * 2, 2, 2); + _news_type_data[news_item].display = ND_FULL; } else if (strcasecmp(item->value, "off") == 0) { - SB(res, news_item * 2, 2, 0); + _news_type_data[news_item].display = ND_OFF; } else if (strcasecmp(item->value, "summarized") == 0) { - SB(res, news_item * 2, 2, 1); + _news_type_data[news_item].display = ND_SUMMARY; } else { DEBUG(misc, 0, "Invalid display value: %s", item->value); continue; } } - - return res; } /* Load a GRF configuration from the given group name */ @@ -1745,7 +1741,7 @@ return first; } -static void NewsDisplaySaveConfig(IniFile *ini, const char *grpname, uint news_display) +static void NewsDisplaySaveConfig(IniFile *ini, const char *grpname) { IniGroup *group = ini_getgroup(ini, grpname, -1); IniItem **item; @@ -1756,11 +1752,11 @@ for (int i = 0; i < NT_END; i++) { const char *value; - int v = GB(news_display, i * 2, 2); + int v = _news_type_data[i].display; - value = (v == 0 ? "off" : (v == 1 ? "summarized" : "full")); + value = (v == ND_OFF ? "off" : (v == ND_SUMMARY ? "summarized" : "full")); - *item = ini_item_alloc(group, _news_display_name[i], strlen(_news_display_name[i])); + *item = ini_item_alloc(group, _news_type_data[i].name, strlen(_news_type_data[i].name)); (*item)->value = (char*)pool_strdup(&ini->pool, value, strlen(value)); item = &(*item)->next; } @@ -1847,7 +1843,7 @@ HandleSettingDescs(ini, ini_load_settings, ini_load_setting_list); _grfconfig_newgame = GRFLoadConfig(ini, "newgrf", false); _grfconfig_static = GRFLoadConfig(ini, "newgrf-static", true); - _news_display_opt = NewsDisplayLoadConfig(ini, "news_display"); + NewsDisplayLoadConfig(ini, "news_display"); CheckDifficultyLevels(); ini_free(ini); } @@ -1859,7 +1855,7 @@ HandleSettingDescs(ini, ini_save_settings, ini_save_setting_list); GRFSaveConfig(ini, "newgrf", _grfconfig_newgame); GRFSaveConfig(ini, "newgrf-static", _grfconfig_static); - NewsDisplaySaveConfig(ini, "news_display", _news_display_opt); + NewsDisplaySaveConfig(ini, "news_display"); SaveVersionInConfig(ini); ini_save(_config_file, ini); ini_free(ini); diff -r e9066a148720 -r b3c58f3df92b src/ship_cmd.cpp --- a/src/ship_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/ship_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -40,6 +40,7 @@ #include "gfx_func.h" #include "settings_type.h" #include "order_func.h" +#include "effectvehicle_func.h" #include "table/strings.h" @@ -210,7 +211,7 @@ if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); - if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2; + if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2; } } @@ -594,7 +595,7 @@ HandleBrokenShip(v); return; } - v->breakdown_ctr--; + if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--; } if (v->vehstatus & VS_STOPPED) return; diff -r e9066a148720 -r b3c58f3df92b src/smallmap_gui.cpp --- a/src/smallmap_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/smallmap_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -682,7 +682,7 @@ byte color; FOR_ALL_VEHICLES(v) { - if (v->type != VEH_SPECIAL && + if (v->type != VEH_EFFECT && (v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0) { /* Remap into flat coordinates. */ Point pt = RemapCoords( @@ -1108,15 +1108,15 @@ static void ExtraViewPortWndProc(Window *w, WindowEvent *e) { switch (e->event) { - case WE_CREATE: /* Disable zoom in button */ + case WE_CREATE: // Disable zoom in button /* New viewport start at (zero,zero) */ - AssignWindowViewport(w, 3, 17, w->widget[4].right - w->widget[4].left - 1, w->widget[4].bottom - w->widget[4].top - 1, 0, ZOOM_LVL_VIEWPORT); + InitializeWindowViewport(w, 3, 17, w->widget[4].right - w->widget[4].left - 1, w->widget[4].bottom - w->widget[4].top - 1, 0, ZOOM_LVL_VIEWPORT); w->DisableWidget(5); break; case WE_PAINT: - // set the number in the title bar + /* set the number in the title bar */ SetDParam(0, w->window_number + 1); DrawWindowWidgets(w); @@ -1128,7 +1128,7 @@ case 5: DoZoomInOutWindow(ZOOM_IN, w); break; case 6: DoZoomInOutWindow(ZOOM_OUT, w); break; - case 7: { /* location button (move main view to same spot as this view) 'Paste Location' */ + case 7: { // location button (move main view to same spot as this view) 'Paste Location' Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0); int x = WP(w, vp_d).scrollpos_x; // Where is the main looking at int y = WP(w, vp_d).scrollpos_y; @@ -1138,7 +1138,7 @@ WP(w2, vp_d).dest_scrollpos_y = y - (w2->viewport->virtual_height - w->viewport->virtual_height) / 2; } break; - case 8: { /* inverse location button (move this view to same spot as main view) 'Copy Location' */ + case 8: { // inverse location button (move this view to same spot as main view) 'Copy Location' const Window *w2 = FindWindowById(WC_MAIN_WINDOW, 0); int x = WP(w2, const vp_d).scrollpos_x; int y = WP(w2, const vp_d).scrollpos_y; diff -r e9066a148720 -r b3c58f3df92b src/sound.cpp --- a/src/sound.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/sound.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -207,6 +207,14 @@ } } +/** + * Decide 'where' (between left and right speaker) to play the sound effect. + * @param sound Sound effect to play + * @param left Left edge of virtual coordinates where the sound is produced + * @param right Right edge of virtual coordinates where the sound is produced + * @param top Top edge of virtual coordinates where the sound is produced + * @param bottom Bottom edge of virtual coordinates where the sound is produced + */ static void SndPlayScreenCoordFx(SoundFx sound, int left, int right, int top, int bottom) { Window* const *wz; @@ -231,7 +239,6 @@ return; } } - } void SndPlayTileFx(SoundFx sound, TileIndex tile) diff -r e9066a148720 -r b3c58f3df92b src/station_base.h --- a/src/station_base.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/station_base.h Sun Apr 20 15:27:28 2008 +0000 @@ -171,6 +171,7 @@ uint16 random_bits; byte waiting_triggers; + uint8 cached_anim_triggers; ///< Combined animation trigger bitmask, used to determine if trigger processing should happen. StationRect rect; ///< Station spread out rectangle (not saved) maintained by StationRect_xxx() functions diff -r e9066a148720 -r b3c58f3df92b src/station_cmd.cpp --- a/src/station_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/station_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -43,6 +43,7 @@ #include "string_func.h" #include "signal_func.h" #include "oldpool_func.h" +#include "animated_tile_func.h" #include "table/sprites.h" #include "table/strings.h" @@ -1127,6 +1128,12 @@ st->rect.BeforeAddRect(tile_org, w_org, h_org, StationRect::ADD_TRY); + if (statspec != NULL) { + /* Include this station spec's animation trigger bitmask + * in the station's cached copy. */ + st->cached_anim_triggers |= statspec->anim_triggers; + } + tile_delta = (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); track = AxisToTrack(axis); @@ -1143,6 +1150,7 @@ MakeRailStation(tile, st->owner, st->index, axis, layout & ~1, (RailType)GB(p2, 0, 4)); SetCustomStationSpecIndex(tile, specindex); SetStationTileRandomBits(tile, GB(Random(), 0, 4)); + SetStationAnimationFrame(tile, 0); if (statspec != NULL) { /* Use a fixed axis for GetPlatformInfo as our platforms / numtracks are always the right way around */ @@ -1151,6 +1159,9 @@ /* As the station is not yet completely finished, the station does not yet exist. */ uint16 callback = GetStationCallback(CBID_STATION_TILE_LAYOUT, platinfo, 0, statspec, NULL, tile); if (callback != CALLBACK_FAILED && callback < 8) SetStationGfx(tile, (callback & ~1) + axis); + + /* Trigger station animation -- after building? */ + StationAnimationTrigger(st, tile, STAT_ANIM_BUILT); } tile += tile_delta; @@ -1372,6 +1383,7 @@ free(st->speclist); st->num_specs = 0; st->speclist = NULL; + st->cached_anim_triggers = 0; InvalidateWindowWidget(WC_STATION_VIEW, st->index, SVW_TRAINS); UpdateStationVirtCoordDirty(st); @@ -2482,6 +2494,11 @@ { GFX_WINDSACK_INTERCON_FIRST, GFX_WINDSACK_INTERCON_LAST, 1 } }; + if (IsRailwayStation(tile)) { + AnimateStationTile(tile); + return; + } + StationGfx gfx = GetStationGfx(tile); for (const AnimData *i = data; i != endof(data); i++) { @@ -2729,7 +2746,16 @@ if (IsValidStationID(i)) StationHandleBigTick(GetStation(i)); Station *st; - FOR_ALL_STATIONS(st) StationHandleSmallTick(st); + FOR_ALL_STATIONS(st) { + StationHandleSmallTick(st); + + /* Run 250 tick interval trigger for station animation. + * Station index is included so that triggers are not all done + * at the same time. */ + if ((_tick_counter + st->index) % 250 == 0) { + StationAnimationTrigger(st, st->xy, STAT_ANIM_250_TICKS); + } + } } void StationMonthlyLoop() @@ -2761,6 +2787,8 @@ st->goods[type].cargo.Append(new CargoPacket(st->index, amount)); SetBit(st->goods[type].acceptance_pickup, GoodsEntry::PICKUP); + StationAnimationTrigger(st, st->xy, STAT_ANIM_NEW_CARGO, type); + InvalidateWindow(WC_STATION_VIEW, st->index); st->MarkTilesDirty(true); } @@ -3135,6 +3163,8 @@ } for (CargoID c = 0; c < NUM_CARGO; c++) st->goods[c].cargo.InvalidateCache(); + + StationUpdateAnimTriggers(st); } } diff -r e9066a148720 -r b3c58f3df92b src/station_gui.cpp --- a/src/station_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/station_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -184,35 +184,36 @@ assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(plstations_d)); /** - * Set the 'SL_REBUILD' flag for all station lists + * Set the station sort flag for all station-list windows. + * @param sl_flag Sort list flag to set for all station-list windows */ -void RebuildStationLists() +static void SetStationListsFlag(StationListFlags sl_flag) { Window *const *wz; FOR_ALL_WINDOWS(wz) { Window *w = *wz; if (w->window_class == WC_STATION_LIST) { - WP(w, plstations_d).flags |= SL_REBUILD; + WP(w, plstations_d).flags |= sl_flag; SetWindowDirty(w); } } } /** + * Set the 'SL_REBUILD' flag for all station lists + */ +void RebuildStationLists() +{ + SetStationListsFlag(SL_REBUILD); +} + +/** * Set the 'SL_RESORT' flag for all station lists */ void ResortStationLists() { - Window *const *wz; - - FOR_ALL_WINDOWS(wz) { - Window *w = *wz; - if (w->window_class == WC_STATION_LIST) { - WP(w, plstations_d).flags |= SL_RESORT; - SetWindowDirty(w); - } - } + SetStationListsFlag(SL_RESORT); } /** diff -r e9066a148720 -r b3c58f3df92b src/stdafx.h --- a/src/stdafx.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/stdafx.h Sun Apr 20 15:27:28 2008 +0000 @@ -309,13 +309,7 @@ #define CloseConnection OTTD_CloseConnection #endif /* __APPLE__ */ -#if !defined(STRGEN) - /* In strgen error is not fatal and returns */ - void NORETURN CDECL error(const char *str, ...); -#else - void CDECL error(const char *str, ...); -#endif - +void NORETURN CDECL error(const char *str, ...); #define NOT_REACHED() error("NOT_REACHED triggered at line %i of %s", __LINE__, __FILE__) #if defined(MORPHOS) || defined(__NDS__) diff -r e9066a148720 -r b3c58f3df92b src/strgen/strgen.cpp --- a/src/strgen/strgen.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/strgen/strgen.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -155,7 +155,7 @@ # define LINE_NUM_FMT ":%d" #endif -static void CDECL warning(const char *s, ...) +static void CDECL strgen_warning(const char *s, ...) { char buf[1024]; va_list va; @@ -166,7 +166,7 @@ _warnings++; } -void CDECL error(const char *s, ...) +static void CDECL strgen_error(const char *s, ...) { char buf[1024]; va_list va; @@ -177,8 +177,7 @@ _errors++; } - -static void NORETURN CDECL fatal(const char *s, ...) +void NORETURN CDECL error(const char *s, ...) { char buf[1024]; va_list va; @@ -191,7 +190,7 @@ static void PutByte(byte c) { - if (_put_pos == lengthof(_put_buf)) fatal("Put buffer too small"); + if (_put_pos == lengthof(_put_buf)) error("Put buffer too small"); _put_buf[_put_pos++] = c; } @@ -213,7 +212,7 @@ PutByte(0x80 + GB(value, 6, 6)); PutByte(0x80 + GB(value, 0, 6)); } else { - warning("Invalid unicode value U+0x%X", value); + strgen_warning("Invalid unicode value U+0x%X", value); } } @@ -245,7 +244,7 @@ static void EmitSingleChar(char *buf, int value) { - if (*buf != '\0') warning("Ignoring trailing letters in command"); + if (*buf != '\0') strgen_warning("Ignoring trailing letters in command"); PutUtf8(value); } @@ -254,7 +253,7 @@ { char *err; int x = strtol(buf, &err, 0); - if (*err != 0) fatal("SetX param invalid"); + if (*err != 0) error("SetX param invalid"); PutUtf8(SCC_SETX); PutByte((byte)x); } @@ -267,9 +266,9 @@ int y; x = strtol(buf, &err, 0); - if (*err != ' ') fatal("SetXY param invalid"); + if (*err != ' ') error("SetXY param invalid"); y = strtol(err + 1, &err, 0); - if (*err != 0) fatal("SetXY param invalid"); + if (*err != 0) error("SetXY param invalid"); PutUtf8(SCC_SETXY); PutByte((byte)x); @@ -371,14 +370,14 @@ } if (nw == 0) - fatal("%s: No plural words", _cur_ident); + error("%s: No plural words", _cur_ident); if (_plural_form_counts[_lang_pluralform] != nw) { if (_translated) { - fatal("%s: Invalid number of plural forms. Expecting %d, found %d.", _cur_ident, + error("%s: Invalid number of plural forms. Expecting %d, found %d.", _cur_ident, _plural_form_counts[_lang_pluralform], nw); } else { - if ((_show_todo & 2) != 0) warning("'%s' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident); + if ((_show_todo & 2) != 0) strgen_warning("'%s' is untranslated. Tweaking english string to allow compilation for plural forms", _cur_ident); if (nw > _plural_form_counts[_lang_pluralform]) { nw = _plural_form_counts[_lang_pluralform]; } else { @@ -405,7 +404,7 @@ // This is a {G=DER} command for (nw = 0; ; nw++) { - if (nw >= 8) fatal("G argument '%s' invalid", buf); + if (nw >= 8) error("G argument '%s' invalid", buf); if (strcmp(buf, _genders[nw]) == 0) break; } // now nw contains the gender index @@ -422,7 +421,7 @@ words[nw] = ParseWord(&buf); if (words[nw] == NULL) break; } - if (nw != _numgenders) fatal("Bad # of arguments for gender command"); + if (nw != _numgenders) error("Bad # of arguments for gender command"); PutUtf8(SCC_GENDER_LIST); PutByte(TranslateArgumentIdx(argidx)); EmitWordList(words, nw); @@ -553,7 +552,7 @@ for (i = 0; i < MAX_NUM_CASES; i++) { if (memcmp(_cases[i], str, len) == 0 && _cases[i][len] == 0) return i + 1; } - fatal("Invalid case-name '%s'", str); + error("Invalid case-name '%s'", str); } @@ -578,7 +577,7 @@ char *end; *argno = strtoul(s, &end, 0); - if (*end != ':') fatal("missing arg #"); + if (*end != ':') error("missing arg #"); s = end + 1; } @@ -590,7 +589,7 @@ cmd = FindCmd(start, s - start - 1); if (cmd == NULL) { - error("Undefined command '%.*s'", s - start - 1, start); + strgen_error("Undefined command '%.*s'", s - start - 1, start); return NULL; } @@ -598,14 +597,14 @@ const char *casep = s; if (!(cmd->flags & C_CASE)) - fatal("Command '%s' can't have a case", cmd->cmd); + error("Command '%s' can't have a case", cmd->cmd); do c = *s++; while (c != '}' && c != ' ' && c != '\0'); *casei = ResolveCaseName(casep, s - casep - 1); } if (c == '\0') { - error("Missing } from command '%s'", start); + strgen_error("Missing } from command '%s'", start); return NULL; } @@ -618,10 +617,10 @@ c = *s++; if (c == '}') break; if (c == '\0') { - error("Missing } from command '%s'", start); + strgen_error("Missing } from command '%s'", start); return NULL; } - if (s - start == 250) fatal("param command too long"); + if (s - start == 250) error("param command too long"); *param++ = c; } } @@ -646,7 +645,7 @@ } else if (!memcmp(str, "plural ", 7)) { _lang_pluralform = atoi(str + 7); if (_lang_pluralform >= lengthof(_plural_form_counts)) - fatal("Invalid pluralform %d", _lang_pluralform); + error("Invalid pluralform %d", _lang_pluralform); } else if (!memcmp(str, "gender ", 7)) { char* buf = str + 7; @@ -654,7 +653,7 @@ const char* s = ParseWord(&buf); if (s == NULL) break; - if (_numgenders >= MAX_NUM_GENDER) fatal("Too many genders, max %d", MAX_NUM_GENDER); + if (_numgenders >= MAX_NUM_GENDER) error("Too many genders, max %d", MAX_NUM_GENDER); ttd_strlcpy(_genders[_numgenders], s, sizeof(_genders[_numgenders])); _numgenders++; } @@ -665,12 +664,12 @@ const char* s = ParseWord(&buf); if (s == NULL) break; - if (_numcases >= MAX_NUM_CASES) fatal("Too many cases, max %d", MAX_NUM_CASES); + if (_numcases >= MAX_NUM_CASES) error("Too many cases, max %d", MAX_NUM_CASES); ttd_strlcpy(_cases[_numcases], s, sizeof(_cases[_numcases])); _numcases++; } } else { - fatal("unknown pragma '%s'", str); + error("unknown pragma '%s'", str); } } @@ -690,16 +689,16 @@ if (ar == NULL) break; // Sanity checking - if (argno != -1 && ar->consumes == 0) fatal("Non consumer param can't have a paramindex"); + if (argno != -1 && ar->consumes == 0) error("Non consumer param can't have a paramindex"); if (ar->consumes) { if (argno != -1) argidx = argno; - if (argidx < 0 || argidx >= lengthof(p->cmd)) fatal("invalid param idx %d", argidx); - if (p->cmd[argidx] != NULL && p->cmd[argidx] != ar) fatal("duplicate param idx %d", argidx); + if (argidx < 0 || argidx >= lengthof(p->cmd)) error("invalid param idx %d", argidx); + if (p->cmd[argidx] != NULL && p->cmd[argidx] != ar) error("duplicate param idx %d", argidx); p->cmd[argidx++] = ar; } else if (!(ar->flags & C_DONTCOUNT)) { // Ignore some of them - if (p->np >= lengthof(p->pairs)) fatal("too many commands in string, max %d", lengthof(p->pairs)); + if (p->np >= lengthof(p->pairs)) error("too many commands in string, max %d", lengthof(p->pairs)); p->pairs[p->np].a = ar; p->pairs[p->np].v = param[0] != '\0' ? strdup(param) : ""; p->np++; @@ -738,7 +737,7 @@ // For each string in templ, see if we find it in lang if (templ.np != lang.np) { - warning("%s: template string and language string have a different # of commands", name); + strgen_warning("%s: template string and language string have a different # of commands", name); result = false; } @@ -756,7 +755,7 @@ } if (!found) { - warning("%s: command '%s' exists in template file but not in language file", name, templ.pairs[i].a->cmd); + strgen_warning("%s: command '%s' exists in template file but not in language file", name, templ.pairs[i].a->cmd); result = false; } } @@ -765,7 +764,7 @@ // Check if the non consumer commands match up also. for (i = 0; i < lengthof(templ.cmd); i++) { if (TranslateCmdForCompare(templ.cmd[i]) != TranslateCmdForCompare(lang.cmd[i])) { - warning("%s: Param idx #%d '%s' doesn't match with template command '%s'", name, i, + strgen_warning("%s: Param idx #%d '%s' doesn't match with template command '%s'", name, i, lang.cmd[i] == NULL ? "" : lang.cmd[i]->cmd, templ.cmd[i] == NULL ? "" : templ.cmd[i]->cmd); result = false; @@ -791,7 +790,7 @@ s = strchr(str, ':'); if (s == NULL) { - error("Line has no ':' delimiter"); + strgen_error("Line has no ':' delimiter"); return; } @@ -806,7 +805,7 @@ const char *tmp; for (tmp = s; *tmp != '\0';) { size_t len = Utf8Validate(tmp); - if (len == 0) fatal("Invalid UTF-8 sequence in '%s'", s); + if (len == 0) error("Invalid UTF-8 sequence in '%s'", s); tmp += len; } } @@ -821,18 +820,18 @@ if (master) { if (ent != NULL && casep == NULL) { - error("String name '%s' is used multiple times", str); + strgen_error("String name '%s' is used multiple times", str); return; } if (ent == NULL && casep != NULL) { - error("Base string name '%s' doesn't exist yet. Define it before defining a case.", str); + strgen_error("Base string name '%s' doesn't exist yet. Define it before defining a case.", str); return; } if (ent == NULL) { if (_strings[_next_string_id]) { - error("String ID 0x%X for '%s' already in use by '%s'", ent, str, _strings[_next_string_id]->name); + strgen_error("String ID 0x%X for '%s' already in use by '%s'", ent, str, _strings[_next_string_id]->name); return; } @@ -859,12 +858,12 @@ } else { if (ent == NULL) { - warning("String name '%s' does not exist in master file", str); + strgen_warning("String name '%s' does not exist in master file", str); return; } if (ent->translated && casep == NULL) { - error("String name '%s' is used multiple times", str); + strgen_error("String name '%s' is used multiple times", str); return; } @@ -912,7 +911,7 @@ // derive some strings from english.... in = fopen(file, "r"); - if (in == NULL) fatal("Cannot open file"); + if (in == NULL) error("Cannot open file"); _cur_line = 1; while (fgets(buf, sizeof(buf), in) != NULL) { rstrip(buf); @@ -922,7 +921,7 @@ fclose(in); if (StrEmpty(_lang_name) || StrEmpty(_lang_ownname) || StrEmpty(_lang_isocode)) { - fatal("Language must include ##name, ##ownname and ##isocode"); + error("Language must include ##name, ##ownname and ##isocode"); } } @@ -991,7 +990,7 @@ if (f2 == NULL) return false; f1 = fopen(n1, "rb"); - if (f1 == NULL) fatal("can't open %s", n1); + if (f1 == NULL) error("can't open %s", n1); do { l1 = fread(b1, 1, sizeof(b1), f1); @@ -1017,7 +1016,7 @@ int next = -1; out = fopen("tmp.xxx", "w"); - if (out == NULL) fatal("can't open tmp.xxx"); + if (out == NULL) error("can't open tmp.xxx"); fprintf(out, "/* This file is automatically generated. Do not modify */\n\n"); fprintf(out, "#ifndef TABLE_STRINGS_H\n"); @@ -1052,7 +1051,7 @@ #if defined(WIN32) || defined(WIN64) unlink(filename); #endif - if (rename("tmp.xxx", filename) == -1) fatal("rename() failed"); + if (rename("tmp.xxx", filename) == -1) error("rename() failed"); } } @@ -1061,7 +1060,7 @@ int i, sum; if (argidx < 0 || argidx >= lengthof(_cur_pcs.cmd)) - fatal("invalid argidx %d", argidx); + error("invalid argidx %d", argidx); for (i = sum = 0; i < argidx; i++) { const CmdStruct *cs = _cur_pcs.cmd[i]; @@ -1112,7 +1111,7 @@ // Output the one from the master string... it's always accurate. cs = _cur_pcs.cmd[_cur_argidx++]; if (cs == NULL) { - fatal("%s: No argument exists at position %d", _cur_ident, _cur_argidx - 1); + error("%s: No argument exists at position %d", _cur_ident, _cur_argidx - 1); } } @@ -1128,7 +1127,7 @@ fputc((length >> 8) | 0xC0, f); fputc(length & 0xFF, f); } else { - fatal("string too long"); + error("string too long"); } } @@ -1142,7 +1141,7 @@ uint j; f = fopen(filename, "wb"); - if (f == NULL) fatal("can't open %s", filename); + if (f == NULL) error("can't open %s", filename); memset(&hdr, 0, sizeof(hdr)); for (i = 0; i != 32; i++) { @@ -1180,7 +1179,7 @@ // Produce a message if a string doesn't have a translation. if (_show_todo > 0 && ls->translated == NULL) { if ((_show_todo & 2) != 0) { - warning("'%s' is untranslated", ls->name); + strgen_warning("'%s' is untranslated", ls->name); } if ((_show_todo & 1) != 0) { const char *s = " "; diff -r e9066a148720 -r b3c58f3df92b src/strings.cpp --- a/src/strings.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/strings.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -37,6 +37,7 @@ #include "settings_type.h" #include "video/video_driver.hpp" #include "engine_func.h" +#include "saveload.h" #include "table/strings.h" #include "table/control_codes.h" @@ -1045,11 +1046,11 @@ static char *StationGetSpecialString(char *buff, int x, const char* last) { - if ((x & 0x01) && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN); - if ((x & 0x02) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY); - if ((x & 0x04) && (buff + Utf8CharLen(SCC_BUS) < last)) buff += Utf8Encode(buff, SCC_BUS); - if ((x & 0x08) && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE); - if ((x & 0x10) && (buff + Utf8CharLen(SCC_SHIP) < last)) buff += Utf8Encode(buff, SCC_SHIP); + if ((x & FACIL_TRAIN) && (buff + Utf8CharLen(SCC_TRAIN) < last)) buff += Utf8Encode(buff, SCC_TRAIN); + if ((x & FACIL_TRUCK_STOP) && (buff + Utf8CharLen(SCC_LORRY) < last)) buff += Utf8Encode(buff, SCC_LORRY); + if ((x & FACIL_BUS_STOP) && (buff + Utf8CharLen(SCC_BUS) < last)) buff += Utf8Encode(buff, SCC_BUS); + if ((x & FACIL_AIRPORT) && (buff + Utf8CharLen(SCC_PLANE) < last)) buff += Utf8Encode(buff, SCC_PLANE); + if ((x & FACIL_DOCK) && (buff + Utf8CharLen(SCC_SHIP) < last)) buff += Utf8Encode(buff, SCC_SHIP); *buff = '\0'; return buff; } @@ -1226,31 +1227,6 @@ return NULL; } -/** - * remap a string ID from the old format to the new format - * @param s StringID that requires remapping - * @return translated ID*/ -StringID RemapOldStringID(StringID s) -{ - switch (s) { - case 0x0006: return STR_SV_EMPTY; - case 0x7000: return STR_SV_UNNAMED; - case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH; - case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH; - case 0x8864: return STR_SV_TRAIN_NAME; - case 0x902B: return STR_SV_ROADVEH_NAME; - case 0x9830: return STR_SV_SHIP_NAME; - case 0xA02F: return STR_SV_AIRCRAFT_NAME; - - default: - if (IsInsideMM(s, 0x300F, 0x3030)) { - return s - 0x300F + STR_SV_STNAME; - } else { - return s; - } - } -} - #ifdef ENABLE_NETWORK extern void SortNetworkLanguages(); #else /* ENABLE_NETWORK */ @@ -1342,6 +1318,8 @@ return getenv("LANG"); } +#else +const char *GetCurrentLocale(const char *param); #endif /* !(defined(WIN32) || defined(__APPLE__)) */ int CDECL StringIDSorter(const void *a, const void *b) @@ -1548,3 +1526,118 @@ } } } + + +/* --- Handling of saving/loading string IDs from old savegames --- */ + +/** + * Remap a string ID from the old format to the new format + * @param s StringID that requires remapping + * @return translated ID + */ +StringID RemapOldStringID(StringID s) +{ + switch (s) { + case 0x0006: return STR_SV_EMPTY; + case 0x7000: return STR_SV_UNNAMED; + case 0x70E4: return SPECSTR_PLAYERNAME_ENGLISH; + case 0x70E9: return SPECSTR_PLAYERNAME_ENGLISH; + case 0x8864: return STR_SV_TRAIN_NAME; + case 0x902B: return STR_SV_ROADVEH_NAME; + case 0x9830: return STR_SV_SHIP_NAME; + case 0xA02F: return STR_SV_AIRCRAFT_NAME; + + default: + if (IsInsideMM(s, 0x300F, 0x3030)) { + return s - 0x300F + STR_SV_STNAME; + } else { + return s; + } + } +} + +/** Location to load the old names to. */ +char *_old_name_array = NULL; + +/** + * Copy and convert old custom names to UTF-8. + * They were all stored in a 512 by 32 long string array and are + * now stored with stations, waypoints and other places with names. + * @param id the StringID of the custom name to clone. + * @return the clones custom name. + */ +char *CopyFromOldName(StringID id) +{ + /* Is this name an (old) custom name? */ + if (GB(id, 11, 5) != 15) return NULL; + + if (CheckSavegameVersion(37)) { + /* Old names were 32 characters long, so 128 characters should be + * plenty to allow for expansion when converted to UTF-8. */ + char tmp[128]; + const char *strfrom = &_old_name_array[32 * GB(id, 0, 9)]; + char *strto = tmp; + + for (; *strfrom != '\0'; strfrom++) { + WChar c = (byte)*strfrom; + + /* Map from non-ISO8859-15 characters to UTF-8. */ + switch (c) { + case 0xA4: c = 0x20AC; break; // Euro + case 0xA6: c = 0x0160; break; // S with caron + case 0xA8: c = 0x0161; break; // s with caron + case 0xB4: c = 0x017D; break; // Z with caron + case 0xB8: c = 0x017E; break; // z with caron + case 0xBC: c = 0x0152; break; // OE ligature + case 0xBD: c = 0x0153; break; // oe ligature + case 0xBE: c = 0x0178; break; // Y with diaresis + default: break; + } + + /* Check character will fit into our buffer. */ + if (strto + Utf8CharLen(c) > lastof(tmp)) break; + + strto += Utf8Encode(strto, c); + } + + /* Terminate the new string and copy it back to the name array */ + *strto = '\0'; + + return strdup(tmp); + } else { + /* Name will already be in UTF-8. */ + return strdup(&_old_name_array[32 * GB(id, 0, 9)]); + } +} + +/** + * Free the memory of the old names array. + * Should be called once the old names have all been converted. + */ +void ResetOldNames() +{ + free(_old_name_array); + _old_name_array = NULL; +} + +/** + * Initialize the old names table memory. + */ +void InitializeOldNames() +{ + free(_old_name_array); + _old_name_array = CallocT(512 * 32); +} + +static void Load_NAME() +{ + int index; + + while ((index = SlIterateArray()) != -1) { + SlArray(&_old_name_array[32 * index], SlGetFieldLength(), SLE_UINT8); + } +} + +extern const ChunkHandler _name_chunk_handlers[] = { + { 'NAME', NULL, Load_NAME, CH_ARRAY | CH_LAST}, +}; diff -r e9066a148720 -r b3c58f3df92b src/strings_func.h --- a/src/strings_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/strings_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -78,4 +78,7 @@ void CheckForMissingGlyphsInLoadedLanguagePack(); +StringID RemapOldStringID(StringID s); +char *CopyFromOldName(StringID id); + #endif /* STRINGS_TYPE_H */ diff -r e9066a148720 -r b3c58f3df92b src/texteff.cpp --- a/src/texteff.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/texteff.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -4,10 +4,8 @@ #include "stdafx.h" #include "openttd.h" -#include "tile_cmd.h" #include "landscape.h" #include "gfx_func.h" -#include "saveload.h" #include "console.h" #include "variables.h" #include "blitter/factory.hpp" @@ -423,128 +421,3 @@ default: NOT_REACHED(); } } - -/** The table/list with animated tiles. */ -TileIndex *_animated_tile_list = NULL; -/** The number of animated tiles in the current state. */ -uint _animated_tile_count = 0; -/** The number of slots for animated tiles allocated currently. */ -static uint _animated_tile_allocated = 0; - -/** - * Removes the given tile from the animated tile table. - * @param tile the tile to remove - */ -void DeleteAnimatedTile(TileIndex tile) -{ - for (TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) { - if (tile == *ti) { - /* Remove the hole - * The order of the remaining elements must stay the same, otherwise the animation loop - * may miss a tile; that's why we must use memmove instead of just moving the last element. - */ - memmove(ti, ti + 1, (_animated_tile_list + _animated_tile_count - (ti + 1)) * sizeof(*ti)); - _animated_tile_count--; - MarkTileDirtyByTile(tile); - return; - } - } -} - -/** - * Add the given tile to the animated tile table (if it does not exist - * on that table yet). Also increases the size of the table if necessary. - * @param tile the tile to make animated - */ -void AddAnimatedTile(TileIndex tile) -{ - MarkTileDirtyByTile(tile); - - for (const TileIndex *ti = _animated_tile_list; ti < _animated_tile_list + _animated_tile_count; ti++) { - if (tile == *ti) return; - } - - /* Table not large enough, so make it larger */ - if (_animated_tile_count == _animated_tile_allocated) { - _animated_tile_allocated *= 2; - _animated_tile_list = ReallocT(_animated_tile_list, _animated_tile_allocated); - } - - _animated_tile_list[_animated_tile_count] = tile; - _animated_tile_count++; -} - -/** - * Animate all tiles in the animated tile list, i.e.\ call AnimateTile on them. - */ -void AnimateAnimatedTiles() -{ - const TileIndex *ti = _animated_tile_list; - while (ti < _animated_tile_list + _animated_tile_count) { - const TileIndex curr = *ti; - AnimateTile(curr); - /* During the AnimateTile call, DeleteAnimatedTile could have been called, - * deleting an element we've already processed and pushing the rest one - * slot to the left. We can detect this by checking whether the index - * in the current slot has changed - if it has, an element has been deleted, - * and we should process the current slot again instead of going forward. - * NOTE: this will still break if more than one animated tile is being - * deleted during the same AnimateTile call, but no code seems to - * be doing this anyway. - */ - if (*ti == curr) ++ti; - } -} - -/** - * Initialize all animated tile variables to some known begin point - */ -void InitializeAnimatedTiles() -{ - _animated_tile_list = ReallocT(_animated_tile_list, 256); - _animated_tile_count = 0; - _animated_tile_allocated = 256; -} - -/** - * Save the ANIT chunk. - */ -static void Save_ANIT() -{ - SlSetLength(_animated_tile_count * sizeof(*_animated_tile_list)); - SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32); -} - -/** - * Load the ANIT chunk; the chunk containing the animated tiles. - */ -static void Load_ANIT() -{ - /* Before version 80 we did NOT have a variable length animated tile table */ - if (CheckSavegameVersion(80)) { - /* In pre version 6, we has 16bit per tile, now we have 32bit per tile, convert it ;) */ - SlArray(_animated_tile_list, 256, CheckSavegameVersion(6) ? (SLE_FILE_U16 | SLE_VAR_U32) : SLE_UINT32); - - for (_animated_tile_count = 0; _animated_tile_count < 256; _animated_tile_count++) { - if (_animated_tile_list[_animated_tile_count] == 0) break; - } - return; - } - - _animated_tile_count = SlGetFieldLength() / sizeof(*_animated_tile_list); - - /* Determine a nice rounded size for the amount of allocated tiles */ - _animated_tile_allocated = 256; - while (_animated_tile_allocated < _animated_tile_count) _animated_tile_allocated *= 2; - - _animated_tile_list = ReallocT(_animated_tile_list, _animated_tile_allocated); - SlArray(_animated_tile_list, _animated_tile_count, SLE_UINT32); -} - -/** - * "Definition" imported by the saveload code to be able to load and save - * the animated tile table. - */ -extern const ChunkHandler _animated_tile_chunk_handlers[] = { - { 'ANIT', Save_ANIT, Load_ANIT, CH_RIFF | CH_LAST}, -}; diff -r e9066a148720 -r b3c58f3df92b src/town_cmd.cpp --- a/src/town_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/town_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -45,6 +45,9 @@ #include "economy_func.h" #include "station_func.h" #include "cheat_func.h" +#include "functions.h" +#include "animated_tile_func.h" +#include "date_func.h" #include "table/strings.h" #include "table/sprites.h" @@ -268,7 +271,10 @@ pos += (pos < dest) ? 1 : -1; SetLiftPosition(tile, pos); - if (pos == dest) HaltLift(tile); + if (pos == dest) { + HaltLift(tile); + DeleteAnimatedTile(tile); + } MarkTileDirtyByTile(tile); } @@ -385,6 +391,7 @@ /* Now that construction is complete, we can add the population of the * building to the town. */ ChangePopulation(GetTownByTile(tile), GetHouseSpecs(GetHouseType(tile))->population); + SetHouseConstructionYear(tile, _cur_year); } MarkTileDirtyByTile(tile); } @@ -1644,6 +1651,9 @@ assert(CmdSucceeded(cc)); MakeHouseTile(tile, tid, counter, stage, type, random_bits); + if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(tile); + + MarkTileDirtyByTile(tile); } diff -r e9066a148720 -r b3c58f3df92b src/town_gui.cpp --- a/src/town_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/town_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -396,7 +396,7 @@ if (w != NULL) { w->flags4 |= WF_DISABLE_VP_SCROLL; - AssignWindowViewport(w, 3, 17, 0xFE, 0x56, GetTown(town)->xy, ZOOM_LVL_TOWN); + InitializeWindowViewport(w, 3, 17, 254, 86, GetTown(town)->xy, ZOOM_LVL_TOWN); } } diff -r e9066a148720 -r b3c58f3df92b src/town_map.h --- a/src/town_map.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/town_map.h Sun Apr 20 15:27:28 2008 +0000 @@ -6,9 +6,8 @@ #define TOWN_MAP_H #include "town.h" -#include "date_func.h" +#include "date_type.h" #include "tile_map.h" -#include "functions.h" /** * Get the index of which town this house/street is attached to. @@ -113,7 +112,6 @@ static inline void HaltLift(TileIndex t) { SB(_me[t].m7, 0, 4, 0); - DeleteAnimatedTile(t); } /** @@ -206,9 +204,6 @@ _m[t].m5 = IsHouseCompleted(t) ? 0 : (stage << 3 | counter); SetHouseAnimationFrame(t, 0); _me[t].m7 = GetHouseSpecs(type)->processing_time; - - if (GetHouseSpecs(type)->building_flags & BUILDING_IS_ANIMATED) AddAnimatedTile(t); - MarkTileDirtyByTile(t); } /** @@ -266,11 +261,22 @@ /* House is now completed. * Store the year of construction as well, for newgrf house purpose */ SetHouseCompleted(t, true); - _m[t].m5 = Clamp(_cur_year - ORIGINAL_BASE_YEAR, 0, 0xFF); } } /** + * Set the year that this house was constructed (between 1920 and 2175). + * @param t the tile of this house + * @param year the year to set + * @pre IsTileType(t, MP_HOUSE) && IsHouseCompleted(t) + */ +static inline void SetHouseConstructionYear(TileIndex t, Year year) +{ + assert(IsTileType(t, MP_HOUSE) && IsHouseCompleted(t)); + _m[t].m5 = Clamp(year - ORIGINAL_BASE_YEAR, 0, 0xFF); +} + +/** * Get the year that this house was constructed (between 1920 and 2175). * @param t the tile of this house * @pre IsTileType(t, MP_HOUSE) diff -r e9066a148720 -r b3c58f3df92b src/train_cmd.cpp --- a/src/train_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/train_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -48,6 +48,8 @@ #include "gfx_func.h" #include "settings_type.h" #include "order_func.h" +#include "newgrf_station.h" +#include "effectvehicle_func.h" #include "table/strings.h" #include "table/train_cmd.h" @@ -2218,6 +2220,8 @@ SND_41_MAGLEV }; + if (IsTileType(this->tile, MP_STATION)) StationAnimationTrigger(NULL, this->tile, STAT_ANIM_TRAIN_DEPARTS); + if (PlayVehicleSound(this, VSE_START)) return; EngineID engtype = this->engine_type; @@ -2638,6 +2642,8 @@ } v->BeginLoading(); + + StationAnimationTrigger(st, v->tile, STAT_ANIM_TRAIN_ARRIVES); } static byte AfterSetTrainPos(Vehicle *v, bool new_tile) @@ -3232,7 +3238,7 @@ if (!(v->vehstatus & VS_HIDDEN)) { Vehicle *u = CreateEffectVehicleRel(v, 4, 4, 5, EV_BREAKDOWN_SMOKE); - if (u != NULL) u->u.special.animation_state = v->breakdown_delay * 2; + if (u != NULL) u->u.effect.animation_state = v->breakdown_delay * 2; } } @@ -3421,7 +3427,7 @@ HandleBrokenTrain(v); return; } - v->breakdown_ctr--; + if (!v->current_order.IsType(OT_LOADING)) v->breakdown_ctr--; } if (HasBit(v->u.rail.flags, VRF_REVERSING) && v->cur_speed == 0) { diff -r e9066a148720 -r b3c58f3df92b src/vehicle.cpp --- a/src/vehicle.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/vehicle.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -47,6 +47,8 @@ #include "settings_type.h" #include "oldpool_func.h" #include "depot_map.h" +#include "animated_tile_func.h" +#include "effectvehicle_base.h" #include "table/sprites.h" #include "table/strings.h" @@ -106,6 +108,7 @@ if (!p->engine_renew) return false; if (this->age - this->max_age < (p->engine_renew_months * 30)) return false; + if (this->age == 0) return false; // rail cars don't age and lacks a max age return true; } @@ -691,11 +694,32 @@ /* now we handle all the vehicles that entered a depot this tick */ v = _first_veh_in_depot_list; - while (v != NULL) { - Vehicle *w = v->depot_list; - v->depot_list = NULL; // it should always be NULL at the end of each tick - MaybeReplaceVehicle(v, false, true); - v = w; + if (v != NULL) { + while (v != NULL) { + /* Autoreplace needs the current player set as the vehicle owner */ + _current_player = v->owner; + + /* Buffer v->depot_list and clear it. + * Autoreplace might clear this so it has to be buffered. */ + Vehicle *w = v->depot_list; + v->depot_list = NULL; // it should always be NULL at the end of each tick + + /* Start vehicle if we stopped them in VehicleEnteredDepotThisTick() + * We need to stop them between VehicleEnteredDepotThisTick() and here or we risk that + * they are already leaving the depot again before being replaced. */ + if (v->leave_depot_instantly) { + v->leave_depot_instantly = false; + v->vehstatus &= ~VS_STOPPED; + } + + CommandCost cost = MaybeReplaceVehicle(v, 0, true); + if (CmdSucceeded(cost) && cost.GetCost() != 0) { + /* Looks like we can replace this vehicle so we go ahead and do so */ + MaybeReplaceVehicle(v, DC_EXEC, true); + } + v = w; + } + _current_player = OWNER_NONE; } } @@ -823,605 +847,6 @@ } } -static void ChimneySmokeInit(Vehicle *v) -{ - uint32 r = Random(); - v->cur_image = SPR_CHIMNEY_SMOKE_0 + GB(r, 0, 3); - v->progress = GB(r, 16, 3); -} - -static void ChimneySmokeTick(Vehicle *v) -{ - if (v->progress > 0) { - v->progress--; - } else { - BeginVehicleMove(v); - - TileIndex tile = TileVirtXY(v->x_pos, v->y_pos); - if (!IsTileType(tile, MP_INDUSTRY)) { - EndVehicleMove(v); - delete v; - return; - } - - if (v->cur_image != SPR_CHIMNEY_SMOKE_7) { - v->cur_image++; - } else { - v->cur_image = SPR_CHIMNEY_SMOKE_0; - } - v->progress = 7; - VehiclePositionChanged(v); - EndVehicleMove(v); - } -} - -static void SteamSmokeInit(Vehicle *v) -{ - v->cur_image = SPR_STEAM_SMOKE_0; - v->progress = 12; -} - -static void SteamSmokeTick(Vehicle *v) -{ - bool moved = false; - - BeginVehicleMove(v); - - v->progress++; - - if ((v->progress & 7) == 0) { - v->z_pos++; - moved = true; - } - - if ((v->progress & 0xF) == 4) { - if (v->cur_image != SPR_STEAM_SMOKE_4) { - v->cur_image++; - } else { - EndVehicleMove(v); - delete v; - return; - } - moved = true; - } - - if (moved) { - VehiclePositionChanged(v); - EndVehicleMove(v); - } -} - -static void DieselSmokeInit(Vehicle *v) -{ - v->cur_image = SPR_DIESEL_SMOKE_0; - v->progress = 0; -} - -static void DieselSmokeTick(Vehicle *v) -{ - v->progress++; - - if ((v->progress & 3) == 0) { - BeginVehicleMove(v); - v->z_pos++; - VehiclePositionChanged(v); - EndVehicleMove(v); - } else if ((v->progress & 7) == 1) { - BeginVehicleMove(v); - if (v->cur_image != SPR_DIESEL_SMOKE_5) { - v->cur_image++; - VehiclePositionChanged(v); - EndVehicleMove(v); - } else { - EndVehicleMove(v); - delete v; - } - } -} - -static void ElectricSparkInit(Vehicle *v) -{ - v->cur_image = SPR_ELECTRIC_SPARK_0; - v->progress = 1; -} - -static void ElectricSparkTick(Vehicle *v) -{ - if (v->progress < 2) { - v->progress++; - } else { - v->progress = 0; - BeginVehicleMove(v); - if (v->cur_image != SPR_ELECTRIC_SPARK_5) { - v->cur_image++; - VehiclePositionChanged(v); - EndVehicleMove(v); - } else { - EndVehicleMove(v); - delete v; - } - } -} - -static void SmokeInit(Vehicle *v) -{ - v->cur_image = SPR_SMOKE_0; - v->progress = 12; -} - -static void SmokeTick(Vehicle *v) -{ - bool moved = false; - - BeginVehicleMove(v); - - v->progress++; - - if ((v->progress & 3) == 0) { - v->z_pos++; - moved = true; - } - - if ((v->progress & 0xF) == 4) { - if (v->cur_image != SPR_SMOKE_4) { - v->cur_image++; - } else { - EndVehicleMove(v); - delete v; - return; - } - moved = true; - } - - if (moved) { - VehiclePositionChanged(v); - EndVehicleMove(v); - } -} - -static void ExplosionLargeInit(Vehicle *v) -{ - v->cur_image = SPR_EXPLOSION_LARGE_0; - v->progress = 0; -} - -static void ExplosionLargeTick(Vehicle *v) -{ - v->progress++; - if ((v->progress & 3) == 0) { - BeginVehicleMove(v); - if (v->cur_image != SPR_EXPLOSION_LARGE_F) { - v->cur_image++; - VehiclePositionChanged(v); - EndVehicleMove(v); - } else { - EndVehicleMove(v); - delete v; - } - } -} - -static void BreakdownSmokeInit(Vehicle *v) -{ - v->cur_image = SPR_BREAKDOWN_SMOKE_0; - v->progress = 0; -} - -static void BreakdownSmokeTick(Vehicle *v) -{ - v->progress++; - if ((v->progress & 7) == 0) { - BeginVehicleMove(v); - if (v->cur_image != SPR_BREAKDOWN_SMOKE_3) { - v->cur_image++; - } else { - v->cur_image = SPR_BREAKDOWN_SMOKE_0; - } - VehiclePositionChanged(v); - EndVehicleMove(v); - } - - v->u.special.animation_state--; - if (v->u.special.animation_state == 0) { - BeginVehicleMove(v); - EndVehicleMove(v); - delete v; - } -} - -static void ExplosionSmallInit(Vehicle *v) -{ - v->cur_image = SPR_EXPLOSION_SMALL_0; - v->progress = 0; -} - -static void ExplosionSmallTick(Vehicle *v) -{ - v->progress++; - if ((v->progress & 3) == 0) { - BeginVehicleMove(v); - if (v->cur_image != SPR_EXPLOSION_SMALL_B) { - v->cur_image++; - VehiclePositionChanged(v); - EndVehicleMove(v); - } else { - EndVehicleMove(v); - delete v; - } - } -} - -static void BulldozerInit(Vehicle *v) -{ - v->cur_image = SPR_BULLDOZER_NE; - v->progress = 0; - v->u.special.animation_state = 0; - v->u.special.animation_substate = 0; -} - -struct BulldozerMovement { - byte direction:2; - byte image:2; - byte duration:3; -}; - -static const BulldozerMovement _bulldozer_movement[] = { - { 0, 0, 4 }, - { 3, 3, 4 }, - { 2, 2, 7 }, - { 0, 2, 7 }, - { 1, 1, 3 }, - { 2, 2, 7 }, - { 0, 2, 7 }, - { 1, 1, 3 }, - { 2, 2, 7 }, - { 0, 2, 7 }, - { 3, 3, 6 }, - { 2, 2, 6 }, - { 1, 1, 7 }, - { 3, 1, 7 }, - { 0, 0, 3 }, - { 1, 1, 7 }, - { 3, 1, 7 }, - { 0, 0, 3 }, - { 1, 1, 7 }, - { 3, 1, 7 } -}; - -static const struct { - int8 x; - int8 y; -} _inc_by_dir[] = { - { -1, 0 }, - { 0, 1 }, - { 1, 0 }, - { 0, -1 } -}; - -static void BulldozerTick(Vehicle *v) -{ - v->progress++; - if ((v->progress & 7) == 0) { - const BulldozerMovement* b = &_bulldozer_movement[v->u.special.animation_state]; - - BeginVehicleMove(v); - - v->cur_image = SPR_BULLDOZER_NE + b->image; - - v->x_pos += _inc_by_dir[b->direction].x; - v->y_pos += _inc_by_dir[b->direction].y; - - v->u.special.animation_substate++; - if (v->u.special.animation_substate >= b->duration) { - v->u.special.animation_substate = 0; - v->u.special.animation_state++; - if (v->u.special.animation_state == lengthof(_bulldozer_movement)) { - EndVehicleMove(v); - delete v; - return; - } - } - VehiclePositionChanged(v); - EndVehicleMove(v); - } -} - -static void BubbleInit(Vehicle *v) -{ - v->cur_image = SPR_BUBBLE_GENERATE_0; - v->spritenum = 0; - v->progress = 0; -} - -struct BubbleMovement { - int8 x:4; - int8 y:4; - int8 z:4; - byte image:4; -}; - -#define MK(x, y, z, i) { x, y, z, i } -#define ME(i) { i, 4, 0, 0 } - -static const BubbleMovement _bubble_float_sw[] = { - MK(0, 0, 1, 0), - MK(1, 0, 1, 1), - MK(0, 0, 1, 0), - MK(1, 0, 1, 2), - ME(1) -}; - - -static const BubbleMovement _bubble_float_ne[] = { - MK( 0, 0, 1, 0), - MK(-1, 0, 1, 1), - MK( 0, 0, 1, 0), - MK(-1, 0, 1, 2), - ME(1) -}; - -static const BubbleMovement _bubble_float_se[] = { - MK(0, 0, 1, 0), - MK(0, 1, 1, 1), - MK(0, 0, 1, 0), - MK(0, 1, 1, 2), - ME(1) -}; - -static const BubbleMovement _bubble_float_nw[] = { - MK(0, 0, 1, 0), - MK(0, -1, 1, 1), - MK(0, 0, 1, 0), - MK(0, -1, 1, 2), - ME(1) -}; - -static const BubbleMovement _bubble_burst[] = { - MK(0, 0, 1, 2), - MK(0, 0, 1, 7), - MK(0, 0, 1, 8), - MK(0, 0, 1, 9), - ME(0) -}; - -static const BubbleMovement _bubble_absorb[] = { - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(0, 0, 1, 0), - MK(0, 0, 1, 2), - MK(0, 0, 1, 0), - MK(0, 0, 1, 1), - MK(2, 1, 3, 0), - MK(1, 1, 3, 1), - MK(2, 1, 3, 0), - MK(1, 1, 3, 2), - MK(2, 1, 3, 0), - MK(1, 1, 3, 1), - MK(2, 1, 3, 0), - MK(1, 0, 1, 2), - MK(0, 0, 1, 0), - MK(1, 0, 1, 1), - MK(0, 0, 1, 0), - MK(1, 0, 1, 2), - MK(0, 0, 1, 0), - MK(1, 0, 1, 1), - MK(0, 0, 1, 0), - MK(1, 0, 1, 2), - ME(2), - MK(0, 0, 0, 0xA), - MK(0, 0, 0, 0xB), - MK(0, 0, 0, 0xC), - MK(0, 0, 0, 0xD), - MK(0, 0, 0, 0xE), - ME(0) -}; -#undef ME -#undef MK - -static const BubbleMovement * const _bubble_movement[] = { - _bubble_float_sw, - _bubble_float_ne, - _bubble_float_se, - _bubble_float_nw, - _bubble_burst, - _bubble_absorb, -}; - -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; - - v->progress++; - if ((v->progress & 3) != 0) return; - - BeginVehicleMove(v); - - if (v->spritenum == 0) { - v->cur_image++; - if (v->cur_image < SPR_BUBBLE_GENERATE_3) { - VehiclePositionChanged(v); - EndVehicleMove(v); - return; - } - if (v->u.special.animation_substate != 0) { - v->spritenum = GB(InteractiveRandom(), 0, 2) + 1; - } else { - v->spritenum = 6; - } - et = 0; - } else { - et = v->engine_type + 1; - } - - const BubbleMovement *b = &_bubble_movement[v->spritenum - 1][et]; - - if (b->y == 4 && b->x == 0) { - EndVehicleMove(v); - delete v; - return; - } - - if (b->y == 4 && b->x == 1) { - if (v->z_pos > 180 || Chance16I(1, 96, InteractiveRandom())) { - v->spritenum = 5; - SndPlayVehicleFx(SND_2F_POP, v); - } - et = 0; - } - - if (b->y == 4 && b->x == 2) { - TileIndex tile; - - et++; - SndPlayVehicleFx(SND_31_EXTRACT, v); - - tile = TileVirtXY(v->x_pos, v->y_pos); - if (IsTileType(tile, MP_INDUSTRY) && GetIndustryGfx(tile) == GFX_BUBBLE_CATCHER) AddAnimatedTile(tile); - } - - v->engine_type = et; - b = &_bubble_movement[v->spritenum - 1][et]; - - v->x_pos += b->x; - v->y_pos += b->y; - v->z_pos += b->z; - v->cur_image = SPR_BUBBLE_0 + b->image; - - VehiclePositionChanged(v); - EndVehicleMove(v); -} - - -typedef void EffectInitProc(Vehicle *v); -typedef void EffectTickProc(Vehicle *v); - -static EffectInitProc * const _effect_init_procs[] = { - ChimneySmokeInit, - SteamSmokeInit, - DieselSmokeInit, - ElectricSparkInit, - SmokeInit, - ExplosionLargeInit, - BreakdownSmokeInit, - ExplosionSmallInit, - BulldozerInit, - BubbleInit, -}; - -static EffectTickProc * const _effect_tick_procs[] = { - ChimneySmokeTick, - SteamSmokeTick, - DieselSmokeTick, - ElectricSparkTick, - SmokeTick, - ExplosionLargeTick, - BreakdownSmokeTick, - ExplosionSmallTick, - BulldozerTick, - BubbleTick, -}; - - -Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type) -{ - Vehicle *v = new SpecialVehicle(); - if (v != NULL) { - v->subtype = type; - v->x_pos = x; - v->y_pos = y; - v->z_pos = z; - v->tile = 0; - v->UpdateDeltaXY(INVALID_DIR); - v->vehstatus = VS_UNCLICKABLE; - - _effect_init_procs[type](v); - - VehiclePositionChanged(v); - BeginVehicleMove(v); - EndVehicleMove(v); - } - return v; -} - -Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type) -{ - int safe_x = Clamp(x, 0, MapMaxX() * TILE_SIZE); - int safe_y = Clamp(y, 0, MapMaxY() * TILE_SIZE); - return CreateEffectVehicle(x, y, GetSlopeZ(safe_x, safe_y) + z, type); -} - -Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type) -{ - return CreateEffectVehicle(v->x_pos + x, v->y_pos + y, v->z_pos + z, type); -} - -void SpecialVehicle::Tick() -{ - _effect_tick_procs[this->subtype](this); -} - Vehicle *CheckClickOnVehicle(const ViewPort *vp, int x, int y) { Vehicle *found = NULL, *v; @@ -1695,16 +1120,11 @@ for (uint i = 0; i < engine_count; i++) { Vehicle *v = vl[i]; - bool stopped = !(v->vehstatus & VS_STOPPED); /* Ensure that the vehicle completely in the depot */ if (!v->IsInDepot()) continue; - if (stopped) { - v->vehstatus |= VS_STOPPED; // Stop the vehicle - v->leave_depot_instantly = true; - } - CommandCost ret = MaybeReplaceVehicle(v, !(flags & DC_EXEC), false); + CommandCost ret = MaybeReplaceVehicle(v, flags, false); if (CmdSucceeded(ret)) { cost.AddCost(ret); @@ -2480,7 +1900,7 @@ /* Vehicle is turning around, get the direction from vehicle's direction */ return DiagdirToDiagTrackdir(DirToDiagDir(v->direction)); - /* case VEH_AIRCRAFT: case VEH_SPECIAL: case VEH_DISASTER: */ + /* case VEH_AIRCRAFT: case VEH_EFFECT: case VEH_DISASTER: */ default: return INVALID_TRACKDIR; } } @@ -2939,7 +2359,7 @@ }; static const SaveLoad _special_desc[] = { - SLE_WRITEBYTE(Vehicle, type, VEH_SPECIAL), + SLE_WRITEBYTE(Vehicle, type, VEH_EFFECT), SLE_VAR(Vehicle, subtype, SLE_UINT8), @@ -2957,8 +2377,8 @@ SLE_VAR(Vehicle, progress, SLE_UINT8), SLE_VAR(Vehicle, vehstatus, SLE_UINT8), - 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), + SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleEffect, animation_state), SLE_UINT16), + SLE_VARX(cpp_offsetof(Vehicle, u) + cpp_offsetof(VehicleEffect, animation_substate), SLE_UINT8), /* reserve extra space in savegame here. (currently 16 bytes) */ SLE_CONDNULL(16, 2, SL_MAX_VERSION), @@ -3046,7 +2466,7 @@ case VEH_ROAD: v = new (index) RoadVehicle(); break; case VEH_SHIP: v = new (index) Ship(); break; case VEH_AIRCRAFT: v = new (index) Aircraft(); break; - case VEH_SPECIAL: v = new (index) SpecialVehicle(); break; + case VEH_EFFECT: v = new (index) EffectVehicle(); break; case VEH_DISASTER: v = new (index) DisasterVehicle(); break; case VEH_INVALID: v = new (index) InvalidVehicle(); break; default: NOT_REACHED(); @@ -3266,15 +2686,6 @@ } } -void SpecialVehicle::UpdateDeltaXY(Direction direction) -{ - this->x_offs = 0; - this->y_offs = 0; - this->x_extent = 1; - this->y_extent = 1; - this->z_extent = 1; -} - void StopAllVehicles() { Vehicle *v; diff -r e9066a148720 -r b3c58f3df92b src/vehicle_base.h --- a/src/vehicle_base.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/vehicle_base.h Sun Apr 20 15:27:28 2008 +0000 @@ -171,7 +171,7 @@ RoadTypes compatible_roadtypes; }; -struct VehicleSpecial { +struct VehicleEffect { uint16 animation_state; byte animation_substate; }; @@ -315,7 +315,7 @@ VehicleRail rail; VehicleAir air; VehicleRoad road; - VehicleSpecial special; + VehicleEffect effect; VehicleDisaster disaster; VehicleShip ship; } u; @@ -541,33 +541,6 @@ * v = new (v) Train(); * * As side-effect the vehicle type is set correctly. - * - * A special vehicle is one of the following: - * - smoke - * - electric sparks for trains - * - explosions - * - bulldozer (road works) - * - bubbles (industry) - */ -struct SpecialVehicle : public Vehicle { - /** Initializes the Vehicle to a special vehicle */ - SpecialVehicle() { this->type = VEH_SPECIAL; } - - /** We want to 'destruct' the right class. */ - virtual ~SpecialVehicle() {} - - const char *GetTypeString() const { return "special vehicle"; } - void UpdateDeltaXY(Direction direction); - void Tick(); -}; - -/** - * This class 'wraps' Vehicle; you do not actually instantiate this class. - * You create a Vehicle using AllocateVehicle, so it is added to the pool - * and you reinitialize that to a Train using: - * v = new (v) Train(); - * - * As side-effect the vehicle type is set correctly. */ struct DisasterVehicle : public Vehicle { /** Initializes the Vehicle to a disaster vehicle */ diff -r e9066a148720 -r b3c58f3df92b src/vehicle_func.h --- a/src/vehicle_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/vehicle_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -1,6 +1,6 @@ /* $Id$ */ -/** @vehicle.h Functions related to vehicles. */ +/** @file vehicle.h Functions related to vehicles. */ #ifndef VEHICLE_FUNC_H #define VEHICLE_FUNC_H @@ -71,7 +71,7 @@ CommandCost SendAllVehiclesToDepot(VehicleType type, uint32 flags, bool service, PlayerID owner, uint16 vlw_flag, uint32 id); void VehicleEnterDepot(Vehicle *v); -CommandCost MaybeReplaceVehicle(Vehicle *v, bool check, bool display_costs); +CommandCost MaybeReplaceVehicle(Vehicle *v, uint32 flags, bool display_costs); bool CanBuildVehicleInfrastructure(VehicleType type); void CcCloneVehicle(bool success, TileIndex tile, uint32 p1, uint32 p2); @@ -171,13 +171,9 @@ bool EnsureNoVehicleOnGround(TileIndex tile); void StopAllVehicles(); -Vehicle *CreateEffectVehicle(int x, int y, int z, EffectVehicle type); -Vehicle *CreateEffectVehicleAbove(int x, int y, int z, EffectVehicle type); -Vehicle *CreateEffectVehicleRel(const Vehicle *v, int x, int y, int z, EffectVehicle type); - extern VehicleID _vehicle_id_ctr_day; extern Vehicle *_place_clicked_vehicle; extern VehicleID _new_vehicle_id; extern uint16 _returned_refit_capacity; -#endif /* VEHICLE_H */ +#endif /* VEHICLE_FUNC_H */ diff -r e9066a148720 -r b3c58f3df92b src/vehicle_gui.cpp --- a/src/vehicle_gui.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/vehicle_gui.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -35,7 +35,6 @@ #include "settings_type.h" #include "widgets/dropdown_func.h" #include "order_func.h" -#include "depot_base.h" #include "table/sprites.h" #include "table/strings.h" @@ -103,7 +102,11 @@ INVALID_STRING_ID }; -void RebuildVehicleLists() +/** + * Set sort list flag for all vehicle list windows + * @param sl_flag Sort list flag to set + */ +static void SetVehicleListsFlag(SortListFlags sl_flag) { Window* const *wz; @@ -115,7 +118,7 @@ case WC_ROADVEH_LIST: case WC_SHIPS_LIST: case WC_AIRCRAFT_LIST: - WP(w, vehiclelist_d).l.flags |= VL_REBUILD; + WP(w, vehiclelist_d).l.flags |= sl_flag; SetWindowDirty(w); break; @@ -124,25 +127,20 @@ } } +/** + * Rebuild all vehicle list windows + */ +void RebuildVehicleLists() +{ + SetVehicleListsFlag(VL_REBUILD); +} + +/** + * Resort all vehicle list windows + */ void ResortVehicleLists() { - Window* const *wz; - - FOR_ALL_WINDOWS(wz) { - Window *w = *wz; - - switch (w->window_class) { - case WC_TRAINS_LIST: - case WC_ROADVEH_LIST: - case WC_SHIPS_LIST: - case WC_AIRCRAFT_LIST: - WP(w, vehiclelist_d).l.flags |= VL_RESORT; - SetWindowDirty(w); - break; - - default: break; - } - } + SetVehicleListsFlag(VL_RESORT); } void BuildVehicleList(vehiclelist_d *vl, PlayerID owner, uint16 index, uint16 window_type) @@ -1753,7 +1751,7 @@ if (w != NULL) { w->caption_color = v->owner; - AssignWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH, + InitializeWindowViewport(w, VV_VIEWPORT_X, VV_VIEWPORT_Y, VV_INITIAL_VIEWPORT_WIDTH, (v->type == VEH_TRAIN) ? VV_INITIAL_VIEWPORT_HEIGHT_TRAIN : VV_INITIAL_VIEWPORT_HEIGHT, w->window_number | (1 << 31), _vehicle_view_zoom_levels[v->type]); } diff -r e9066a148720 -r b3c58f3df92b src/vehicle_type.h --- a/src/vehicle_type.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/vehicle_type.h Sun Apr 20 15:27:28 2008 +0000 @@ -14,7 +14,7 @@ VEH_ROAD, VEH_SHIP, VEH_AIRCRAFT, - VEH_SPECIAL, + VEH_EFFECT, VEH_DISASTER, VEH_END, VEH_INVALID = 0xFF, @@ -38,20 +38,6 @@ static const VehicleID INVALID_VEHICLE = 0xFFFF; -/* Effect vehicle types */ -enum EffectVehicle { - EV_CHIMNEY_SMOKE = 0, - EV_STEAM_SMOKE = 1, - EV_DIESEL_SMOKE = 2, - EV_ELECTRIC_SPARK = 3, - EV_SMOKE = 4, - EV_EXPLOSION_LARGE = 5, - EV_BREAKDOWN_SMOKE = 6, - EV_EXPLOSION_SMALL = 7, - EV_BULLDOZER = 8, - EV_BUBBLE = 9 -}; - /** Pathfinding option states */ enum { VPF_OPF = 0, ///< The Original PathFinder diff -r e9066a148720 -r b3c58f3df92b src/video/cocoa/wnd_quartz.mm --- a/src/video/cocoa/wnd_quartz.mm Fri Apr 18 21:20:03 2008 +0000 +++ b/src/video/cocoa/wnd_quartz.mm Sun Apr 20 15:27:28 2008 +0000 @@ -175,7 +175,8 @@ CMCloseProfile(sysProfile); } - assert(colorSpace != NULL); + if (colorSpace == NULL) + error("Could not get system colour space. You might need to recalibrate your monitor."); } return colorSpace; diff -r e9066a148720 -r b3c58f3df92b src/video/dedicated_v.cpp --- a/src/video/dedicated_v.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/video/dedicated_v.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -140,6 +140,7 @@ _screen.width = _screen.pitch = _cur_resolution[0]; _screen.height = _cur_resolution[1]; + ScreenSizeChanged(); SetDebugString("net=6"); diff -r e9066a148720 -r b3c58f3df92b src/video/null_v.cpp --- a/src/video/null_v.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/video/null_v.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -15,6 +15,8 @@ this->ticks = GetDriverParamInt(parm, "ticks", 1000); _screen.width = _screen.pitch = _cur_resolution[0]; _screen.height = _cur_resolution[1]; + ScreenSizeChanged(); + /* Do not render, nor blit */ DEBUG(misc, 1, "Forcing blitter 'null'..."); BlitterFactoryBase::SelectBlitter("null"); diff -r e9066a148720 -r b3c58f3df92b src/video/sdl_v.cpp --- a/src/video/sdl_v.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/video/sdl_v.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -127,8 +127,7 @@ for (i = 0; modes[i]; i++) { int w = modes[i]->w; int h = modes[i]->h; - if (IsInsideMM(w, 640, MAX_SCREEN_WIDTH + 1) && - IsInsideMM(h, 480, MAX_SCREEN_HEIGHT + 1)) { + if (w >= 640 && h >= 480) { int j; for (j = 0; j < n; j++) { if (_resolutions[j][0] == w && _resolutions[j][1] == h) break; @@ -419,8 +418,8 @@ break; case SDL_VIDEORESIZE: { - int w = Clamp(ev.resize.w, 64, MAX_SCREEN_WIDTH); - int h = Clamp(ev.resize.h, 64, MAX_SCREEN_HEIGHT); + int w = max(ev.resize.w, 64); + int h = max(ev.resize.h, 64); ChangeResInGame(w, h); break; } diff -r e9066a148720 -r b3c58f3df92b src/video/win32_v.cpp --- a/src/video/win32_v.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/video/win32_v.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -545,8 +545,8 @@ w = r->right - r->left - (r2.right - r2.left); h = r->bottom - r->top - (r2.bottom - r2.top); - w = Clamp(w, 64, MAX_SCREEN_WIDTH); - h = Clamp(h, 64, MAX_SCREEN_HEIGHT); + w = max(w, 64); + h = max(h, 64); SetRect(&r2, 0, 0, w, h); AdjustWindowRect(&r2, GetWindowLong(hwnd, GWL_STYLE), FALSE); @@ -677,8 +677,8 @@ HDC dc; int bpp = BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth(); - w = Clamp(w, 64, MAX_SCREEN_WIDTH); - h = Clamp(h, 64, MAX_SCREEN_HEIGHT); + w = max(w, 64); + h = max(h, 64); if (bpp == 0) error("Can't use a blitter that blits 0 bpp for normal visuals"); @@ -737,8 +737,8 @@ * Doesn't really matter since we don't pass a string anyways, but still * a letdown */ for (i = 0; EnumDisplaySettingsA(NULL, i, &dm) != 0; i++) { - if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && IsInsideMM(dm.dmPelsWidth, 640, MAX_SCREEN_WIDTH + 1) && - IsInsideMM(dm.dmPelsHeight, 480, MAX_SCREEN_HEIGHT + 1)) { + if (dm.dmBitsPerPel == BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() && + dm.dmPelsWidth >= 640 && dm.dmPelsHeight >= 480) { uint j; for (j = 0; j < n; j++) { @@ -787,10 +787,10 @@ _wnd.height_org = _cur_resolution[1]; AllocateDibSection(_cur_resolution[0], _cur_resolution[1]); + MakeWindow(_fullscreen); + MarkWholeScreenDirty(); - MakeWindow(_fullscreen); - return NULL; } diff -r e9066a148720 -r b3c58f3df92b src/viewport.cpp --- a/src/viewport.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/viewport.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -159,7 +159,19 @@ w->viewport = NULL; } -void AssignWindowViewport(Window *w, int x, int y, +/** + * Initialize viewport of the window for use. + * @param w Window to use/display the viewport in + * @param x Offset of left edge of viewport with respect to left edge window \a w + * @param y Offset of top edge of viewport with respect to top edge window \a w + * @param width Width of the viewport + * @param height Height of the viewport + * @param follow_flags Flags controlling the viewport. + * - If bit 31 is set, the lower 16 bits are the vehicle that the viewport should follow. + * - If bit 31 is clear, it is a tile position. + * @param zoom Zoomlevel to display + */ +void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom) { assert(w->viewport == NULL); @@ -325,7 +337,14 @@ } } - +/** + * Is a xy position inside the viewport of the window? + * @param w Window to examine its viewport + * @param x X coordinate of the xy position + * @param y Y coordinate of the xy position + * @return Pointer to the viewport if the xy position is in the viewport of the window, + * otherwise \c NULL is returned. + */ ViewPort *IsPtInWindowViewport(const Window *w, int x, int y) { ViewPort *vp = w->viewport; @@ -1617,11 +1636,12 @@ } /** - * Marks a viewport as dirty for repaint. - * - * @param vp The viewport to mark as dirty - * @todo documents the missing parameters @c left, @c top, @c right and @c bottom - * @todo detailed description missing + * Marks a viewport as dirty for repaint if it displays (a part of) the area the needs to be repainted. + * @param vp The viewport to mark as dirty + * @param left Left edge of area to repaint + * @param top Top edge of area to repaint + * @param right Right edge of area to repaint + * @param bottom Bottom edge of area to repaint * @ingroup dirty */ static void MarkViewportDirty(const ViewPort *vp, int left, int top, int right, int bottom) @@ -1648,6 +1668,14 @@ ); } +/** + * Mark all viewports that display an area as dirty (in need of repaint). + * @param left Left edge of area to repaint + * @param top Top edge of area to repaint + * @param right Right edge of area to repaint + * @param bottom Bottom edge of area to repaint + * @ingroup dirty + */ void MarkAllViewportsDirty(int left, int top, int right, int bottom) { Window **wz; diff -r e9066a148720 -r b3c58f3df92b src/viewport_func.h --- a/src/viewport_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/viewport_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -13,7 +13,7 @@ void SetSelectionRed(bool); void DeleteWindowViewport(Window *w); -void AssignWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom); +void InitializeWindowViewport(Window *w, int x, int y, int width, int height, uint32 follow_flags, ZoomLevel zoom); ViewPort *IsPtInWindowViewport(const Window *w, int x, int y); Point GetTileBelowCursor(); void UpdateViewportPosition(Window *w); diff -r e9066a148720 -r b3c58f3df92b src/water_cmd.cpp --- a/src/water_cmd.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/water_cmd.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -39,6 +39,7 @@ #include "station_base.h" #include "airport.h" #include "newgrf_cargo.h" +#include "effectvehicle_func.h" #include "table/sprites.h" #include "table/strings.h" diff -r e9066a148720 -r b3c58f3df92b src/window.cpp --- a/src/window.cpp Fri Apr 18 21:20:03 2008 +0000 +++ b/src/window.cpp Sun Apr 20 15:27:28 2008 +0000 @@ -303,6 +303,7 @@ } } + /* Setup blitter, and dispatch a repaint event to window *wz */ DrawPixelInfo *dp = _cur_dpi; dp->width = right - left; dp->height = bottom - top; @@ -334,6 +335,7 @@ bottom > w->top && left < w->left + w->width && top < w->top + w->height) { + /* Window w intersects with the rectangle => needs repaint */ DrawOverlappedWindow(wz, left, top, right, bottom); } } @@ -398,7 +400,8 @@ } /** - * Remove window and all its child windows from the window stack + * Remove window and all its child windows from the window stack. + * @param w Window to delete */ void DeleteWindow(Window *w) { @@ -622,11 +625,11 @@ { Window* const *wz; - for (wz = _z_windows;; wz++) { + FOR_ALL_WINDOWS(wz) { Window *w = *wz; - assert(wz < _last_z_window); if (w->window_class != WC_MAIN_WINDOW && !IsVitalWindow(w)) return w; } + NOT_REACHED(); } bool IsWindowOfPrototype(const Window *w, const Widget *widget) @@ -1018,9 +1021,7 @@ * @return a pointer to the found window if any, NULL otherwise */ Window *FindWindowFromPt(int x, int y) { - Window* const *wz; - - for (wz = _last_z_window; wz != _z_windows;) { + for (Window * const *wz = _last_z_window; wz != _z_windows;) { Window *w = *--wz; if (IsInsideBS(x, w->left, w->width) && IsInsideBS(y, w->top, w->height)) { return w; @@ -1038,6 +1039,7 @@ IConsoleClose(); _last_z_window = _z_windows; + _mouseover_last_w = NULL; _no_scroll = 0; } @@ -1604,8 +1606,7 @@ static bool MaybeBringWindowToFront(const Window *w) { bool bring_to_front = false; - Window* const *wz; - Window* const *uz; + Window * const *wz; if (w->window_class == WC_MAIN_WINDOW || IsVitalWindow(w) || @@ -1615,7 +1616,7 @@ } wz = FindWindowZPosition(w); - for (uz = wz; ++uz != _last_z_window;) { + for (Window * const *uz = wz; ++uz != _last_z_window;) { Window *u = *uz; /* A modal child will prevent the activation of the parent window */ @@ -1789,9 +1790,6 @@ } } -extern void UpdateTileSelection(); -extern bool VpHandlePlaceSizingDrag(); - /** * Local counter that is incremented each time an mouse input event is detected. * The counter is used to stop auto-scrolling. @@ -1852,6 +1850,9 @@ TIME_BETWEEN_DOUBLE_CLICK = 500, ///< Time between 2 left clicks before it becoming a double click, in ms }; +extern void UpdateTileSelection(); +extern bool VpHandlePlaceSizingDrag(); + void MouseLoop(MouseClick click, int mousewheel) { int x,y; @@ -2064,8 +2065,9 @@ } /** - * Mark window data as invalid (in need of re-computing) - * @param w Window with invalid data + * Mark window as dirty (in need of repainting) + * @param cls Window class + * @param number Window number in that class */ void InvalidateWindow(WindowClass cls, WindowNumber number) { @@ -2077,7 +2079,7 @@ } } -/* +/** * Mark a particular widget in a particular window as dirty (in need of repainting) * @param cls Window class * @param number Window number in that class @@ -2095,7 +2097,7 @@ } } -/* +/** * Mark all windows of a particular class as dirty (in need of repainting) * @param cls Window class */ @@ -2119,7 +2121,7 @@ } /** - * Mark window data the window of a given class and specific window number as invalid (in need of re-computing) + * Mark window data of the window of a given class and specific window number as invalid (in need of re-computing) * @param cls Window class * @param number Window number within the class */ @@ -2151,13 +2153,17 @@ */ void CallWindowTickEvent() { - Window* const *wz; - - for (wz = _last_z_window; wz != _z_windows;) { + for (Window * const *wz = _last_z_window; wz != _z_windows;) { CallWindowEventNP(*--wz, WE_TICK); } } +/** + * Try to delete a non-vital window. + * Non-vital windows are windows other than the game selection, main toolbar, + * status bar, toolbar menu, and tooltip windows. Stickied windows are also + * considered vital. + */ void DeleteNonVitalWindows() { Window* const *wz; diff -r e9066a148720 -r b3c58f3df92b src/window_func.h --- a/src/window_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/window_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -32,7 +32,6 @@ void DeleteAllNonVitalWindows(); void HideVitalWindows(); void ShowVitalWindows(); -Window **FindWindowZPosition(const Window *w); void InvalidateWindow(WindowClass cls, WindowNumber number); void InvalidateWindowWidget(WindowClass cls, WindowNumber number, byte widget_index); diff -r e9066a148720 -r b3c58f3df92b src/window_gui.h --- a/src/window_gui.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/window_gui.h Sun Apr 20 15:27:28 2008 +0000 @@ -549,15 +549,9 @@ bool IsWindowOfPrototype(const Window *w, const Widget *widget); void AssignWidgetToWindow(Window *w, const Widget *widget); -Window *AllocateWindow( - int x, - int y, - int width, - int height, - WindowProc *proc, - WindowClass cls, - const Widget *widget, - void *data = NULL); +Window *AllocateWindow(int x, int y, int width, int height, + WindowProc *proc, WindowClass cls, const Widget *widget, + void *data = NULL); Window *AllocateWindowDesc(const WindowDesc *desc, void *data = NULL); Window *AllocateWindowDescFront(const WindowDesc *desc, int window_number, void *data = NULL); @@ -594,12 +588,6 @@ void DrawSortButtonState(const Window *w, int widget, SortButtonState state); -Window *GetCallbackWnd(); -void DeleteNonVitalWindows(); -void DeleteAllNonVitalWindows(); -void HideVitalWindows(); -void ShowVitalWindows(); -Window **FindWindowZPosition(const Window *w); /* window.cpp */ extern Window *_z_windows[]; @@ -624,6 +612,13 @@ WSM_PRESIZE = 3, }; +Window *GetCallbackWnd(); +void DeleteNonVitalWindows(); +void DeleteAllNonVitalWindows(); +void HideVitalWindows(); +void ShowVitalWindows(); +Window **FindWindowZPosition(const Window *w); + void ScrollbarClickHandler(Window *w, const Widget *wi, int x, int y); void ResizeButtons(Window *w, byte left, byte right); diff -r e9066a148720 -r b3c58f3df92b src/zoom_func.h --- a/src/zoom_func.h Fri Apr 18 21:20:03 2008 +0000 +++ b/src/zoom_func.h Sun Apr 20 15:27:28 2008 +0000 @@ -1,6 +1,6 @@ /* $Id$ */ -/** @file zoom_func.hpp */ +/** @file zoom_func.h */ #ifndef ZOOM_FUNC_H #define ZOOM_FUNC_H