diff --git a/changelog.txt b/changelog.txt index cf1bf9e0d7..75a03dfdd9 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,50 @@ +1.0.1-RC1 (2010-04-17) +------------------------------------------------------------------------ +- Feature: [NewGRF] Support for extended text code 0x9A 11, print qword (r19570) +- Feature: Give more detailed error message when trying to build a too long bridge (r19561) +- Feature: Add rail speed limit to land area information window (r19556, r19434) +- Add: [NoAI] AIRail::GetMaxSpeed(RailType) to get the speed limit of railtypes (r19591) +- Change: Sync Debian packaging updates from Debian, but keep building a single package (r19572) +- Fix: Crash of a dedicated server if the null blitter is overridden and (after a while) there is no company 0 on new year anymore [FS#3749] (r19664) +- Fix: In rare cases, update of signals could be missed (r19663) +- Fix: Various improvements of command handling, missing error messages (r19658, r19657, r19656, r19655, r19654, r19637, r19633, r19621, r19616, r19605, r19604) +- Fix: Industry generation failed for large maps and lots of industry types (r19652, r19643) +- Fix: When a company is sold, move connected clients to spectators [FS#3745] (r19651) +- Fix: A client would not be properly moved when moved while joining, e.g. when entering a company's password. This caused the client to be in the wrong company (according to the rest of the clients) and the client being kicked on the first command [FS#3760] (r19648) +- Fix: Trains loaded above the original IDs did not have a default railtypelabel assigned to them, causing them to be unavailable. Could cause desyncs if the multiplayer game was not started from a savegame [FS#3768] (r19647) +- Fix: Do not allow building cacti outside of the desert or rain forest trees outside of the rain forest area. This to prevent people from thinking planting rain forest trees makes the rain forest bigger and thus adds more place to build a lumber mill [FS#3728] (r19644, r19635, r19634) +- Fix: Desync when taking over companies (r19636) +- Fix: Chat message caused glitch when rejoining a network game [FS#3757] (r19629) +- Fix: Desync when a command is received and in the queue while a client starts joining, i.e. save the game state. This can happen in two ways: with frame_freq > 1 a command received in a previous frame might not be executed yet or when a command is received in the same frame as the join but before the savegame is made. In both cases the joining client would not get all commands to get in-sync with the server (and the other clients) (r19620) +- Fix: Company related graphs were not updated correctly after changing the company colour [FS#3763] (r19615) +- Fix: Possible invalid read when server moves client to spectators before he finishes joining [FS#3755] (r19613) +- Fix: Crash when opening a savegame with a waypoint from around 0.4.0 [FS#3756] (r19612) +- Fix: Improve joining behaviour; kicking clients when entering passwords that was just cleared, 'connection lost' for people failing the password (r19610, r19609, r19608, r19607, r19606) +- Fix: Desync debugging; false positives in the cache validity checks and saving/loading the command stream (r19619, r19617, r19602, r19601, r19600, r19596, r19593, r19592, r19589, r19587, r19586) +- Fix: Presence of online content was not properly updated after download due to duplicate slashes in the path (r19600) +- Fix: [NewGRF] Setting industry prop 0x24 to 0 caused empty station names (r19590) +- Fix: Crash when pressing 'h' (non-stop) in the order window of a ship or aircraft [FS#3744] (r19584) +- Fix: Graphs were not properly updated when going toggling keys (i.e. companies) (r19574) +- Fix: The timetable button was not automatically raised [FS#3739] (r19571) +- Fix: [NewGRF] Possible buffer underflow in NewGRF string code (r19569) +- Fix: [NewGRF] Do not return a random colour for unowned industries in var 45; TTDPatch does not seem to set the colour data in that case either and it could lead to desyncs (r19566) +- Fix: Window::OnResize() was not always called while resizing a window causing incorrect windows [FS#3730] (r19563, r19558) +- Fix: Bridge build error message should not show the same message twice (r19560, r19559) +- Fix: [NewGRF] During NewGRF loading, store rail type labels in temporary data and process after loading has finished. This avoids deactivated rail vehicles being reactivated if the climate property is set after the rail type property (r19557, r19502) +- Fix: Improperly scaled cargo payment graph when having lots of cargo (r19550, 19543) +- Fix: [NewGRF] Properties set before property 08 (house, industry, industry tiles) should be ignored, not trigger the NewGRF to be disabled [FS#3725] (r19547) +- Fix: Sorting industries by production was broken for NewGRF industries (r19538) +- Fix: Vehicle details window did not resize correctly after refitting a road vehicle to a longer variant [FS#3720] (r19533) +- Fix: Prevent drawing industries disabled at the smallmap as land tiles when they are built on water (r19523) +- Fix: Tunnels, bridges and roadstops are build with only one roadtype (r19506) +- Fix: Remove same_industry_close setting did not do what it said and caused NewGRF trouble (r19499) +- Fix: Keep number padding intact when cloning vehicle names [FS#3710] (r19498) +- Fix: [NewGRF] Bytes and words get sign-extended for temporary/persistent storage (r19497) +- Fix: Stop reducing the size of the vehicle list after selecting a vehicle with a long description (r19480) +- Fix: Implement custom sound effect for helicopter take-off [FS#3668] (r19364) +- Update: Plural type of Slovak (r19452) + + 1.0.0 (2010-04-01) ------------------------------------------------------------------------ - Fix: Network clients would crash while connecting to a server with AIs (r19526) diff --git a/config.lib b/config.lib index bd72f6aca8..54c88f4d55 100644 --- a/config.lib +++ b/config.lib @@ -3154,6 +3154,7 @@ showhelp() { echo " --with-midi=midi define which midi-player to use" echo " --with-midi-arg=arg define which args to use for the" echo " midi-player" + echo " --with-libtimidity enables libtimidity support" echo " --with-allegrol[=allegro-config]" echo " enables Allegro video driver support" echo " --with-cocoa enables COCOA video driver (OSX ONLY)" diff --git a/known-bugs.txt b/known-bugs.txt index 4af6ddda12..0a708adaf1 100644 --- a/known-bugs.txt +++ b/known-bugs.txt @@ -1,6 +1,6 @@ OpenTTD's known bugs -Last updated: 2010-04-01 -Release version: 1.0.0 +Last updated: 2010-04-17 +Release version: 1.0.1-RC1 ------------------------------------------------------------------------ @@ -34,8 +34,6 @@ that you can find at: http://bugs.openttd.org If the bugs are closed but still listed here it means that the bug is fixed and that the nightlies and next major release will not have that bug. -- 3725 [NewGRF] Incorrect handling of some house action0s -- 3720 When refitting to a vehicle with more trailers, the details view is not made bigger - 3714 Some corrupted savegames can cause crashes - 3695 Behaviour inconsistency building railway/road down towards water - 3651 [OSX] Crash when selecting full screen diff --git a/os/debian/changelog b/os/debian/changelog index f33c7fcbfd..5d3e9a5c6c 100644 --- a/os/debian/changelog +++ b/os/debian/changelog @@ -1,3 +1,9 @@ +openttd (1.0.1~rc1-0) unstable; urgency=low + + * New upstream release 1.0.1-RC1 + + -- Matthijs Kooijman Sat, 17 Apr 2010 23:36:21 +0000 + openttd (1.0.0-1) unstable; urgency=low * [30a2162] New upstream release 1.0.0. (Closes: #570104) diff --git a/os/windows/installer/install.nsi b/os/windows/installer/install.nsi index d17e9bf45a..9d5d1b5d98 100644 --- a/os/windows/installer/install.nsi +++ b/os/windows/installer/install.nsi @@ -1,9 +1,9 @@ # Version numbers to update !define APPV_MAJOR 1 !define APPV_MINOR 0 -!define APPV_MAINT 0 -!define APPV_BUILD 7 -!define APPV_EXTRA "" +!define APPV_MAINT 1 +!define APPV_BUILD 0 +!define APPV_EXTRA "-RC1" !define APPNAME "OpenTTD" ; Define application name !define APPVERSION "${APPV_MAJOR}.${APPV_MINOR}.${APPV_MAINT}${APPV_EXTRA}" ; Define application version diff --git a/readme.txt b/readme.txt index fa3bc75b0a..9d480127f8 100644 --- a/readme.txt +++ b/readme.txt @@ -1,6 +1,6 @@ OpenTTD README -Last updated: 2010-04-01 -Release version: 1.0.0 +Last updated: 2010-04-17 +Release version: 1.0.1-RC1 ------------------------------------------------------------------------ diff --git a/src/ai/api/ai_tunnel.cpp b/src/ai/api/ai_tunnel.cpp index 71b700e9b1..5d3f116703 100644 --- a/src/ai/api/ai_tunnel.cpp +++ b/src/ai/api/ai_tunnel.cpp @@ -77,10 +77,10 @@ static void _DoCommandReturnBuildTunnel1(class AIInstance *instance) uint type = 0; if (vehicle_type == AIVehicle::VT_ROAD) { - type |= (TRANSPORT_ROAD << 9); + type |= (TRANSPORT_ROAD << 8); type |= ::RoadTypeToRoadTypes((::RoadType)AIObject::GetRoadType()); } else { - type |= (TRANSPORT_RAIL << 9); + type |= (TRANSPORT_RAIL << 8); type |= AIRail::GetCurrentRailType(); } diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index e26b84c378..e181fe6c4f 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -237,9 +237,10 @@ void GetAircraftSpriteSize(EngineID engine, uint &width, uint &height) */ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (!IsEngineBuildable(p1, VEH_AIRCRAFT, _current_company)) return_cmd_error(STR_ERROR_AIRCRAFT_NOT_AVAILABLE); + EngineID eid = GB(p1, 0, 16); + if (!IsEngineBuildable(eid, VEH_AIRCRAFT, _current_company)) return_cmd_error(STR_ERROR_AIRCRAFT_NOT_AVAILABLE); - const Engine *e = Engine::Get(p1); + const Engine *e = Engine::Get(eid); const AircraftVehicleInfo *avi = &e->u.air; CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); @@ -252,7 +253,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (!IsHangarTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Prevent building aircraft types at places which can't handle them */ - if (!CanVehicleUseStation(p1, Station::GetByTile(tile))) return CMD_ERROR; + if (!CanVehicleUseStation(eid, Station::GetByTile(tile))) return CMD_ERROR; /* We will need to allocate 2 or 3 vehicle structs, depending on type */ if (!Vehicle::CanAllocateItem(avi->subtype & AIR_CTOL ? 2 : 3)) { @@ -299,8 +300,8 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin v->max_speed = avi->max_speed; v->acceleration = avi->acceleration; - v->engine_type = p1; - u->engine_type = p1; + v->engine_type = eid; + u->engine_type = eid; v->subtype = (avi->subtype & AIR_CTOL ? AIR_AIRCRAFT : AIR_HELICOPTER); v->UpdateDeltaXY(INVALID_DIR); @@ -362,7 +363,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin /* Aircraft with 3 vehicles (chopper)? */ if (v->subtype == AIR_HELICOPTER) { Aircraft *w = new Aircraft(); - w->engine_type = p1; + w->engine_type = eid; w->direction = DIR_N; w->owner = _current_company; w->x_pos = v->x_pos; @@ -387,7 +388,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin if (IsLocalCompany()) InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Aircraft window - Company::Get(_current_company)->num_engines[p1]++; + Company::Get(_current_company)->num_engines[eid]++; } return value; diff --git a/src/cmd_helper.h b/src/cmd_helper.h index 8c9c789ca2..0b56fb7670 100644 --- a/src/cmd_helper.h +++ b/src/cmd_helper.h @@ -12,25 +12,16 @@ #ifndef CMD_HELPER_H #define CMD_HELPER_H -#include "direction_type.h" -#include "road_type.h" +#include "core/enum_type.hpp" - -template static inline void ExtractValid(); -template<> inline void ExtractValid<1>() {} - - -template struct ExtractBits; -template<> struct ExtractBits { static const uint Count = 1; }; -template<> struct ExtractBits { static const uint Count = 2; }; -template<> struct ExtractBits { static const uint Count = 4; }; - - -template static inline T Extract(U v) +template static inline T Extract(U v) { /* Check if there are enough bits in v */ - ExtractValid::Count <= sizeof(U) * 8>(); - return (T)GB(v, N, ExtractBits::Count); + assert_tcompile(N == EnumPropsT::num_bits); + assert_tcompile(S + N <= sizeof(U) * 8); + assert_tcompile(EnumPropsT::end <= (1 << N)); + U masked = GB(v, S, N); + return IsInsideMM(masked, EnumPropsT::begin, EnumPropsT::end) ? (T)masked : EnumPropsT::invalid; } #endif diff --git a/src/command.cpp b/src/command.cpp index 241c45faa9..b45f87fbc5 100644 --- a/src/command.cpp +++ b/src/command.cpp @@ -678,6 +678,9 @@ CommandCost DoCommandPInternal(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, /* If we're needing more money and we haven't done * anything yet, ask for the money! */ if (_additional_cash_required != 0 && res2.GetCost() == 0) { + /* It could happen we removed rail, thus gained money, and deleted something else. + * So make sure the signal buffer is empty even in this case */ + UpdateSignalsInBuffer(); SetDParam(0, _additional_cash_required); return_dcpi(CommandCost(STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY), false); } diff --git a/src/company_cmd.cpp b/src/company_cmd.cpp index 7189db70b1..c59a64ca11 100644 --- a/src/company_cmd.cpp +++ b/src/company_cmd.cpp @@ -15,6 +15,7 @@ #include "company_gui.h" #include "town.h" #include "news_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "network/network.h" #include "network/network_func.h" @@ -894,14 +895,11 @@ CommandCost CmdSetCompanyManagerFace(TileIndex tile, DoCommandFlag flags, uint32 */ CommandCost CmdSetCompanyColour(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (p2 >= 16) return CMD_ERROR; // max 16 colours - - Colours colour = (Colours)p2; - - LiveryScheme scheme = (LiveryScheme)GB(p1, 0, 8); + Colours colour = Extract(p2); + LiveryScheme scheme = Extract(p1); byte state = GB(p1, 8, 2); - if (scheme >= LS_END || state >= 3) return CMD_ERROR; + if (scheme >= LS_END || state >= 3 || colour == INVALID_COLOUR) return CMD_ERROR; Company *c = Company::Get(_current_company); diff --git a/src/core/enum_type.hpp b/src/core/enum_type.hpp index f6c111aae2..ad157f30b6 100644 --- a/src/core/enum_type.hpp +++ b/src/core/enum_type.hpp @@ -58,14 +58,16 @@ template struct EnumPropsT; * @param Tbegin first valid value from the contiguous range (i.e. TRACK_BEGIN) * @param Tend one past the last valid value from the contiguous range (i.e. TRACK_END) * @param Tinvalid value used as invalid value marker (i.e. INVALID_TRACK) + * @param Tnum_bits Number of bits for storing the enum in command parameters */ -template +template struct MakeEnumPropsT { typedef Tenum_t type; ///< enum type (i.e. Trackdir) typedef Tstorage_t storage; ///< storage type (i.e. byte) static const Tenum_t begin = Tbegin; ///< lowest valid value (i.e. TRACKDIR_BEGIN) static const Tenum_t end = Tend; ///< one after the last valid value (i.e. TRACKDIR_END) static const Tenum_t invalid = Tinvalid; ///< what value is used as invalid value (i.e. INVALID_TRACKDIR) + static const uint num_bits = Tnum_bits; ///< Number of bits for storing the enum in command parameters }; diff --git a/src/direction_type.h b/src/direction_type.h index 89197e36b2..1f062e5075 100644 --- a/src/direction_type.h +++ b/src/direction_type.h @@ -41,7 +41,7 @@ enum Direction { DECLARE_POSTFIX_INCREMENT(Direction); /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT DirectionByte; // typedefing-enumification of Direction @@ -91,7 +91,7 @@ enum DiagDirection { DECLARE_POSTFIX_INCREMENT(DiagDirection); /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT DiagDirectionByte; // typedefing-enumification of DiagDirection @@ -130,5 +130,6 @@ enum Axis { AXIS_END, ///< Used for iterations INVALID_AXIS = 0xFF, ///< Flag for an invalid Axis }; +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* DIRECTION_TYPE_H */ diff --git a/src/economy.cpp b/src/economy.cpp index 7548513e75..98a6c248c6 100644 --- a/src/economy.cpp +++ b/src/economy.cpp @@ -1488,12 +1488,12 @@ extern int GetAmountOwnedBy(const Company *c, Owner owner); CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost cost(EXPENSES_OTHER); - - Company *c = Company::GetIfValid(p1); + CompanyID target_company = (CompanyID)p1; + Company *c = Company::GetIfValid(target_company); /* Check if buying shares is allowed (protection against modified clients) * Cannot buy own shares */ - if (c == NULL || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR; + if (c == NULL || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR; /* Protect new companies from hostile takeovers */ if (_cur_year - c->inaugurated_year < 6) return_cmd_error(STR_ERROR_PROTECTED); @@ -1519,7 +1519,7 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, break; } } - SetWindowDirty(WC_COMPANY, p1); + SetWindowDirty(WC_COMPANY, target_company); } return cost; } @@ -1534,11 +1534,12 @@ CommandCost CmdBuyShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, */ CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Company *c = Company::GetIfValid(p1); + CompanyID target_company = (CompanyID)p1; + Company *c = Company::GetIfValid(target_company); /* Check if selling shares is allowed (protection against modified clients) * Cannot sell own shares */ - if (c == NULL || !_settings_game.economy.allow_shares || _current_company == (CompanyID)p1) return CMD_ERROR; + if (c == NULL || !_settings_game.economy.allow_shares || _current_company == target_company) return CMD_ERROR; /* Those lines are here for network-protection (clients can be slow) */ if (GetAmountOwnedBy(c, _current_company) == 0) return CommandCost(); @@ -1551,7 +1552,7 @@ CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1 OwnerByte *b = c->share_owners; while (*b != _current_company) b++; // share owners is guaranteed to contain company *b = COMPANY_SPECTATOR; - SetWindowDirty(WC_COMPANY, p1); + SetWindowDirty(WC_COMPANY, target_company); } return CommandCost(EXPENSES_OTHER, cost); } @@ -1569,7 +1570,8 @@ CommandCost CmdSellShareInCompany(TileIndex tile, DoCommandFlag flags, uint32 p1 */ CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Company *c = Company::GetIfValid(p1); + CompanyID target_company = (CompanyID)p1; + Company *c = Company::GetIfValid(target_company); if (c == NULL) return CMD_ERROR; /* Disable takeovers when not asked */ @@ -1579,7 +1581,7 @@ CommandCost CmdBuyCompany(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (!_networking && _local_company == c->index) return CMD_ERROR; /* Do not allow companies to take over themselves */ - if ((CompanyID)p1 == _current_company) return CMD_ERROR; + if (target_company == _current_company) return CMD_ERROR; /* Get the cost here as the company is deleted in DoAcquireCompany. */ CommandCost cost(EXPENSES_OTHER, c->bankrupt_value); diff --git a/src/gfx_type.h b/src/gfx_type.h index 968c0c993b..0afbbe7b65 100644 --- a/src/gfx_type.h +++ b/src/gfx_type.h @@ -196,6 +196,7 @@ enum Colours { COLOUR_END, INVALID_COLOUR = 0xFF, }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** Colour of the strings, see _string_colourmap in table/palettes.h or docs/ottd-colourtext-palette.png */ enum TextColour { diff --git a/src/group_cmd.cpp b/src/group_cmd.cpp index 63e8f99fe9..194615b1e8 100644 --- a/src/group_cmd.cpp +++ b/src/group_cmd.cpp @@ -10,6 +10,7 @@ /** @file group_cmd.cpp Handling of the engine groups */ #include "stdafx.h" +#include "cmd_helper.h" #include "command_func.h" #include "group.h" #include "train.h" @@ -82,7 +83,7 @@ void InitializeGroup() */ CommandCost CmdCreateGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - VehicleType vt = (VehicleType)p1; + VehicleType vt = Extract(p1); if (!IsCompanyBuildableVehicleType(vt)) return CMD_ERROR; if (!Group::CanAllocateItem()) return CMD_ERROR; @@ -258,13 +259,12 @@ CommandCost CmdAddVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - VehicleType type = (VehicleType)p2; - if (!Group::IsValidID(p1) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; + VehicleType type = Extract(p2); + GroupID id_g = p1; + if (!Group::IsValidID(id_g) || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; if (flags & DC_EXEC) { Vehicle *v; - VehicleType type = (VehicleType)p2; - GroupID id_g = p1; /* Find the first front engine which belong to the group id_g * then add all shared vehicles of this front engine to the group id_g */ @@ -298,13 +298,13 @@ CommandCost CmdAddSharedVehicleGroup(TileIndex tile, DoCommandFlag flags, uint32 */ CommandCost CmdRemoveAllVehiclesGroup(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Group *g = Group::GetIfValid(p1); - VehicleType type = (VehicleType)p2; + GroupID old_g = p1; + Group *g = Group::GetIfValid(old_g); + VehicleType type = Extract(p2); if (g == NULL || g->owner != _current_company || !IsCompanyBuildableVehicleType(type)) return CMD_ERROR; if (flags & DC_EXEC) { - GroupID old_g = p1; Vehicle *v; /* Find each Vehicle that belongs to the group old_g and add it to the default group */ diff --git a/src/industry_gui.cpp b/src/industry_gui.cpp index 56ceeb81b3..02d1144900 100644 --- a/src/industry_gui.cpp +++ b/src/industry_gui.cpp @@ -955,18 +955,14 @@ protected: /** Sort industries by production and name */ static int CDECL IndustryProductionSorter(const Industry * const *a, const Industry * const *b) { - int r = 0; - - if ((*a)->produced_cargo[0] == CT_INVALID) { - if ((*b)->produced_cargo[0] != CT_INVALID) return -1; - } else { - if ((*b)->produced_cargo[0] == CT_INVALID) return 1; - - r = ((*a)->last_month_production[0] + (*a)->last_month_production[1]) - - ((*b)->last_month_production[0] + (*b)->last_month_production[1]); + uint prod_a = 0, prod_b = 0; + for (uint i = 0; i < lengthof((*a)->produced_cargo); i++) { + if ((*a)->produced_cargo[i] != CT_INVALID) prod_a += (*a)->last_month_production[i]; + if ((*b)->produced_cargo[i] != CT_INVALID) prod_b += (*b)->last_month_production[i]; } + int r = prod_a - prod_b; - return (r == 0) ? IndustryNameSorter(a, b) : r; + return (r == 0) ? IndustryTypeSorter(a, b) : r; } /** Sort industries by transported cargo and name */ diff --git a/src/landscape.cpp b/src/landscape.cpp index f122c0c301..e85c22d824 100644 --- a/src/landscape.cpp +++ b/src/landscape.cpp @@ -604,8 +604,8 @@ CommandCost CmdLandscapeClear(TileIndex tile, DoCommandFlag flags, uint32 p1, ui /** Clear a big piece of landscape * @param tile end tile of area dragging - * @param p1 start tile of area dragging * @param flags of operation to conduct + * @param p1 start tile of area dragging * @param p2 unused * @param text unused * @return the cost of this operation or an error diff --git a/src/livery.h b/src/livery.h index df8029427f..5688efd21d 100644 --- a/src/livery.h +++ b/src/livery.h @@ -55,6 +55,7 @@ enum LiveryScheme { }; DECLARE_POSTFIX_INCREMENT(LiveryScheme); +template <> struct EnumPropsT : MakeEnumPropsT {}; /* List of different livery classes, used only by the livery GUI. */ enum LiveryClass { diff --git a/src/misc_cmd.cpp b/src/misc_cmd.cpp index ffa6450af1..2525ae7029 100644 --- a/src/misc_cmd.cpp +++ b/src/misc_cmd.cpp @@ -97,7 +97,7 @@ CommandCost CmdDecreaseLoan(TileIndex tile, DoCommandFlag flags, uint32 p1, uint loan -= loan % LOAN_INTERVAL; break; case 2: // Repay the given amount of loan - if ((p1 % LOAN_INTERVAL != 0) || ((int32)p1 < LOAN_INTERVAL)) return CMD_ERROR; // Invalid amount to loan + if (p1 % LOAN_INTERVAL != 0 || (int32)p1 < LOAN_INTERVAL || p1 > c->current_loan) return CMD_ERROR; // Invalid amount to loan loan = p1; break; } diff --git a/src/newgrf_station.h b/src/newgrf_station.h index 84420c793b..8427c78af3 100644 --- a/src/newgrf_station.h +++ b/src/newgrf_station.h @@ -27,6 +27,7 @@ enum StationClassID { STAT_CLASS_MAX = 32, ///< Maximum number of classes. }; typedef SimpleTinyEnumT StationClassIDByte; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** Allow incrementing of StationClassID variables */ DECLARE_POSTFIX_INCREMENT(StationClassID); diff --git a/src/openttd.cpp b/src/openttd.cpp index 3e5a3dbf63..e87ced87f9 100644 --- a/src/openttd.cpp +++ b/src/openttd.cpp @@ -797,7 +797,7 @@ static void MakeNewGameDone() SettingsDisableElrail(_settings_game.vehicle.disable_elrails); /* In a dedicated server, the server does not play */ - if (BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0) { + if (_network_dedicated || BlitterFactoryBase::GetCurrentBlitter()->GetScreenDepth() == 0) { SetLocalCompany(COMPANY_SPECTATOR); IConsoleCmdExec("exec scripts/game_start.scr 0"); return; diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp index e1985893e3..512dd02b34 100644 --- a/src/order_cmd.cpp +++ b/src/order_cmd.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" #include "debug.h" +#include "cmd_helper.h" #include "command_func.h" #include "company_func.h" #include "news_func.h" @@ -468,7 +469,7 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 Order new_order(p2); Vehicle *v = Vehicle::GetIfValid(veh); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; /* Check if the inserted order is to the correct destination (owner, type), * and has the correct flags if any */ @@ -547,8 +548,6 @@ CommandCost CmdInsertOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 default: return CMD_ERROR; } } - } else { - if (!IsCompanyBuildableVehicleType(v)) return CMD_ERROR; } if (new_order.GetNonStopType() != ONSF_STOP_EVERYWHERE && v->type != VEH_TRAIN && v->type != VEH_ROAD) return CMD_ERROR; @@ -729,7 +728,7 @@ CommandCost CmdDeleteOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 Vehicle *v = Vehicle::GetIfValid(veh_id); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; /* If we did not select an order, we maybe want to de-clone the orders */ if (sel_ord >= v->GetNumOrders()) @@ -795,10 +794,7 @@ CommandCost CmdSkipToOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 Vehicle *v = Vehicle::GetIfValid(veh_id); - if (v == NULL || !CheckOwnership(v->owner) || sel_ord == v->cur_order_index || - sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) { - return CMD_ERROR; - } + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner) || sel_ord == v->cur_order_index || sel_ord >= v->GetNumOrders() || v->GetNumOrders() < 2) return CMD_ERROR; if (flags & DC_EXEC) { v->cur_order_index = sel_ord; @@ -835,7 +831,7 @@ CommandCost CmdMoveOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 VehicleOrderID target_order = GB(p2, 16, 16); Vehicle *v = Vehicle::GetIfValid(veh); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; /* Don't make senseless movements */ if (moving_order >= v->GetNumOrders() || target_order >= v->GetNumOrders() || @@ -910,13 +906,13 @@ CommandCost CmdModifyOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint3 { VehicleOrderID sel_ord = GB(p1, 16, 16); // XXX - automatically truncated to 8 bits. VehicleID veh = GB(p1, 0, 16); - ModifyOrderFlags mof = (ModifyOrderFlags)GB(p2, 0, 4); - uint16 data = GB(p2, 4, 11); + ModifyOrderFlags mof = Extract(p2); + uint16 data = GB(p2, 4, 11); if (mof >= MOF_END) return CMD_ERROR; Vehicle *v = Vehicle::GetIfValid(veh); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; /* Is it a valid order? */ if (sel_ord >= v->GetNumOrders()) return CMD_ERROR; @@ -1139,17 +1135,14 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 VehicleID veh_dst = GB(p1, 0, 16); Vehicle *dst = Vehicle::GetIfValid(veh_dst); - - if (dst == NULL || !CheckOwnership(dst->owner)) return CMD_ERROR; + if (dst == NULL || !dst->IsPrimaryVehicle() || !CheckOwnership(dst->owner)) return CMD_ERROR; switch (p2) { case CO_SHARE: { Vehicle *src = Vehicle::GetIfValid(veh_src); /* Sanity checks */ - if (src == NULL || !CheckOwnership(src->owner) || dst->type != src->type || dst == src) { - return CMD_ERROR; - } + if (src == NULL || !src->IsPrimaryVehicle() || !CheckOwnership(src->owner) || dst->type != src->type || dst == src) return CMD_ERROR; /* Trucks can't share orders with busses (and visa versa) */ if (src->type == VEH_ROAD && RoadVehicle::From(src)->IsBus() != RoadVehicle::From(dst)->IsBus()) { @@ -1188,9 +1181,7 @@ CommandCost CmdCloneOrder(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 Vehicle *src = Vehicle::GetIfValid(veh_src); /* Sanity checks */ - if (src == NULL || !CheckOwnership(src->owner) || dst->type != src->type || dst == src) { - return CMD_ERROR; - } + if (src == NULL || !src->IsPrimaryVehicle() || !CheckOwnership(src->owner) || dst->type != src->type || dst == src) return CMD_ERROR; /* Trucks can't copy all the orders from busses (and visa versa), * and neither can helicopters and aircarft. */ @@ -1263,8 +1254,10 @@ CommandCost CmdOrderRefit(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 CargoID cargo = GB(p2, 0, 8); byte subtype = GB(p2, 8, 8); + if (cargo >= NUM_CARGO) return CMD_ERROR; + const Vehicle *v = Vehicle::GetIfValid(veh); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; Order *order = v->GetOrder(order_number); if (order == NULL) return CMD_ERROR; @@ -1416,7 +1409,8 @@ CommandCost CmdRestoreOrderIndex(TileIndex tile, DoCommandFlag flags, uint32 p1, Vehicle *v = Vehicle::GetIfValid(p1); /* Check the vehicle type and ownership, and if the service interval and order are in range */ - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; + if (serv_int != GetServiceIntervalClamped(serv_int, v->owner) || cur_ord >= v->GetNumOrders()) return CMD_ERROR; if (flags & DC_EXEC) { diff --git a/src/order_type.h b/src/order_type.h index 52940ba399..3b3d80ef88 100644 --- a/src/order_type.h +++ b/src/order_type.h @@ -149,6 +149,7 @@ enum ModifyOrderFlags { MOF_COND_DESTINATION,///< Change the destination of a conditional order. MOF_END }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * Depot action to switch to when doing a MOF_DEPOT_ACTION. diff --git a/src/rail.cpp b/src/rail.cpp index 663753e9f3..21ae806614 100644 --- a/src/rail.cpp +++ b/src/rail.cpp @@ -181,7 +181,7 @@ bool HasRailtypeAvail(const CompanyID company, const RailType railtype) bool ValParamRailtype(const RailType rail) { - return HasRailtypeAvail(_current_company, rail); + return rail < RAILTYPE_END && HasRailtypeAvail(_current_company, rail); } RailType GetBestRailtype(const CompanyID company) diff --git a/src/rail_cmd.cpp b/src/rail_cmd.cpp index 1676375a9a..f9f9f6242c 100644 --- a/src/rail_cmd.cpp +++ b/src/rail_cmd.cpp @@ -369,8 +369,8 @@ static inline bool ValParamTrackOrientation(Track track) {return IsValidTrack(tr */ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - RailType railtype = (RailType)p1; - Track track = (Track)p2; + RailType railtype = Extract(p1); + Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; @@ -509,11 +509,11 @@ CommandCost CmdBuildSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdRemoveSingleRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)p2; + Track track = Extract(p2); CommandCost cost(EXPENSES_CONSTRUCTION); bool crossing = false; - if (!ValParamTrackOrientation((Track)p2)) return CMD_ERROR; + if (!ValParamTrackOrientation(track)) return CMD_ERROR; TrackBits trackbit = TrackToTrackBits(track); /* Need to read tile owner now because it may change when the rail is removed @@ -743,9 +743,9 @@ static CommandCost ValidateAutoDrag(Trackdir *trackdir, TileIndex start, TileInd static CommandCost CmdRailTrackHelper(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost ret, total_cost(EXPENSES_CONSTRUCTION); - Track track = (Track)GB(p2, 4, 3); + Track track = Extract(p2); bool remove = HasBit(p2, 7); - RailType railtype = (RailType)GB(p2, 0, 4); + RailType railtype = Extract(p2); if (!ValParamRailtype(railtype) || !ValParamTrackOrientation(track)) return CMD_ERROR; if (p1 >= MapSize()) return CMD_ERROR; @@ -830,11 +830,12 @@ CommandCost CmdRemoveRailroadTrack(TileIndex tile, DoCommandFlag flags, uint32 p CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* check railtype and valid direction for depot (0 through 3), 4 in total */ - if (!ValParamRailtype((RailType)p1)) return CMD_ERROR; + RailType railtype = Extract(p1); + if (!ValParamRailtype(railtype)) return CMD_ERROR; Slope tileh = GetTileSlope(tile, NULL); - DiagDirection dir = Extract(p2); + DiagDirection dir = Extract(p2); /* Prohibit construction if * The tile is non-flat AND @@ -862,7 +863,7 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u Depot *d = new Depot(tile); d->town_index = ClosestTownFromTile(tile, UINT_MAX)->index; - MakeRailDepot(tile, _current_company, d->index, dir, (RailType)p1); + MakeRailDepot(tile, _current_company, d->index, dir, railtype); MarkTileDirtyByTile(tile); AddSideToSignalBuffer(tile, INVALID_DIAGDIR, _current_company); @@ -895,16 +896,17 @@ CommandCost CmdBuildTrainDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, u */ CommandCost CmdBuildSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)GB(p1, 0, 3); + Track track = Extract(p1); bool ctrl_pressed = HasBit(p1, 3); // was the CTRL button pressed SignalVariant sigvar = (ctrl_pressed ^ HasBit(p1, 4)) ? SIG_SEMAPHORE : SIG_ELECTRIC; // the signal variant of the new signal - SignalType sigtype = (SignalType)GB(p1, 5, 3); // the signal type of the new signal + SignalType sigtype = Extract(p1); // the signal type of the new signal bool convert_signal = HasBit(p1, 8); // convert button pressed - SignalType cycle_start = (SignalType)GB(p1, 9, 3); - SignalType cycle_stop = (SignalType)GB(p1, 12, 3); + SignalType cycle_start = Extract(p1); + SignalType cycle_stop = Extract(p1); uint num_dir_cycle = GB(p1, 15, 2); if (sigtype > SIGTYPE_LAST) return CMD_ERROR; + if (cycle_start > cycle_stop || cycle_stop > SIGTYPE_LAST) return CMD_ERROR; /* You can only build signals on plain rail tiles, and the selected track must exist */ if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || @@ -1122,15 +1124,14 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin bool err = true; TileIndex start_tile = tile; - Track track = (Track)GB(p2, 0, 3); + Track track = Extract(p2); bool mode = HasBit(p2, 3); bool semaphores = HasBit(p2, 4); bool remove = HasBit(p2, 5); bool autofill = HasBit(p2, 6); - Trackdir trackdir = TrackToTrackdir(track); byte signal_density = GB(p2, 24, 8); - if (p1 >= MapSize()) return CMD_ERROR; + if (p1 >= MapSize() || !ValParamTrackOrientation(track)) return CMD_ERROR; TileIndex end_tile = p1; if (signal_density == 0 || signal_density > 20) return CMD_ERROR; @@ -1140,6 +1141,7 @@ static CommandCost CmdSignalTrackHelper(TileIndex tile, DoCommandFlag flags, uin * since the original amount will be too dense (shorter tracks) */ signal_density *= 2; + Trackdir trackdir = TrackToTrackdir(track); if (ValidateAutoDrag(&trackdir, tile, end_tile).Failed()) return CMD_ERROR; track = TrackdirToTrack(trackdir); // trackdir might have changed, keep track in sync @@ -1261,7 +1263,7 @@ CommandCost CmdBuildSignalTrack(TileIndex tile, DoCommandFlag flags, uint32 p1, */ CommandCost CmdRemoveSingleSignal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - Track track = (Track)GB(p1, 0, 3); + Track track = Extract(p1); if (!ValParamTrackOrientation(track) || !IsPlainRailTile(tile) || @@ -1361,7 +1363,7 @@ static Vehicle *UpdateTrainPowerProc(Vehicle *v, void *data) CommandCost CmdConvertRail(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { CommandCost cost(EXPENSES_CONSTRUCTION); - RailType totype = (RailType)p2; + RailType totype = Extract(p2); if (!ValParamRailtype(totype)) return CMD_ERROR; if (p1 >= MapSize()) return CMD_ERROR; diff --git a/src/rail_gui.cpp b/src/rail_gui.cpp index 3ff64991fb..ce9c284b01 100644 --- a/src/rail_gui.cpp +++ b/src/rail_gui.cpp @@ -270,7 +270,7 @@ void CcBuildRailTunnel(const CommandCost &result, TileIndex tile, uint32 p1, uin static void PlaceRail_Tunnel(TileIndex tile) { - DoCommandP(tile, _cur_railtype, 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRailTunnel); + DoCommandP(tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRailTunnel); } static void PlaceRail_ConvertRail(TileIndex tile) @@ -814,7 +814,7 @@ struct BuildRailToolbarWindow : Window { virtual void OnPlacePresize(Point pt, TileIndex tile) { - DoCommand(tile, _cur_railtype, 0, DC_AUTO, CMD_BUILD_TUNNEL); + DoCommand(tile, _cur_railtype | (TRANSPORT_RAIL << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } diff --git a/src/rail_type.h b/src/rail_type.h index 1ad5d96986..b34f54c1f1 100644 --- a/src/rail_type.h +++ b/src/rail_type.h @@ -43,7 +43,7 @@ enum RailType { /** Allow incrementing of Track variables */ DECLARE_POSTFIX_INCREMENT(RailType); /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT RailTypeByte; /** diff --git a/src/road_cmd.cpp b/src/road_cmd.cpp index 70fc176585..48054792ce 100644 --- a/src/road_cmd.cpp +++ b/src/road_cmd.cpp @@ -455,15 +455,15 @@ CommandCost CmdBuildRoad(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2 = (town != NULL) ? town->index : (TownID)INVALID_TOWN; } - RoadBits pieces = Extract(p1); + RoadBits pieces = Extract(p1); /* do not allow building 'zero' road bits, code wouldn't handle it */ if (pieces == ROAD_NONE) return CMD_ERROR; - RoadType rt = (RoadType)GB(p1, 4, 2); + RoadType rt = Extract(p1); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; - DisallowedRoadDirections toggle_drd = (DisallowedRoadDirections)GB(p1, 6, 2); + DisallowedRoadDirections toggle_drd = Extract(p1); Slope tileh = GetTileSlope(tile, NULL); @@ -714,10 +714,10 @@ CommandCost CmdBuildLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 p if (p1 >= MapSize()) return CMD_ERROR; TileIndex end_tile = p1; - RoadType rt = (RoadType)GB(p2, 3, 2); + RoadType rt = Extract(p2); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; - Axis axis = Extract(p2); + Axis axis = Extract(p2); /* Only drag in X or Y direction dictated by the direction variable */ if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis @@ -801,10 +801,10 @@ CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 if (p1 >= MapSize()) return CMD_ERROR; TileIndex end_tile = p1; - RoadType rt = (RoadType)GB(p2, 3, 2); + RoadType rt = Extract(p2); if (!IsValidRoadType(rt)) return CMD_ERROR; - Axis axis = Extract(p2); + Axis axis = Extract(p2); /* Only drag in X or Y direction dictated by the direction variable */ if (axis == AXIS_X && TileY(start_tile) != TileY(end_tile)) return CMD_ERROR; // x-axis if (axis == AXIS_Y && TileX(start_tile) != TileX(end_tile)) return CMD_ERROR; // y-axis @@ -864,8 +864,8 @@ CommandCost CmdRemoveLongRoad(TileIndex start_tile, DoCommandFlag flags, uint32 */ CommandCost CmdBuildRoadDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - DiagDirection dir = Extract(p1); - RoadType rt = (RoadType)GB(p1, 2, 2); + DiagDirection dir = Extract(p1); + RoadType rt = Extract(p1); if (!IsValidRoadType(rt) || !ValParamRoadType(rt)) return CMD_ERROR; diff --git a/src/road_gui.cpp b/src/road_gui.cpp index f42b78aa92..3c75ccc877 100644 --- a/src/road_gui.cpp +++ b/src/road_gui.cpp @@ -174,7 +174,7 @@ static const RoadTypeInfo _road_type_infos[] = { static void PlaceRoad_Tunnel(TileIndex tile) { - DoCommandP(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel); + DoCommandP(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, CMD_BUILD_TUNNEL | CMD_MSG(STR_ERROR_CAN_T_BUILD_TUNNEL_HERE), CcBuildRoadTunnel); } static void BuildRoadOutsideStation(TileIndex tile, DiagDirection direction) @@ -613,7 +613,7 @@ struct BuildRoadToolbarWindow : Window { virtual void OnPlacePresize(Point pt, TileIndex tile) { - DoCommand(tile, 0x200 | RoadTypeToRoadTypes(_cur_roadtype), 0, DC_AUTO, CMD_BUILD_TUNNEL); + DoCommand(tile, RoadTypeToRoadTypes(_cur_roadtype) | (TRANSPORT_ROAD << 8), 0, DC_AUTO, CMD_BUILD_TUNNEL); VpSetPresizeRange(tile, _build_tunnel_endtile == 0 ? tile : _build_tunnel_endtile); } diff --git a/src/road_map.h b/src/road_map.h index 46060ddfd6..814c8eb09c 100644 --- a/src/road_map.h +++ b/src/road_map.h @@ -168,6 +168,7 @@ enum DisallowedRoadDirections { DRD_END }; DECLARE_ENUM_AS_BIT_SET(DisallowedRoadDirections); +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * Gets the disallowed directions diff --git a/src/road_type.h b/src/road_type.h index 0379ba12b9..2c58b31499 100644 --- a/src/road_type.h +++ b/src/road_type.h @@ -27,6 +27,7 @@ enum RoadType { INVALID_ROADTYPE = 0xFF ///< flag for invalid roadtype }; DECLARE_POSTFIX_INCREMENT(RoadType); +template <> struct EnumPropsT : MakeEnumPropsT {}; /** * The different roadtypes we support, but then a bitmask of them @@ -41,6 +42,7 @@ enum RoadTypes { INVALID_ROADTYPES = 0xFF ///< Invalid roadtypes }; DECLARE_ENUM_AS_BIT_SET(RoadTypes); +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef SimpleTinyEnumT RoadTypesByte; @@ -67,5 +69,6 @@ enum RoadBits { ROAD_ALL = ROAD_X | ROAD_Y ///< Full 4-way crossing }; DECLARE_ENUM_AS_BIT_SET(RoadBits); +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* ROAD_TYPE_H */ diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index f7317b44db..ea02bee561 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -200,9 +200,10 @@ void RoadVehUpdateCache(RoadVehicle *v) */ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - if (!IsEngineBuildable(p1, VEH_ROAD, _current_company)) return_cmd_error(STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE); + EngineID eid = GB(p1, 0, 16); + if (!IsEngineBuildable(eid, VEH_ROAD, _current_company)) return_cmd_error(STR_ERROR_ROAD_VEHICLE_NOT_AVAILABLE); - const Engine *e = Engine::Get(p1); + const Engine *e = Engine::Get(eid); /* Engines without valid cargo should not be available */ if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; @@ -216,7 +217,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (HasTileRoadType(tile, ROADTYPE_TRAM) != HasBit(e->info.misc_flags, EF_ROAD_TRAM)) return_cmd_error(STR_ERROR_DEPOT_WRONG_DEPOT_TYPE); - uint num_vehicles = 1 + CountArticulatedParts(p1, false); + uint num_vehicles = 1 + CountArticulatedParts(eid, false); /* Allow for the front and the articulated parts */ if (!Vehicle::CanAllocateItem(num_vehicles)) { @@ -254,7 +255,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint v->last_station_visited = INVALID_STATION; v->max_speed = rvi->max_speed; - v->engine_type = (EngineID)p1; + v->engine_type = eid; v->rcache.first_engine = INVALID_ENGINE; // needs to be set before first callback v->reliability = e->reliability; @@ -297,7 +298,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Road window } - Company::Get(_current_company)->num_engines[p1]++; + Company::Get(_current_company)->num_engines[eid]++; CheckConsistencyOfArticulatedVehicle(v); } diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index ec907d2d77..e994fe9ccc 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -611,11 +611,12 @@ bool Ship::Tick() */ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { + EngineID eid = GB(p1, 0, 16); UnitID unit_num; - if (!IsEngineBuildable(p1, VEH_SHIP, _current_company)) return_cmd_error(STR_ERROR_SHIP_NOT_AVAILABLE); + if (!IsEngineBuildable(eid, VEH_SHIP, _current_company)) return_cmd_error(STR_ERROR_SHIP_NOT_AVAILABLE); - const Engine *e = Engine::Get(p1); + const Engine *e = Engine::Get(eid); CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); /* Engines without valid cargo should not be available */ @@ -660,7 +661,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 v->last_station_visited = INVALID_STATION; v->max_speed = svi->max_speed; - v->engine_type = p1; + v->engine_type = eid; v->reliability = e->reliability; v->reliability_spd_dec = e->reliability_spd_dec; @@ -692,7 +693,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Ship window } - Company::Get(_current_company)->num_engines[p1]++; + Company::Get(_current_company)->num_engines[eid]++; } return value; diff --git a/src/signal_type.h b/src/signal_type.h index 8c9c4bcfc2..5a8d564d2a 100644 --- a/src/signal_type.h +++ b/src/signal_type.h @@ -27,9 +27,12 @@ enum SignalType { SIGTYPE_COMBO = 3, ///< presignal inter-block SIGTYPE_PBS = 4, ///< normal pbs signal SIGTYPE_PBS_ONEWAY = 5, ///< no-entry signal + + SIGTYPE_END, SIGTYPE_LAST = SIGTYPE_PBS_ONEWAY, SIGTYPE_LAST_NOPBS = SIGTYPE_COMBO }; +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* SIGNAL_TYPE_H */ diff --git a/src/station_cmd.cpp b/src/station_cmd.cpp index 8618f254c6..8357f92181 100644 --- a/src/station_cmd.cpp +++ b/src/station_cmd.cpp @@ -973,13 +973,13 @@ CommandCost FindJoiningWaypoint(StationID existing_waypoint, StationID waypoint_ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* Unpack parameters */ - RailType rt = (RailType)GB(p1, 0, 4); - Axis axis = Extract(p1); + RailType rt = Extract(p1); + Axis axis = Extract(p1); byte numtracks = GB(p1, 8, 8); byte plat_len = GB(p1, 16, 8); bool adjacent = HasBit(p1, 24); - StationClassID spec_class = (StationClassID)GB(p2, 0, 8); + StationClassID spec_class = Extract(p2); byte spec_index = GB(p2, 8, 8); StationID station_to_join = GB(p2, 16, 16); @@ -988,7 +988,7 @@ CommandCost CmdBuildRailStation(TileIndex tile_org, DoCommandFlag flags, uint32 if (!ValParamRailtype(rt)) return CMD_ERROR; /* Check if the given station class is valid */ - if ((uint)spec_class >= GetNumStationClasses()) return CMD_ERROR; + if ((uint)spec_class >= GetNumStationClasses() || spec_class == STAT_CLASS_WAYP) return CMD_ERROR; if (spec_index >= GetNumCustomStations(spec_class)) return CMD_ERROR; if (plat_len == 0 || numtracks == 0) return CMD_ERROR; @@ -1524,7 +1524,7 @@ CommandCost CmdBuildRoadStop(TileIndex tile, DoCommandFlag flags, uint32 p1, uin bool type = HasBit(p2, 0); bool is_drive_through = HasBit(p2, 1); bool build_over_road = is_drive_through && IsNormalRoadTile(tile); - RoadTypes rts = (RoadTypes)GB(p2, 2, 2); + RoadTypes rts = Extract(p2); StationID station_to_join = GB(p2, 16, 16); bool reuse = (station_to_join != NEW_STATION); if (!reuse) station_to_join = INVALID_STATION; diff --git a/src/stdafx.h b/src/stdafx.h index 16376e8c59..35ec1f1367 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -313,15 +313,20 @@ typedef unsigned char byte; #define PERSONAL_DIR "" #endif -/* Compile time assertions. Prefer c++0x static_assert() */ +/* Compile time assertions. Prefer c++0x static_assert(). + * Older compilers cannot evaluate some expressions at compile time, + * typically when templates are involved, try assert_tcompile() in those cases. */ #if defined(__STDCXX_VERSION__) || defined(__GXX_EXPERIMENTAL_CXX0X__) || defined(__GXX_EXPERIMENTAL_CPP0X__) || defined(static_assert) /* __STDCXX_VERSION__ is c++0x feature macro, __GXX_EXPERIMENTAL_CXX0X__ is used by gcc, __GXX_EXPERIMENTAL_CPP0X__ by icc */ #define assert_compile(expr) static_assert(expr, #expr ) + #define assert_tcompile(expr) assert_compile(expr) #elif defined(__OS2__) /* Disabled for OS/2 */ #define assert_compile(expr) + #define assert_tcompile(expr) assert_compile(expr) #else #define assert_compile(expr) typedef int __ct_assert__[1 - 2 * !(expr)] + #define assert_tcompile(expr) assert(expr) #endif /* Check if the types have the bitsizes like we are using them */ diff --git a/src/terraform_cmd.cpp b/src/terraform_cmd.cpp index 61df82d1f0..6005004a1f 100644 --- a/src/terraform_cmd.cpp +++ b/src/terraform_cmd.cpp @@ -372,7 +372,7 @@ CommandCost CmdLevelLand(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 uint oldh = TileHeight(p1); /* compute new height */ - uint h = oldh + p2; + uint h = oldh + (int8)p2; /* Check range of destination height */ if (h > MAX_TILE_HEIGHT) return_cmd_error((oldh == 0) ? STR_ERROR_ALREADY_AT_SEA_LEVEL : STR_ERROR_TOO_HIGH); diff --git a/src/town_cmd.cpp b/src/town_cmd.cpp index 6ab50c3ff9..200e81ebe9 100644 --- a/src/town_cmd.cpp +++ b/src/town_cmd.cpp @@ -14,6 +14,7 @@ #include "road_cmd.h" #include "landscape.h" #include "viewport_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "industry.h" #include "station_base.h" @@ -1445,7 +1446,7 @@ static void DoCreateTown(Town *t, TileIndex tile, uint32 townnameparts, TownSize t->larger_town = city; int x = (int)size * 16 + 3; - if (size == TS_RANDOM) x = (Random() & 0xF) + 8; + if (size == TSZ_RANDOM) x = (Random() & 0xF) + 8; /* Don't create huge cities when founding town in-game */ if (city && (!manual || _game_mode == GM_EDITOR)) x *= _settings_game.economy.initial_city_size; @@ -1518,20 +1519,20 @@ static bool IsUniqueTownName(const char *name) */ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TownSize size = (TownSize)GB(p1, 0, 2); + TownSize size = Extract(p1); bool city = HasBit(p1, 2); - TownLayout layout = (TownLayout)GB(p1, 3, 3); + TownLayout layout = Extract(p1); TownNameParams par(_settings_game.game_creation.town_name); bool random = HasBit(p1, 6); uint32 townnameparts = p2; - if (size > TS_RANDOM) return CMD_ERROR; + if (size > TSZ_RANDOM) return CMD_ERROR; if (layout > TL_RANDOM) return CMD_ERROR; /* Some things are allowed only in the scenario editor */ if (_game_mode != GM_EDITOR) { if (_settings_game.economy.found_town == TF_FORBIDDEN) return CMD_ERROR; - if (size == TS_LARGE) return CMD_ERROR; + if (size == TSZ_LARGE) return CMD_ERROR; if (random) return CMD_ERROR; if (_settings_game.economy.found_town != TF_CUSTOM_LAYOUT && layout != _settings_game.economy.town_layout) { return CMD_ERROR; @@ -1555,7 +1556,7 @@ CommandCost CmdFoundTown(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 if (ret.Failed()) return ret; } - static const byte price_mult[][TS_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }}; + static const byte price_mult[][TSZ_RANDOM + 1] = {{ 15, 25, 40, 25 }, { 20, 35, 55, 35 }}; /* multidimensional arrays have to have defined length of non-first dimension */ assert_compile(lengthof(price_mult[0]) == 4); @@ -1782,7 +1783,7 @@ bool GenerateTowns(TownLayout layout) /* Get a unique name for the town. */ if (!GenerateTownName(&townnameparts)) continue; /* try 20 times to create a random-sized town for the first loop. */ - if (CreateRandomTown(20, townnameparts, TS_RANDOM, city, layout) != NULL) num++; // if creation successfull, raise a flag + if (CreateRandomTown(20, townnameparts, TSZ_RANDOM, city, layout) != NULL) num++; // If creation was successful, raise a flag. } while (--n); if (num != 0) return true; @@ -1790,7 +1791,7 @@ bool GenerateTowns(TownLayout layout) /* If num is still zero at this point, it means that not a single town has been created. * So give it a last try, but now more aggressive */ if (GenerateTownName(&townnameparts) && - CreateRandomTown(10000, townnameparts, TS_RANDOM, _settings_game.economy.larger_towns != 0, layout) != NULL) { + CreateRandomTown(10000, townnameparts, TSZ_RANDOM, _settings_game.economy.larger_towns != 0, layout) != NULL) { return true; } diff --git a/src/town_gui.cpp b/src/town_gui.cpp index be4f3b3a82..e80bca40a3 100644 --- a/src/town_gui.cpp +++ b/src/town_gui.cpp @@ -1053,7 +1053,7 @@ private: public: FoundTownWindow(const WindowDesc *desc, WindowNumber window_number) : QueryStringBaseWindow(MAX_LENGTH_TOWN_NAME_BYTES), - town_size(TS_MEDIUM), + town_size(TSZ_MEDIUM), town_layout(_settings_game.economy.town_layout), params(_settings_game.game_creation.town_name) { diff --git a/src/town_type.h b/src/town_type.h index 266e952148..93dcc1a3af 100644 --- a/src/town_type.h +++ b/src/town_type.h @@ -19,11 +19,14 @@ struct Town; /** Supported initial town sizes */ enum TownSize { - TS_SMALL, ///< small town - TS_MEDIUM, ///< medium town - TS_LARGE, ///< large town - TS_RANDOM, ///< random size, bigger than small, smaller than large + TSZ_SMALL, ///< Small town. + TSZ_MEDIUM, ///< Medium town. + TSZ_LARGE, ///< Large town. + TSZ_RANDOM, ///< Random size, bigger than small, smaller than large. + + TSZ_END, ///< Number of available town sizes. }; +template <> struct EnumPropsT : MakeEnumPropsT {}; enum { /* These refer to the maximums, so Appalling is -1000 to -400 @@ -87,6 +90,7 @@ enum TownLayout { NUM_TLS, ///< Number of town layouts }; +template <> struct EnumPropsT : MakeEnumPropsT {}; /** It needs to be 8bits, because we save and load it as such */ typedef SimpleTinyEnumT TownLayoutByte; // typedefing-enumification of TownLayout diff --git a/src/track_type.h b/src/track_type.h index b2428f7f80..36934f8e37 100644 --- a/src/track_type.h +++ b/src/track_type.h @@ -33,7 +33,7 @@ enum Track { /** Allow incrementing of Track variables */ DECLARE_POSTFIX_INCREMENT(Track); /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT TrackByte; @@ -94,7 +94,7 @@ enum Trackdir { }; /** Define basic enum properties */ -template <> struct EnumPropsT : MakeEnumPropsT {}; +template <> struct EnumPropsT : MakeEnumPropsT {}; typedef TinyEnumT TrackdirByte; /** diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 2b2f7c458f..80b4db2531 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -816,10 +816,11 @@ static void AddRearEngineToMultiheadedTrain(Train *v) */ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { + EngineID eid = GB(p1, 0, 16); /* Check if the engine-type is valid (for the company) */ - if (!IsEngineBuildable(p1, VEH_TRAIN, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE); + if (!IsEngineBuildable(eid, VEH_TRAIN, _current_company)) return_cmd_error(STR_ERROR_RAIL_VEHICLE_NOT_AVAILABLE); - const Engine *e = Engine::Get(p1); + const Engine *e = Engine::Get(eid); const RailVehicleInfo *rvi = &e->u.rail; CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); @@ -833,11 +834,11 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, if (!IsRailDepotTile(tile)) return CMD_ERROR; if (!IsTileOwner(tile, _current_company)) return CMD_ERROR; - if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(p1, tile, flags); + if (rvi->railveh_type == RAILVEH_WAGON) return CmdBuildRailWagon(eid, tile, flags); uint num_vehicles = (rvi->railveh_type == RAILVEH_MULTIHEAD ? 2 : 1) + - CountArticulatedParts(p1, false); + CountArticulatedParts(eid, false); /* Check if depot and new engine uses the same kind of tracks * * We need to see if the engine got power on the tile to avoid eletric engines in non-electric depots */ @@ -875,7 +876,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, v->value = value.GetCost(); v->last_station_visited = INVALID_STATION; - v->engine_type = p1; + v->engine_type = eid; v->tcache.first_engine = INVALID_ENGINE; // needs to be set before first callback v->reliability = e->reliability; @@ -920,7 +921,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, InvalidateAutoreplaceWindow(v->engine_type, v->group_id); // updates the replace Train window } - Company::Get(_current_company)->num_engines[p1]++; + Company::Get(_current_company)->num_engines[eid]++; CheckConsistencyOfArticulatedVehicle(v); } diff --git a/src/transport_type.h b/src/transport_type.h index 71b452b5f5..65af9c75b3 100644 --- a/src/transport_type.h +++ b/src/transport_type.h @@ -30,5 +30,6 @@ enum TransportType { TRANSPORT_END, INVALID_TRANSPORT = 0xff, }; +template <> struct EnumPropsT : MakeEnumPropsT {}; #endif /* TRANSPORT_TYPE_H */ diff --git a/src/tunnelbridge_cmd.cpp b/src/tunnelbridge_cmd.cpp index bd59a155d7..200d44abf2 100644 --- a/src/tunnelbridge_cmd.cpp +++ b/src/tunnelbridge_cmd.cpp @@ -17,6 +17,7 @@ #include "landscape.h" #include "unmovable_map.h" #include "viewport_func.h" +#include "cmd_helper.h" #include "command_func.h" #include "town.h" #include "variables.h" @@ -191,7 +192,7 @@ CommandCost CheckBridgeAvailability(BridgeType bridge_type, uint bridge_len, DoC * @param p1 packed start tile coords (~ dx) * @param p2 various bitstuffed elements * - p2 = (bit 0- 7) - bridge type (hi bh) - * - p2 = (bit 8-14) - rail type or road types. + * - p2 = (bit 8-11) - rail type or road types. * - p2 = (bit 15-16) - transport type. * @param text unused * @return the cost of this operation or an error @@ -208,17 +209,17 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u if (p1 >= MapSize()) return CMD_ERROR; - TransportType transport_type = (TransportType)GB(p2, 15, 2); + TransportType transport_type = Extract(p2); /* type of bridge */ switch (transport_type) { case TRANSPORT_ROAD: - roadtypes = (RoadTypes)GB(p2, 8, 2); + roadtypes = Extract(p2); if (!HasExactlyOneBit(roadtypes) || !HasRoadTypesAvail(_current_company, roadtypes)) return CMD_ERROR; break; case TRANSPORT_RAIL: - railtype = (RailType)GB(p2, 8, 7); + railtype = Extract(p2); if (!ValParamRailtype(railtype)) return CMD_ERROR; break; @@ -479,22 +480,32 @@ CommandCost CmdBuildBridge(TileIndex end_tile, DoCommandFlag flags, uint32 p1, u /** Build Tunnel. * @param start_tile start tile of tunnel * @param flags type of operation - * @param p1 railtype or roadtypes. bit 9 set means road tunnel + * @param p1 bit 0-3 railtype or roadtypes + * bit 8-9 transport type * @param p2 unused * @param text unused * @return the cost of this operation or an error */ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TransportType transport_type = (TransportType)GB(p1, 9, 1); + TransportType transport_type = Extract(p1); CommandCost cost(EXPENSES_CONSTRUCTION); + RailType railtype = INVALID_RAILTYPE; + RoadTypes rts = ROADTYPES_NONE; _build_tunnel_endtile = 0; - if (transport_type == TRANSPORT_RAIL) { - if (!ValParamRailtype((RailType)p1)) return CMD_ERROR; - } else { - const RoadTypes rts = (RoadTypes)GB(p1, 0, 2); - if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR; + switch (transport_type) { + case TRANSPORT_RAIL: + railtype = Extract(p1); + if (!ValParamRailtype(railtype)) return CMD_ERROR; + break; + + case TRANSPORT_ROAD: + rts = Extract(p1); + if (!HasExactlyOneBit(rts) || !HasRoadTypesAvail(_current_company, rts)) return CMD_ERROR; + break; + + default: return CMD_ERROR; } uint start_z; @@ -581,13 +592,13 @@ CommandCost CmdBuildTunnel(TileIndex start_tile, DoCommandFlag flags, uint32 p1, if (flags & DC_EXEC) { if (transport_type == TRANSPORT_RAIL) { - MakeRailTunnel(start_tile, _current_company, direction, (RailType)GB(p1, 0, 4)); - MakeRailTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RailType)GB(p1, 0, 4)); + MakeRailTunnel(start_tile, _current_company, direction, railtype); + MakeRailTunnel(end_tile, _current_company, ReverseDiagDir(direction), railtype); AddSideToSignalBuffer(start_tile, INVALID_DIAGDIR, _current_company); YapfNotifyTrackLayoutChange(start_tile, DiagDirToDiagTrack(direction)); } else { - MakeRoadTunnel(start_tile, _current_company, direction, (RoadTypes)GB(p1, 0, 2)); - MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), (RoadTypes)GB(p1, 0, 2)); + MakeRoadTunnel(start_tile, _current_company, direction, rts); + MakeRoadTunnel(end_tile, _current_company, ReverseDiagDir(direction), rts); } } diff --git a/src/vehicle_cmd.cpp b/src/vehicle_cmd.cpp index 12b6e8c63f..4557ddca79 100644 --- a/src/vehicle_cmd.cpp +++ b/src/vehicle_cmd.cpp @@ -13,6 +13,7 @@ #include "roadveh.h" #include "news_func.h" #include "airport.h" +#include "cmd_helper.h" #include "command_func.h" #include "company_func.h" #include "vehicle_gui.h" @@ -123,22 +124,24 @@ CommandCost CmdStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, * - bit 0-4 Vehicle type * - bit 5 false = start vehicles, true = stop vehicles * - bit 6 if set, then it's a vehicle list window, not a depot and Tile is ignored in this case - * - bit 8-11 Vehicle List Window type (ignored unless bit 1 is set) + * - bit 8-11 Vehicle List Window type (ignored unless bit 6 is set) * @param text unused * @return the cost of this operation or an error */ CommandCost CmdMassStartStopVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { VehicleList list; - VehicleType vehicle_type = (VehicleType)GB(p2, 0, 5); + VehicleType vehicle_type = Extract(p2); bool start_stop = HasBit(p2, 5); bool vehicle_list_window = HasBit(p2, 6); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; + if (vehicle_list_window) { uint32 id = p1; uint16 window_type = p2 & VLW_MASK; - GenerateVehicleSortList(&list, vehicle_type, _current_company, id, window_type); + if (!GenerateVehicleSortList(&list, vehicle_type, _current_company, id, window_type)) return CMD_ERROR; } else { /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, NULL); @@ -177,9 +180,11 @@ CommandCost CmdDepotSellAllVehicles(TileIndex tile, DoCommandFlag flags, uint32 VehicleList list; CommandCost cost(EXPENSES_NEW_VEHICLES); - VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); + VehicleType vehicle_type = Extract(p1); uint sell_command = GetCmdSellVeh(vehicle_type); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; + /* Get the list of vehicles in the depot */ BuildDepotVehicleList(vehicle_type, tile, &list, &list); @@ -205,8 +210,9 @@ CommandCost CmdDepotMassAutoReplace(TileIndex tile, DoCommandFlag flags, uint32 { VehicleList list; CommandCost cost = CommandCost(EXPENSES_NEW_VEHICLES); - VehicleType vehicle_type = (VehicleType)GB(p1, 0, 8); + VehicleType vehicle_type = Extract(p1); + if (!IsCompanyBuildableVehicleType(vehicle_type)) return CMD_ERROR; if (!IsDepotTile(tile) || !IsTileOwner(tile, _current_company)) return CMD_ERROR; /* Get the list of vehicles in the depot */ @@ -395,7 +401,7 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint uint32 build_argument = 2; Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle()) return CMD_ERROR; Vehicle *v_front = v; Vehicle *w = NULL; Vehicle *w_front = NULL; @@ -580,7 +586,7 @@ CommandCost SendAllVehiclesToDepot(VehicleType type, DoCommandFlag flags, bool s { VehicleList list; - GenerateVehicleSortList(&list, type, owner, id, vlw_flag); + if (!GenerateVehicleSortList(&list, type, owner, id, vlw_flag)) return CMD_ERROR; /* Send all the vehicles to a depot */ for (uint i = 0; i < list.Length(); i++) { @@ -610,7 +616,7 @@ CommandCost SendAllVehiclesToDepot(VehicleType type, DoCommandFlag flags, bool s CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; bool reset = StrEmpty(text); @@ -641,7 +647,7 @@ CommandCost CmdRenameVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uin CommandCost CmdChangeServiceInt(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { Vehicle *v = Vehicle::GetIfValid(p1); - if (v == NULL || !CheckOwnership(v->owner)) return CMD_ERROR; + if (v == NULL || !v->IsPrimaryVehicle() || !CheckOwnership(v->owner)) return CMD_ERROR; uint16 serv_int = GetServiceIntervalClamped(p2, v->owner); // Double check the service interval from the user-input if (serv_int != p2) return CMD_ERROR; diff --git a/src/vehicle_type.h b/src/vehicle_type.h index e384761db8..e3d19fa033 100644 --- a/src/vehicle_type.h +++ b/src/vehicle_type.h @@ -28,6 +28,7 @@ enum VehicleType { VEH_INVALID = 0xFF, ///< Non-existing type of vehicle. }; DECLARE_POSTFIX_INCREMENT(VehicleType); +template <> struct EnumPropsT : MakeEnumPropsT {}; /** It needs to be 8bits, because we save and load it as such */ typedef SimpleTinyEnumT VehicleTypeByte; diff --git a/src/vehiclelist.cpp b/src/vehiclelist.cpp index 848fba1a9c..ce312ff090 100644 --- a/src/vehiclelist.cpp +++ b/src/vehiclelist.cpp @@ -76,8 +76,9 @@ void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine *
  • VLW_WAYPOINT_LIST: index of waypoint to generate a list for
  • * * @param window_type The type of window the list is for, using the VLW_ flags in vehicle_gui.h + * @return false if invalid list is requested */ -void GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, uint32 index, uint16 window_type) +bool GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, uint32 index, uint16 window_type) { list->Clear(); @@ -101,7 +102,10 @@ void GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, u case VLW_SHARED_ORDERS: /* Add all vehicles from this vehicle's shared order list */ - for (v = Vehicle::Get(index); v != NULL; v = v->NextShared()) { + v = Vehicle::GetIfValid(index); + if (v == NULL || v->type != type || !v->IsPrimaryVehicle()) return false; + + for (; v != NULL; v = v->NextShared()) { *list->Append() = v; } break; @@ -153,8 +157,9 @@ void GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, u } break; - default: NOT_REACHED(); + default: return false; } list->Compact(); + return true; } diff --git a/src/vehiclelist.h b/src/vehiclelist.h index 04caccb5a0..18357b9413 100644 --- a/src/vehiclelist.h +++ b/src/vehiclelist.h @@ -19,7 +19,7 @@ typedef SmallVector VehicleList; -void GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, uint32 index, uint16 window_type); +bool GenerateVehicleSortList(VehicleList *list, VehicleType type, Owner owner, uint32 index, uint16 window_type); void BuildDepotVehicleList(VehicleType type, TileIndex tile, VehicleList *engine_list, VehicleList *wagon_list, bool individual_wagons = false); #endif /* VEHICLELIST_H */ diff --git a/src/water_cmd.cpp b/src/water_cmd.cpp index 25d876792f..ad6426edfc 100644 --- a/src/water_cmd.cpp +++ b/src/water_cmd.cpp @@ -104,13 +104,9 @@ static void MarkCanalsAndRiversAroundDirty(TileIndex tile) */ CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { - TileIndex tile2; + Axis axis = Extract(p1); - CommandCost ret; - - Axis axis = Extract(p1); - - tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); + TileIndex tile2 = tile + (axis == AXIS_X ? TileDiffXY(1, 0) : TileDiffXY(0, 1)); if (!IsWaterTile(tile) || !IsWaterTile(tile2)) { return_cmd_error(STR_ERROR_MUST_BE_BUILT_ON_WATER); @@ -125,7 +121,7 @@ CommandCost CmdBuildShipDepot(TileIndex tile, DoCommandFlag flags, uint32 p1, ui WaterClass wc1 = GetWaterClass(tile); WaterClass wc2 = GetWaterClass(tile2); - ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); + CommandCost ret = DoCommand(tile, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return CMD_ERROR; ret = DoCommand(tile2, 0, 0, flags, CMD_LANDSCAPE_CLEAR); if (ret.Failed()) return CMD_ERROR; @@ -291,7 +287,7 @@ CommandCost CmdBuildCanal(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 { CommandCost cost(EXPENSES_CONSTRUCTION); - if (p1 >= MapSize()) return CMD_ERROR; + if (p1 >= MapSize() || p2 > 2) return CMD_ERROR; /* Outside of the editor you can only build canals, not oceans */ if (p2 != 0 && _game_mode != GM_EDITOR) return CMD_ERROR; diff --git a/src/waypoint_cmd.cpp b/src/waypoint_cmd.cpp index 64c5f5f4e9..3ccbc1f764 100644 --- a/src/waypoint_cmd.cpp +++ b/src/waypoint_cmd.cpp @@ -11,6 +11,7 @@ #include "stdafx.h" +#include "cmd_helper.h" #include "command_func.h" #include "landscape.h" #include "bridge_map.h" @@ -214,12 +215,12 @@ extern bool CanExpandRailStation(const BaseStation *st, TileArea &new_ta, Axis a CommandCost CmdBuildRailWaypoint(TileIndex start_tile, DoCommandFlag flags, uint32 p1, uint32 p2, const char *text) { /* Unpack parameters */ - Axis axis = (Axis)GB(p1, 4, 1); + Axis axis = Extract(p1); byte width = GB(p1, 8, 8); byte height = GB(p1, 16, 8); bool adjacent = HasBit(p1, 24); - StationClassID spec_class = (StationClassID)GB(p2, 0, 8); + StationClassID spec_class = Extract(p2); byte spec_index = GB(p2, 8, 8); StationID station_to_join = GB(p2, 16, 16);