diff options
author | frosch <frosch@openttd.org> | 2009-02-21 12:52:41 +0000 |
---|---|---|
committer | frosch <frosch@openttd.org> | 2009-02-21 12:52:41 +0000 |
commit | d3850e101c7deb3d6549dae3dcad9daa90c40946 (patch) | |
tree | 62e06798cf27a41c73412fa15906f2df18c9826c | |
parent | b674d1f6f5c680d42c3297f1a79a87a124d0e52d (diff) | |
download | openttd-d3850e101c7deb3d6549dae3dcad9daa90c40946.tar.xz |
(svn r15541) -Revert (r15399): 'v->cargo_type' is also used in other places, which cannot accept CT_INVALID.
-Codechange: Add Engine::GetDefaultCargoType() and Engine::CanCarryCargo() and use them.
-Fix [FS#2617]: When articulated parts have no available default cargo, use the cargo type of the first part for livery selection.
-Change: To decide whether a vehicle is refittable do not test its current capacity for being zero, but always use the 'capacity property'.
Note: The property is used unmodifed without calling CB 15/36. By setting it to a non-zero value and returning zero in the callback vehicles can be refitted to/from zero capacity for e.g. livery effects.
Note: It is intentional that you cannot control refittability by CB 36.
-rw-r--r-- | bin/ai/regression/regression.txt | 6 | ||||
-rw-r--r-- | src/ai/api/ai_engine.cpp | 24 | ||||
-rw-r--r-- | src/ai/api/ai_event_types.cpp | 25 | ||||
-rw-r--r-- | src/aircraft_cmd.cpp | 15 | ||||
-rw-r--r-- | src/articulated_vehicles.cpp | 68 | ||||
-rw-r--r-- | src/build_vehicle_gui.cpp | 8 | ||||
-rw-r--r-- | src/engine.cpp | 93 | ||||
-rw-r--r-- | src/engine_base.h | 2 | ||||
-rw-r--r-- | src/engine_func.h | 1 | ||||
-rw-r--r-- | src/engine_gui.cpp | 15 | ||||
-rw-r--r-- | src/newgrf_engine.cpp | 5 | ||||
-rw-r--r-- | src/roadveh_cmd.cpp | 16 | ||||
-rw-r--r-- | src/ship_cmd.cpp | 5 | ||||
-rw-r--r-- | src/train_cmd.cpp | 28 | ||||
-rw-r--r-- | src/vehicle.cpp | 23 |
15 files changed, 171 insertions, 163 deletions
diff --git a/bin/ai/regression/regression.txt b/bin/ai/regression/regression.txt index 7cb4a3848..47c52a3fb 100644 --- a/bin/ai/regression/regression.txt +++ b/bin/ai/regression/regression.txt @@ -1085,7 +1085,7 @@ Engine 0 IsValidEngine(): true GetName(): Kirby Paul Tank (Steam) - GetCargoType(): 0 + GetCargoType(): 255 CanRefitCargo(): false GetCapacity(): -1 GetReliability(): 75 @@ -1229,7 +1229,7 @@ Engine 8 IsValidEngine(): true GetName(): Chaney 'Jubilee' (Steam) - GetCargoType(): 0 + GetCargoType(): 255 CanRefitCargo(): false GetCapacity(): -1 GetReliability(): 79 @@ -1247,7 +1247,7 @@ Engine 9 IsValidEngine(): true GetName(): Ginzu 'A4' (Steam) - GetCargoType(): 0 + GetCargoType(): 255 CanRefitCargo(): false GetCapacity(): -1 GetReliability(): 83 diff --git a/src/ai/api/ai_engine.cpp b/src/ai/api/ai_engine.cpp index c6bee2bb6..3a2621299 100644 --- a/src/ai/api/ai_engine.cpp +++ b/src/ai/api/ai_engine.cpp @@ -33,28 +33,10 @@ { if (!IsValidEngine(engine_id)) return CT_INVALID; - switch (::GetEngine(engine_id)->type) { - case VEH_ROAD: { - const RoadVehicleInfo *vi = ::RoadVehInfo(engine_id); - return vi->cargo_type; - } break; - - case VEH_TRAIN: { - const RailVehicleInfo *vi = ::RailVehInfo(engine_id); - return vi->cargo_type; - } break; - - case VEH_SHIP: { - const ShipVehicleInfo *vi = ::ShipVehInfo(engine_id); - return vi->cargo_type; - } break; - - case VEH_AIRCRAFT: { - return CT_PASSENGERS; - } break; + const Engine *e = ::GetEngine(engine_id); + if (!e->CanCarryCargo()) return CT_INVALID; - default: NOT_REACHED(); - } + return e->GetDefaultCargoType(); } /* static */ bool AIEngine::CanRefitCargo(EngineID engine_id, CargoID cargo_id) diff --git a/src/ai/api/ai_event_types.cpp b/src/ai/api/ai_event_types.cpp index d3e0b4d83..4c66ceadb 100644 --- a/src/ai/api/ai_event_types.cpp +++ b/src/ai/api/ai_event_types.cpp @@ -21,28 +21,9 @@ char *AIEventEnginePreview::GetName() CargoID AIEventEnginePreview::GetCargoType() { - switch (::GetEngine(engine)->type) { - case VEH_ROAD: { - const RoadVehicleInfo *vi = ::RoadVehInfo(engine); - return vi->cargo_type; - } break; - - case VEH_TRAIN: { - const RailVehicleInfo *vi = ::RailVehInfo(engine); - return vi->cargo_type; - } break; - - case VEH_SHIP: { - const ShipVehicleInfo *vi = ::ShipVehInfo(engine); - return vi->cargo_type; - } break; - - case VEH_AIRCRAFT: { - return CT_PASSENGERS; - } break; - - default: NOT_REACHED(); - } + const Engine *e = ::GetEngine(engine); + if (!e->CanCarryCargo()) return CT_INVALID; + return e->GetDefaultCargoType(); } int32 AIEventEnginePreview::GetCapacity() diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp index 200e83653..fc3307218 100644 --- a/src/aircraft_cmd.cpp +++ b/src/aircraft_cmd.cpp @@ -254,6 +254,9 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin const Engine *e = GetEngine(p1); CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); + /* Engines without valid cargo should not be available */ + if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; + /* to just query the cost, it is not neccessary to have a valid tile (automation/AI) */ if (flags & DC_QUERY_COST) return value; @@ -309,7 +312,7 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin v->cargo_cap = avi->passenger_capacity; u->cargo_cap = avi->mail_capacity; - v->cargo_type = CT_PASSENGERS; + v->cargo_type = e->GetDefaultCargoType(); u->cargo_type = CT_MAIL; v->cargo_subtype = 0; @@ -334,17 +337,9 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, uint32 p1, uin u->subtype = AIR_SHADOW; u->UpdateDeltaXY(INVALID_DIR); - /* Danger, Will Robinson! - * If the aircraft is refittable, but cannot be refitted to - * passengers, we select the cargo type from the refit mask. - * This is a fairly nasty hack to get around the fact that TTD - * has no default cargo type specifier for planes... */ - CargoID cargo = FindFirstRefittableCargo(p1); - if (cargo != CT_INVALID && cargo != CT_PASSENGERS) { + if (v->cargo_type != CT_PASSENGERS) { uint16 callback = CALLBACK_FAILED; - v->cargo_type = cargo; - if (HasBit(EngInfo(p1)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { callback = GetVehicleCallback(CBID_VEHICLE_REFIT_CAPACITY, 0, 0, v->engine_type, v); } diff --git a/src/articulated_vehicles.cpp b/src/articulated_vehicles.cpp index 0c4eeec8e..ac894f362 100644 --- a/src/articulated_vehicles.cpp +++ b/src/articulated_vehicles.cpp @@ -5,6 +5,7 @@ #include "stdafx.h" #include "train.h" #include "roadveh.h" +#include "aircraft.h" #include "newgrf_engine.h" #include "vehicle_func.h" @@ -45,30 +46,22 @@ uint CountArticulatedParts(EngineID engine_type, bool purchase_window) */ static inline uint16 GetVehicleDefaultCapacity(EngineID engine, VehicleType type, CargoID *cargo_type) { + const Engine *e = GetEngine(engine); + CargoID cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID); + if (cargo_type != NULL) *cargo_type = cargo; + if (cargo == CT_INVALID) return 0; switch (type) { - case VEH_TRAIN: { - const RailVehicleInfo *rvi = RailVehInfo(engine); - if (cargo_type != NULL) *cargo_type = rvi->cargo_type; - return GetEngineProperty(engine, 0x14, rvi->capacity) + (rvi->railveh_type == RAILVEH_MULTIHEAD ? rvi->capacity : 0); - } + case VEH_TRAIN: + return GetEngineProperty(engine, 0x14, e->u.rail.capacity) + (e->u.rail.railveh_type == RAILVEH_MULTIHEAD ? e->u.rail.capacity : 0); - case VEH_ROAD: { - const RoadVehicleInfo *rvi = RoadVehInfo(engine); - if (cargo_type != NULL) *cargo_type = rvi->cargo_type; - return GetEngineProperty(engine, 0x0F, rvi->capacity); - } + case VEH_ROAD: + return GetEngineProperty(engine, 0x0F, e->u.road.capacity); - case VEH_SHIP: { - const ShipVehicleInfo *svi = ShipVehInfo(engine); - if (cargo_type != NULL) *cargo_type = svi->cargo_type; - return GetEngineProperty(engine, 0x0D, svi->capacity); - } + case VEH_SHIP: + return GetEngineProperty(engine, 0x0D, e->u.ship.capacity); - case VEH_AIRCRAFT: { - const AircraftVehicleInfo *avi = AircraftVehInfo(engine); - if (cargo_type != NULL) *cargo_type = CT_PASSENGERS; - return avi->passenger_capacity; - } + case VEH_AIRCRAFT: + return AircraftDefaultCargoCapacity(cargo, &e->u.air); default: NOT_REACHED(); } @@ -264,28 +257,30 @@ void AddArticulatedParts(Vehicle **vl, VehicleType type) u->cur_image = 0xAC2; u->random_bits = VehicleRandomBits(); + const Engine *e_artic = GetEngine(engine_type); switch (type) { default: NOT_REACHED(); - case VEH_TRAIN: { - const RailVehicleInfo *rvi_artic = RailVehInfo(engine_type); - + case VEH_TRAIN: u = new (u) Train(); previous->SetNext(u); u->u.rail.track = v->u.rail.track; u->u.rail.railtype = v->u.rail.railtype; u->u.rail.first_engine = v->engine_type; - u->spritenum = rvi_artic->image_index; - u->cargo_type = rvi_artic->cargo_type; - u->cargo_cap = rvi_artic->capacity; // Callback 36 is called when the consist is finished + u->spritenum = e_artic->u.rail.image_index; + if (e_artic->CanCarryCargo()) { + u->cargo_type = e_artic->GetDefaultCargoType(); + u->cargo_cap = e_artic->u.rail.capacity; // Callback 36 is called when the consist is finished + } else { + u->cargo_type = v->cargo_type; // Needed for livery selection + u->cargo_cap = 0; + } SetArticulatedPart(u); - } break; - - case VEH_ROAD: { - const RoadVehicleInfo *rvi_artic = RoadVehInfo(engine_type); + break; + case VEH_ROAD: u = new (u) RoadVehicle(); previous->SetNext(u); u->u.road.first_engine = v->engine_type; @@ -295,12 +290,17 @@ void AddArticulatedParts(Vehicle **vl, VehicleType type) u->u.road.roadtype = v->u.road.roadtype; u->u.road.compatible_roadtypes = v->u.road.compatible_roadtypes; - u->spritenum = rvi_artic->image_index; - u->cargo_type = rvi_artic->cargo_type; - u->cargo_cap = rvi_artic->capacity; // Callback 36 is called when the consist is finished + u->spritenum = e_artic->u.road.image_index; + if (e_artic->CanCarryCargo()) { + u->cargo_type = e_artic->GetDefaultCargoType(); + u->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished + } else { + u->cargo_type = v->cargo_type; // Needed for livery selection + u->cargo_cap = 0; + } SetRoadVehArticPart(u); - } break; + break; } if (flip_image) u->spritenum++; diff --git a/src/build_vehicle_gui.cpp b/src/build_vehicle_gui.cpp index feb01a051..888091e04 100644 --- a/src/build_vehicle_gui.cpp +++ b/src/build_vehicle_gui.cpp @@ -484,7 +484,8 @@ static int DrawRailWagonPurchaseInfo(int x, int y, EngineID engine_number, const /* Wagon weight - (including cargo) */ uint weight = e->GetDisplayWeight(); SetDParam(0, weight); - SetDParam(1, (GetCargo(rvi->cargo_type)->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4) + weight); + uint cargo_weight = (e->CanCarryCargo() ? GetCargo(e->GetDefaultCargoType())->weight * GetEngineProperty(engine_number, 0x14, rvi->capacity) >> 4 : 0); + SetDParam(1, cargo_weight + weight); DrawString(x, y, STR_PURCHASE_INFO_WEIGHT_CWEIGHT, TC_FROMSTRING); y += 10; @@ -582,7 +583,7 @@ static int DrawShipPurchaseInfo(int x, int y, EngineID engine_number, const Ship y += 10; /* Cargo type + capacity */ - SetDParam(0, svi->cargo_type); + SetDParam(0, e->GetDefaultCargoType()); SetDParam(1, GetEngineProperty(engine_number, 0x0D, svi->capacity)); SetDParam(2, IsEngineRefittable(engine_number) ? STR_9842_REFITTABLE : STR_EMPTY); DrawString(x, y, STR_PURCHASE_INFO_CAPACITY, TC_FROMSTRING); @@ -599,8 +600,8 @@ static int DrawShipPurchaseInfo(int x, int y, EngineID engine_number, const Ship /* Draw aircraft specific details */ static int DrawAircraftPurchaseInfo(int x, int y, EngineID engine_number, const AircraftVehicleInfo *avi) { - CargoID cargo; const Engine *e = GetEngine(engine_number); + CargoID cargo = e->GetDefaultCargoType(); /* Purchase cost - Max speed */ SetDParam(0, e->GetCost()); @@ -609,7 +610,6 @@ static int DrawAircraftPurchaseInfo(int x, int y, EngineID engine_number, const y += 10; /* Cargo capacity */ - cargo = FindFirstRefittableCargo(engine_number); if (cargo == CT_INVALID || cargo == CT_PASSENGERS) { SetDParam(0, avi->passenger_capacity); SetDParam(1, avi->mail_capacity); diff --git a/src/engine.cpp b/src/engine.cpp index 8373d9430..d48b23bff 100644 --- a/src/engine.cpp +++ b/src/engine.cpp @@ -113,6 +113,66 @@ Engine::~Engine() free(this->name); } +/** + * Determines the default cargo type of an engine. + * + * Usually a valid cargo is returned, even though the vehicle has zero capacity, and can therefore not carry anything. But the cargotype is still used + * for livery selection etc.. + * + * Vehicles with CT_INVALID as default cargo are usally not available, but it can appear as default cargo of articulated parts. + * + * @return The default cargo type. + * @see CanCarryCargo + */ +CargoID Engine::GetDefaultCargoType() const +{ + switch (this->type) { + case VEH_TRAIN: + return this->u.rail.cargo_type; + + case VEH_ROAD: + return this->u.road.cargo_type; + + case VEH_SHIP: + return this->u.ship.cargo_type; + + case VEH_AIRCRAFT: + return FindFirstRefittableCargo(this->index); + + default: NOT_REACHED(); + } +} + +/** + * Determines whether an engine can carry something. + * A vehicle cannot carry anything if its capacity is zero, or none of the possible cargos is available in the climate. + * @return true if the vehicle can carry something. + */ +bool Engine::CanCarryCargo() const +{ + /* For engines that can appear in a consist (i.e. rail vehicles and (articulated) road vehicles), a capacity + * of zero is a special case, to define the vehicle to not carry anything. The default cargotype is still used + * for livery selection etc. + * Note: Only the property is tested. A capacity callback returning 0 does not have the same effect. + */ + switch (this->type) { + case VEH_TRAIN: + if (this->u.rail.capacity == 0) return false; + break; + + case VEH_ROAD: + if (this->u.road.capacity == 0) return false; + break; + + case VEH_SHIP: + case VEH_AIRCRAFT: + break; + + default: NOT_REACHED(); + } + return this->GetDefaultCargoType() != CT_INVALID; +} + Money Engine::GetRunningCost() const { switch (this->type) { @@ -668,6 +728,8 @@ bool IsEngineRefittable(EngineID engine) if (e->type == VEH_SHIP && !e->u.ship.refittable) return false; + if (!e->CanCarryCargo()) return false; + const EngineInfo *ei = &e->info; if (ei->refit_mask == 0) return false; @@ -676,35 +738,6 @@ bool IsEngineRefittable(EngineID engine) if (HasBit(ei->callbackmask, CBM_VEHICLE_CARGO_SUFFIX)) return true; /* Is there any cargo except the default cargo? */ - CargoID default_cargo = GetEngineCargoType(engine); + CargoID default_cargo = e->GetDefaultCargoType(); return default_cargo != CT_INVALID && ei->refit_mask != 1U << default_cargo; } - -/** Get the default cargo type for a certain engine type - * @param engine The ID to get the cargo for - * @return The cargo type. CT_INVALID means no cargo capacity - */ -CargoID GetEngineCargoType(EngineID engine) -{ - assert(IsEngineIndex(engine)); - - switch (GetEngine(engine)->type) { - case VEH_TRAIN: - if (RailVehInfo(engine)->capacity == 0) return CT_INVALID; - return RailVehInfo(engine)->cargo_type; - - case VEH_ROAD: - if (RoadVehInfo(engine)->capacity == 0) return CT_INVALID; - return RoadVehInfo(engine)->cargo_type; - - case VEH_SHIP: - if (ShipVehInfo(engine)->capacity == 0) return CT_INVALID; - return ShipVehInfo(engine)->cargo_type; - - case VEH_AIRCRAFT: - /* all aircraft starts as passenger planes with cargo capacity */ - return CT_PASSENGERS; - - default: NOT_REACHED(); return CT_INVALID; - } -} diff --git a/src/engine_base.h b/src/engine_base.h index dbbb2c308..34852dc59 100644 --- a/src/engine_base.h +++ b/src/engine_base.h @@ -50,6 +50,8 @@ struct Engine : PoolItem<Engine, EngineID, &_Engine_pool> { inline bool IsValid() const { return this->info.climates != 0; } + CargoID GetDefaultCargoType() const; + bool CanCarryCargo() const; Money GetRunningCost() const; Money GetCost() const; uint GetDisplayMaxSpeed() const; diff --git a/src/engine_func.h b/src/engine_func.h index 1117311cb..65e88fe31 100644 --- a/src/engine_func.h +++ b/src/engine_func.h @@ -21,7 +21,6 @@ void DrawAircraftEngine(int x, int y, EngineID engine, SpriteID pal); bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company); bool IsEngineRefittable(EngineID engine); -CargoID GetEngineCargoType(EngineID engine); void SetCachedEngineCounts(); void SetYearEngineAgingStops(); void StartupOneEngine(Engine *e, Date aging_date); diff --git a/src/engine_gui.cpp b/src/engine_gui.cpp index 5487f5686..ce20e8756 100644 --- a/src/engine_gui.cpp +++ b/src/engine_gui.cpp @@ -123,7 +123,6 @@ static uint GetTotalCapacityOfArticulatedParts(EngineID engine, VehicleType type static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw) { - const RailVehicleInfo *rvi = RailVehInfo(engine); const Engine *e = GetEngine(engine); SetDParam(0, e->GetCost()); @@ -135,7 +134,7 @@ static void DrawTrainEngineInfo(EngineID engine, int x, int y, int maxw) uint capacity = GetTotalCapacityOfArticulatedParts(engine, VEH_TRAIN); if (capacity != 0) { - SetDParam(5, rvi->cargo_type); + SetDParam(5, e->GetDefaultCargoType()); SetDParam(6, capacity); } else { SetDParam(5, CT_INVALID); @@ -159,14 +158,18 @@ static void DrawAircraftEngineInfo(EngineID engine, int x, int y, int maxw) static void DrawRoadVehEngineInfo(EngineID engine, int x, int y, int maxw) { - const RoadVehicleInfo *rvi = RoadVehInfo(engine); const Engine *e = GetEngine(engine); SetDParam(0, e->GetCost()); SetDParam(1, e->GetDisplayMaxSpeed()); SetDParam(2, e->GetRunningCost()); - SetDParam(3, rvi->cargo_type); - SetDParam(4, GetTotalCapacityOfArticulatedParts(engine, VEH_ROAD)); + uint capacity = GetTotalCapacityOfArticulatedParts(engine, VEH_ROAD); + if (capacity != 0) { + SetDParam(3, e->GetDefaultCargoType()); + SetDParam(4, capacity); + } else { + SetDParam(3, CT_INVALID); + } DrawStringMultiCenter(x, y, STR_902A_COST_SPEED_RUNNING_COST, maxw); } @@ -178,7 +181,7 @@ static void DrawShipEngineInfo(EngineID engine, int x, int y, int maxw) SetDParam(0, e->GetCost()); SetDParam(1, e->GetDisplayMaxSpeed()); - SetDParam(2, svi->cargo_type); + SetDParam(2, e->GetDefaultCargoType()); SetDParam(3, GetEngineProperty(engine, 0x0D, svi->capacity)); SetDParam(4, e->GetRunningCost()); DrawStringMultiCenter(x, y, STR_982E_COST_MAX_SPEED_CAPACITY, maxw); diff --git a/src/newgrf_engine.cpp b/src/newgrf_engine.cpp index d05130ee9..bf64c95f8 100644 --- a/src/newgrf_engine.cpp +++ b/src/newgrf_engine.cpp @@ -850,12 +850,7 @@ static const SpriteGroup *GetVehicleSpriteGroup(EngineID engine, const Vehicle * const Engine *e = GetEngine(engine); - /* Engines are not available, when their cargo is not available. - * But that does not apply to articulated parts. */ - if (cargo == CT_INVALID) cargo = CT_DEFAULT; - assert(cargo < lengthof(e->group)); - group = e->group[cargo]; if (group != NULL) return group; diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp index a15581a47..7878a9d05 100644 --- a/src/roadveh_cmd.cpp +++ b/src/roadveh_cmd.cpp @@ -166,6 +166,9 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (!IsEngineBuildable(p1, VEH_ROAD, _current_company)) return_cmd_error(STR_ROAD_VEHICLE_NOT_AVAILABLE); const Engine *e = GetEngine(p1); + /* Engines without valid cargo should not be available */ + if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; + CommandCost cost(EXPENSES_NEW_VEHICLES, e->GetCost()); if (flags & DC_QUERY_COST) return cost; @@ -217,7 +220,7 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; v->spritenum = rvi->image_index; - v->cargo_type = rvi->cargo_type; + v->cargo_type = e->GetDefaultCargoType(); v->cargo_subtype = 0; v->cargo_cap = rvi->capacity; // v->cargo_count = 0; @@ -262,7 +265,8 @@ CommandCost CmdBuildRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint /* Call callback 36s after the whole consist has been constructed */ for (Vehicle *u = v; u != NULL; u = u->Next()) { - u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap); + /* Cargo capacity is zero if and only if the vehicle cannot carry anything */ + if (u->cargo_cap != 0) u->cargo_cap = GetVehicleProperty(u, 0x0F, u->cargo_cap); } VehiclePositionChanged(v); @@ -2009,7 +2013,8 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint * [Refit] button near each wagon. */ if (!CanRefitTo(v->engine_type, new_cid)) continue; - if (v->cargo_cap == 0) continue; + const Engine *e = GetEngine(v->engine_type); + if (!e->CanCarryCargo()) continue; if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { /* Back up the cargo type */ @@ -2028,14 +2033,13 @@ CommandCost CmdRefitRoadVeh(TileIndex tile, DoCommandFlag flags, uint32 p1, uint if (capacity == CALLBACK_FAILED) { /* callback failed or not used, use default capacity */ - const RoadVehicleInfo *rvi = RoadVehInfo(v->engine_type); - CargoID old_cid = rvi->cargo_type; + CargoID old_cid = e->GetDefaultCargoType(); /* normally, the capacity depends on the cargo type, a vehicle can * carry twice as much mail/goods as normal cargo, and four times as * many passengers */ - capacity = GetVehicleProperty(v, 0x0F, rvi->capacity); + capacity = GetVehicleProperty(v, 0x0F, e->u.road.capacity); switch (old_cid) { case CT_PASSENGERS: break; case CT_MAIL: diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp index cb3949b7f..10d962357 100644 --- a/src/ship_cmd.cpp +++ b/src/ship_cmd.cpp @@ -737,6 +737,9 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 const Engine *e = GetEngine(p1); CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); + /* Engines without valid cargo should not be available */ + if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; + if (flags & DC_QUERY_COST) return value; /* The ai_new queries the vehicle cost before building the route, @@ -772,7 +775,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, uint32 p1, uint32 v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; v->spritenum = svi->image_index; - v->cargo_type = svi->cargo_type; + v->cargo_type = e->GetDefaultCargoType(); v->cargo_subtype = 0; v->cargo_cap = svi->capacity; v->value = value.GetCost(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 43159297c..008cbfb42 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -265,7 +265,8 @@ void TrainConsistChanged(Vehicle *v, bool same_length) } for (Vehicle *u = v; u != NULL; u = u->Next()) { - const RailVehicleInfo *rvi_u = RailVehInfo(u->engine_type); + const Engine *e_u = GetEngine(u->engine_type); + const RailVehicleInfo *rvi_u = &e_u->u.rail; if (!HasBit(EngInfo(u->engine_type)->misc_flags, EF_RAIL_TILTS)) train_can_tilt = false; @@ -326,7 +327,7 @@ void TrainConsistChanged(Vehicle *v, bool same_length) } } - if (u->cargo_type == rvi_u->cargo_type && u->cargo_subtype == 0) { + if (e_u->CanCarryCargo() && u->cargo_type == e_u->GetDefaultCargoType() && u->cargo_subtype == 0) { /* Set cargo capacity if we've not been refitted */ u->cargo_cap = GetVehicleProperty(u, 0x14, rvi_u->capacity); } @@ -581,8 +582,12 @@ void DrawTrainEngine(int x, int y, EngineID engine, SpriteID pal) static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandFlag flags) { - const RailVehicleInfo *rvi = RailVehInfo(engine); - CommandCost value(EXPENSES_NEW_VEHICLES, GetEngine(engine)->GetCost()); + const Engine *e = GetEngine(engine); + const RailVehicleInfo *rvi = &e->u.rail; + CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); + + /* Engines without valid cargo should not be available */ + if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; if (flags & DC_QUERY_COST) return value; @@ -643,7 +648,7 @@ static CommandCost CmdBuildRailWagon(EngineID engine, TileIndex tile, DoCommandF InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile); } - v->cargo_type = rvi->cargo_type; + v->cargo_type = e->GetDefaultCargoType(); // v->cargo_subtype = 0; v->cargo_cap = rvi->capacity; v->value = value.GetCost(); @@ -733,6 +738,9 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, const Engine *e = GetEngine(p1); CommandCost value(EXPENSES_NEW_VEHICLES, e->GetCost()); + /* Engines with CT_INVALID should not be available */ + if (e->GetDefaultCargoType() == CT_INVALID) return CMD_ERROR; + if (flags & DC_QUERY_COST) return value; /* Check if the train is actually being built in a depot belonging @@ -783,7 +791,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, v->u.rail.track = TRACK_BIT_DEPOT; v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL; v->spritenum = rvi->image_index; - v->cargo_type = rvi->cargo_type; + v->cargo_type = e->GetDefaultCargoType(); // v->cargo_subtype = 0; v->cargo_cap = rvi->capacity; v->max_speed = rvi->max_speed; @@ -2015,7 +2023,8 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, * some nice [Refit] button near each wagon. --pasky */ if (!CanRefitTo(v->engine_type, new_cid)) continue; - if (v->cargo_cap != 0) { + const Engine *e = GetEngine(v->engine_type); + if (e->CanCarryCargo()) { uint16 amount = CALLBACK_FAILED; if (HasBit(EngInfo(v->engine_type)->callbackmask, CBM_VEHICLE_REFIT_CAPACITY)) { @@ -2032,13 +2041,12 @@ CommandCost CmdRefitRailVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, } if (amount == CALLBACK_FAILED) { // callback failed or not used, use default - const RailVehicleInfo *rvi = RailVehInfo(v->engine_type); - CargoID old_cid = rvi->cargo_type; + CargoID old_cid = e->GetDefaultCargoType(); /* normally, the capacity depends on the cargo type, a rail vehicle can * carry twice as much mail/goods as normal cargo, and four times as * many passengers */ - amount = rvi->capacity; + amount = e->u.rail.capacity; switch (old_cid) { case CT_PASSENGERS: break; case CT_MAIL: diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 5dc223b94..0ca03f3b6 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1296,7 +1296,8 @@ CommandCost CmdCloneVehicle(TileIndex tile, DoCommandFlag flags, uint32 p1, uint break; } } else { - CargoID initial_cargo = GetEngineCargoType(v->engine_type); + const Engine *e = GetEngine(v->engine_type); + CargoID initial_cargo = (e->CanCarryCargo() ? e->GetDefaultCargoType() : (CargoID)CT_INVALID); if (v->cargo_type != initial_cargo && initial_cargo != CT_INVALID) { total_cost.AddCost(GetRefitCost(v->engine_type)); @@ -1828,7 +1829,8 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID * whether any _other_ liveries are in use. */ if (c->livery[LS_DEFAULT].in_use && (_settings_client.gui.liveries == 2 || (_settings_client.gui.liveries == 1 && company == _local_company))) { /* Determine the livery scheme to use */ - switch (GetEngine(engine_type)->type) { + const Engine *e = GetEngine(engine_type); + switch (e->type) { default: NOT_REACHED(); case VEH_TRAIN: { const RailVehicleInfo *rvi = RailVehInfo(engine_type); @@ -1836,11 +1838,13 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID /* Wagonoverrides use the coloir scheme of the front engine. * Articulated parts use the colour scheme of the first part. (Not supported for articulated wagons) */ engine_type = parent_engine_type; + e = GetEngine(engine_type); rvi = RailVehInfo(engine_type); /* Note: Luckily cargo_type is not needed for engines */ } - if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type; + if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType(); + if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo if (rvi->railveh_type == RAILVEH_WAGON) { if (!GetCargo(cargo_type)->is_freight) { if (parent_engine_type == INVALID_ENGINE) { @@ -1877,10 +1881,11 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID /* Always use the livery of the front */ if (v != NULL && parent_engine_type != INVALID_ENGINE) { engine_type = parent_engine_type; + e = GetEngine(engine_type); cargo_type = v->First()->cargo_type; } - const RoadVehicleInfo *rvi = RoadVehInfo(engine_type); - if (cargo_type == CT_INVALID) cargo_type = rvi->cargo_type; + if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType(); + if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo /* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */ if (HasBit(EngInfo(engine_type)->misc_flags, EF_ROAD_TRAM)) { @@ -1894,16 +1899,14 @@ const Livery *GetEngineLivery(EngineID engine_type, CompanyID company, EngineID } case VEH_SHIP: { - const ShipVehicleInfo *svi = ShipVehInfo(engine_type); - if (cargo_type == CT_INVALID) cargo_type = svi->cargo_type; + if (cargo_type == CT_INVALID) cargo_type = e->GetDefaultCargoType(); + if (cargo_type == CT_INVALID) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo scheme = IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP; break; } case VEH_AIRCRAFT: { - const AircraftVehicleInfo *avi = AircraftVehInfo(engine_type); - if (cargo_type == CT_INVALID) cargo_type = CT_PASSENGERS; - switch (avi->subtype) { + switch (e->u.air.subtype) { case AIR_HELI: scheme = LS_HELICOPTER; break; case AIR_CTOL: scheme = LS_SMALL_PLANE; break; case AIR_CTOL | AIR_FAST: scheme = LS_LARGE_PLANE; break; |