summaryrefslogtreecommitdiff
path: root/src/newgrf.cpp
diff options
context:
space:
mode:
authorfrosch <frosch@openttd.org>2021-04-30 21:15:27 +0200
committerfrosch <github@elsenhans.name>2021-05-13 23:28:43 +0200
commit1da0ba95b2ca102b49a816b46ba7999ddc6a2858 (patch)
treeac36934ce4d0eb2f6d713b1d55aa223f711393b3 /src/newgrf.cpp
parent9f8d0b1bee104471aff1a5e318b2a92bc235d934 (diff)
downloadopenttd-1da0ba95b2ca102b49a816b46ba7999ddc6a2858.tar.xz
Feature: Define refittability of default vehicles using cargo classes.
This ensures that default vehicles can transport any NewGRF defined cargos, albeit with weird graphics and vehicle names. This also changes the refittability of default vehicles with default industries.
Diffstat (limited to 'src/newgrf.cpp')
-rw-r--r--src/newgrf.cpp147
1 files changed, 89 insertions, 58 deletions
diff --git a/src/newgrf.cpp b/src/newgrf.cpp
index dd03e2327..29b6a4903 100644
--- a/src/newgrf.cpp
+++ b/src/newgrf.cpp
@@ -8725,64 +8725,115 @@ GRFFile::~GRFFile()
/**
- * List of what cargo labels are refittable for the given the vehicle-type.
- * Only currently active labels are applied.
- */
-static const CargoLabel _default_refitmasks_rail[] = {
- 'PASS', 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD',
- 'IORE', 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE',
- 'WATR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
- 'PLST', 'FZDR',
- 0 };
-
-static const CargoLabel _default_refitmasks_road[] = {
- 0 };
-
-static const CargoLabel _default_refitmasks_ships[] = {
- 'COAL', 'MAIL', 'LVST', 'GOOD', 'GRAI', 'WHEA', 'MAIZ', 'WOOD', 'IORE',
- 'STEL', 'VALU', 'GOLD', 'DIAM', 'PAPR', 'FOOD', 'FRUT', 'CORE', 'WATR',
- 'RUBR', 'SUGR', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL',
- 'PLST', 'FZDR',
- 0 };
-
-static const CargoLabel _default_refitmasks_aircraft[] = {
- 'PASS', 'MAIL', 'GOOD', 'VALU', 'GOLD', 'DIAM', 'FOOD', 'FRUT', 'SUGR',
- 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR',
- 0 };
-
-static const CargoLabel * const _default_refitmasks[] = {
- _default_refitmasks_rail,
- _default_refitmasks_road,
- _default_refitmasks_ships,
- _default_refitmasks_aircraft,
-};
-
-
-/**
* Precalculate refit masks from cargo classes for all vehicles.
*/
static void CalculateRefitMasks()
{
+ CargoTypes original_known_cargoes = 0;
+ for (int ct = 0; ct != NUM_ORIGINAL_CARGO; ++ct) {
+ CargoID cid = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ct));
+ if (cid != CT_INVALID) SetBit(original_known_cargoes, cid);
+ }
+
for (Engine *e : Engine::Iterate()) {
EngineID engine = e->index;
EngineInfo *ei = &e->info;
bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo
- /* If the NewGRF did not set any cargo properties, we apply default cargo translation. */
+ /* If the NewGRF did not set any cargo properties, we apply default values. */
if (_gted[engine].defaultcargo_grf == nullptr) {
+ /* If the vehicle has any capacity, apply the default refit masks */
+ if (e->type != VEH_TRAIN || e->u.rail.capacity != 0) {
+ static constexpr byte T = 1 << LT_TEMPERATE;
+ static constexpr byte A = 1 << LT_ARCTIC;
+ static constexpr byte S = 1 << LT_TROPIC;
+ static constexpr byte Y = 1 << LT_TOYLAND;
+ static const struct DefaultRefitMasks {
+ byte climate;
+ CargoType cargo_type;
+ CargoTypes cargo_allowed;
+ CargoTypes cargo_disallowed;
+ } _default_refit_masks[] = {
+ {T | A | S | Y, CT_PASSENGERS, CC_PASSENGERS, 0},
+ {T | A | S , CT_MAIL, CC_MAIL, 0},
+ {T | A | S , CT_VALUABLES, CC_ARMOURED, CC_LIQUID},
+ { Y, CT_MAIL, CC_MAIL | CC_ARMOURED, CC_LIQUID},
+ {T | A , CT_COAL, CC_BULK, 0},
+ { S , CT_COPPER_ORE, CC_BULK, 0},
+ { Y, CT_SUGAR, CC_BULK, 0},
+ {T | A | S , CT_OIL, CC_LIQUID, 0},
+ { Y, CT_COLA, CC_LIQUID, 0},
+ {T , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
+ { A | S , CT_GOODS, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS | CC_REFRIGERATED},
+ { A | S , CT_FOOD, CC_REFRIGERATED, 0},
+ { Y, CT_CANDY, CC_PIECE_GOODS | CC_EXPRESS, CC_LIQUID | CC_PASSENGERS},
+ };
+
+ if (e->type == VEH_AIRCRAFT) {
+ /* Aircraft default to "light" cargoes */
+ _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS;
+ _gted[engine].cargo_disallowed = CC_LIQUID;
+ } else if (e->type == VEH_SHIP) {
+ switch (ei->cargo_type) {
+ case CT_PASSENGERS:
+ /* Ferries */
+ _gted[engine].cargo_allowed = CC_PASSENGERS;
+ _gted[engine].cargo_disallowed = 0;
+ break;
+ case CT_OIL:
+ /* Tankers */
+ _gted[engine].cargo_allowed = CC_LIQUID;
+ _gted[engine].cargo_disallowed = 0;
+ break;
+ default:
+ /* Cargo ships */
+ if (_settings_game.game_creation.landscape == LT_TOYLAND) {
+ /* No tanker in toyland :( */
+ _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
+ _gted[engine].cargo_disallowed = CC_PASSENGERS;
+ } else {
+ _gted[engine].cargo_allowed = CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS;
+ _gted[engine].cargo_disallowed = CC_LIQUID | CC_PASSENGERS;
+ }
+ break;
+ }
+ e->u.ship.old_refittable = true;
+ } else if (e->type == VEH_TRAIN && e->u.rail.railveh_type != RAILVEH_WAGON) {
+ /* Train engines default to all cargoes, so you can build single-cargo consists with fast engines.
+ * Trains loading multiple cargoes may start stations accepting unwanted cargoes. */
+ _gted[engine].cargo_allowed = CC_PASSENGERS | CC_MAIL | CC_ARMOURED | CC_EXPRESS | CC_BULK | CC_PIECE_GOODS | CC_LIQUID;
+ _gted[engine].cargo_disallowed = 0;
+ } else {
+ /* Train wagons and road vehicles are classified by their default cargo type */
+ for (const auto &drm : _default_refit_masks) {
+ if (!HasBit(drm.climate, _settings_game.game_creation.landscape)) continue;
+ if (drm.cargo_type != ei->cargo_type) continue;
+
+ _gted[engine].cargo_allowed = drm.cargo_allowed;
+ _gted[engine].cargo_disallowed = drm.cargo_disallowed;
+ break;
+ }
+
+ /* All original cargoes have specialised vehicles, so exclude them */
+ _gted[engine].ctt_exclude_mask = original_known_cargoes;
+ }
+ }
+ _gted[engine].UpdateRefittability(_gted[engine].cargo_allowed != 0);
+
/* Translate cargo_type using the original climate-specific cargo table. */
ei->cargo_type = GetDefaultCargoID(_settings_game.game_creation.landscape, static_cast<CargoType>(ei->cargo_type));
+ if (ei->cargo_type != CT_INVALID) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
}
- /* Did the newgrf specify any refitting? If not, use defaults. */
- if (_gted[engine].refittability != GRFTempEngineData::UNSET) {
+ /* Compute refittability */
+ {
CargoTypes mask = 0;
CargoTypes not_mask = 0;
CargoTypes xor_mask = ei->refit_mask;
/* If the original masks set by the grf are zero, the vehicle shall only carry the default cargo.
* Note: After applying the translations, the vehicle may end up carrying no defined cargo. It becomes unavailable in that case. */
- only_defaultcargo = _gted[engine].refittability == GRFTempEngineData::EMPTY;
+ only_defaultcargo = _gted[engine].refittability != GRFTempEngineData::NONEMPTY;
if (_gted[engine].cargo_allowed != 0) {
/* Build up the list of cargo types from the set cargo classes. */
@@ -8797,26 +8848,6 @@ static void CalculateRefitMasks()
/* Apply explicit refit includes/excludes. */
ei->refit_mask |= _gted[engine].ctt_include_mask;
ei->refit_mask &= ~_gted[engine].ctt_exclude_mask;
- } else {
- CargoTypes xor_mask = 0;
-
- /* Don't apply default refit mask to wagons nor engines with no capacity */
- if (e->type != VEH_TRAIN || (e->u.rail.capacity != 0 && e->u.rail.railveh_type != RAILVEH_WAGON)) {
- const CargoLabel *cl = _default_refitmasks[e->type];
- for (uint i = 0;; i++) {
- if (cl[i] == 0) break;
-
- CargoID cargo = GetCargoIDByLabel(cl[i]);
- if (cargo == CT_INVALID) continue;
-
- SetBit(xor_mask, cargo);
- }
- }
-
- ei->refit_mask = xor_mask & _cargo_mask;
-
- /* If the mask is zero, the vehicle shall only carry the default cargo */
- only_defaultcargo = (ei->refit_mask == 0);
}
/* Clear invalid cargoslots (from default vehicles or pre-NewCargo GRFs) */