diff options
Diffstat (limited to 'src/newgrf.cpp')
-rw-r--r-- | src/newgrf.cpp | 147 |
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) */ |