Merge tag '14.0-beta2' into jgrpp
# Conflicts: # CMakeLists.txt # src/cargotype.cpp # src/console_cmds.cpp # src/graph_gui.cpp # src/industry_cmd.cpp # src/industrytype.h # src/misc_gui.cpp # src/network/network_client.cpp # src/newgrf.cpp # src/newgrf_town.cpp # src/object_cmd.cpp # src/openttd.cpp # src/pathfinder/water_regions.cpp # src/saveload/saveload.cpp # src/saveload/saveload.h # src/table/build_industry.h # src/table/engines.h # src/vehicle.cpp # src/vehicle_cmd.cpp # src/vehicle_gui.cpp
This commit is contained in:
@@ -350,6 +350,10 @@ if(NOT OPTION_NO_SPLIT_LIB)
|
||||
target_link_libraries(openttd openttd_lib)
|
||||
|
||||
target_link_libraries(openttd_test PRIVATE openttd_lib)
|
||||
if(ANDROID)
|
||||
target_link_libraries(openttd_test PRIVATE log)
|
||||
endif()
|
||||
|
||||
include(Catch)
|
||||
catch_discover_tests(openttd_test)
|
||||
endif()
|
||||
|
@@ -1,3 +1,15 @@
|
||||
14.0-beta2 (2023-02-04)
|
||||
------------------------------------------------------------------------
|
||||
Change: [NewGRF] Improved support for redefining default cargo types (#11719)
|
||||
Fix #11982: Crash when trying to place signals on things other than plain rails (#11977)
|
||||
Fix #11975: Inconsistent behaviour when changing first AI company settings (#11976)
|
||||
Fix #11972: Year cut off in graph windows (#11974)
|
||||
Fix #11968: Crash when opening orders window of new vehicles (#11973)
|
||||
Fix #11966: Monospace text in windows may not have been fully scrollable (#11981)
|
||||
Fix #11802: Made determining water region edge traversability more robust (#11986)
|
||||
Fix: Second colour vehicle-type default liveries were not being updated (#11971)
|
||||
|
||||
|
||||
14.0-beta1 (2023-02-03)
|
||||
------------------------------------------------------------------------
|
||||
Feature: Order option to unbunch vehicles at depot (#11945)
|
||||
|
@@ -163,6 +163,17 @@ struct AIConfigWindow : public Window {
|
||||
switch (widget) {
|
||||
case WID_AIC_LIST: {
|
||||
Rect tr = r.Shrink(WidgetDimensions::scaled.matrix);
|
||||
int max_slot = GetGameSettings().difficulty.max_no_competitors;
|
||||
if (_game_mode == GM_NORMAL) {
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
if (c->is_ai) max_slot--;
|
||||
}
|
||||
for (CompanyID cid = COMPANY_FIRST; cid < (CompanyID)max_slot && cid < MAX_COMPANIES; cid++) {
|
||||
if (Company::IsValidID(cid)) max_slot++;
|
||||
}
|
||||
} else {
|
||||
max_slot++; // Slot 0 is human
|
||||
}
|
||||
for (int i = this->vscroll->GetPosition(); this->vscroll->IsVisible(i) && i < MAX_COMPANIES; i++) {
|
||||
StringID text;
|
||||
|
||||
@@ -179,13 +190,6 @@ struct AIConfigWindow : public Window {
|
||||
if (this->selected_slot == i) {
|
||||
tc = TC_WHITE;
|
||||
} else if (IsEditable((CompanyID)i)) {
|
||||
int max_slot = GetGameSettings().difficulty.max_no_competitors;
|
||||
for (const Company *c : Company::Iterate()) {
|
||||
if (c->is_ai) max_slot--;
|
||||
}
|
||||
for (CompanyID cid = COMPANY_FIRST; cid < (CompanyID)max_slot && cid < MAX_COMPANIES; cid++) {
|
||||
if (Company::IsValidHumanID(cid)) max_slot++;
|
||||
}
|
||||
if (i < max_slot) tc = TC_ORANGE;
|
||||
} else if (Company::IsValidAiID(i)) {
|
||||
tc = TC_GREEN;
|
||||
|
@@ -319,11 +319,16 @@ CommandCost CmdBuildAircraft(TileIndex tile, DoCommandFlag flags, const Engine *
|
||||
|
||||
v->cargo_cap = avi->passenger_capacity;
|
||||
v->refit_cap = 0;
|
||||
u->cargo_cap = avi->mail_capacity;
|
||||
u->refit_cap = 0;
|
||||
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
u->cargo_type = CT_MAIL;
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail)) {
|
||||
u->cargo_type = mail;
|
||||
u->cargo_cap = avi->mail_capacity;
|
||||
}
|
||||
|
||||
v->name.clear();
|
||||
v->last_station_visited = INVALID_STATION;
|
||||
|
@@ -479,6 +479,7 @@ void AddArticulatedParts(Vehicle *first)
|
||||
rv->spritenum = e_artic->u.road.image_index;
|
||||
if (e_artic->CanCarryCargo()) {
|
||||
rv->cargo_type = e_artic->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(rv->cargo_type));
|
||||
rv->cargo_cap = e_artic->u.road.capacity; // Callback 36 is called when the consist is finished
|
||||
} else {
|
||||
rv->cargo_type = front->cargo_type; // Needed for livery selection
|
||||
|
@@ -1035,7 +1035,7 @@ static int DrawAircraftPurchaseInfo(int left, int right, int y, EngineID engine_
|
||||
if (te.mail_capacity > 0) {
|
||||
SetDParam(0, te.cargo);
|
||||
SetDParam(1, te.capacity);
|
||||
SetDParam(2, CT_MAIL);
|
||||
SetDParam(2, GetCargoIDByLabel(CT_MAIL));
|
||||
SetDParam(3, te.mail_capacity);
|
||||
DrawString(left, right, y, STR_PURCHASE_INFO_AIRCRAFT_CAPACITY);
|
||||
} else {
|
||||
@@ -1117,7 +1117,11 @@ void TestedEngineDetails::FillDefaultCapacities(const Engine *e)
|
||||
} else {
|
||||
this->capacity = e->GetDisplayDefaultCapacity(&this->mail_capacity);
|
||||
this->all_capacities[this->cargo] = this->capacity;
|
||||
this->all_capacities[CT_MAIL] = this->mail_capacity;
|
||||
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
|
||||
this->all_capacities[GetCargoIDByLabel(CT_MAIL)] = this->mail_capacity;
|
||||
} else {
|
||||
this->mail_capacity = 0;
|
||||
}
|
||||
}
|
||||
if (this->all_capacities.GetCount() == 0) this->cargo = INVALID_CARGO;
|
||||
}
|
||||
|
@@ -11,61 +11,67 @@
|
||||
#define CARGO_TYPE_H
|
||||
|
||||
#include "core/enum_type.hpp"
|
||||
#include "core/strong_typedef_type.hpp"
|
||||
|
||||
/** Globally unique label of a cargo type. */
|
||||
using CargoLabel = StrongType::Typedef<uint32_t, struct CargoLabelTag, StrongType::Compare>;
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
|
||||
/**
|
||||
* Cargo slots to indicate a cargo type within a game.
|
||||
* Numbers are re-used between different climates.
|
||||
* @see CargoTypes
|
||||
*/
|
||||
typedef byte CargoID;
|
||||
using CargoID = byte;
|
||||
|
||||
/** Available types of cargo */
|
||||
enum CargoType {
|
||||
/* Temperate */
|
||||
CT_PASSENGERS = 0,
|
||||
CT_COAL = 1,
|
||||
CT_MAIL = 2,
|
||||
CT_OIL = 3,
|
||||
CT_LIVESTOCK = 4,
|
||||
CT_GOODS = 5,
|
||||
CT_GRAIN = 6,
|
||||
CT_WOOD = 7,
|
||||
CT_IRON_ORE = 8,
|
||||
CT_STEEL = 9,
|
||||
CT_VALUABLES = 10,
|
||||
/**
|
||||
* Available types of cargo
|
||||
* Labels may be re-used between different climates.
|
||||
*/
|
||||
|
||||
/* Arctic */
|
||||
CT_WHEAT = 6,
|
||||
CT_HILLY_UNUSED = 8,
|
||||
CT_PAPER = 9,
|
||||
CT_GOLD = 10,
|
||||
CT_FOOD = 11,
|
||||
/* Temperate */
|
||||
static constexpr CargoLabel CT_PASSENGERS = CargoLabel{'PASS'};
|
||||
static constexpr CargoLabel CT_COAL = CargoLabel{'COAL'};
|
||||
static constexpr CargoLabel CT_MAIL = CargoLabel{'MAIL'};
|
||||
static constexpr CargoLabel CT_OIL = CargoLabel{'OIL_'};
|
||||
static constexpr CargoLabel CT_LIVESTOCK = CargoLabel{'LVST'};
|
||||
static constexpr CargoLabel CT_GOODS = CargoLabel{'GOOD'};
|
||||
static constexpr CargoLabel CT_GRAIN = CargoLabel{'GRAI'};
|
||||
static constexpr CargoLabel CT_WOOD = CargoLabel{'WOOD'};
|
||||
static constexpr CargoLabel CT_IRON_ORE = CargoLabel{'IORE'};
|
||||
static constexpr CargoLabel CT_STEEL = CargoLabel{'STEL'};
|
||||
static constexpr CargoLabel CT_VALUABLES = CargoLabel{'VALU'};
|
||||
|
||||
/* Tropic */
|
||||
CT_RUBBER = 1,
|
||||
CT_FRUIT = 4,
|
||||
CT_MAIZE = 6,
|
||||
CT_COPPER_ORE = 8,
|
||||
CT_WATER = 9,
|
||||
CT_DIAMONDS = 10,
|
||||
/* Arctic */
|
||||
static constexpr CargoLabel CT_WHEAT = CargoLabel{'WHEA'};
|
||||
static constexpr CargoLabel CT_PAPER = CargoLabel{'PAPR'};
|
||||
static constexpr CargoLabel CT_GOLD = CargoLabel{'GOLD'};
|
||||
static constexpr CargoLabel CT_FOOD = CargoLabel{'FOOD'};
|
||||
|
||||
/* Toyland */
|
||||
CT_SUGAR = 1,
|
||||
CT_TOYS = 3,
|
||||
CT_BATTERIES = 4,
|
||||
CT_CANDY = 5,
|
||||
CT_TOFFEE = 6,
|
||||
CT_COLA = 7,
|
||||
CT_COTTON_CANDY = 8,
|
||||
CT_BUBBLES = 9,
|
||||
CT_PLASTIC = 10,
|
||||
CT_FIZZY_DRINKS = 11,
|
||||
/* Tropic */
|
||||
static constexpr CargoLabel CT_RUBBER = CargoLabel{'RUBR'};
|
||||
static constexpr CargoLabel CT_FRUIT = CargoLabel{'FRUI'};
|
||||
static constexpr CargoLabel CT_MAIZE = CargoLabel{'MAIZ'};
|
||||
static constexpr CargoLabel CT_COPPER_ORE = CargoLabel{'CORE'};
|
||||
static constexpr CargoLabel CT_WATER = CargoLabel{'WATR'};
|
||||
static constexpr CargoLabel CT_DIAMONDS = CargoLabel{'DIAM'};
|
||||
|
||||
CT_INVALID = 0xFF, ///< Invalid cargo type.
|
||||
};
|
||||
/* Toyland */
|
||||
static constexpr CargoLabel CT_SUGAR = CargoLabel{'SUGR'};
|
||||
static constexpr CargoLabel CT_TOYS = CargoLabel{'TOYS'};
|
||||
static constexpr CargoLabel CT_BATTERIES = CargoLabel{'BATT'};
|
||||
static constexpr CargoLabel CT_CANDY = CargoLabel{'SWET'};
|
||||
static constexpr CargoLabel CT_TOFFEE = CargoLabel{'TOFF'};
|
||||
static constexpr CargoLabel CT_COLA = CargoLabel{'COLA'};
|
||||
static constexpr CargoLabel CT_COTTON_CANDY = CargoLabel{'CTCD'};
|
||||
static constexpr CargoLabel CT_BUBBLES = CargoLabel{'BUBL'};
|
||||
static constexpr CargoLabel CT_PLASTIC = CargoLabel{'PLST'};
|
||||
static constexpr CargoLabel CT_FIZZY_DRINKS = CargoLabel{'FZDR'};
|
||||
|
||||
/** Dummy label for engines that carry no cargo; they actually carry 0 passengers. */
|
||||
static constexpr CargoLabel CT_NONE = CT_PASSENGERS;
|
||||
|
||||
static constexpr CargoLabel CT_INVALID = CargoLabel{UINT32_MAX}; ///< Invalid cargo type.
|
||||
|
||||
static const CargoID NUM_ORIGINAL_CARGO = 12; ///< Original number of cargo types.
|
||||
static const CargoID NUM_CARGO = 64; ///< Maximum number of cargo types in a game.
|
||||
@@ -88,7 +94,7 @@ namespace CargoFilterCriteria {
|
||||
};
|
||||
|
||||
/** Test whether cargo type is not CT_INVALID */
|
||||
inline bool IsValidCargoType(CargoType t) { return t != CT_INVALID; }
|
||||
inline bool IsValidCargoType(CargoLabel t) { return t != CT_INVALID; }
|
||||
/** Test whether cargo type is not INVALID_CARGO */
|
||||
inline bool IsValidCargoID(CargoID t) { return t != INVALID_CARGO; }
|
||||
|
||||
|
@@ -15,6 +15,7 @@
|
||||
#include "string_func.h"
|
||||
#include "strings_func.h"
|
||||
#include "settings_type.h"
|
||||
#include "3rdparty/cpp-btree/btree_map.h"
|
||||
|
||||
#include "table/sprites.h"
|
||||
#include "table/strings.h"
|
||||
@@ -36,6 +37,16 @@ CargoTypes _cargo_mask;
|
||||
*/
|
||||
CargoTypes _standard_cargo_mask;
|
||||
|
||||
/**
|
||||
* List of default cargo labels, used when setting up cargo types for default vehicles.
|
||||
* This is done by label so that a cargo label can be redefined in a different slot.
|
||||
*/
|
||||
static std::vector<CargoLabel> _default_cargo_labels;
|
||||
|
||||
static btree::btree_map<CargoLabel, CargoID> _cargo_label_map; ///< Translation map from CargoLabel to Cargo ID.
|
||||
CargoID _cargo_id_passengers = INVALID_CARGO;
|
||||
CargoID _cargo_id_mail = INVALID_CARGO;
|
||||
|
||||
/**
|
||||
* Set up the default cargo types for the given landscape type.
|
||||
* @param l Landscape
|
||||
@@ -45,18 +56,20 @@ void SetupCargoForClimate(LandscapeID l)
|
||||
assert(l < lengthof(_default_climate_cargo));
|
||||
|
||||
_cargo_mask = 0;
|
||||
_default_cargo_labels.clear();
|
||||
|
||||
/* Copy from default cargo by label or index. */
|
||||
auto insert = std::begin(CargoSpec::array);
|
||||
for (const CargoLabel &cl : _default_climate_cargo[l]) {
|
||||
for (const auto &cl : _default_climate_cargo[l]) {
|
||||
|
||||
/* Check if value is an index into the cargo table */
|
||||
if (cl < lengthof(_default_cargo)) {
|
||||
if (std::holds_alternative<int>(cl)) {
|
||||
/* Copy the default cargo by index. */
|
||||
*insert = _default_cargo[cl];
|
||||
*insert = _default_cargo[std::get<int>(cl)];
|
||||
} else {
|
||||
/* Search for label in default cargo types and copy if found. */
|
||||
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&cl](const CargoSpec &cs) { return cs.label == cl; });
|
||||
CargoLabel label = std::get<CargoLabel>(cl);
|
||||
auto found = std::find_if(std::begin(_default_cargo), std::end(_default_cargo), [&label](const CargoSpec &cs) { return cs.label == label; });
|
||||
if (found != std::end(_default_cargo)) {
|
||||
*insert = *found;
|
||||
} else {
|
||||
@@ -65,12 +78,51 @@ void SetupCargoForClimate(LandscapeID l)
|
||||
}
|
||||
}
|
||||
|
||||
if (insert->IsValid()) SetBit(_cargo_mask, insert->Index());
|
||||
if (insert->IsValid()) {
|
||||
SetBit(_cargo_mask, insert->Index());
|
||||
_default_cargo_labels.push_back(insert->label);
|
||||
}
|
||||
++insert;
|
||||
}
|
||||
|
||||
/* Reset and disable remaining cargo types. */
|
||||
std::fill(insert, std::end(CargoSpec::array), CargoSpec{});
|
||||
|
||||
BuildCargoLabelMap();
|
||||
}
|
||||
|
||||
/**
|
||||
* Build cargo label map.
|
||||
* This is called multiple times during NewGRF initialization as cargos are defined, so that TranslateRefitMask() and
|
||||
* GetCargoTranslation(), also used during initialization, get the correct information.
|
||||
*/
|
||||
void BuildCargoLabelMap()
|
||||
{
|
||||
_cargo_label_map.clear();
|
||||
for (const CargoSpec &cs : CargoSpec::array) {
|
||||
/* During initialization, CargoSpec can be marked valid before the label has been set. */
|
||||
if (!cs.IsValid() || cs.label == CargoLabel{0}) continue;
|
||||
/* Label already exists, don't add again. */
|
||||
if (_cargo_label_map.count(cs.label) != 0) continue;
|
||||
|
||||
_cargo_label_map.insert(std::make_pair(cs.label, cs.Index()));
|
||||
}
|
||||
_cargo_id_passengers = GetCargoIDByLabelUsingMap(CT_PASSENGERS);
|
||||
_cargo_id_mail = GetCargoIDByLabelUsingMap(CT_MAIL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test if a cargo is a default cargo type.
|
||||
* @param cid Cargo ID.
|
||||
* @returns true iff the cargo type is a default cargo type.
|
||||
*/
|
||||
bool IsDefaultCargo(CargoID cid)
|
||||
{
|
||||
auto cs = CargoSpec::Get(cid);
|
||||
if (!cs->IsValid()) return false;
|
||||
|
||||
CargoLabel label = cs->label;
|
||||
return std::any_of(std::begin(_default_cargo_labels), std::end(_default_cargo_labels), [&label](const CargoLabel &cl) { return cl == label; });
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,44 +138,13 @@ Dimension GetLargestCargoIconSize()
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cargo ID of a default cargo, if present.
|
||||
* @param l Landscape
|
||||
* @param ct Default cargo type.
|
||||
* @return ID number if the cargo exists, else #INVALID_CARGO
|
||||
*/
|
||||
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct)
|
||||
CargoID GetCargoIDByLabelUsingMap(CargoLabel label)
|
||||
{
|
||||
assert(l < lengthof(_default_climate_cargo));
|
||||
|
||||
if (ct == CT_INVALID) return INVALID_CARGO;
|
||||
|
||||
assert(ct < lengthof(_default_climate_cargo[0]));
|
||||
CargoLabel cl = _default_climate_cargo[l][ct];
|
||||
/* Bzzt: check if cl is just an index into the cargo table */
|
||||
if (cl < lengthof(_default_cargo)) {
|
||||
cl = _default_cargo[cl].label;
|
||||
}
|
||||
|
||||
return GetCargoIDByLabel(cl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the cargo ID by cargo label.
|
||||
* @param cl Cargo type to get.
|
||||
* @return ID number if the cargo exists, else #INVALID_CARGO
|
||||
*/
|
||||
CargoID GetCargoIDByLabel(CargoLabel cl)
|
||||
{
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
if (cs->label == cl) return cs->Index();
|
||||
}
|
||||
|
||||
/* No matching label was found, so it is invalid */
|
||||
auto found = _cargo_label_map.find(label);
|
||||
if (found != _cargo_label_map.end()) return found->second;
|
||||
return INVALID_CARGO;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the CargoID of a 'bitnum' value.
|
||||
* @param bitnum 'bitnum' to find.
|
||||
|
@@ -18,9 +18,6 @@
|
||||
#include "core/bitmath_func.hpp"
|
||||
#include <vector>
|
||||
|
||||
/** Globally unique label of a cargo type. */
|
||||
typedef uint32_t CargoLabel;
|
||||
|
||||
/** Town growth effect when delivering cargo. */
|
||||
enum TownAcceptanceEffect : byte {
|
||||
TAE_BEGIN = 0,
|
||||
@@ -206,6 +203,7 @@ private:
|
||||
static CargoSpec array[NUM_CARGO]; ///< Array holding all CargoSpecs
|
||||
|
||||
friend void SetupCargoForClimate(LandscapeID l);
|
||||
friend void BuildCargoLabelMap();
|
||||
friend void FinaliseCargoArray();
|
||||
};
|
||||
|
||||
@@ -213,9 +211,21 @@ extern CargoTypes _cargo_mask;
|
||||
extern CargoTypes _standard_cargo_mask;
|
||||
|
||||
void SetupCargoForClimate(LandscapeID l);
|
||||
CargoID GetCargoIDByLabel(CargoLabel cl);
|
||||
bool IsDefaultCargo(CargoID cid);
|
||||
void BuildCargoLabelMap();
|
||||
CargoID GetCargoIDByBitnum(uint8_t bitnum);
|
||||
CargoID GetDefaultCargoID(LandscapeID l, CargoType ct);
|
||||
|
||||
CargoID GetCargoIDByLabelUsingMap(CargoLabel label);
|
||||
|
||||
inline CargoID GetCargoIDByLabel(CargoLabel label)
|
||||
{
|
||||
extern CargoID _cargo_id_passengers;
|
||||
extern CargoID _cargo_id_mail;
|
||||
if (label == CT_PASSENGERS) return _cargo_id_passengers;
|
||||
if (label == CT_MAIL) return _cargo_id_mail;
|
||||
return GetCargoIDByLabelUsingMap(label);
|
||||
}
|
||||
|
||||
Dimension GetLargestCargoIconSize();
|
||||
|
||||
void InitializeSortedCargoSpecs();
|
||||
|
@@ -3047,7 +3047,7 @@ DEF_CONSOLE_CMD(ConDumpCargoTypes)
|
||||
IConsolePrintF(CC_DEFAULT, " %02u Bit: %2u, Label: %c%c%c%c, Callback mask: 0x%02X, Cargo class: %c%c%c%c%c%c%c%c%c%c%c, GRF: %08X, %s",
|
||||
(uint) i,
|
||||
spec->bitnum,
|
||||
spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label,
|
||||
spec->label.base() >> 24, spec->label.base() >> 16, spec->label.base() >> 8, spec->label.base(),
|
||||
spec->callback_mask,
|
||||
(spec->classes & CC_PASSENGERS) != 0 ? 'p' : '-',
|
||||
(spec->classes & CC_MAIL) != 0 ? 'm' : '-',
|
||||
@@ -3161,10 +3161,10 @@ DEF_CONSOLE_CMD(ConDumpGrfCargoTables)
|
||||
char *b = buffer;
|
||||
for (const CargoSpec *cs : CargoSpec::Iterate()) {
|
||||
if (grf->cargo_map[cs->Index()] == i) {
|
||||
b += seprintf(b, lastof(buffer), "%s%02u[%c%c%c%c]", (b == buffer) ? ": " : ", ", cs->Index(), GB(cs->label, 24, 8), GB(cs->label, 16, 8), GB(cs->label, 8, 8), GB(cs->label, 0, 8));
|
||||
b += seprintf(b, lastof(buffer), "%s%02u[%c%c%c%c]", (b == buffer) ? ": " : ", ", cs->Index(), GB(cs->label.base(), 24, 8), GB(cs->label.base(), 16, 8), GB(cs->label.base(), 8, 8), GB(cs->label.base(), 0, 8));
|
||||
}
|
||||
}
|
||||
IConsolePrintF(CC_DEFAULT, " %c%c%c%c%s", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8), buffer);
|
||||
IConsolePrintF(CC_DEFAULT, " %c%c%c%c%s", GB(cl.base(), 24, 8), GB(cl.base(), 16, 8), GB(cl.base(), 8, 8), GB(cl.base(), 0, 8), buffer);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@@ -283,8 +283,10 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
|
||||
if (!IsCargoInClass(cargo_type, CC_PASSENGERS)) {
|
||||
extra_mail_cap = GetEngineProperty(this->index, PROP_AIRCRAFT_MAIL_CAPACITY, this->u.air.mail_capacity, v);
|
||||
}
|
||||
if (!new_multipliers && cargo_type == CT_MAIL) return capacity + extra_mail_cap;
|
||||
default_cargo = CT_PASSENGERS; // Always use 'passengers' wrt. cargo multipliers
|
||||
if (IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
|
||||
if (!new_multipliers && cargo_type == GetCargoIDByLabel(CT_MAIL)) return capacity + extra_mail_cap;
|
||||
}
|
||||
default_cargo = GetCargoIDByLabel(CT_PASSENGERS); // Always use 'passengers' wrt. cargo multipliers
|
||||
break;
|
||||
|
||||
default: NOT_REACHED();
|
||||
@@ -301,8 +303,8 @@ uint Engine::DetermineCapacity(const Vehicle *v, uint16_t *mail_capacity) const
|
||||
uint16_t default_multiplier = new_multipliers ? 0x100 : CargoSpec::Get(default_cargo)->multiplier;
|
||||
uint16_t cargo_multiplier = CargoSpec::Get(cargo_type)->multiplier;
|
||||
capacity *= cargo_multiplier;
|
||||
if (extra_mail_cap > 0) {
|
||||
uint mail_multiplier = CargoSpec::Get(CT_MAIL)->multiplier;
|
||||
if (extra_mail_cap > 0 && IsValidCargoID(GetCargoIDByLabel(CT_MAIL))) {
|
||||
uint mail_multiplier = CargoSpec::Get(GetCargoIDByLabel(CT_MAIL))->multiplier;
|
||||
capacity += (default_multiplier * extra_mail_cap * cargo_multiplier + mail_multiplier / 2) / mail_multiplier;
|
||||
}
|
||||
capacity = (capacity + default_multiplier / 2) / default_multiplier;
|
||||
|
@@ -254,7 +254,7 @@ static StringID GetAircraftEngineInfoString(const Engine *e)
|
||||
SetDParam(9, mail_capacity > 0 ? STR_ENGINE_PREVIEW_CAPACITY_2 : STR_ENGINE_PREVIEW_CAPACITY);
|
||||
SetDParam(10, cargo);
|
||||
SetDParam(11, capacity);
|
||||
SetDParam(12, CT_MAIL);
|
||||
SetDParam(12, GetCargoIDByLabel(CT_MAIL));
|
||||
SetDParam(13, mail_capacity);
|
||||
|
||||
return STR_ENGINE_PREVIEW_TEXT4;
|
||||
|
@@ -149,6 +149,7 @@ struct EngineInfo {
|
||||
byte load_amount;
|
||||
byte climates; ///< Climates supported by the engine.
|
||||
CargoID cargo_type;
|
||||
CargoLabel cargo_label;
|
||||
CargoTypes refit_mask;
|
||||
byte refit_cost;
|
||||
byte misc_flags; ///< Miscellaneous flags. @see EngineMiscFlags
|
||||
|
@@ -570,7 +570,7 @@ public:
|
||||
SetDParam(1, INT64_MAX);
|
||||
uint y_label_width = GetStringBoundingBox(STR_GRAPH_Y_LABEL).width;
|
||||
|
||||
size->width = std::max<uint>(size->width, ScaleGUITrad(5) + y_label_width + this->num_on_x_axis * (x_label_width + ScaleGUITrad(5)) + ScaleGUITrad(9));
|
||||
size->width = std::max<uint>(size->width, ScaleGUITrad(5) + y_label_width + this->num_vert_lines * (x_label_width + ScaleGUITrad(5)) + ScaleGUITrad(9));
|
||||
size->height = std::max<uint>(size->height, ScaleGUITrad(5) + (1 + MIN_GRAPH_NUM_LINES_Y * 2 + (this->draw_dates ? 3 : 1)) * GetCharacterHeight(FS_SMALL) + ScaleGUITrad(4));
|
||||
size->height = std::max<uint>(size->height, size->width / 3);
|
||||
}
|
||||
@@ -1488,7 +1488,7 @@ struct PaymentRatesGraphWindow : BaseGraphWindow {
|
||||
|
||||
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
|
||||
this->colours[i] = cs->legend_colour;
|
||||
for (int j = 0; j != 20; j++) {
|
||||
for (int j = 0; j != this->num_on_x_axis; j++) {
|
||||
const byte ctt = _cargo_payment_x_mode ? static_cast<byte>(factor / static_cast<float>((j + 1) * this->x_values_increment)) : (j + 1) * 4;
|
||||
this->cost[i][j] = GetTransportedGoodsIncome(_cargo_payment_x_mode ? 1 : 10, _cargo_payment_x_mode ? 200 : 20, ctt, cs->Index());
|
||||
}
|
||||
|
@@ -113,6 +113,7 @@ struct HouseSpec {
|
||||
byte mail_generation; ///< mail generation multiplier (tile based, as the acceptances below)
|
||||
byte cargo_acceptance[HOUSE_NUM_ACCEPTS]; ///< acceptance level for the cargo slots
|
||||
CargoID accepts_cargo[HOUSE_NUM_ACCEPTS]; ///< input cargo slots
|
||||
CargoLabel accepts_cargo_label[HOUSE_NUM_ACCEPTS]; ///< input landscape cargo slots
|
||||
BuildingFlags building_flags; ///< some flags that describe the house (size, stadium etc...)
|
||||
HouseZones building_availability; ///< where can it be built (climates, zones)
|
||||
bool enabled; ///< the house is available to build (true by default, but can be disabled by newgrf)
|
||||
|
@@ -1025,7 +1025,7 @@ bool IsTileForestIndustry(TileIndex tile)
|
||||
/* Check for wood production */
|
||||
for (uint i = 0; i < lengthof(ind->produced_cargo); i++) {
|
||||
/* The industry produces wood. */
|
||||
if (ind->produced_cargo[i] != INVALID_CARGO && CargoSpec::Get(ind->produced_cargo[i])->label == 'WOOD') return true;
|
||||
if (ind->produced_cargo[i] != INVALID_CARGO && CargoSpec::Get(ind->produced_cargo[i])->label == CT_WOOD) return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -1914,7 +1914,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
|
||||
uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->accepts_cargo) : 3;
|
||||
for (uint j = 0; j < maxcargoes; j++) {
|
||||
uint16_t res = GetIndustryCallback(CBID_INDUSTRY_INPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
|
||||
if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
|
||||
if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
|
||||
if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
|
||||
ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_INPUT_CARGO_TYPES, res);
|
||||
break;
|
||||
@@ -1946,7 +1946,7 @@ static void DoCreateNewIndustry(Industry *i, TileIndex tile, IndustryType type,
|
||||
uint maxcargoes = (indspec->behaviour & INDUSTRYBEH_CARGOTYPES_UNLIMITED) ? lengthof(i->produced_cargo) : 2;
|
||||
for (uint j = 0; j < maxcargoes; j++) {
|
||||
uint16_t res = GetIndustryCallback(CBID_INDUSTRY_OUTPUT_CARGO_TYPES, j, 0, i, type, INVALID_TILE);
|
||||
if (res == CALLBACK_FAILED || GB(res, 0, 8) == CT_INVALID) break;
|
||||
if (res == CALLBACK_FAILED || GB(res, 0, 8) == UINT8_MAX) break;
|
||||
if (indspec->grf_prop.grffile->grf_version >= 8 && res >= 0x100) {
|
||||
ErrorUnknownCallbackResult(indspec->grf_prop.grffile->grfid, CBID_INDUSTRY_OUTPUT_CARGO_TYPES, res);
|
||||
break;
|
||||
@@ -2956,7 +2956,7 @@ static void ChangeIndustryProduction(Industry *i, bool monthly)
|
||||
|
||||
/* Prevent production to overflow or Oil Rig passengers to be over-"produced" */
|
||||
new_prod = Clamp(new_prod, 1, 255);
|
||||
if (i->produced_cargo[j] == CT_PASSENGERS && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
|
||||
if (IsValidCargoID(i->produced_cargo[j]) && i->produced_cargo[j] == GetCargoIDByLabel(CT_PASSENGERS) && !(indspec->behaviour & INDUSTRYBEH_NO_PAX_PROD_CLAMP)) {
|
||||
new_prod = Clamp(new_prod, 0, 16);
|
||||
}
|
||||
|
||||
|
@@ -113,6 +113,7 @@ struct IndustrySpec {
|
||||
IndustryType conflicting[3]; ///< Industries this industry cannot be close to
|
||||
byte check_proc; ///< Index to a procedure to check for conflicting circumstances
|
||||
std::array<CargoID, INDUSTRY_NUM_OUTPUTS> produced_cargo{};
|
||||
std::array<CargoLabel, INDUSTRY_NUM_OUTPUTS> produced_cargo_label{};
|
||||
std::array<byte, INDUSTRY_NUM_OUTPUTS> production_rate{};
|
||||
/**
|
||||
* minimum amount of cargo transported to the stations.
|
||||
@@ -120,6 +121,7 @@ struct IndustrySpec {
|
||||
*/
|
||||
byte minimal_cargo;
|
||||
std::array<CargoID, INDUSTRY_NUM_INPUTS> accepts_cargo{}; ///< 16 accepted cargoes.
|
||||
std::array<CargoLabel, INDUSTRY_NUM_INPUTS> accepts_cargo_label{};
|
||||
uint16_t input_cargo_multiplier[INDUSTRY_NUM_INPUTS][INDUSTRY_NUM_OUTPUTS]; ///< Input cargo multipliers (multiply amount of incoming cargo for the produced cargoes)
|
||||
IndustryLifeType life_type; ///< This is also known as Industry production flag, in newgrf specs
|
||||
byte climate_availability; ///< Bitmask, giving landscape enums as bit position
|
||||
@@ -156,6 +158,7 @@ struct IndustrySpec {
|
||||
*/
|
||||
struct IndustryTileSpec {
|
||||
std::array<CargoID, INDUSTRY_NUM_INPUTS> accepts_cargo; ///< Cargo accepted by this tile
|
||||
std::array<CargoLabel, INDUSTRY_NUM_INPUTS> accepts_cargo_label;
|
||||
std::array<int8_t, INDUSTRY_NUM_INPUTS> acceptance; ///< Level of acceptance per cargo type (signed, may be negative!)
|
||||
Slope slopes_refused; ///< slope pattern on which this tile cannot be built
|
||||
byte anim_production; ///< Animation frame to start when goods are produced
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include "viewport_func.h"
|
||||
#include "rev.h"
|
||||
#include "core/backup_type.hpp"
|
||||
#include "pathfinder/water_regions.h"
|
||||
|
||||
#include "widgets/misc_widget.h"
|
||||
|
||||
@@ -145,6 +146,8 @@ public:
|
||||
DEBUG(misc, LANDINFOD_LEVEL, "m6 = %#x", _me[tile].m6);
|
||||
DEBUG(misc, LANDINFOD_LEVEL, "m7 = %#x", _me[tile].m7);
|
||||
DEBUG(misc, LANDINFOD_LEVEL, "m8 = %#x", _me[tile].m8);
|
||||
|
||||
PrintWaterRegionDebugInfo(tile);
|
||||
}
|
||||
#undef LANDINFOD_LEVEL
|
||||
}
|
||||
|
@@ -170,7 +170,6 @@ ClientNetworkGameSocketHandler::~ClientNetworkGameSocketHandler()
|
||||
ClientNetworkGameSocketHandler::my_client = nullptr;
|
||||
_network_settings_access = false;
|
||||
|
||||
delete this->savegame;
|
||||
delete this->GetInfo();
|
||||
|
||||
if (this->desync_log_file) {
|
||||
@@ -754,7 +753,7 @@ bool ClientNetworkGameSocketHandler::IsConnected()
|
||||
************/
|
||||
|
||||
extern bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir,
|
||||
struct LoadFilter *lf = nullptr, std::string *error_detail = nullptr);
|
||||
std::shared_ptr<struct LoadFilter> lf = nullptr, std::string *error_detail = nullptr);
|
||||
|
||||
NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_FULL(Packet *)
|
||||
{
|
||||
@@ -985,7 +984,7 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_BEGIN(Packe
|
||||
|
||||
if (this->savegame != nullptr) return NETWORK_RECV_STATUS_MALFORMED_PACKET;
|
||||
|
||||
this->savegame = new PacketReader();
|
||||
this->savegame = std::make_shared<PacketReader>();
|
||||
|
||||
_frame_counter = _frame_counter_server = _frame_counter_max = p->Recv_uint32();
|
||||
|
||||
@@ -1031,21 +1030,13 @@ NetworkRecvStatus ClientNetworkGameSocketHandler::Receive_SERVER_MAP_DONE(Packet
|
||||
_network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
|
||||
SetWindowDirty(WC_NETWORK_STATUS_WINDOW, WN_NETWORK_STATUS_WINDOW_JOIN);
|
||||
|
||||
/*
|
||||
* Make sure everything is set for reading.
|
||||
*
|
||||
* We need the local copy and reset this->savegame because when
|
||||
* loading fails the network gets reset upon loading the intro
|
||||
* game, which would cause us to free this->savegame twice.
|
||||
*/
|
||||
LoadFilter *lf = this->savegame;
|
||||
this->savegame = nullptr;
|
||||
lf->Reset();
|
||||
this->savegame->Reset();
|
||||
|
||||
/* The map is done downloading, load it */
|
||||
ClearErrorMessages();
|
||||
std::string error_detail;
|
||||
bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, lf, &error_detail);
|
||||
bool load_success = SafeLoad({}, SLO_LOAD, DFT_GAME_FILE, GM_NORMAL, NO_DIRECTORY, std::move(this->savegame), &error_detail);
|
||||
this->savegame = nullptr;
|
||||
|
||||
/* Long savegame loads shouldn't affect the lag calculation! */
|
||||
this->last_packet = std::chrono::steady_clock::now();
|
||||
|
@@ -16,7 +16,7 @@
|
||||
class ClientNetworkGameSocketHandler : public NetworkGameSocketHandler {
|
||||
private:
|
||||
std::string connection_string; ///< Address we are connected to.
|
||||
struct PacketReader *savegame; ///< Packet reader for reading the savegame.
|
||||
std::shared_ptr<struct PacketReader> savegame; ///< Packet reader for reading the savegame.
|
||||
byte token; ///< The token we need to send back to the server to prove we're the right client.
|
||||
NetworkSharedSecrets last_rcon_shared_secrets; ///< Keys for last rcon (and incoming replies)
|
||||
|
||||
|
@@ -642,7 +642,7 @@ NetworkRecvStatus ServerNetworkGameSocketHandler::SendMap()
|
||||
|
||||
if (this->status == STATUS_AUTHORIZED) {
|
||||
WaitTillSaved();
|
||||
this->savegame = new PacketWriter(this);
|
||||
this->savegame = std::make_shared<PacketWriter>(this);
|
||||
|
||||
/* Now send the _frame_counter and how many packets are coming */
|
||||
Packet *p = new Packet(PACKET_SERVER_MAP_BEGIN, SHRT_MAX);
|
||||
|
@@ -85,7 +85,7 @@ public:
|
||||
bool settings_authed = false;///< Authorised to control all game settings
|
||||
bool supports_zstd = false; ///< Client supports zstd compression
|
||||
|
||||
struct PacketWriter *savegame; ///< Writer used to write the savegame.
|
||||
std::shared_ptr<struct PacketWriter> savegame; ///< Writer used to write the savegame.
|
||||
NetworkAddress client_address; ///< IP-address of the client (so they can be banned)
|
||||
|
||||
std::string desync_log;
|
||||
|
@@ -1105,6 +1105,7 @@ static ChangeInfoResult RailVehicleChangeInfo(uint engine, int numinfo, int prop
|
||||
ei->cargo_type = INVALID_CARGO;
|
||||
grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
|
||||
}
|
||||
ei->cargo_label = CT_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1367,6 +1368,7 @@ static ChangeInfoResult RoadVehicleChangeInfo(uint engine, int numinfo, int prop
|
||||
ei->cargo_type = INVALID_CARGO;
|
||||
grfmsg(2, "RailVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
|
||||
}
|
||||
ei->cargo_label = CT_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1563,6 +1565,7 @@ static ChangeInfoResult ShipVehicleChangeInfo(uint engine, int numinfo, int prop
|
||||
ei->cargo_type = INVALID_CARGO;
|
||||
grfmsg(2, "ShipVehicleChangeInfo: Invalid cargo type %d, using first refittable", ctype);
|
||||
}
|
||||
ei->cargo_label = CT_INVALID;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2421,7 +2424,9 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, con
|
||||
* climate. This can cause problems when copying the properties
|
||||
* of a house that accepts food, where the new house is valid
|
||||
* in the temperate climate. */
|
||||
if (!CargoSpec::Get(housespec->accepts_cargo[2])->IsValid()) {
|
||||
CargoID cid = housespec->accepts_cargo[2];
|
||||
if (!IsValidCargoID(cid)) cid = GetCargoIDByLabel(housespec->accepts_cargo_label[2]);
|
||||
if (!IsValidCargoID(cid) || !CargoSpec::Get(cid)->IsValid()) {
|
||||
housespec->cargo_acceptance[2] = 0;
|
||||
}
|
||||
}
|
||||
@@ -2457,13 +2462,14 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, con
|
||||
|
||||
/* If value of goods is negative, it means in fact food or, if in toyland, fizzy_drink acceptance.
|
||||
* Else, we have "standard" 3rd cargo type, goods or candy, for toyland once more */
|
||||
CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_CANDY : CT_GOODS) :
|
||||
((_settings_game.game_creation.landscape == LT_TOYLAND) ? CT_FIZZY_DRINKS : CT_FOOD);
|
||||
CargoID cid = (goods >= 0) ? ((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_CANDY) : GetCargoIDByLabel(CT_GOODS)) :
|
||||
((_settings_game.game_creation.landscape == LT_TOYLAND) ? GetCargoIDByLabel(CT_FIZZY_DRINKS) : GetCargoIDByLabel(CT_FOOD));
|
||||
|
||||
/* Make sure the cargo type is valid in this climate. */
|
||||
if (!CargoSpec::Get(cid)->IsValid()) goods = 0;
|
||||
|
||||
housespec->accepts_cargo[2] = cid;
|
||||
housespec->accepts_cargo_label[2] = CT_INVALID;
|
||||
housespec->cargo_acceptance[2] = abs(goods); // but we do need positive value here
|
||||
break;
|
||||
}
|
||||
@@ -2631,7 +2637,7 @@ static ChangeInfoResult TownHouseChangeInfo(uint hid, int numinfo, int prop, con
|
||||
* @return ChangeInfoResult.
|
||||
*/
|
||||
template <typename T>
|
||||
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader *buf, T &translation_table, const char *name)
|
||||
static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader *buf, std::vector<T> &translation_table, const char *name)
|
||||
{
|
||||
if (gvid != 0) {
|
||||
grfmsg(1, "LoadTranslationTable: %s translation table must start at zero", name);
|
||||
@@ -2640,8 +2646,7 @@ static ChangeInfoResult LoadTranslationTable(uint gvid, int numinfo, ByteReader
|
||||
|
||||
translation_table.clear();
|
||||
for (int i = 0; i < numinfo; i++) {
|
||||
uint32_t item = buf->ReadDWord();
|
||||
translation_table.push_back(BSWAP32(item));
|
||||
translation_table.push_back(T(BSWAP32(buf->ReadDWord())));
|
||||
}
|
||||
|
||||
return CIR_SUCCESS;
|
||||
@@ -3029,6 +3034,7 @@ static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, const G
|
||||
} else {
|
||||
ClrBit(_cargo_mask, cid + i);
|
||||
}
|
||||
BuildCargoLabelMap();
|
||||
break;
|
||||
|
||||
case 0x09: // String ID for cargo type name
|
||||
@@ -3096,8 +3102,8 @@ static ChangeInfoResult CargoChangeInfo(uint cid, int numinfo, int prop, const G
|
||||
break;
|
||||
|
||||
case 0x17: // Cargo label
|
||||
cs->label = buf->ReadDWord();
|
||||
cs->label = BSWAP32(cs->label);
|
||||
cs->label = CargoLabel{BSWAP32(buf->ReadDWord())};
|
||||
BuildCargoLabelMap();
|
||||
break;
|
||||
|
||||
case 0x18: { // Town growth substitute type
|
||||
@@ -3704,12 +3710,14 @@ static ChangeInfoResult IndustriesChangeInfo(uint indid, int numinfo, int prop,
|
||||
case 0x10: // Production cargo types
|
||||
for (byte j = 0; j < 2; j++) {
|
||||
indsp->produced_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
|
||||
indsp->produced_cargo_label[j] = CT_INVALID;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x11: // Acceptance cargo types
|
||||
for (byte j = 0; j < 3; j++) {
|
||||
indsp->accepts_cargo[j] = GetCargoTranslation(buf->ReadByte(), _cur.grffile);
|
||||
indsp->accepts_cargo_label[j] = CT_INVALID;
|
||||
}
|
||||
buf->ReadByte(); // Unnused, eat it up
|
||||
break;
|
||||
@@ -6359,18 +6367,18 @@ static CargoID TranslateCargo(uint8_t feature, uint8_t ctype)
|
||||
|
||||
/* Look up the cargo label from the translation table */
|
||||
CargoLabel cl = _cur.grffile->cargo_list[ctype];
|
||||
if (cl == 0) {
|
||||
if (cl == CT_INVALID) {
|
||||
grfmsg(5, "TranslateCargo: Cargo type %d not available in this climate, skipping.", ctype);
|
||||
return INVALID_CARGO;
|
||||
}
|
||||
|
||||
CargoID cid = GetCargoIDByLabel(cl);
|
||||
if (cid == INVALID_CARGO) {
|
||||
grfmsg(5, "TranslateCargo: Cargo '%c%c%c%c' unsupported, skipping.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8));
|
||||
grfmsg(5, "TranslateCargo: Cargo '%c%c%c%c' unsupported, skipping.", GB(cl.base(), 24, 8), GB(cl.base(), 16, 8), GB(cl.base(), 8, 8), GB(cl.base(), 0, 8));
|
||||
return INVALID_CARGO;
|
||||
}
|
||||
|
||||
grfmsg(6, "TranslateCargo: Cargo '%c%c%c%c' mapped to cargo type %d.", GB(cl, 24, 8), GB(cl, 16, 8), GB(cl, 8, 8), GB(cl, 0, 8), cid);
|
||||
grfmsg(6, "TranslateCargo: Cargo '%c%c%c%c' mapped to cargo type %d.", GB(cl.base(), 24, 8), GB(cl.base(), 16, 8), GB(cl.base(), 8, 8), GB(cl.base(), 0, 8), cid);
|
||||
return cid;
|
||||
}
|
||||
|
||||
@@ -7759,9 +7767,9 @@ static void SkipIf(ByteReader *buf)
|
||||
if (condtype >= 0x0B) {
|
||||
/* Tests that ignore 'param' */
|
||||
switch (condtype) {
|
||||
case 0x0B: result = GetCargoIDByLabel(BSWAP32(cond_val)) == INVALID_CARGO;
|
||||
case 0x0B: result = !IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
|
||||
break;
|
||||
case 0x0C: result = GetCargoIDByLabel(BSWAP32(cond_val)) != INVALID_CARGO;
|
||||
case 0x0C: result = IsValidCargoID(GetCargoIDByLabel(CargoLabel(BSWAP32(cond_val))));
|
||||
break;
|
||||
case 0x0D: result = GetRailTypeByLabel(BSWAP32(cond_val)) == INVALID_RAILTYPE;
|
||||
break;
|
||||
@@ -10612,9 +10620,8 @@ GRFFile::~GRFFile()
|
||||
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 != INVALID_CARGO) SetBit(original_known_cargoes, cid);
|
||||
for (CargoID cid = 0; cid != NUM_CARGO; ++cid) {
|
||||
if (IsDefaultCargo(cid)) SetBit(original_known_cargoes, cid);
|
||||
}
|
||||
|
||||
for (Engine *e : Engine::Iterate()) {
|
||||
@@ -10622,6 +10629,11 @@ static void CalculateRefitMasks()
|
||||
EngineInfo *ei = &e->info;
|
||||
bool only_defaultcargo; ///< Set if the vehicle shall carry only the default cargo
|
||||
|
||||
/* Apply default cargo translation map if cargo type hasn't been set, either explicitly or by aircraft cargo handling. */
|
||||
if (!IsValidCargoID(e->info.cargo_type)) {
|
||||
e->info.cargo_type = GetCargoIDByLabel(e->info.cargo_label);
|
||||
}
|
||||
|
||||
/* 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 */
|
||||
@@ -10632,7 +10644,7 @@ static void CalculateRefitMasks()
|
||||
static constexpr byte Y = 1 << LT_TOYLAND;
|
||||
static const struct DefaultRefitMasks {
|
||||
byte climate;
|
||||
CargoType cargo_type;
|
||||
CargoLabel cargo_label;
|
||||
CargoTypes cargo_allowed;
|
||||
CargoTypes cargo_disallowed;
|
||||
} _default_refit_masks[] = {
|
||||
@@ -10656,13 +10668,13 @@ static void CalculateRefitMasks()
|
||||
_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:
|
||||
switch (ei->cargo_label.base()) {
|
||||
case CT_PASSENGERS.base():
|
||||
/* Ferries */
|
||||
_gted[engine].cargo_allowed = CC_PASSENGERS;
|
||||
_gted[engine].cargo_disallowed = 0;
|
||||
break;
|
||||
case CT_OIL:
|
||||
case CT_OIL.base():
|
||||
/* Tankers */
|
||||
_gted[engine].cargo_allowed = CC_LIQUID;
|
||||
_gted[engine].cargo_disallowed = 0;
|
||||
@@ -10689,7 +10701,7 @@ static void CalculateRefitMasks()
|
||||
/* 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;
|
||||
if (drm.cargo_label != ei->cargo_label) continue;
|
||||
|
||||
_gted[engine].cargo_allowed = drm.cargo_allowed;
|
||||
_gted[engine].cargo_disallowed = drm.cargo_disallowed;
|
||||
@@ -10702,9 +10714,7 @@ static void CalculateRefitMasks()
|
||||
}
|
||||
_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 != INVALID_CARGO) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
|
||||
if (IsValidCargoID(ei->cargo_type)) ClrBit(_gted[engine].ctt_exclude_mask, ei->cargo_type);
|
||||
}
|
||||
|
||||
/* Compute refittability */
|
||||
@@ -10857,9 +10867,9 @@ void FinaliseCargoArray()
|
||||
for (CargoSpec &cs : CargoSpec::array) {
|
||||
if (cs.town_production_effect == INVALID_TPE) {
|
||||
/* Set default town production effect by cargo label. */
|
||||
switch (cs.label) {
|
||||
case 'PASS': cs.town_production_effect = TPE_PASSENGERS; break;
|
||||
case 'MAIL': cs.town_production_effect = TPE_MAIL; break;
|
||||
switch (cs.label.base()) {
|
||||
case CT_PASSENGERS.base(): cs.town_production_effect = TPE_PASSENGERS; break;
|
||||
case CT_MAIL.base(): cs.town_production_effect = TPE_MAIL; break;
|
||||
default: cs.town_production_effect = TPE_NONE; break;
|
||||
}
|
||||
}
|
||||
@@ -11003,6 +11013,13 @@ static void FinaliseHouseArray()
|
||||
* this one in the pool is properly handled as 1x1 house. */
|
||||
hs->building_flags = TILE_NO_FLAG;
|
||||
}
|
||||
|
||||
/* Apply default cargo translation map for unset cargo slots */
|
||||
for (uint i = 0; i < lengthof(hs->accepts_cargo); ++i) {
|
||||
if (!IsValidCargoID(hs->accepts_cargo[i])) hs->accepts_cargo[i] = GetCargoIDByLabel(hs->accepts_cargo_label[i]);
|
||||
/* Disable acceptance if cargo type is invalid. */
|
||||
if (!IsValidCargoID(hs->accepts_cargo[i])) hs->cargo_acceptance[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
HouseZones climate_mask = (HouseZones)(1 << (_settings_game.game_creation.landscape + 12));
|
||||
@@ -11077,6 +11094,21 @@ static void FinaliseIndustriesArray()
|
||||
if (!indsp.enabled) {
|
||||
indsp.name = STR_NEWGRF_INVALID_INDUSTRYTYPE;
|
||||
}
|
||||
|
||||
/* Apply default cargo translation map for unset cargo slots */
|
||||
for (uint i = 0; i < lengthof(indsp.produced_cargo); ++i) {
|
||||
if (!IsValidCargoID(indsp.produced_cargo[i])) indsp.produced_cargo[i] = GetCargoIDByLabel(indsp.produced_cargo_label[i]);
|
||||
}
|
||||
for (uint i = 0; i < lengthof(indsp.accepts_cargo); ++i) {
|
||||
if (!IsValidCargoID(indsp.accepts_cargo[i])) indsp.accepts_cargo[i] = GetCargoIDByLabel(indsp.accepts_cargo_label[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto &indtsp : _industry_tile_specs) {
|
||||
/* Apply default cargo translation map for unset cargo slots */
|
||||
for (uint i = 0; i < lengthof(indtsp.accepts_cargo); ++i) {
|
||||
if (!IsValidCargoID(indtsp.accepts_cargo[i])) indtsp.accepts_cargo[i] = GetCargoIDByLabel(indtsp.accepts_cargo_label[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@ GrfSpecFeature CargoResolverObject::GetFeature() const
|
||||
|
||||
uint32_t CargoResolverObject::GetDebugID() const
|
||||
{
|
||||
return this->cargospec->label;
|
||||
return this->cargospec->label.base();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -17,6 +17,7 @@
|
||||
|
||||
/* virtual */ uint32_t TownScopeResolver::GetVariable(uint16_t variable, uint32_t parameter, GetVariableExtra *extra) const
|
||||
{
|
||||
CargoID cid;
|
||||
switch (variable) {
|
||||
/* Larger towns */
|
||||
case 0x40:
|
||||
@@ -81,24 +82,24 @@
|
||||
case 0xB2: return this->t->statues;
|
||||
case 0xB6: return ClampTo<uint16_t>(this->t->cache.num_houses);
|
||||
case 0xB9: return this->t->growth_rate / TOWN_GROWTH_TICKS;
|
||||
case 0xBA: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_max);
|
||||
case 0xBB: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_max), 8, 8);
|
||||
case 0xBC: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_max);
|
||||
case 0xBD: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_max), 8, 8);
|
||||
case 0xBE: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_act);
|
||||
case 0xBF: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].new_act), 8, 8);
|
||||
case 0xC0: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_act);
|
||||
case 0xC1: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].new_act), 8, 8);
|
||||
case 0xC2: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_max);
|
||||
case 0xC3: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_max), 8, 8);
|
||||
case 0xC4: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_max);
|
||||
case 0xC5: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_max), 8, 8);
|
||||
case 0xC6: return ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_act);
|
||||
case 0xC7: return GB(ClampTo<uint16_t>(this->t->supplied[CT_PASSENGERS].old_act), 8, 8);
|
||||
case 0xC8: return ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_act);
|
||||
case 0xC9: return GB(ClampTo<uint16_t>(this->t->supplied[CT_MAIL].old_act), 8, 8);
|
||||
case 0xCA: return this->t->GetPercentTransported(CT_PASSENGERS);
|
||||
case 0xCB: return this->t->GetPercentTransported(CT_MAIL);
|
||||
case 0xBA: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_max) : 0;
|
||||
case 0xBB: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_max), 8, 8) : 0;
|
||||
case 0xBC: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_max) : 0;
|
||||
case 0xBD: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_max), 8, 8) : 0;
|
||||
case 0xBE: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_act) : 0;
|
||||
case 0xBF: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_act), 8, 8) : 0;
|
||||
case 0xC0: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].new_act) : 0;
|
||||
case 0xC1: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].new_act), 8, 8) : 0;
|
||||
case 0xC2: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_max) : 0;
|
||||
case 0xC3: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_max), 8, 8) : 0;
|
||||
case 0xC4: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_max) : 0;
|
||||
case 0xC5: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_max), 8, 8) : 0;
|
||||
case 0xC6: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_act) : 0;
|
||||
case 0xC7: cid = GetCargoIDByLabel(CT_PASSENGERS); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_act), 8, 8) : 0;
|
||||
case 0xC8: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? ClampTo<uint16_t>(this->t->supplied[cid].old_act) : 0;
|
||||
case 0xC9: cid = GetCargoIDByLabel(CT_MAIL); return IsValidCargoID(cid) ? GB(ClampTo<uint16_t>(this->t->supplied[cid].old_act), 8, 8) : 0;
|
||||
case 0xCA: return this->t->GetPercentTransported(GetCargoIDByLabel(CT_PASSENGERS));
|
||||
case 0xCB: return this->t->GetPercentTransported(GetCargoIDByLabel(CT_MAIL));
|
||||
case 0xCC: return this->t->received[TAE_FOOD].new_act;
|
||||
case 0xCD: return GB(this->t->received[TAE_FOOD].new_act, 8, 8);
|
||||
case 0xCE: return this->t->received[TAE_WATER].new_act;
|
||||
|
@@ -819,23 +819,31 @@ static void AddAcceptedCargo_Object(TileIndex tile, CargoArray &acceptance, Carg
|
||||
|
||||
/* Top town building generates 10, so to make HQ interesting, the top
|
||||
* type makes 20. */
|
||||
acceptance[CT_PASSENGERS] += std::max(1U, level);
|
||||
SetBit(*always_accepted, CT_PASSENGERS);
|
||||
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
|
||||
if (IsValidCargoID(pass)) {
|
||||
acceptance[pass] += std::max(1U, level);
|
||||
SetBit(*always_accepted, pass);
|
||||
}
|
||||
|
||||
/* Top town building generates 4, HQ can make up to 8. The
|
||||
* proportion passengers:mail is different because such a huge
|
||||
* commercial building generates unusually high amount of mail
|
||||
* correspondence per physical visitor. */
|
||||
acceptance[CT_MAIL] += std::max(1U, level / 2);
|
||||
SetBit(*always_accepted, CT_MAIL);
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail)) {
|
||||
acceptance[mail] += std::max(1U, level / 2);
|
||||
SetBit(*always_accepted, mail);
|
||||
}
|
||||
}
|
||||
|
||||
static void AddProducedCargo_Object(TileIndex tile, CargoArray &produced)
|
||||
{
|
||||
if (!IsObjectType(tile, OBJECT_HQ)) return;
|
||||
|
||||
produced[CT_PASSENGERS]++;
|
||||
produced[CT_MAIL]++;
|
||||
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
|
||||
if (IsValidCargoID(pass)) produced[pass]++;
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail)) produced[mail]++;
|
||||
}
|
||||
|
||||
|
||||
@@ -979,19 +987,31 @@ static void TileLoop_Object(TileIndex tile)
|
||||
|
||||
uint r = Random();
|
||||
/* Top town buildings generate 250, so the top HQ type makes 256. */
|
||||
if (GB(r, 0, 8) < (256 / 4 / (6 - level))) {
|
||||
CargoID pass = GetCargoIDByLabel(CT_PASSENGERS);
|
||||
if (IsValidCargoID(pass) && GB(r, 0, 8) < (256 / 4 / (6 - level))) {
|
||||
uint amt = GB(r, 0, 8) / 8 / 4 + 1;
|
||||
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
|
||||
MoveGoodsToStation(CT_PASSENGERS, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
|
||||
|
||||
/* Scale by cargo scale setting. */
|
||||
amt = _town_cargo_scaler.ScaleAllowTrunc(amt);
|
||||
if (amt != 0) {
|
||||
MoveGoodsToStation(pass, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
|
||||
}
|
||||
}
|
||||
|
||||
/* Top town building generates 90, HQ can make up to 196. The
|
||||
* proportion passengers:mail is about the same as in the acceptance
|
||||
* equations. */
|
||||
if (GB(r, 8, 8) < (196 / 4 / (6 - level))) {
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail) && GB(r, 8, 8) < (196 / 4 / (6 - level))) {
|
||||
uint amt = GB(r, 8, 8) / 8 / 4 + 1;
|
||||
if (EconomyIsInRecession()) amt = (amt + 1) >> 1;
|
||||
MoveGoodsToStation(CT_MAIL, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
|
||||
|
||||
/* Scale by cargo scale setting. */
|
||||
amt = _town_cargo_scaler.ScaleAllowTrunc(amt);
|
||||
if (amt != 0) {
|
||||
MoveGoodsToStation(mail, amt, SourceType::Headquarters, GetTileOwner(tile), stations.GetStations());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -1305,7 +1305,7 @@ static void MakeNewEditorWorld()
|
||||
* @param error_detail Optional string to fill with detaied error information.
|
||||
*/
|
||||
bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileType dft, GameMode newgm, Subdirectory subdir,
|
||||
struct LoadFilter *lf = nullptr, std::string *error_detail = nullptr)
|
||||
std::shared_ptr<struct LoadFilter> lf = nullptr, std::string *error_detail = nullptr)
|
||||
{
|
||||
assert(fop == SLO_LOAD);
|
||||
assert(dft == DFT_GAME_FILE || (lf == nullptr && dft == DFT_OLD_GAME_FILE));
|
||||
@@ -1313,7 +1313,7 @@ bool SafeLoad(const std::string &filename, SaveLoadOperation fop, DetailedFileTy
|
||||
|
||||
_game_mode = newgm;
|
||||
|
||||
SaveOrLoadResult result = (lf == nullptr) ? SaveOrLoad(filename, fop, dft, subdir) : LoadWithFilter(lf);
|
||||
SaveOrLoadResult result = (lf == nullptr) ? SaveOrLoad(filename, fop, dft, subdir) : LoadWithFilter(std::move(lf));
|
||||
if (result == SL_OK) return true;
|
||||
|
||||
if (error_detail != nullptr) *error_detail = GetSaveLoadErrorString();
|
||||
|
@@ -3207,7 +3207,7 @@ VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v, Pro
|
||||
// OrderConditionCompare ignores the last parameter for occ == OCC_IS_TRUE or occ == OCC_IS_FALSE.
|
||||
switch (order->GetConditionVariable()) {
|
||||
case OCV_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, nullptr), value); break;
|
||||
case OCV_CARGO_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilledOfCargo(v, (CargoType) value), order->GetXData()); break;
|
||||
case OCV_CARGO_LOAD_PERCENTAGE: skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilledOfCargo(v, (CargoID)value), order->GetXData()); break;
|
||||
case OCV_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->reliability), value); break;
|
||||
case OCV_MAX_RELIABILITY: skip_order = OrderConditionCompare(occ, ToPercent16(v->GetEngine()->reliability), value); break;
|
||||
case OCV_MAX_SPEED: skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed() * 10 / 16, value); break;
|
||||
|
@@ -8,6 +8,7 @@
|
||||
/** @file water_regions.cpp Handles dividing the water in the map into square regions to assist pathfinding. */
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "debug_fmt.h"
|
||||
#include "map_func.h"
|
||||
#include "water_regions.h"
|
||||
#include "map_func.h"
|
||||
@@ -86,6 +87,9 @@ class WaterRegion
|
||||
bool has_cross_region_aqueducts = false;
|
||||
TWaterRegionPatchLabel number_of_patches = 0; // 0 = no water, 1 = one single patch of water, etc...
|
||||
std::unique_ptr<TWaterRegionPatchLabelArray> tile_patch_labels;
|
||||
|
||||
public:
|
||||
void Invalidate() { this->initialized = false; }
|
||||
};
|
||||
|
||||
static std::unique_ptr<TWaterRegionPatchLabelArray> _spare_labels;
|
||||
@@ -186,6 +190,7 @@ public:
|
||||
}
|
||||
|
||||
this->wr.tile_patch_labels->fill(INVALID_WATER_REGION_PATCH);
|
||||
this->wr.edge_traversability_bits.fill(0);
|
||||
|
||||
TWaterRegionPatchLabel current_label = 1;
|
||||
TWaterRegionPatchLabel highest_assigned_label = 0;
|
||||
@@ -222,7 +227,18 @@ public:
|
||||
for (const Trackdir dir : SetTrackdirBitIterator(valid_dirs)) {
|
||||
/* By using a TrackFollower we "play by the same rules" as the actual ship pathfinder */
|
||||
CFollowTrackWater ft;
|
||||
if (ft.Follow(tile, dir) && this->ContainsTile(ft.m_new_tile)) tiles_to_check.push_back(ft.m_new_tile);
|
||||
if (ft.Follow(tile, dir)) {
|
||||
if (this->ContainsTile(ft.m_new_tile)) {
|
||||
tiles_to_check.push_back(ft.m_new_tile);
|
||||
} else if (!ft.m_is_bridge) {
|
||||
assert(DistanceManhattan(ft.m_new_tile, tile) == 1);
|
||||
const auto side = DiagdirBetweenTiles(tile, ft.m_new_tile);
|
||||
const int local_x_or_y = DiagDirToAxis(side) == AXIS_X ? TileY(tile) - this->tile_y : TileX(tile) - this->tile_x;
|
||||
SetBit(this->wr.edge_traversability_bits[side], local_x_or_y);
|
||||
} else {
|
||||
this->wr.has_cross_region_aqueducts = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,18 +248,6 @@ public:
|
||||
this->wr.number_of_patches = highest_assigned_label;
|
||||
this->wr.initialized = true;
|
||||
|
||||
/* Calculate the traversability (whether the tile can be entered / exited) for all edges. Note that
|
||||
* we always follow the same X and Y scanning direction, this is important for comparisons later on! */
|
||||
this->wr.edge_traversability_bits.fill(0);
|
||||
const uint32_t top_x = this->tile_x;
|
||||
const uint32_t top_y = this->tile_y;
|
||||
for (uint32_t i = 0; i < WATER_REGION_EDGE_LENGTH; ++i) {
|
||||
if (GetWaterTracks(TileXY(top_x + i, top_y)) & TRACK_BIT_3WAY_NW) SetBit(this->wr.edge_traversability_bits[DIAGDIR_NW], i); // NW edge
|
||||
if (GetWaterTracks(TileXY(top_x + i, top_y + WATER_REGION_EDGE_LENGTH - 1)) & TRACK_BIT_3WAY_SE) SetBit(this->wr.edge_traversability_bits[DIAGDIR_SE], i); // SE edge
|
||||
if (GetWaterTracks(TileXY(top_x, top_y + i)) & TRACK_BIT_3WAY_NE) SetBit(this->wr.edge_traversability_bits[DIAGDIR_NE], i); // NE edge
|
||||
if (GetWaterTracks(TileXY(top_x + WATER_REGION_EDGE_LENGTH - 1, top_y + i)) & TRACK_BIT_3WAY_SW) SetBit(this->wr.edge_traversability_bits[DIAGDIR_SW], i); // SW edge
|
||||
}
|
||||
|
||||
if (this->wr.number_of_patches == 0 || (this->wr.number_of_patches == 1 && !this->HasNonMatchingPatchLabel(1))) {
|
||||
/* No need for patch storage: trivial cases */
|
||||
_spare_labels = std::move(this->wr.tile_patch_labels);
|
||||
@@ -273,6 +277,33 @@ public:
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void PrintDebugInfo()
|
||||
{
|
||||
Debug(map, 9, "Water region {},{} labels and edge traversability = ...", this->tile_x / WATER_REGION_EDGE_LENGTH, this->tile_y / WATER_REGION_EDGE_LENGTH);
|
||||
|
||||
const size_t max_element_width = std::to_string(this->wr.number_of_patches).size();
|
||||
|
||||
std::array<int, 16> traversability_NW{0};
|
||||
for (auto bitIndex : SetBitIterator(GetEdgeTraversabilityBits(DIAGDIR_NW))) *(traversability_NW.rbegin() + bitIndex) = 1;
|
||||
Debug(map, 9, " {:{}}", fmt::join(traversability_NW, " "), max_element_width);
|
||||
Debug(map, 9, " +{:->{}}+", "", WATER_REGION_EDGE_LENGTH * (max_element_width + 1) + 1);
|
||||
|
||||
for (uint y = 0; y < WATER_REGION_EDGE_LENGTH; ++y) {
|
||||
std::string line{};
|
||||
for (uint x = 0; x < WATER_REGION_EDGE_LENGTH; ++x) {
|
||||
const auto label = this->GetLabel(TileXY(this->tile_x + x, this->tile_y + y));
|
||||
const std::string label_str = label == INVALID_WATER_REGION_PATCH ? "." : std::to_string(label);
|
||||
line = fmt::format("{:{}}", label_str, max_element_width) + " " + line;
|
||||
}
|
||||
Debug(map, 9, "{} | {}| {}", GB(this->GetEdgeTraversabilityBits(DIAGDIR_SW), y, 1), line, GB(this->GetEdgeTraversabilityBits(DIAGDIR_NE), y, 1));
|
||||
}
|
||||
|
||||
Debug(map, 9, " +{:->{}}+", "", WATER_REGION_EDGE_LENGTH * (max_element_width + 1) + 1);
|
||||
std::array<int, 16> traversability_SE{0};
|
||||
for (auto bitIndex : SetBitIterator(this->GetEdgeTraversabilityBits(DIAGDIR_SE))) *(traversability_SE.rbegin() + bitIndex) = 1;
|
||||
Debug(map, 9, " {:{}}", fmt::join(traversability_SE, " "), max_element_width);
|
||||
}
|
||||
};
|
||||
|
||||
std::unique_ptr<WaterRegion[]> _water_regions;
|
||||
@@ -371,9 +402,20 @@ WaterRegionPatchDesc GetWaterRegionPatchInfo(TileIndex tile)
|
||||
*/
|
||||
void InvalidateWaterRegion(TileIndex tile)
|
||||
{
|
||||
if (tile < MapSize()) {
|
||||
GetWaterRegionRef(tile).Invalidate();
|
||||
}
|
||||
if (tile >= MapSize()) return;
|
||||
|
||||
const TWaterRegionIndex region = GetWaterRegionIndex(tile);
|
||||
_water_regions[region].Invalidate();
|
||||
|
||||
/* When updating the water region we look into the first tile of adjacent water regions to determine edge
|
||||
* traversability. This means that if we invalidate any region edge tiles we might also change the traversability
|
||||
* of the adjacent region. This code ensures the adjacent regions also get invalidated in such a case. */
|
||||
const uint x = TileX(tile);
|
||||
const uint y = TileY(tile);
|
||||
if ((x & WATER_REGION_EDGE_MASK) == 0 && x > 0) _water_regions[region - 1].Invalidate();
|
||||
if ((x & WATER_REGION_EDGE_MASK) == WATER_REGION_EDGE_MASK && x < MapMaxX()) _water_regions[region + 1].Invalidate();
|
||||
if ((y & WATER_REGION_EDGE_MASK) == 0 && y > 0) _water_regions[region - GetWaterRegionMapSizeX()].Invalidate();
|
||||
if ((y & WATER_REGION_EDGE_MASK) == WATER_REGION_EDGE_MASK && y < MapMaxY()) _water_regions[region + GetWaterRegionMapSizeX()].Invalidate();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -553,3 +595,8 @@ void WaterRegionCheckCaches(std::function<void(const char *)> log)
|
||||
}
|
||||
#undef CCLOG
|
||||
}
|
||||
|
||||
void PrintWaterRegionDebugInfo(TileIndex tile)
|
||||
{
|
||||
if (_debug_map_level >= 9) GetUpdatedWaterRegion(tile).PrintDebugInfo();
|
||||
}
|
||||
|
@@ -79,4 +79,6 @@ struct WaterRegionSaveLoadInfo
|
||||
bool initialized;
|
||||
};
|
||||
|
||||
void PrintWaterRegionDebugInfo(TileIndex tile);
|
||||
|
||||
#endif /* WATER_REGIONS_H */
|
||||
|
@@ -302,6 +302,7 @@ CommandCost CmdBuildRoadVehicle(TileIndex tile, DoCommandFlag flags, const Engin
|
||||
|
||||
v->spritenum = rvi->image_index;
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
v->cargo_cap = rvi->capacity;
|
||||
v->refit_cap = 0;
|
||||
|
||||
|
@@ -133,22 +133,23 @@ static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
/* Slots 0 and 2 are passengers and mail respectively for old saves. */
|
||||
SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[0].old_max, "supplied[CT_PASSENGERS].old_max", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[2].old_max, "supplied[CT_MAIL].old_max", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[0].new_max, "supplied[CT_PASSENGERS].new_max", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[2].new_max, "supplied[CT_MAIL].new_max", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[0].old_act, "supplied[CT_PASSENGERS].old_act", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[2].old_act, "supplied[CT_MAIL].old_act", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[0].new_act, "supplied[CT_PASSENGERS].new_act", SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVARNAME(Town, supplied[2].new_act, "supplied[CT_MAIL].new_act", SLE_UINT32, SLV_9, SLV_165),
|
||||
|
||||
SLE_CONDVARNAME(Town, received[TAE_FOOD].old_act, "received[TE_FOOD].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
SLE_CONDVARNAME(Town, received[TAE_WATER].old_act, "received[TE_WATER].old_act", SLE_UINT16, SL_MIN_VERSION, SLV_165),
|
||||
|
@@ -44,7 +44,7 @@
|
||||
* like "PASS", "COAL", "OIL_". New ones can be defined by NewGRFs */
|
||||
std::string cargo_label;
|
||||
for (uint i = 0; i < sizeof(cargo->label); i++) {
|
||||
cargo_label.push_back(GB(cargo->label, (uint8_t)(sizeof(cargo->label) - i - 1) * 8, 8));
|
||||
cargo_label.push_back(GB(cargo->label.base(), (uint8_t)(sizeof(cargo->label) - i - 1) * 8, 8));
|
||||
}
|
||||
return cargo_label;
|
||||
}
|
||||
|
@@ -1186,6 +1186,7 @@ CommandCost CmdBuildShip(TileIndex tile, DoCommandFlag flags, const Engine *e, V
|
||||
|
||||
v->spritenum = svi->image_index;
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
v->cargo_cap = svi->capacity;
|
||||
v->refit_cap = 0;
|
||||
|
||||
|
@@ -589,14 +589,15 @@ static const OldChunks town_chunk[] = {
|
||||
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, time_until_rebuild ),
|
||||
OCL_SVAR( OC_FILE_U8 | OC_VAR_U16, Town, growth_rate ),
|
||||
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].new_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].new_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_PASSENGERS].old_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[CT_MAIL].old_act ),
|
||||
/* Slots 0 and 2 are passengers and mail respectively for old saves. */
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].new_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].new_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_max ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[0].old_act ),
|
||||
OCL_SVAR( OC_FILE_U16 | OC_VAR_U32, Town, supplied[2].old_act ),
|
||||
|
||||
OCL_NULL( 2 ), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
|
||||
|
||||
@@ -1304,10 +1305,10 @@ bool LoadOldVehicle(LoadgameState *ls, int num)
|
||||
|
||||
switch (v->spritenum) {
|
||||
case 2: // oil tanker && cargo type != oil
|
||||
if (v->cargo_type != CT_OIL) v->spritenum = 0; // make it a coal/goods ship
|
||||
if (v->cargo_type != 3) v->spritenum = 0; // make it a coal/goods ship
|
||||
break;
|
||||
case 4: // passenger ship && cargo type == mail
|
||||
if (v->cargo_type == CT_MAIL) v->spritenum = 0; // make it a mail ship
|
||||
if (v->cargo_type == 2) v->spritenum = 0; // make it a mail ship
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@@ -178,16 +178,16 @@ void MemoryDumper::AllocateBuffer()
|
||||
* Flush this dumper into a writer.
|
||||
* @param writer The filter we want to use.
|
||||
*/
|
||||
void MemoryDumper::Flush(SaveFilter *writer)
|
||||
void MemoryDumper::Flush(SaveFilter &writer)
|
||||
{
|
||||
this->FinaliseBlock();
|
||||
|
||||
size_t block_count = this->blocks.size();
|
||||
for (size_t i = 0; i < block_count; i++) {
|
||||
writer->Write(this->blocks[i].data, this->blocks[i].size);
|
||||
writer.Write(this->blocks[i].data, this->blocks[i].size);
|
||||
}
|
||||
|
||||
writer->Finish();
|
||||
writer.Finish();
|
||||
}
|
||||
|
||||
void MemoryDumper::StartAutoLength()
|
||||
@@ -234,11 +234,11 @@ struct SaveLoadParams {
|
||||
|
||||
uint32_t current_chunk_id; ///< Current chunk ID
|
||||
|
||||
MemoryDumper *dumper; ///< Memory dumper to write the savegame to.
|
||||
SaveFilter *sf; ///< Filter to write the savegame to.
|
||||
std::unique_ptr<MemoryDumper> dumper;///< Memory dumper to write the savegame to.
|
||||
std::shared_ptr<SaveFilter> sf; ///< Filter to write the savegame to.
|
||||
|
||||
ReadBuffer *reader; ///< Savegame reading buffer.
|
||||
LoadFilter *lf; ///< Filter to read the savegame from.
|
||||
std::unique_ptr<ReadBuffer> reader; ///< Savegame reading buffer.
|
||||
std::shared_ptr<LoadFilter> lf; ///< Filter to read the savegame from.
|
||||
|
||||
StringID error_str; ///< the translatable error message to show
|
||||
std::string extra_msg; ///< the error message
|
||||
@@ -251,12 +251,12 @@ static SaveLoadParams _sl; ///< Parameters used for/at saveload.
|
||||
|
||||
ReadBuffer *ReadBuffer::GetCurrent()
|
||||
{
|
||||
return _sl.reader;
|
||||
return _sl.reader.get();
|
||||
}
|
||||
|
||||
MemoryDumper *MemoryDumper::GetCurrent()
|
||||
{
|
||||
return _sl.dumper;
|
||||
return _sl.dumper.get();
|
||||
}
|
||||
|
||||
static const std::vector<ChunkHandler> &ChunkHandlers()
|
||||
@@ -2743,9 +2743,6 @@ struct FileReader : LoadFilter {
|
||||
{
|
||||
if (this->file != nullptr) fclose(this->file);
|
||||
this->file = nullptr;
|
||||
|
||||
/* Make sure we don't double free. */
|
||||
_sl.sf = nullptr;
|
||||
}
|
||||
|
||||
size_t Read(byte *buf, size_t size) override
|
||||
@@ -2781,9 +2778,6 @@ struct FileWriter : SaveFilter {
|
||||
~FileWriter()
|
||||
{
|
||||
this->Finish();
|
||||
|
||||
/* Make sure we don't double free. */
|
||||
_sl.sf = nullptr;
|
||||
}
|
||||
|
||||
void Write(byte *buf, size_t size) override
|
||||
@@ -2817,7 +2811,7 @@ struct LZOLoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
LZOLoadFilter(LoadFilter *chain) : LoadFilter(chain)
|
||||
LZOLoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain))
|
||||
{
|
||||
if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
|
||||
}
|
||||
@@ -2865,7 +2859,7 @@ struct LZOSaveFilter : SaveFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @param compression_level The requested level of compression.
|
||||
*/
|
||||
LZOSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
|
||||
LZOSaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level) : SaveFilter(std::move(chain))
|
||||
{
|
||||
if (lzo_init() != LZO_E_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
|
||||
}
|
||||
@@ -2905,7 +2899,7 @@ struct NoCompLoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
NoCompLoadFilter(LoadFilter *chain) : LoadFilter(chain)
|
||||
NoCompLoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2922,7 +2916,7 @@ struct NoCompSaveFilter : SaveFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @param compression_level The requested level of compression.
|
||||
*/
|
||||
NoCompSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
|
||||
NoCompSaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level) : SaveFilter(std::move(chain))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2948,7 +2942,7 @@ struct ZlibLoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
ZlibLoadFilter(LoadFilter *chain) : LoadFilter(chain)
|
||||
ZlibLoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain))
|
||||
{
|
||||
memset(&this->z, 0, sizeof(this->z));
|
||||
if (inflateInit(&this->z) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
|
||||
@@ -2993,7 +2987,7 @@ struct ZlibSaveFilter : SaveFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @param compression_level The requested level of compression.
|
||||
*/
|
||||
ZlibSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
|
||||
ZlibSaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level) : SaveFilter(std::move(chain))
|
||||
{
|
||||
memset(&this->z, 0, sizeof(this->z));
|
||||
if (deflateInit(&this->z, compression_level) != Z_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
|
||||
@@ -3077,7 +3071,7 @@ struct LZMALoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
LZMALoadFilter(LoadFilter *chain) : LoadFilter(chain), lzma(_lzma_init)
|
||||
LZMALoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain)), lzma(_lzma_init)
|
||||
{
|
||||
/* Allow saves up to 256 MB uncompressed */
|
||||
if (lzma_auto_decoder(&this->lzma, 1 << 28, 0) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize decompressor");
|
||||
@@ -3121,7 +3115,7 @@ struct LZMASaveFilter : SaveFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @param compression_level The requested level of compression.
|
||||
*/
|
||||
LZMASaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain), lzma(_lzma_init)
|
||||
LZMASaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level) : SaveFilter(std::move(chain)), lzma(_lzma_init)
|
||||
{
|
||||
if (lzma_easy_encoder(&this->lzma, compression_level, LZMA_CHECK_CRC32) != LZMA_OK) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
|
||||
}
|
||||
@@ -3190,7 +3184,7 @@ struct ZSTDLoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
ZSTDLoadFilter(LoadFilter *chain) : LoadFilter(chain)
|
||||
ZSTDLoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain))
|
||||
{
|
||||
this->zstd = ZSTD_createDCtx();
|
||||
if (!this->zstd) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
|
||||
@@ -3234,7 +3228,7 @@ struct ZSTDSaveFilter : SaveFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @param compression_level The requested level of compression.
|
||||
*/
|
||||
ZSTDSaveFilter(SaveFilter *chain, byte compression_level) : SaveFilter(chain)
|
||||
ZSTDSaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level) : SaveFilter(std::move(chain))
|
||||
{
|
||||
this->zstd = ZSTD_createCCtx();
|
||||
if (!this->zstd) SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, "cannot initialize compressor");
|
||||
@@ -3302,8 +3296,8 @@ struct SaveLoadFormat {
|
||||
const char *name; ///< name of the compressor/decompressor (debug-only)
|
||||
uint32_t tag; ///< the 4-letter tag by which it is identified in the savegame
|
||||
|
||||
LoadFilter *(*init_load)(LoadFilter *chain); ///< Constructor for the load filter.
|
||||
SaveFilter *(*init_write)(SaveFilter *chain, byte compression); ///< Constructor for the save filter.
|
||||
std::shared_ptr<LoadFilter> (*init_load)(std::shared_ptr<LoadFilter> chain); ///< Constructor for the load filter.
|
||||
std::shared_ptr<SaveFilter> (*init_write)(std::shared_ptr<SaveFilter> chain, byte compression); ///< Constructor for the save filter.
|
||||
|
||||
byte min_compression; ///< the minimum compression level of this format
|
||||
byte default_compression; ///< the default compression level of this format
|
||||
@@ -3420,20 +3414,11 @@ static void ResetSaveloadData()
|
||||
*/
|
||||
static inline void ClearSaveLoadState()
|
||||
{
|
||||
delete _sl.dumper;
|
||||
_sl.dumper = nullptr;
|
||||
|
||||
delete _sl.sf;
|
||||
_sl.sf = nullptr;
|
||||
|
||||
delete _sl.reader;
|
||||
_sl.reader = nullptr;
|
||||
|
||||
delete _sl.lf;
|
||||
_sl.lf = nullptr;
|
||||
|
||||
_sl.save_flags = SMF_NONE;
|
||||
|
||||
_sl.current_chunk_id = 0;
|
||||
|
||||
GamelogStopAnyAction();
|
||||
@@ -3500,7 +3485,7 @@ static SaveOrLoadResult SaveFileToDisk(bool threaded)
|
||||
_sl.sf->Write((byte*)hdr, sizeof(hdr));
|
||||
|
||||
_sl.sf = fmt->init_write(_sl.sf, compression);
|
||||
_sl.dumper->Flush(_sl.sf);
|
||||
_sl.dumper->Flush(*(_sl.sf));
|
||||
|
||||
ClearSaveLoadState();
|
||||
|
||||
@@ -3542,12 +3527,12 @@ void WaitTillSaved()
|
||||
* @param threaded Whether to try to perform the saving asynchronously.
|
||||
* @return Return the result of the action. #SL_OK or #SL_ERROR
|
||||
*/
|
||||
static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
|
||||
static SaveOrLoadResult DoSave(std::shared_ptr<SaveFilter> writer, bool threaded)
|
||||
{
|
||||
assert(!_sl.saveinprogress);
|
||||
|
||||
_sl.dumper = new MemoryDumper();
|
||||
_sl.sf = writer;
|
||||
_sl.dumper = std::make_unique<MemoryDumper>();
|
||||
_sl.sf = std::move(writer);
|
||||
|
||||
_sl_version = SAVEGAME_VERSION;
|
||||
SlXvSetCurrentState();
|
||||
@@ -3576,12 +3561,12 @@ static SaveOrLoadResult DoSave(SaveFilter *writer, bool threaded)
|
||||
* @param flags Save mode flags.
|
||||
* @return Return the result of the action. #SL_OK or #SL_ERROR
|
||||
*/
|
||||
SaveOrLoadResult SaveWithFilter(SaveFilter *writer, bool threaded, SaveModeFlags flags)
|
||||
SaveOrLoadResult SaveWithFilter(std::shared_ptr<SaveFilter> writer, bool threaded, SaveModeFlags flags)
|
||||
{
|
||||
try {
|
||||
_sl.action = SLA_SAVE;
|
||||
_sl.save_flags = flags;
|
||||
return DoSave(writer, threaded);
|
||||
return DoSave(std::move(writer), threaded);
|
||||
} catch (...) {
|
||||
ClearSaveLoadState();
|
||||
return SL_ERROR;
|
||||
@@ -3620,7 +3605,7 @@ struct ThreadedLoadFilter : LoadFilter {
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
ThreadedLoadFilter(LoadFilter *chain) : LoadFilter(chain)
|
||||
ThreadedLoadFilter(std::shared_ptr<LoadFilter> chain) : LoadFilter(std::move(chain))
|
||||
{
|
||||
std::unique_lock<std::mutex> lk(this->mutex);
|
||||
if (!StartNewThread(&this->read_thread, "ottd:loadgame", &ThreadedLoadFilter::RunThread, this)) {
|
||||
@@ -3710,9 +3695,9 @@ struct ThreadedLoadFilter : LoadFilter {
|
||||
* @param load_check Whether to perform the checking ("preview") or actually load the game.
|
||||
* @return Return the result of the action. #SL_OK or #SL_REINIT ("unload" the game)
|
||||
*/
|
||||
static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
|
||||
static SaveOrLoadResult DoLoad(std::shared_ptr<LoadFilter> reader, bool load_check)
|
||||
{
|
||||
_sl.lf = reader;
|
||||
_sl.lf = std::move(reader);
|
||||
|
||||
if (load_check) {
|
||||
/* Clear previous check data */
|
||||
@@ -3804,11 +3789,11 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
|
||||
SlError(STR_GAME_SAVELOAD_ERROR_BROKEN_INTERNAL_ERROR, err_str);
|
||||
}
|
||||
|
||||
_sl.lf = fmt->init_load(_sl.lf);
|
||||
_sl.lf = fmt->init_load(std::move(_sl.lf));
|
||||
if (!(fmt->flags & SLF_NO_THREADED_LOAD)) {
|
||||
_sl.lf = new ThreadedLoadFilter(_sl.lf);
|
||||
_sl.lf = std::make_shared<ThreadedLoadFilter>(std::move(_sl.lf));
|
||||
}
|
||||
_sl.reader = new ReadBuffer(_sl.lf);
|
||||
_sl.reader = std::make_unique<ReadBuffer>(_sl.lf);
|
||||
_next_offs = 0;
|
||||
|
||||
upstream_sl::SlResetLoadState();
|
||||
@@ -3948,11 +3933,11 @@ static SaveOrLoadResult DoLoad(LoadFilter *reader, bool load_check)
|
||||
* @param reader The filter to read the savegame from.
|
||||
* @return Return the result of the action. #SL_OK or #SL_REINIT ("unload" the game)
|
||||
*/
|
||||
SaveOrLoadResult LoadWithFilter(LoadFilter *reader)
|
||||
SaveOrLoadResult LoadWithFilter(std::shared_ptr<LoadFilter> reader)
|
||||
{
|
||||
try {
|
||||
_sl.action = SLA_LOAD;
|
||||
return DoLoad(reader, false);
|
||||
return DoLoad(std::move(reader), false);
|
||||
} catch (...) {
|
||||
ClearSaveLoadState();
|
||||
|
||||
@@ -4045,13 +4030,13 @@ SaveOrLoadResult SaveOrLoad(const std::string &filename, SaveLoadOperation fop,
|
||||
DEBUG(desync, 1, "save: %s; %s", debug_date_dumper().HexDate(), filename.c_str());
|
||||
if (!_settings_client.gui.threaded_saves) threaded = false;
|
||||
|
||||
return DoSave(new FileWriter(fh), threaded);
|
||||
return DoSave(std::make_shared<FileWriter>(fh), threaded);
|
||||
}
|
||||
|
||||
/* LOAD game */
|
||||
assert(fop == SLO_LOAD || fop == SLO_CHECK);
|
||||
DEBUG(desync, 1, "load: %s", filename.c_str());
|
||||
return DoLoad(new FileReader(fh), fop == SLO_CHECK);
|
||||
return DoLoad(std::make_shared<FileReader>(fh), fop == SLO_CHECK);
|
||||
} catch (...) {
|
||||
/* This code may be executed both for old and new save games. */
|
||||
ClearSaveLoadState();
|
||||
|
@@ -76,8 +76,8 @@ void DoExitSave();
|
||||
|
||||
void DoAutoOrNetsave(FiosNumberedSaveName &counter, bool threaded, FiosNumberedSaveName *lt_counter = nullptr);
|
||||
|
||||
SaveOrLoadResult SaveWithFilter(struct SaveFilter *writer, bool threaded, SaveModeFlags flags);
|
||||
SaveOrLoadResult LoadWithFilter(struct LoadFilter *reader);
|
||||
SaveOrLoadResult SaveWithFilter(std::shared_ptr<struct SaveFilter> writer, bool threaded, SaveModeFlags flags);
|
||||
SaveOrLoadResult LoadWithFilter(std::shared_ptr<struct LoadFilter> reader);
|
||||
bool IsNetworkServerSave();
|
||||
bool IsScenarioSave();
|
||||
|
||||
|
@@ -29,14 +29,14 @@ struct ReadBuffer {
|
||||
byte buf[MEMORY_CHUNK_SIZE]; ///< Buffer we're going to read from.
|
||||
byte *bufp; ///< Location we're at reading the buffer.
|
||||
byte *bufe; ///< End of the buffer we can read from.
|
||||
LoadFilter *reader; ///< The filter used to actually read.
|
||||
std::shared_ptr<LoadFilter> reader; ///< The filter used to actually read.
|
||||
size_t read; ///< The amount of read bytes so far from the filter.
|
||||
|
||||
/**
|
||||
* Initialise our variables.
|
||||
* @param reader The filter to actually read data.
|
||||
*/
|
||||
ReadBuffer(LoadFilter *reader) : bufp(nullptr), bufe(nullptr), reader(reader), read(0)
|
||||
ReadBuffer(std::shared_ptr<LoadFilter> reader) : bufp(nullptr), bufe(nullptr), reader(std::move(reader)), read(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -265,7 +265,7 @@ struct MemoryDumper {
|
||||
this->buf += 8;
|
||||
}
|
||||
|
||||
void Flush(SaveFilter *writer);
|
||||
void Flush(SaveFilter &writer);
|
||||
size_t GetSize() const;
|
||||
void StartAutoLength();
|
||||
std::pair<byte *, size_t> StopAutoLength();
|
||||
|
@@ -13,20 +13,19 @@
|
||||
/** Interface for filtering a savegame till it is loaded. */
|
||||
struct LoadFilter {
|
||||
/** Chained to the (savegame) filters. */
|
||||
LoadFilter *chain;
|
||||
std::shared_ptr<LoadFilter> chain;
|
||||
|
||||
/**
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
LoadFilter(LoadFilter *chain) : chain(chain)
|
||||
LoadFilter(std::shared_ptr<LoadFilter> chain) : chain(std::move(chain))
|
||||
{
|
||||
}
|
||||
|
||||
/** Make sure the writers are properly closed. */
|
||||
virtual ~LoadFilter()
|
||||
{
|
||||
delete this->chain;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -51,28 +50,27 @@ struct LoadFilter {
|
||||
* @param chain The next filter in this chain.
|
||||
* @tparam T The type of load filter to create.
|
||||
*/
|
||||
template <typename T> LoadFilter *CreateLoadFilter(LoadFilter *chain)
|
||||
template <typename T> std::shared_ptr<LoadFilter> CreateLoadFilter(std::shared_ptr<LoadFilter> chain)
|
||||
{
|
||||
return new T(chain);
|
||||
return std::make_shared<T>(chain);
|
||||
}
|
||||
|
||||
/** Interface for filtering a savegame till it is written. */
|
||||
struct SaveFilter {
|
||||
/** Chained to the (savegame) filters. */
|
||||
SaveFilter *chain;
|
||||
std::shared_ptr<SaveFilter> chain;
|
||||
|
||||
/**
|
||||
* Initialise this filter.
|
||||
* @param chain The next filter in this chain.
|
||||
*/
|
||||
SaveFilter(SaveFilter *chain) : chain(chain)
|
||||
SaveFilter(std::shared_ptr<SaveFilter> chain) : chain(std::move(chain))
|
||||
{
|
||||
}
|
||||
|
||||
/** Make sure the writers are properly closed. */
|
||||
virtual ~SaveFilter()
|
||||
{
|
||||
delete this->chain;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,9 +95,9 @@ struct SaveFilter {
|
||||
* @param compression_level The requested level of compression.
|
||||
* @tparam T The type of save filter to create.
|
||||
*/
|
||||
template <typename T> SaveFilter *CreateSaveFilter(SaveFilter *chain, byte compression_level)
|
||||
template <typename T> std::shared_ptr<SaveFilter> CreateSaveFilter(std::shared_ptr<SaveFilter> chain, byte compression_level)
|
||||
{
|
||||
return new T(chain, compression_level);
|
||||
return std::make_shared<T>(chain, compression_level);
|
||||
}
|
||||
|
||||
#endif /* SL_SAVELOAD_FILTER_H */
|
||||
|
@@ -183,31 +183,31 @@ static const SaveLoad _town_desc[] = {
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, 8, SLV_4, SLV_104),
|
||||
SLE_CONDARR(Town, unwanted, SLE_INT8, MAX_COMPANIES, SLV_104, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[0].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[2].old_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[0].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[2].new_max, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[0].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[2].old_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[0].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
SLE_CONDVAR(Town, supplied[2].new_act, SLE_FILE_U16 | SLE_VAR_U32, SL_MIN_VERSION, SLV_9),
|
||||
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[0].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[2].old_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[0].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[2].new_max, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[0].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[2].old_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_PASSENGERS].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[0].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDNULL_X(4, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
SLE_CONDVAR(Town, supplied[CT_MAIL].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
SLE_CONDVAR(Town, supplied[2].new_act, SLE_UINT32, SLV_9, SLV_165),
|
||||
|
||||
SLE_CONDNULL(2, SL_MIN_VERSION, SLV_164), ///< pct_pass_transported / pct_mail_transported, now computed on the fly
|
||||
SLE_CONDNULL_X(3, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_CHILLPP, SL_CHILLPP_232)),
|
||||
|
@@ -1128,8 +1128,10 @@ enum IndustryTypes {
|
||||
#define MI(tbl, sndc, snd, d, pc, ai1, ai2, ai3, ai4, ag1, ag2, ag3, ag4, col, \
|
||||
c1, c2, c3, proc, p1, r1, p2, r2, m, a1, im1, a2, im2, a3, im3, pr, clim, bev, in, intx, s1, s2, s3) \
|
||||
{tbl, {}, d, 0, pc, {c1, c2, c3}, proc, \
|
||||
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
|
||||
{p1, p2, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
|
||||
{r1, r2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, m, \
|
||||
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
|
||||
{a1, a2, a3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
|
||||
{{im1, 0}, {im2, 0}, {im3, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}, {0, 0}}, \
|
||||
pr, clim, bev, col, in, intx, s1, s2, s3, STR_UNDEFINED, {ai1, ai2, ai3, ai4}, {ag1, ag2, ag3, ag4}, \
|
||||
@@ -1530,7 +1532,11 @@ static const IndustrySpec _origin_industry_specs[NEW_INDUSTRYOFFSET] = {
|
||||
* @param a2 next frame of animation
|
||||
* @param a3 chooses between animation or construction state
|
||||
*/
|
||||
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) {{c1, c2, c3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, {ca1, ca2, ca3}, sl, a1, a2, a3, 0, {0, ANIM_STATUS_NO_ANIMATION, 2, 0}, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE)}
|
||||
#define MT(ca1, c1, ca2, c2, ca3, c3, sl, a1, a2, a3) { \
|
||||
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
|
||||
{c1, c2, c3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
|
||||
{ca1, ca2, ca3}, sl, a1, a2, a3, 0, {0, ANIM_STATUS_NO_ANIMATION, 2, 0}, INDTILE_SPECIAL_NONE, true, GRFFileProps(INVALID_INDUSTRYTILE) \
|
||||
}
|
||||
static const IndustryTileSpec _origin_industry_tile_specs[NEW_INDUSTRYTILEOFFSET] = {
|
||||
/* Coal Mine */
|
||||
MT(0, CT_INVALID, 0, CT_INVALID, 0, CT_INVALID, SLOPE_STEEP, INDUSTRYTILE_NOANIM, INDUSTRYTILE_NOANIM, false),
|
||||
|
@@ -7,6 +7,8 @@
|
||||
|
||||
/** @file cargo_const.h Table of all default cargo types */
|
||||
|
||||
#include <variant>
|
||||
|
||||
/** Construction macros for the #CargoSpec StringID entries. */
|
||||
#define MK_STR_CARGO_PLURAL(label_plural) STR_CARGO_PLURAL_ ## label_plural
|
||||
#define MK_STR_CARGO_SINGULAR(label_singular) STR_CARGO_SINGULAR_ ## label_singular
|
||||
@@ -50,56 +52,56 @@
|
||||
|
||||
/** Cargo types available by default. */
|
||||
static const CargoSpec _default_cargo[] = {
|
||||
MK( 0, 'PASS', 152, 1, 0x400, 3185, 0, 24, false, TAE_PASSENGERS, PASSENGERS, PASSENGER, STR_PASSENGERS, CC_PASSENGERS),
|
||||
MK( 1, 'COAL', 6, 16, 0x100, 5916, 7, 255, true, TAE_NONE, COAL, COAL, STR_TONS, CC_BULK),
|
||||
MK( 2, 'MAIL', 15, 4, 0x200, 4550, 20, 90, false, TAE_MAIL, MAIL, MAIL, STR_BAGS, CC_MAIL),
|
||||
MK( 0, CT_PASSENGERS, 152, 1, 0x400, 3185, 0, 24, false, TAE_PASSENGERS, PASSENGERS, PASSENGER, STR_PASSENGERS, CC_PASSENGERS),
|
||||
MK( 1, CT_COAL, 6, 16, 0x100, 5916, 7, 255, true, TAE_NONE, COAL, COAL, STR_TONS, CC_BULK),
|
||||
MK( 2, CT_MAIL, 15, 4, 0x200, 4550, 20, 90, false, TAE_MAIL, MAIL, MAIL, STR_BAGS, CC_MAIL),
|
||||
/* Oil in temperate and arctic */
|
||||
MK( 3, 'OIL_', 174, 16, 0x100, 4437, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
|
||||
MK( 3, CT_OIL, 174, 16, 0x100, 4437, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
|
||||
/* Oil in subtropic */
|
||||
MK( 3, 'OIL_', 174, 16, 0x100, 4892, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
|
||||
MK( 4, 'LVST', 208, 3, 0x100, 4322, 4, 18, true, TAE_NONE, LIVESTOCK, LIVESTOCK, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 5, 'GOOD', 194, 8, 0x200, 6144, 5, 28, true, TAE_GOODS, GOODS, GOODS, STR_CRATES, CC_EXPRESS),
|
||||
MK( 6, 'GRAI', 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, GRAIN, GRAIN, STR_TONS, CC_BULK),
|
||||
MK( 6, 'WHEA', 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, WHEAT, WHEAT, STR_TONS, CC_BULK),
|
||||
MK( 6, 'MAIZ', 191, 16, 0x100, 4322, 4, 40, true, TAE_NONE, MAIZE, MAIZE, STR_TONS, CC_BULK),
|
||||
MK( 3, CT_OIL, 174, 16, 0x100, 4892, 25, 255, true, TAE_NONE, OIL, OIL, STR_LITERS, CC_LIQUID),
|
||||
MK( 4, CT_LIVESTOCK, 208, 3, 0x100, 4322, 4, 18, true, TAE_NONE, LIVESTOCK, LIVESTOCK, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 5, CT_GOODS, 194, 8, 0x200, 6144, 5, 28, true, TAE_GOODS, GOODS, GOODS, STR_CRATES, CC_EXPRESS),
|
||||
MK( 6, CT_GRAIN, 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, GRAIN, GRAIN, STR_TONS, CC_BULK),
|
||||
MK( 6, CT_WHEAT, 191, 16, 0x100, 4778, 4, 40, true, TAE_NONE, WHEAT, WHEAT, STR_TONS, CC_BULK),
|
||||
MK( 6, CT_MAIZE, 191, 16, 0x100, 4322, 4, 40, true, TAE_NONE, MAIZE, MAIZE, STR_TONS, CC_BULK),
|
||||
/* Wood in temperate and arctic */
|
||||
MK( 7, 'WOOD', 84, 16, 0x100, 5005, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 7, CT_WOOD, 84, 16, 0x100, 5005, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
|
||||
/* Wood in subtropic */
|
||||
MK( 7, 'WOOD', 84, 16, 0x100, 7964, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 8, 'IORE', 184, 16, 0x100, 5120, 9, 255, true, TAE_NONE, IRON_ORE, IRON_ORE, STR_TONS, CC_BULK),
|
||||
MK( 9, 'STEL', 10, 16, 0x100, 5688, 7, 255, true, TAE_NONE, STEEL, STEEL, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 10, 'VALU', 202, 2, 0x100, 7509, 1, 32, true, TAE_NONE, VALUABLES, VALUABLES, STR_BAGS, CC_ARMOURED),
|
||||
MK( 10, 'GOLD', 202, 8, 0x100, 5802, 10, 40, true, TAE_NONE, GOLD, GOLD, STR_BAGS, CC_ARMOURED),
|
||||
MK( 10, 'DIAM', 202, 2, 0x100, 5802, 10, 255, true, TAE_NONE, DIAMONDS, DIAMOND, STR_BAGS, CC_ARMOURED),
|
||||
MK( 11, 'PAPR', 10, 16, 0x100, 5461, 7, 60, true, TAE_NONE, PAPER, PAPER, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 12, 'FOOD', 48, 16, 0x100, 5688, 0, 30, true, TAE_FOOD, FOOD, FOOD, STR_TONS, CC_EXPRESS | CC_REFRIGERATED),
|
||||
MK( 13, 'FRUT', 208, 16, 0x100, 4209, 0, 15, true, TAE_NONE, FRUIT, FRUIT, STR_TONS, CC_BULK | CC_REFRIGERATED),
|
||||
MK( 14, 'CORE', 184, 16, 0x100, 4892, 12, 255, true, TAE_NONE, COPPER_ORE, COPPER_ORE, STR_TONS, CC_BULK),
|
||||
MK( 15, 'WATR', 10, 16, 0x100, 4664, 20, 80, true, TAE_WATER, WATER, WATER, STR_LITERS, CC_LIQUID),
|
||||
MK( 16, 'RUBR', 6, 16, 0x100, 4437, 2, 20, true, TAE_NONE, RUBBER, RUBBER, STR_LITERS, CC_LIQUID),
|
||||
MK( 17, 'SUGR', 6, 16, 0x100, 4437, 20, 255, true, TAE_NONE, SUGAR, SUGAR, STR_TONS, CC_BULK),
|
||||
MK( 18, 'TOYS', 174, 2, 0x100, 5574, 25, 255, true, TAE_NONE, TOYS, TOY, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 19, 'BATT', 208, 4, 0x100, 4322, 2, 30, true, TAE_NONE, BATTERIES, BATTERY, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 20, 'SWET', 194, 5, 0x200, 6144, 8, 40, true, TAE_GOODS, SWEETS, SWEETS, STR_BAGS, CC_EXPRESS),
|
||||
MK( 21, 'TOFF', 191, 16, 0x100, 4778, 14, 60, true, TAE_NONE, TOFFEE, TOFFEE, STR_TONS, CC_BULK),
|
||||
MK( 22, 'COLA', 84, 16, 0x100, 4892, 5, 75, true, TAE_NONE, COLA, COLA, STR_LITERS, CC_LIQUID),
|
||||
MK( 23, 'CTCD', 184, 16, 0x100, 5005, 10, 25, true, TAE_NONE, CANDYFLOSS, CANDYFLOSS, STR_TONS, CC_BULK),
|
||||
MK( 24, 'BUBL', 10, 1, 0x100, 5077, 20, 80, true, TAE_NONE, BUBBLES, BUBBLE, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 25, 'PLST', 202, 16, 0x100, 4664, 30, 255, true, TAE_NONE, PLASTIC, PLASTIC, STR_LITERS, CC_LIQUID),
|
||||
MK( 26, 'FZDR', 48, 2, 0x100, 6250, 30, 50, true, TAE_FOOD, FIZZY_DRINKS, FIZZY_DRINK, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 7, CT_WOOD, 84, 16, 0x100, 7964, 15, 255, true, TAE_NONE, WOOD, WOOD, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 8, CT_IRON_ORE, 184, 16, 0x100, 5120, 9, 255, true, TAE_NONE, IRON_ORE, IRON_ORE, STR_TONS, CC_BULK),
|
||||
MK( 9, CT_STEEL, 10, 16, 0x100, 5688, 7, 255, true, TAE_NONE, STEEL, STEEL, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 10, CT_VALUABLES, 202, 2, 0x100, 7509, 1, 32, true, TAE_NONE, VALUABLES, VALUABLES, STR_BAGS, CC_ARMOURED),
|
||||
MK( 10, CT_GOLD, 202, 8, 0x100, 5802, 10, 40, true, TAE_NONE, GOLD, GOLD, STR_BAGS, CC_ARMOURED),
|
||||
MK( 10, CT_DIAMONDS, 202, 2, 0x100, 5802, 10, 255, true, TAE_NONE, DIAMONDS, DIAMOND, STR_BAGS, CC_ARMOURED),
|
||||
MK( 11, CT_PAPER, 10, 16, 0x100, 5461, 7, 60, true, TAE_NONE, PAPER, PAPER, STR_TONS, CC_PIECE_GOODS),
|
||||
MK( 12, CT_FOOD, 48, 16, 0x100, 5688, 0, 30, true, TAE_FOOD, FOOD, FOOD, STR_TONS, CC_EXPRESS | CC_REFRIGERATED),
|
||||
MK( 13, CT_FRUIT, 208, 16, 0x100, 4209, 0, 15, true, TAE_NONE, FRUIT, FRUIT, STR_TONS, CC_BULK | CC_REFRIGERATED),
|
||||
MK( 14, CT_COPPER_ORE, 184, 16, 0x100, 4892, 12, 255, true, TAE_NONE, COPPER_ORE, COPPER_ORE, STR_TONS, CC_BULK),
|
||||
MK( 15, CT_WATER, 10, 16, 0x100, 4664, 20, 80, true, TAE_WATER, WATER, WATER, STR_LITERS, CC_LIQUID),
|
||||
MK( 16, CT_RUBBER, 6, 16, 0x100, 4437, 2, 20, true, TAE_NONE, RUBBER, RUBBER, STR_LITERS, CC_LIQUID),
|
||||
MK( 17, CT_SUGAR, 6, 16, 0x100, 4437, 20, 255, true, TAE_NONE, SUGAR, SUGAR, STR_TONS, CC_BULK),
|
||||
MK( 18, CT_TOYS, 174, 2, 0x100, 5574, 25, 255, true, TAE_NONE, TOYS, TOY, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 19, CT_BATTERIES, 208, 4, 0x100, 4322, 2, 30, true, TAE_NONE, BATTERIES, BATTERY, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 20, CT_CANDY, 194, 5, 0x200, 6144, 8, 40, true, TAE_GOODS, SWEETS, SWEETS, STR_BAGS, CC_EXPRESS),
|
||||
MK( 21, CT_TOFFEE, 191, 16, 0x100, 4778, 14, 60, true, TAE_NONE, TOFFEE, TOFFEE, STR_TONS, CC_BULK),
|
||||
MK( 22, CT_COLA, 84, 16, 0x100, 4892, 5, 75, true, TAE_NONE, COLA, COLA, STR_LITERS, CC_LIQUID),
|
||||
MK( 23, CT_COTTON_CANDY, 184, 16, 0x100, 5005, 10, 25, true, TAE_NONE, CANDYFLOSS, CANDYFLOSS, STR_TONS, CC_BULK),
|
||||
MK( 24, CT_BUBBLES, 10, 1, 0x100, 5077, 20, 80, true, TAE_NONE, BUBBLES, BUBBLE, STR_ITEMS, CC_PIECE_GOODS),
|
||||
MK( 25, CT_PLASTIC, 202, 16, 0x100, 4664, 30, 255, true, TAE_NONE, PLASTIC, PLASTIC, STR_LITERS, CC_LIQUID),
|
||||
MK( 26, CT_FIZZY_DRINKS, 48, 2, 0x100, 6250, 30, 50, true, TAE_FOOD, FIZZY_DRINKS, FIZZY_DRINK, STR_ITEMS, CC_PIECE_GOODS),
|
||||
|
||||
/* Void slot in temperate */
|
||||
MK(0xFF, 0, 1, 0, 0x100, 5688, 0, 30, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
|
||||
MK(0xFF, CT_INVALID, 1, 0, 0x100, 5688, 0, 30, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
|
||||
/* Void slot in arctic */
|
||||
MK(0xFF, 0, 184, 0, 0x100, 5120, 9, 255, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
|
||||
MK(0xFF, CT_INVALID, 184, 0, 0x100, 5120, 9, 255, true, TAE_NONE, NOTHING, NOTHING, STR_TONS, CC_NOAVAILABLE),
|
||||
};
|
||||
|
||||
|
||||
/** Table of cargo types available in each climate, by default */
|
||||
static const CargoLabel _default_climate_cargo[NUM_LANDSCAPE][NUM_ORIGINAL_CARGO] = {
|
||||
{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'GRAI', 'WOOD', 'IORE', 'STEL', 'VALU', 33, },
|
||||
{ 'PASS', 'COAL', 'MAIL', 'OIL_', 'LVST', 'GOOD', 'WHEA', 'WOOD', 34, 'PAPR', 'GOLD', 'FOOD', },
|
||||
{ 'PASS', 'RUBR', 'MAIL', 4, 'FRUT', 'GOOD', 'MAIZ', 11, 'CORE', 'WATR', 'DIAM', 'FOOD', },
|
||||
{ 'PASS', 'SUGR', 'MAIL', 'TOYS', 'BATT', 'SWET', 'TOFF', 'COLA', 'CTCD', 'BUBL', 'PLST', 'FZDR', },
|
||||
static const std::variant<CargoLabel, int> _default_climate_cargo[NUM_LANDSCAPE][NUM_ORIGINAL_CARGO] = {
|
||||
{ CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_GRAIN, CT_WOOD, CT_IRON_ORE, CT_STEEL, CT_VALUABLES, 33, },
|
||||
{ CT_PASSENGERS, CT_COAL, CT_MAIL, CT_OIL, CT_LIVESTOCK, CT_GOODS, CT_WHEAT, CT_WOOD, 34, CT_PAPER, CT_GOLD, CT_FOOD, },
|
||||
{ CT_PASSENGERS, CT_RUBBER, CT_MAIL, 4, CT_FRUIT, CT_GOODS, CT_MAIZE, 11, CT_COPPER_ORE, CT_WATER, CT_DIAMONDS, CT_FOOD, },
|
||||
{ CT_PASSENGERS, CT_SUGAR, CT_MAIL, CT_TOYS, CT_BATTERIES, CT_CANDY, CT_TOFFEE, CT_COLA, CT_COTTON_CANDY, CT_BUBBLES, CT_PLASTIC, CT_FIZZY_DRINKS, },
|
||||
};
|
||||
|
||||
|
@@ -24,7 +24,7 @@
|
||||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MT(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MT(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/**
|
||||
* Writes the properties of a multiple-unit train into the EngineInfo struct.
|
||||
@@ -37,7 +37,7 @@
|
||||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MM(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MM(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 1 << EF_RAIL_IS_MU, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/**
|
||||
* Writes the properties of a train carriage into the EngineInfo struct.
|
||||
@@ -50,7 +50,7 @@
|
||||
* @see MT
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MW(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MW(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/**
|
||||
* Writes the properties of a road vehicle into the EngineInfo struct.
|
||||
@@ -63,7 +63,7 @@
|
||||
* @param f Bitmask of the climates
|
||||
* @note the 5 between b and f is the load amount
|
||||
*/
|
||||
#define MR(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MR(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 5, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/**
|
||||
* Writes the properties of a ship into the EngineInfo struct.
|
||||
@@ -75,7 +75,7 @@
|
||||
* @param f Bitmask of the climates
|
||||
* @note the 10 between b and f is the load amount
|
||||
*/
|
||||
#define MS(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MS(a, b, c, d, e, f) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 10, f, INVALID_CARGO, e, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/**
|
||||
* Writes the properties of an aeroplane into the EngineInfo struct.
|
||||
@@ -86,7 +86,7 @@
|
||||
* @param e Bitmask of the climates
|
||||
* @note the 20 between b and e is the load amount
|
||||
*/
|
||||
#define MA(a, b, c, d, e) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
#define MA(a, b, c, d, e) { CalTime::DAYS_TILL_ORIGINAL_BASE_YEAR + a, c, d, b, 20, e, INVALID_CARGO, CT_INVALID, 0, 8, 0, 0, 0, STR_EMPTY, CARGO_AGING_TICKS, INVALID_ENGINE, ExtraEngineFlags::None }
|
||||
|
||||
/* Climates
|
||||
* T = Temperate
|
||||
@@ -102,33 +102,33 @@ static const EngineInfo _orig_engine_info[] = {
|
||||
* | decay_speed cargo_type
|
||||
* | | lifelength | climates
|
||||
* | | | | | | */
|
||||
MT( 1827, 20, 15, 30, 0 , T ), // 0 Kirby Paul Tank (Steam)
|
||||
MT( 12784, 20, 22, 30, 0 , A|S ), // 1 MJS 250 (Diesel)
|
||||
MT( 9497, 20, 20, 50, 0 , Y), // 2 Ploddyphut Choo-Choo
|
||||
MT( 11688, 20, 20, 30, 0 , Y), // 3 Powernaut Choo-Choo
|
||||
MT( 16802, 20, 20, 30, 0 , Y), // 4 Mightymover Choo-Choo
|
||||
MT( 18993, 20, 20, 30, 0 , Y), // 5 Ploddyphut Diesel
|
||||
MT( 20820, 20, 20, 30, 0 , Y), // 6 Powernaut Diesel
|
||||
MT( 8766, 20, 20, 30, 0 , A|S ), // 7 Wills 2-8-0 (Steam)
|
||||
MT( 5114, 20, 21, 30, 0 , T ), // 8 Chaney 'Jubilee' (Steam)
|
||||
MT( 5479, 20, 20, 30, 0 , T ), // 9 Ginzu 'A4' (Steam)
|
||||
MT( 12419, 20, 23, 25, 0 , T ), // 10 SH '8P' (Steam)
|
||||
MT( 1827, 20, 15, 30, CT_NONE , T ), // 0 Kirby Paul Tank (Steam)
|
||||
MT( 12784, 20, 22, 30, CT_NONE , A|S ), // 1 MJS 250 (Diesel)
|
||||
MT( 9497, 20, 20, 50, CT_NONE , Y), // 2 Ploddyphut Choo-Choo
|
||||
MT( 11688, 20, 20, 30, CT_NONE , Y), // 3 Powernaut Choo-Choo
|
||||
MT( 16802, 20, 20, 30, CT_NONE , Y), // 4 Mightymover Choo-Choo
|
||||
MT( 18993, 20, 20, 30, CT_NONE , Y), // 5 Ploddyphut Diesel
|
||||
MT( 20820, 20, 20, 30, CT_NONE , Y), // 6 Powernaut Diesel
|
||||
MT( 8766, 20, 20, 30, CT_NONE , A|S ), // 7 Wills 2-8-0 (Steam)
|
||||
MT( 5114, 20, 21, 30, CT_NONE , T ), // 8 Chaney 'Jubilee' (Steam)
|
||||
MT( 5479, 20, 20, 30, CT_NONE , T ), // 9 Ginzu 'A4' (Steam)
|
||||
MT( 12419, 20, 23, 25, CT_NONE , T ), // 10 SH '8P' (Steam)
|
||||
MM( 13149, 20, 12, 30, CT_PASSENGERS , T ), // 11 Manley-Morel DMU (Diesel)
|
||||
MM( 23376, 20, 15, 35, CT_PASSENGERS , T ), // 12 'Dash' (Diesel)
|
||||
MT( 14976, 20, 18, 28, 0 , T ), // 13 SH/Hendry '25' (Diesel)
|
||||
MT( 14245, 20, 20, 30, 0 , T ), // 14 UU '37' (Diesel)
|
||||
MT( 15341, 20, 22, 33, 0 , T ), // 15 Floss '47' (Diesel)
|
||||
MT( 14976, 20, 20, 25, 0 , A|S ), // 16 CS 4000 (Diesel)
|
||||
MT( 16437, 20, 20, 30, 0 , A|S ), // 17 CS 2400 (Diesel)
|
||||
MT( 18993, 20, 22, 30, 0 , A|S ), // 18 Centennial (Diesel)
|
||||
MT( 13880, 20, 22, 30, 0 , A|S ), // 19 Kelling 3100 (Diesel)
|
||||
MM( 20454, 20, 22, 30, 0 , A|S ), // 20 Turner Turbo (Diesel)
|
||||
MT( 16071, 20, 22, 30, 0 , A|S ), // 21 MJS 1000 (Diesel)
|
||||
MT( 14976, 20, 18, 28, CT_NONE , T ), // 13 SH/Hendry '25' (Diesel)
|
||||
MT( 14245, 20, 20, 30, CT_NONE , T ), // 14 UU '37' (Diesel)
|
||||
MT( 15341, 20, 22, 33, CT_NONE , T ), // 15 Floss '47' (Diesel)
|
||||
MT( 14976, 20, 20, 25, CT_NONE , A|S ), // 16 CS 4000 (Diesel)
|
||||
MT( 16437, 20, 20, 30, CT_NONE , A|S ), // 17 CS 2400 (Diesel)
|
||||
MT( 18993, 20, 22, 30, CT_NONE , A|S ), // 18 Centennial (Diesel)
|
||||
MT( 13880, 20, 22, 30, CT_NONE , A|S ), // 19 Kelling 3100 (Diesel)
|
||||
MM( 20454, 20, 22, 30, CT_NONE , A|S ), // 20 Turner Turbo (Diesel)
|
||||
MT( 16071, 20, 22, 30, CT_NONE , A|S ), // 21 MJS 1000 (Diesel)
|
||||
MT( 20820, 20, 20, 25, CT_MAIL , T ), // 22 SH '125' (Diesel)
|
||||
MT( 16437, 20, 23, 30, 0 , T ), // 23 SH '30' (Electric)
|
||||
MT( 19359, 20, 23, 80, 0 , T ), // 24 SH '40' (Electric)
|
||||
MM( 23376, 20, 25, 30, 0 , T ), // 25 'T.I.M.' (Electric)
|
||||
MM( 26298, 20, 25, 50, 0 , T ), // 26 'AsiaStar' (Electric)
|
||||
MT( 16437, 20, 23, 30, CT_NONE , T ), // 23 SH '30' (Electric)
|
||||
MT( 19359, 20, 23, 80, CT_NONE , T ), // 24 SH '40' (Electric)
|
||||
MM( 23376, 20, 25, 30, CT_NONE , T ), // 25 'T.I.M.' (Electric)
|
||||
MM( 26298, 20, 25, 50, CT_NONE , T ), // 26 'AsiaStar' (Electric)
|
||||
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 27 Passenger Carriage
|
||||
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 28 Mail Van
|
||||
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 29 Coal Truck
|
||||
@@ -156,9 +156,9 @@ static const EngineInfo _orig_engine_info[] = {
|
||||
MW( 1827, 20, 20, 50, CT_BATTERIES , Y), // 51 Battery Truck
|
||||
MW( 1827, 20, 20, 50, CT_FIZZY_DRINKS, Y), // 52 Fizzy Drink Truck
|
||||
MW( 1827, 20, 20, 50, CT_PLASTIC , Y), // 53 Plastic Truck
|
||||
MT( 28490, 20, 20, 50, 0 , T|A|S ), // 54 'X2001' (Electric)
|
||||
MT( 28490, 20, 20, 50, CT_NONE , T|A|S ), // 54 'X2001' (Electric)
|
||||
MT( 31047, 20, 20, 50, CT_PASSENGERS , T|A|S ), // 55 'Millennium Z1' (Electric)
|
||||
MT( 28855, 20, 20, 50, 0 , Y), // 56 Wizzowow Z99
|
||||
MT( 28855, 20, 20, 50, CT_NONE , Y), // 56 Wizzowow Z99
|
||||
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 57 Passenger Carriage
|
||||
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 58 Mail Van
|
||||
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 59 Coal Truck
|
||||
@@ -186,11 +186,11 @@ static const EngineInfo _orig_engine_info[] = {
|
||||
MW( 1827, 20, 20, 50, CT_BATTERIES , Y), // 81 Battery Truck
|
||||
MW( 1827, 20, 20, 50, CT_FIZZY_DRINKS, Y), // 82 Fizzy Drink Truck
|
||||
MW( 1827, 20, 20, 50, CT_PLASTIC , Y), // 83 Plastic Truck
|
||||
MT( 36525, 20, 20, 50, 0 , T|A|S ), // 84 Lev1 'Leviathan' (Electric)
|
||||
MT( 39447, 20, 20, 50, 0 , T|A|S ), // 85 Lev2 'Cyclops' (Electric)
|
||||
MT( 42004, 20, 20, 50, 0 , T|A|S ), // 86 Lev3 'Pegasus' (Electric)
|
||||
MT( 42735, 20, 20, 50, 0 , T|A|S ), // 87 Lev4 'Chimaera' (Electric)
|
||||
MT( 36891, 20, 20, 60, 0 , Y), // 88 Wizzowow Rocketeer
|
||||
MT( 36525, 20, 20, 50, CT_NONE , T|A|S ), // 84 Lev1 'Leviathan' (Electric)
|
||||
MT( 39447, 20, 20, 50, CT_NONE , T|A|S ), // 85 Lev2 'Cyclops' (Electric)
|
||||
MT( 42004, 20, 20, 50, CT_NONE , T|A|S ), // 86 Lev3 'Pegasus' (Electric)
|
||||
MT( 42735, 20, 20, 50, CT_NONE , T|A|S ), // 87 Lev4 'Chimaera' (Electric)
|
||||
MT( 36891, 20, 20, 60, CT_NONE , Y), // 88 Wizzowow Rocketeer
|
||||
MW( 1827, 20, 20, 50, CT_PASSENGERS , T|A|S|Y), // 89 Passenger Carriage
|
||||
MW( 1827, 20, 20, 50, CT_MAIL , T|A|S|Y), // 90 Mail Van
|
||||
MW( 1827, 20, 20, 50, CT_COAL , T|A ), // 91 Coal Truck
|
||||
|
@@ -1346,7 +1346,7 @@ class NIHCargo : public NIHelper {
|
||||
const CargoSpec *spec = CargoSpec::Get(index);
|
||||
seprintf(buffer, lastof(buffer), " Bit: %2u, Label: %c%c%c%c, Callback mask: 0x%02X",
|
||||
spec->bitnum,
|
||||
spec->label >> 24, spec->label >> 16, spec->label >> 8, spec->label,
|
||||
spec->label.base() >> 24, spec->label.base() >> 16, spec->label.base() >> 8, spec->label.base(),
|
||||
spec->callback_mask);
|
||||
output.print(buffer);
|
||||
int written = seprintf(buffer, lastof(buffer), " Cargo class: %s%s%s%s%s%s%s%s%s%s%s",
|
||||
|
@@ -1813,6 +1813,7 @@ static_assert(lengthof(_town_draw_tile_data) == (NEW_HOUSE_OFFSET) * 4 * 4);
|
||||
#define MS(mnd, mxd, p, rc, bn, rr, mg, ca1, ca2, ca3, bf, ba, cg1, cg2, cg3) \
|
||||
{mnd, mxd, p, rc, bn, rr, mg, \
|
||||
{ca1, ca2, ca3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, \
|
||||
{INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO, INVALID_CARGO}, \
|
||||
{cg1, cg2, cg3, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID, CT_INVALID}, \
|
||||
bf, ba, true, GRFFileProps(INVALID_HOUSE_ID), 0, {COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN, COLOUR_BEGIN}, \
|
||||
16, NO_EXTRA_FLAG, HCF_NONE, HOUSE_NO_CLASS, {0, 2, 0, 0}, 0, 0, 0}
|
||||
|
@@ -857,6 +857,9 @@ void TextfileWindow::LoadText(std::string_view buf)
|
||||
this->AfterLoadText();
|
||||
|
||||
CheckForMissingGlyphs(true, this);
|
||||
|
||||
/* The font may have changed when searching for glyphs, so ensure widget sizes are updated just in case. */
|
||||
this->ReInit();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -110,7 +110,11 @@ struct Town : TownPool::PoolItem<&_town_pool> {
|
||||
|
||||
std::string text; ///< General text with additional information.
|
||||
|
||||
inline byte GetPercentTransported(CargoID cid) const { return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1); }
|
||||
inline byte GetPercentTransported(CargoID cid) const
|
||||
{
|
||||
if (!IsValidCargoID(cid)) return 0;
|
||||
return this->supplied[cid].old_act * 256 / (this->supplied[cid].old_max + 1);
|
||||
}
|
||||
|
||||
StationList stations_near; ///< NOSAVE: List of nearby stations.
|
||||
|
||||
|
@@ -945,7 +945,7 @@ void AddAcceptedHouseCargo(HouseID house_id, TileIndex tile, CargoArray &accepta
|
||||
AddAcceptedCargoSetMask(accepts[1], GB(callback, 4, 4), acceptance, always_accepted);
|
||||
if (_settings_game.game_creation.landscape != LT_TEMPERATE && HasBit(callback, 12)) {
|
||||
/* The 'S' bit indicates food instead of goods */
|
||||
AddAcceptedCargoSetMask(CT_FOOD, GB(callback, 8, 4), acceptance, always_accepted);
|
||||
AddAcceptedCargoSetMask(GetCargoIDByLabel(CT_FOOD), GB(callback, 8, 4), acceptance, always_accepted);
|
||||
} else {
|
||||
AddAcceptedCargoSetMask(accepts[2], GB(callback, 8, 4), acceptance, always_accepted);
|
||||
}
|
||||
@@ -2184,8 +2184,12 @@ void UpdateTownRadii()
|
||||
|
||||
void UpdateTownMaxPass(Town *t)
|
||||
{
|
||||
t->supplied[CT_PASSENGERS].old_max = _town_cargo_scaler.Scale(t->cache.population >> 3);
|
||||
t->supplied[CT_MAIL].old_max = _town_cargo_scaler.Scale(t->cache.population >> 4);
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_PASSENGERS]) {
|
||||
t->supplied[cs->Index()].old_max = _town_cargo_scaler.Scale(t->cache.population >> 3);
|
||||
}
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[TPE_MAIL]) {
|
||||
t->supplied[cs->Index()].old_max = _town_cargo_scaler.Scale(t->cache.population >> 4);
|
||||
}
|
||||
}
|
||||
|
||||
static void UpdateTownGrowthRate(Town *t);
|
||||
@@ -4171,10 +4175,19 @@ static uint GetNormalGrowthRate(Town *t)
|
||||
* The growth rate can only be decreased by this setting, not increased.
|
||||
*/
|
||||
uint32_t inverse_m = UINT32_MAX / m;
|
||||
auto calculate_cargo_ratio_fix15 = [](const TransportedCargoStat<uint32_t> &stat) -> uint32_t {
|
||||
return stat.old_max ? ((uint64_t) (stat.old_act << 15)) / stat.old_max : 1 << 15;
|
||||
};
|
||||
uint32_t cargo_ratio_fix16 = calculate_cargo_ratio_fix15(t->supplied[CT_PASSENGERS]) + calculate_cargo_ratio_fix15(t->supplied[CT_MAIL]);
|
||||
|
||||
uint32_t cargo_ratio_fix16 = 0;
|
||||
for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) {
|
||||
uint32_t old_max = 0;
|
||||
uint32_t old_act = 0;
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
|
||||
const TransportedCargoStat<uint32_t> &stat = t->supplied[cs->Index()];
|
||||
old_max += stat.old_max;
|
||||
old_act += stat.old_act;
|
||||
}
|
||||
cargo_ratio_fix16 += old_max ? ((uint64_t) (old_act << 15)) / old_max : 1 << 15;
|
||||
}
|
||||
|
||||
uint64_t cargo_dependant_part = (((uint64_t) cargo_ratio_fix16) * ((uint64_t) inverse_m) * _settings_game.economy.town_growth_cargo_transported) >> 16;
|
||||
uint64_t non_cargo_dependant_part = ((uint64_t) inverse_m) * (100 - _settings_game.economy.town_growth_cargo_transported);
|
||||
uint64_t total = (cargo_dependant_part + non_cargo_dependant_part);
|
||||
|
@@ -1477,6 +1477,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
|
||||
InvalidateWindowData(WC_VEHICLE_DEPOT, v->tile);
|
||||
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
v->cargo_cap = rvi->capacity;
|
||||
v->refit_cap = 0;
|
||||
|
||||
@@ -1613,6 +1614,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
|
||||
v->vehstatus = VS_HIDDEN | VS_STOPPED | VS_DEFPAL;
|
||||
v->spritenum = rvi->image_index;
|
||||
v->cargo_type = e->GetDefaultCargoType();
|
||||
assert(IsValidCargoID(v->cargo_type));
|
||||
v->cargo_cap = rvi->capacity;
|
||||
v->refit_cap = 0;
|
||||
v->last_station_visited = INVALID_STATION;
|
||||
|
@@ -3069,8 +3069,9 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
|
||||
/* Note: Luckily cargo_type is not needed for engines */
|
||||
}
|
||||
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = e->GetDefaultCargoType();
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
|
||||
assert(IsValidCargoID(cargo_type));
|
||||
if (e->u.rail.railveh_type == RAILVEH_WAGON) {
|
||||
if (!CargoSpec::Get(cargo_type)->is_freight) {
|
||||
if (parent_engine_type == INVALID_ENGINE) {
|
||||
@@ -3109,8 +3110,9 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
|
||||
e = Engine::Get(engine_type);
|
||||
cargo_type = v->First()->cargo_type;
|
||||
}
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = e->GetDefaultCargoType();
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
|
||||
assert(IsValidCargoID(cargo_type));
|
||||
|
||||
/* Important: Use Tram Flag of front part. Luckily engine_type refers to the front part here. */
|
||||
if (HasBit(e->info.misc_flags, EF_ROAD_TRAM)) {
|
||||
@@ -3122,8 +3124,9 @@ LiveryScheme GetEngineLiveryScheme(EngineID engine_type, EngineID parent_engine_
|
||||
}
|
||||
|
||||
case VEH_SHIP:
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = e->GetDefaultCargoType();
|
||||
if (cargo_type == INVALID_CARGO) cargo_type = CT_GOODS; // The vehicle does not carry anything, let's pick some freight cargo
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = e->GetDefaultCargoType();
|
||||
if (!IsValidCargoID(cargo_type)) cargo_type = GetCargoIDByLabel(CT_GOODS); // The vehicle does not carry anything, let's pick some freight cargo
|
||||
assert(IsValidCargoID(cargo_type));
|
||||
return IsCargoInClass(cargo_type, CC_PASSENGERS) ? LS_PASSENGER_SHIP : LS_FREIGHT_SHIP;
|
||||
|
||||
case VEH_AIRCRAFT:
|
||||
|
@@ -178,7 +178,8 @@ CommandCost CmdBuildVehicle(TileIndex tile, DoCommandFlag flags, uint32_t p1, ui
|
||||
_returned_refit_capacity = e->GetDisplayDefaultCapacity(&_returned_mail_refit_capacity);
|
||||
_returned_vehicle_capacities.Clear();
|
||||
_returned_vehicle_capacities[default_cargo] = _returned_refit_capacity;
|
||||
_returned_vehicle_capacities[CT_MAIL] = _returned_mail_refit_capacity;
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail)) _returned_vehicle_capacities[mail] = _returned_mail_refit_capacity;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +439,8 @@ static CommandCost RefitVehicle(Vehicle *v, bool only_this, uint8_t num_vehicles
|
||||
total_mail_capacity += mail_capacity;
|
||||
|
||||
_returned_vehicle_capacities[new_cid] += amount;
|
||||
_returned_vehicle_capacities[CT_MAIL] += mail_capacity;
|
||||
CargoID mail = GetCargoIDByLabel(CT_MAIL);
|
||||
if (IsValidCargoID(mail)) _returned_vehicle_capacities[mail] += mail_capacity;
|
||||
|
||||
if (!refittable) continue;
|
||||
|
||||
|
@@ -1040,7 +1040,7 @@ struct RefitWindow : public Window {
|
||||
|
||||
Money money = cost.GetCost();
|
||||
if (_returned_mail_refit_capacity > 0) {
|
||||
SetDParam(2, CT_MAIL);
|
||||
SetDParam(2, GetCargoIDByLabel(CT_MAIL));
|
||||
SetDParam(3, _returned_mail_refit_capacity);
|
||||
if (this->order != INVALID_VEH_ORDER_ID) {
|
||||
/* No predictable cost */
|
||||
|
@@ -193,14 +193,23 @@ SpriteID TileZoneCheckUnservedBuildingsEvaluation(TileIndex tile, Owner owner)
|
||||
return ZONING_INVALID_SPRITE_ID;
|
||||
}
|
||||
|
||||
auto has_town_cargo = [&](const CargoArray &dat) {
|
||||
for (auto tpe : {TPE_PASSENGERS, TPE_MAIL}) {
|
||||
for (const CargoSpec *cs : CargoSpec::town_production_cargoes[tpe]) {
|
||||
if (dat[cs->Index()] > 0) return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
CargoArray dat{};
|
||||
dat.Clear();
|
||||
AddAcceptedCargo(tile, dat, nullptr);
|
||||
if (dat[CT_MAIL] + dat[CT_PASSENGERS] == 0) {
|
||||
// nothing is accepted, so now test if cargo is produced
|
||||
if (!has_town_cargo(dat)) {
|
||||
/* nothing is accepted, so now test if cargo is produced */
|
||||
AddProducedCargo(tile, dat);
|
||||
if (dat[CT_MAIL] + dat[CT_PASSENGERS] == 0) {
|
||||
// total is still 0, so give up
|
||||
if (!has_town_cargo(dat)) {
|
||||
/* still don't have town cargo, so give up */
|
||||
return ZONING_INVALID_SPRITE_ID;
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user