mirror of https://github.com/OpenTTD/OpenTTD
Merge 1fec42024c
into ebc74c8905
commit
c3b3c2ebf9
|
@ -363,7 +363,7 @@ void AddArticulatedParts(Vehicle *first)
|
||||||
|
|
||||||
t->subtype = 0;
|
t->subtype = 0;
|
||||||
t->track = front->track;
|
t->track = front->track;
|
||||||
t->railtype = front->railtype;
|
t->railtypes = front->railtypes;
|
||||||
|
|
||||||
t->spritenum = e_artic->u.rail.image_index;
|
t->spritenum = e_artic->u.rail.image_index;
|
||||||
if (e_artic->CanCarryCargo()) {
|
if (e_artic->CanCarryCargo()) {
|
||||||
|
|
|
@ -71,7 +71,7 @@ bool CheckAutoreplaceValidity(EngineID from, EngineID to, CompanyID company)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case VEH_TRAIN: {
|
case VEH_TRAIN: {
|
||||||
/* make sure the railtypes are compatible */
|
/* make sure the railtypes are compatible */
|
||||||
if (!GetRailTypeInfo(e_from->u.rail.railtype)->compatible_railtypes.Any(GetRailTypeInfo(e_to->u.rail.railtype)->compatible_railtypes)) return false;
|
if (!GetAllCompatibleRailTypes(e_from->u.rail.railtypes).Any(GetAllCompatibleRailTypes(e_to->u.rail.railtypes))) return false;
|
||||||
|
|
||||||
/* make sure we do not replace wagons with engines or vice versa */
|
/* make sure we do not replace wagons with engines or vice versa */
|
||||||
if ((e_from->u.rail.railveh_type == RAILVEH_WAGON) != (e_to->u.rail.railveh_type == RAILVEH_WAGON)) return false;
|
if ((e_from->u.rail.railveh_type == RAILVEH_WAGON) != (e_to->u.rail.railveh_type == RAILVEH_WAGON)) return false;
|
||||||
|
|
|
@ -111,7 +111,7 @@ class ReplaceVehicleWindow : public Window {
|
||||||
|
|
||||||
if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
|
if (draw_left && this->sel_railtype != INVALID_RAILTYPE) {
|
||||||
/* Ensure that the railtype is specific to the selected one */
|
/* Ensure that the railtype is specific to the selected one */
|
||||||
if (rvi->railtype != this->sel_railtype) return false;
|
if (!rvi->railtypes.Test(this->sel_railtype)) return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -632,14 +632,31 @@ static int DrawRailEnginePurchaseInfo(int left, int right, int y, EngineID engin
|
||||||
}
|
}
|
||||||
y += GetCharacterHeight(FS_NORMAL);
|
y += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
|
/* Supported rail types */
|
||||||
|
std::string railtypes{};
|
||||||
|
std::string_view list_separator = GetListSeparator();
|
||||||
|
|
||||||
|
for (RailType rt : rvi->railtypes) {
|
||||||
|
if (!railtypes.empty()) railtypes += list_separator;
|
||||||
|
AppendStringInPlace(railtypes, GetRailTypeInfo(rt)->strings.name);
|
||||||
|
}
|
||||||
|
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_RAILTYPES, railtypes));
|
||||||
|
y += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
/* Max speed - Engine power */
|
/* Max speed - Engine power */
|
||||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_SPEED_POWER, PackVelocity(e->GetDisplayMaxSpeed(), e->type), e->GetPower()));
|
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_SPEED_POWER, PackVelocity(e->GetDisplayMaxSpeed(), e->type), e->GetPower()));
|
||||||
y += GetCharacterHeight(FS_NORMAL);
|
y += GetCharacterHeight(FS_NORMAL);
|
||||||
|
|
||||||
/* Max tractive effort - not applicable if old acceleration or maglev */
|
/* Max tractive effort - not applicable if old acceleration or maglev */
|
||||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(rvi->railtype)->acceleration_type != 2) {
|
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) {
|
||||||
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_MAX_TE, e->GetDisplayMaxTractiveEffort()));
|
bool is_maglev = true;
|
||||||
y += GetCharacterHeight(FS_NORMAL);
|
for (RailType rt : rvi->railtypes) {
|
||||||
|
is_maglev &= GetRailTypeInfo(rt)->acceleration_type == VehicleAccelerationModel::Maglev;
|
||||||
|
}
|
||||||
|
if (!is_maglev) {
|
||||||
|
DrawString(left, right, y, GetString(STR_PURCHASE_INFO_MAX_TE, e->GetDisplayMaxTractiveEffort()));
|
||||||
|
y += GetCharacterHeight(FS_NORMAL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Running cost */
|
/* Running cost */
|
||||||
|
@ -1378,7 +1395,7 @@ struct BuildVehicleWindow : Window {
|
||||||
EngineID eid = e->index;
|
EngineID eid = e->index;
|
||||||
const RailVehicleInfo *rvi = &e->u.rail;
|
const RailVehicleInfo *rvi = &e->u.rail;
|
||||||
|
|
||||||
if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtype, this->filter.railtype)) continue;
|
if (this->filter.railtype != INVALID_RAILTYPE && !HasPowerOnRail(rvi->railtypes, this->filter.railtype)) continue;
|
||||||
if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue;
|
if (!IsEngineBuildable(eid, VEH_TRAIN, _local_company)) continue;
|
||||||
|
|
||||||
/* Filter now! So num_engines and num_wagons is valid */
|
/* Filter now! So num_engines and num_wagons is valid */
|
||||||
|
|
|
@ -602,15 +602,13 @@ void SettingsDisableElrail(int32_t new_value)
|
||||||
|
|
||||||
void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
|
void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
|
||||||
{
|
{
|
||||||
/* pick appropriate railtype for elrail engines depending on setting */
|
|
||||||
const RailType new_railtype = disable ? RAILTYPE_RAIL : RAILTYPE_ELECTRIC;
|
|
||||||
|
|
||||||
/* walk through all train engines */
|
/* walk through all train engines */
|
||||||
for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
||||||
RailVehicleInfo *rv_info = &e->u.rail;
|
RailVehicleInfo *rv_info = &e->u.rail;
|
||||||
/* update railtype of engines intended to use elrail */
|
/* update railtype of engines intended to use elrail */
|
||||||
if (rv_info->intended_railtype == RAILTYPE_ELECTRIC) {
|
if (rv_info->intended_railtypes.Test(RAILTYPE_ELECTRIC)) {
|
||||||
rv_info->railtype = new_railtype;
|
rv_info->railtypes.Set(RAILTYPE_ELECTRIC, !disable);
|
||||||
|
rv_info->railtypes.Set(RAILTYPE_RAIL, disable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -618,11 +616,12 @@ void UpdateDisableElrailSettingState(bool disable, bool update_vehicles)
|
||||||
* normal rail too */
|
* normal rail too */
|
||||||
if (disable) {
|
if (disable) {
|
||||||
for (Train *t : Train::Iterate()) {
|
for (Train *t : Train::Iterate()) {
|
||||||
if (t->railtype == RAILTYPE_ELECTRIC) {
|
if (t->railtypes.Test(RAILTYPE_ELECTRIC)) {
|
||||||
/* this railroad vehicle is now compatible only with elrail,
|
/* this railroad vehicle is now compatible only with elrail,
|
||||||
* so add there also normal rail compatibility */
|
* so add there also normal rail compatibility */
|
||||||
t->compatible_railtypes.Set(RAILTYPE_RAIL);
|
t->compatible_railtypes.Set(RAILTYPE_RAIL);
|
||||||
t->railtype = RAILTYPE_RAIL;
|
t->railtypes.Reset(RAILTYPE_ELECTRIC);
|
||||||
|
t->railtypes.Set(RAILTYPE_RAIL);
|
||||||
t->flags.Set(VehicleRailFlag::AllowedOnNormalRail);
|
t->flags.Set(VehicleRailFlag::AllowedOnNormalRail);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1107,8 +1107,12 @@ static void NewVehicleAvailable(Engine *e)
|
||||||
|
|
||||||
if (e->type == VEH_TRAIN) {
|
if (e->type == VEH_TRAIN) {
|
||||||
/* maybe make another rail type available */
|
/* maybe make another rail type available */
|
||||||
assert(e->u.rail.railtype < RAILTYPE_END);
|
assert(e->u.rail.railtypes != RailTypes{});
|
||||||
for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | GetRailTypeInfo(e->u.rail.railtype)->introduces_railtypes, TimerGameCalendar::date);
|
RailTypes introduced{};
|
||||||
|
for (RailType rt : e->u.rail.railtypes) {
|
||||||
|
introduced |= GetRailTypeInfo(rt)->introduces_railtypes;
|
||||||
|
}
|
||||||
|
for (Company *c : Company::Iterate()) c->avail_railtypes = AddDateIntroducedRailTypes(c->avail_railtypes | introduced, TimerGameCalendar::date);
|
||||||
} else if (e->type == VEH_ROAD) {
|
} else if (e->type == VEH_ROAD) {
|
||||||
/* maybe make another road type available */
|
/* maybe make another road type available */
|
||||||
assert(e->u.road.roadtype < ROADTYPE_END);
|
assert(e->u.road.roadtype < ROADTYPE_END);
|
||||||
|
@ -1267,7 +1271,7 @@ bool IsEngineBuildable(EngineID engine, VehicleType type, CompanyID company)
|
||||||
if (type == VEH_TRAIN && company != OWNER_DEITY) {
|
if (type == VEH_TRAIN && company != OWNER_DEITY) {
|
||||||
/* Check if the rail type is available to this company */
|
/* Check if the rail type is available to this company */
|
||||||
const Company *c = Company::Get(company);
|
const Company *c = Company::Get(company);
|
||||||
if (!GetRailTypeInfo(e->u.rail.railtype)->compatible_railtypes.Any(c->avail_railtypes)) return false;
|
if (!GetAllCompatibleRailTypes(e->u.rail.railtypes).Any(c->avail_railtypes)) return false;
|
||||||
}
|
}
|
||||||
if (type == VEH_ROAD && company != OWNER_DEITY) {
|
if (type == VEH_ROAD && company != OWNER_DEITY) {
|
||||||
/* Check if the road type is available to this company */
|
/* Check if the road type is available to this company */
|
||||||
|
|
|
@ -47,7 +47,8 @@ StringID GetEngineCategoryName(EngineID engine)
|
||||||
case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
|
case VEH_AIRCRAFT: return STR_ENGINE_PREVIEW_AIRCRAFT;
|
||||||
case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
|
case VEH_SHIP: return STR_ENGINE_PREVIEW_SHIP;
|
||||||
case VEH_TRAIN:
|
case VEH_TRAIN:
|
||||||
return GetRailTypeInfo(e->u.rail.railtype)->strings.new_loco;
|
assert(e->u.rail.railtypes.Any());
|
||||||
|
return GetRailTypeInfo(e->u.rail.railtypes.GetNthSetBit(0).value())->strings.new_loco;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -181,7 +182,24 @@ static std::string GetTrainEngineInfoString(const Engine &e)
|
||||||
res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight());
|
res << GetString(STR_ENGINE_PREVIEW_COST_WEIGHT, e.GetCost(), e.GetDisplayWeight());
|
||||||
res << '\n';
|
res << '\n';
|
||||||
|
|
||||||
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && GetRailTypeInfo(e.u.rail.railtype)->acceleration_type != 2) {
|
if (e.u.rail.railtypes.Count() > 1) {
|
||||||
|
std::string railtypes{};
|
||||||
|
std::string_view list_separator = GetListSeparator();
|
||||||
|
|
||||||
|
for (RailType rt : e.u.rail.railtypes) {
|
||||||
|
if (!railtypes.empty()) railtypes += list_separator;
|
||||||
|
AppendStringInPlace(railtypes, GetRailTypeInfo(rt)->strings.name);
|
||||||
|
}
|
||||||
|
res << GetString(STR_ENGINE_PREVIEW_RAILTYPES, railtypes);
|
||||||
|
res << '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_maglev = true;
|
||||||
|
for (RailType rt : e.u.rail.railtypes) {
|
||||||
|
is_maglev &= GetRailTypeInfo(rt)->acceleration_type == VehicleAccelerationModel::Maglev;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_settings_game.vehicle.train_acceleration_model != AM_ORIGINAL && !is_maglev) {
|
||||||
res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER_MAX_TE, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower(), e.GetDisplayMaxTractiveEffort());
|
res << GetString(STR_ENGINE_PREVIEW_SPEED_POWER_MAX_TE, PackVelocity(e.GetDisplayMaxSpeed(), e.type), e.GetPower(), e.GetDisplayMaxTractiveEffort());
|
||||||
res << '\n';
|
res << '\n';
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -43,13 +43,20 @@ enum EngineClass : uint8_t {
|
||||||
EC_MAGLEV, ///< Maglev engine.
|
EC_MAGLEV, ///< Maglev engine.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Acceleration model of a vehicle. */
|
||||||
|
enum class VehicleAccelerationModel : uint8_t {
|
||||||
|
Normal, ///< Default acceleration model.
|
||||||
|
Monorail, ///< Monorail acceleration model.
|
||||||
|
Maglev, ///< Maglev acceleration model.
|
||||||
|
};
|
||||||
|
|
||||||
/** Information about a rail vehicle. */
|
/** Information about a rail vehicle. */
|
||||||
struct RailVehicleInfo {
|
struct RailVehicleInfo {
|
||||||
uint8_t image_index = 0;
|
uint8_t image_index = 0;
|
||||||
RailVehicleTypes railveh_type{};
|
RailVehicleTypes railveh_type{};
|
||||||
uint8_t cost_factor = 0; ///< Purchase cost factor; For multiheaded engines the sum of both engine prices.
|
uint8_t cost_factor = 0; ///< Purchase cost factor; For multiheaded engines the sum of both engine prices.
|
||||||
RailType railtype{}; ///< Railtype, mangled if elrail is disabled.
|
RailTypes railtypes{}; ///< Railtypes, mangled if elrail is disabled.
|
||||||
RailType intended_railtype{}; ///< Intended railtype, regardless of elrail being enabled or disabled.
|
RailTypes intended_railtypes{}; ///< Intended railtypes, regardless of elrail being enabled or disabled.
|
||||||
uint8_t ai_passenger_only = 0; ///< Bit value to tell AI that this engine is for passenger use only
|
uint8_t ai_passenger_only = 0; ///< Bit value to tell AI that this engine is for passenger use only
|
||||||
uint16_t max_speed = 0; ///< Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
|
uint16_t max_speed = 0; ///< Maximum speed (1 unit = 1/1.6 mph = 1 km-ish/h)
|
||||||
uint16_t power = 0; ///< Power of engine (hp); For multiheaded engines the sum of both engine powers.
|
uint16_t power = 0; ///< Power of engine (hp); For multiheaded engines the sum of both engine powers.
|
||||||
|
|
|
@ -131,7 +131,7 @@ int GroundVehicle<T, Type>::GetAcceleration() const
|
||||||
*/
|
*/
|
||||||
int64_t resistance = 0;
|
int64_t resistance = 0;
|
||||||
|
|
||||||
bool maglev = v->GetAccelerationType() == 2;
|
bool maglev = v->GetAccelerationType() == VehicleAccelerationModel::Maglev;
|
||||||
|
|
||||||
const int area = v->GetAirDragArea();
|
const int area = v->GetAirDragArea();
|
||||||
if (!maglev) {
|
if (!maglev) {
|
||||||
|
|
|
@ -4173,6 +4173,7 @@ STR_PURCHASE_INFO_ALL_BUT :All but {CARGO_
|
||||||
STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Tractive Effort: {GOLD}{FORCE}
|
STR_PURCHASE_INFO_MAX_TE :{BLACK}Max. Tractive Effort: {GOLD}{FORCE}
|
||||||
STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Range: {GOLD}{COMMA} tiles
|
STR_PURCHASE_INFO_AIRCRAFT_RANGE :{BLACK}Range: {GOLD}{COMMA} tiles
|
||||||
STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Aircraft type: {GOLD}{STRING}
|
STR_PURCHASE_INFO_AIRCRAFT_TYPE :{BLACK}Aircraft type: {GOLD}{STRING}
|
||||||
|
STR_PURCHASE_INFO_RAILTYPES :{BLACK}Rail types: {GOLD}{RAW_STRING}
|
||||||
|
|
||||||
###length 3
|
###length 3
|
||||||
STR_CARGO_TYPE_FILTER_ALL :All cargo types
|
STR_CARGO_TYPE_FILTER_ALL :All cargo types
|
||||||
|
@ -4356,6 +4357,7 @@ STR_ENGINE_PREVIEW_RUNCOST_YEAR :Running Cost: {
|
||||||
STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Running Cost: {CURRENCY_LONG}/period
|
STR_ENGINE_PREVIEW_RUNCOST_PERIOD :Running Cost: {CURRENCY_LONG}/period
|
||||||
STR_ENGINE_PREVIEW_CAPACITY :Capacity: {CARGO_LONG}
|
STR_ENGINE_PREVIEW_CAPACITY :Capacity: {CARGO_LONG}
|
||||||
STR_ENGINE_PREVIEW_CAPACITY_2 :Capacity: {CARGO_LONG}, {CARGO_LONG}
|
STR_ENGINE_PREVIEW_CAPACITY_2 :Capacity: {CARGO_LONG}, {CARGO_LONG}
|
||||||
|
STR_ENGINE_PREVIEW_RAILTYPES :Rail types: {RAW_STRING}
|
||||||
|
|
||||||
# Autoreplace window
|
# Autoreplace window
|
||||||
STR_REPLACE_VEHICLES_WHITE :{WHITE}Replace {STRING} - {STRING1}
|
STR_REPLACE_VEHICLES_WHITE :{WHITE}Replace {STRING} - {STRING1}
|
||||||
|
|
|
@ -270,7 +270,8 @@ Engine *GetNewEngine(const GRFFile *file, VehicleType type, uint16_t internal_id
|
||||||
_gted.resize(Engine::GetPoolSize());
|
_gted.resize(Engine::GetPoolSize());
|
||||||
}
|
}
|
||||||
if (type == VEH_TRAIN) {
|
if (type == VEH_TRAIN) {
|
||||||
_gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
|
_gted[e->index].railtypelabels.clear();
|
||||||
|
for (RailType rt : e->u.rail.railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
GrfMsg(5, "Created new engine at index {} for GRFID {:x}, type {}, index {}", e->index, std::byteswap(file->grfid), type, internal_id);
|
GrfMsg(5, "Created new engine at index {} for GRFID {:x}, type {}, index {}", e->index, std::byteswap(file->grfid), type, internal_id);
|
||||||
|
@ -424,7 +425,8 @@ void ResetNewGRFData()
|
||||||
|
|
||||||
/* Fill rail type label temporary data for default trains */
|
/* Fill rail type label temporary data for default trains */
|
||||||
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
for (const Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
||||||
_gted[e->index].railtypelabel = GetRailTypeInfo(e->u.rail.railtype)->label;
|
_gted[e->index].railtypelabels.clear();
|
||||||
|
for (RailType rt : e->u.rail.railtypes) _gted[e->index].railtypelabels.push_back(GetRailTypeInfo(rt)->label);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Reset GRM reservations */
|
/* Reset GRM reservations */
|
||||||
|
@ -861,7 +863,11 @@ static void FinaliseEngineArray()
|
||||||
if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
|
if (!e->info.climates.Test(_settings_game.game_creation.landscape)) continue;
|
||||||
|
|
||||||
switch (e->type) {
|
switch (e->type) {
|
||||||
case VEH_TRAIN: AppendCopyableBadgeList(e->badges, GetRailTypeInfo(e->u.rail.railtype)->badges, GSF_TRAINS); break;
|
case VEH_TRAIN:
|
||||||
|
for (RailType rt : e->u.rail.railtypes) {
|
||||||
|
AppendCopyableBadgeList(e->badges, GetRailTypeInfo(rt)->badges, GSF_TRAINS);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case VEH_ROAD: AppendCopyableBadgeList(e->badges, GetRoadTypeInfo(e->u.road.roadtype)->badges, GSF_ROADVEHICLES); break;
|
case VEH_ROAD: AppendCopyableBadgeList(e->badges, GetRoadTypeInfo(e->u.road.roadtype)->badges, GSF_ROADVEHICLES); break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
|
@ -1708,13 +1714,18 @@ static void AfterLoadGRFs()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
for (Engine *e : Engine::IterateType(VEH_TRAIN)) {
|
||||||
RailType railtype = GetRailTypeByLabel(_gted[e->index].railtypelabel);
|
RailTypes railtypes{};
|
||||||
if (railtype == INVALID_RAILTYPE) {
|
for (RailTypeLabel label : _gted[e->index].railtypelabels) {
|
||||||
|
auto rt = GetRailTypeByLabel(label);
|
||||||
|
if (rt != INVALID_RAILTYPE) railtypes.Set(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (railtypes.Any()) {
|
||||||
|
e->u.rail.railtypes = railtypes;
|
||||||
|
e->u.rail.intended_railtypes = railtypes;
|
||||||
|
} else {
|
||||||
/* Rail type is not available, so disable this engine */
|
/* Rail type is not available, so disable this engine */
|
||||||
e->info.climates = {};
|
e->info.climates = {};
|
||||||
} else {
|
|
||||||
e->u.rail.railtype = railtype;
|
|
||||||
e->u.rail.intended_railtype = railtype;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -117,7 +117,7 @@ static ChangeInfoResult RailTypeChangeInfo(uint first, uint last, int prop, Byte
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x15: // Acceleration model
|
case 0x15: // Acceleration model
|
||||||
rti->acceleration_type = Clamp(buf.ReadByte(), 0, 2);
|
rti->acceleration_type = static_cast<VehicleAccelerationModel>(Clamp(buf.ReadByte(), 0, 2));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0x16: // Map colour
|
case 0x16: // Map colour
|
||||||
|
|
|
@ -41,15 +41,16 @@ ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteRead
|
||||||
case 0x05: { // Track type
|
case 0x05: { // Track type
|
||||||
uint8_t tracktype = buf.ReadByte();
|
uint8_t tracktype = buf.ReadByte();
|
||||||
|
|
||||||
|
_gted[e->index].railtypelabels.clear();
|
||||||
if (tracktype < _cur_gps.grffile->railtype_list.size()) {
|
if (tracktype < _cur_gps.grffile->railtype_list.size()) {
|
||||||
_gted[e->index].railtypelabel = _cur_gps.grffile->railtype_list[tracktype];
|
_gted[e->index].railtypelabels.push_back(_cur_gps.grffile->railtype_list[tracktype]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (tracktype) {
|
switch (tracktype) {
|
||||||
case 0: _gted[e->index].railtypelabel = rvi->engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL; break;
|
case 0: _gted[e->index].railtypelabels.push_back(rvi->engclass >= 2 ? RAILTYPE_LABEL_ELECTRIC : RAILTYPE_LABEL_RAIL); break;
|
||||||
case 1: _gted[e->index].railtypelabel = RAILTYPE_LABEL_MONO; break;
|
case 1: _gted[e->index].railtypelabels.push_back(RAILTYPE_LABEL_MONO); break;
|
||||||
case 2: _gted[e->index].railtypelabel = RAILTYPE_LABEL_MAGLEV; break;
|
case 2: _gted[e->index].railtypelabels.push_back(RAILTYPE_LABEL_MAGLEV); break;
|
||||||
default:
|
default:
|
||||||
GrfMsg(1, "RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
|
GrfMsg(1, "RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
|
||||||
break;
|
break;
|
||||||
|
@ -179,11 +180,11 @@ ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteRead
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_cur_gps.grffile->railtype_list.empty()) {
|
if (_cur_gps.grffile->railtype_list.empty() && !_gted[e->index].railtypelabels.empty()) {
|
||||||
/* Use traction type to select between normal and electrified
|
/* Use traction type to select between normal and electrified
|
||||||
* rail only when no translation list is in place. */
|
* rail only when no translation list is in place. */
|
||||||
if (_gted[e->index].railtypelabel == RAILTYPE_LABEL_RAIL && engclass >= EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_LABEL_ELECTRIC;
|
if (_gted[e->index].railtypelabels[0] == RAILTYPE_LABEL_RAIL && engclass >= EC_ELECTRIC) _gted[e->index].railtypelabels[0] = RAILTYPE_LABEL_ELECTRIC;
|
||||||
if (_gted[e->index].railtypelabel == RAILTYPE_LABEL_ELECTRIC && engclass < EC_ELECTRIC) _gted[e->index].railtypelabel = RAILTYPE_LABEL_RAIL;
|
if (_gted[e->index].railtypelabels[0] == RAILTYPE_LABEL_ELECTRIC && engclass < EC_ELECTRIC) _gted[e->index].railtypelabels[0] = RAILTYPE_LABEL_RAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
rvi->engclass = engclass;
|
rvi->engclass = engclass;
|
||||||
|
@ -327,6 +328,22 @@ ChangeInfoResult RailVehicleChangeInfo(uint first, uint last, int prop, ByteRead
|
||||||
e->badges = ReadBadgeList(buf, GSF_TRAINS);
|
e->badges = ReadBadgeList(buf, GSF_TRAINS);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 0x34: { // List of track types
|
||||||
|
uint8_t count = buf.ReadByte();
|
||||||
|
|
||||||
|
_gted[e->index].railtypelabels.clear();
|
||||||
|
while (count--) {
|
||||||
|
uint8_t tracktype = buf.ReadByte();
|
||||||
|
|
||||||
|
if (tracktype < _cur_gps.grffile->railtype_list.size()) {
|
||||||
|
_gted[e->index].railtypelabels.push_back(_cur_gps.grffile->railtype_list[tracktype]);
|
||||||
|
} else {
|
||||||
|
GrfMsg(1, "RailVehicleChangeInfo: Invalid track type {} specified, ignoring", tracktype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
ret = CommonVehicleChangeInfo(ei, prop, buf);
|
ret = CommonVehicleChangeInfo(ei, prop, buf);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -27,7 +27,7 @@ struct GRFTempEngineData {
|
||||||
CargoClasses cargo_allowed; ///< Bitmask of cargo classes that are allowed as a refit.
|
CargoClasses cargo_allowed; ///< Bitmask of cargo classes that are allowed as a refit.
|
||||||
CargoClasses cargo_allowed_required; ///< Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
|
CargoClasses cargo_allowed_required; ///< Bitmask of cargo classes that are required to be all present to allow a cargo as a refit.
|
||||||
CargoClasses cargo_disallowed; ///< Bitmask of cargo classes that are disallowed as a refit.
|
CargoClasses cargo_disallowed; ///< Bitmask of cargo classes that are disallowed as a refit.
|
||||||
RailTypeLabel railtypelabel;
|
std::vector<RailTypeLabel> railtypelabels;
|
||||||
uint8_t roadtramtype;
|
uint8_t roadtramtype;
|
||||||
const GRFFile *defaultcargo_grf; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
|
const GRFFile *defaultcargo_grf; ///< GRF defining the cargo translation table to use if the default cargo is the 'first refittable'.
|
||||||
Refittability refittability; ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
|
Refittability refittability; ///< Did the newgrf set any refittability property? If not, default refittability will be applied.
|
||||||
|
|
|
@ -565,7 +565,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
||||||
RailType rt = GetTileRailType(v->tile);
|
RailType rt = GetTileRailType(v->tile);
|
||||||
const RailTypeInfo *rti = GetRailTypeInfo(rt);
|
const RailTypeInfo *rti = GetRailTypeInfo(rt);
|
||||||
return (rti->flags.Test(RailTypeFlag::Catenary) ? 0x200 : 0) |
|
return (rti->flags.Test(RailTypeFlag::Catenary) ? 0x200 : 0) |
|
||||||
(HasPowerOnRail(Train::From(v)->railtype, rt) ? 0x100 : 0) |
|
(HasPowerOnRail(Train::From(v)->railtypes, rt) ? 0x100 : 0) |
|
||||||
GetReverseRailTypeTranslation(rt, object->ro.grffile);
|
GetReverseRailTypeTranslation(rt, object->ro.grffile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -721,7 +721,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
||||||
const Train *u = is_powered_wagon ? t->First() : t; // for powered wagons the engine defines the type of engine (i.e. railtype)
|
const Train *u = is_powered_wagon ? t->First() : t; // for powered wagons the engine defines the type of engine (i.e. railtype)
|
||||||
RailType railtype = GetRailType(v->tile);
|
RailType railtype = GetRailType(v->tile);
|
||||||
bool powered = t->IsEngine() || is_powered_wagon;
|
bool powered = t->IsEngine() || is_powered_wagon;
|
||||||
bool has_power = HasPowerOnRail(u->railtype, railtype);
|
bool has_power = HasPowerOnRail(u->railtypes, railtype);
|
||||||
|
|
||||||
if (powered && has_power) SetBit(modflags, 5);
|
if (powered && has_power) SetBit(modflags, 5);
|
||||||
if (powered && !has_power) SetBit(modflags, 6);
|
if (powered && !has_power) SetBit(modflags, 6);
|
||||||
|
@ -904,7 +904,7 @@ static uint32_t VehicleGetVariable(Vehicle *v, const VehicleScopeResolver *objec
|
||||||
Train *t = Train::From(v);
|
Train *t = Train::From(v);
|
||||||
switch (variable - 0x80) {
|
switch (variable - 0x80) {
|
||||||
case 0x62: return t->track;
|
case 0x62: return t->track;
|
||||||
case 0x66: return t->railtype;
|
case 0x66: return t->railtypes.GetNthSetBit(0).value_or(RailType::INVALID_RAILTYPE);
|
||||||
case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length;
|
case 0x73: return 0x80 + VEHICLE_LENGTH - t->gcache.cached_veh_length;
|
||||||
case 0x74: return t->gcache.cached_power;
|
case 0x74: return t->gcache.cached_power;
|
||||||
case 0x75: return GB(t->gcache.cached_power, 8, 24);
|
case 0x75: return GB(t->gcache.cached_power, 8, 24);
|
||||||
|
|
|
@ -22,7 +22,7 @@ public:
|
||||||
void SetDestination(const Train *v, bool override_rail_type = false)
|
void SetDestination(const Train *v, bool override_rail_type = false)
|
||||||
{
|
{
|
||||||
this->compatible_railtypes = v->compatible_railtypes;
|
this->compatible_railtypes = v->compatible_railtypes;
|
||||||
if (override_rail_type) this->compatible_railtypes.Set(GetRailTypeInfo(v->railtype)->compatible_railtypes);
|
if (override_rail_type) this->compatible_railtypes.Set(GetAllCompatibleRailTypes(v->railtypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsCompatibleRailType(RailType rt)
|
bool IsCompatibleRailType(RailType rt)
|
||||||
|
|
|
@ -296,7 +296,7 @@ PBSTileInfo FollowTrainReservation(const Train *v, Vehicle **train_on_res)
|
||||||
if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) return PBSTileInfo(tile, trackdir, false);
|
if (IsRailDepotTile(tile) && !GetDepotReservationTrackBits(tile)) return PBSTileInfo(tile, trackdir, false);
|
||||||
|
|
||||||
FindTrainOnTrackInfo ftoti;
|
FindTrainOnTrackInfo ftoti;
|
||||||
ftoti.res = FollowReservation(v->owner, GetRailTypeInfo(v->railtype)->compatible_railtypes, tile, trackdir);
|
ftoti.res = FollowReservation(v->owner, GetAllCompatibleRailTypes(v->railtypes), tile, trackdir);
|
||||||
ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
ftoti.res.okay = IsSafeWaitingPosition(v, ftoti.res.tile, ftoti.res.trackdir, true, _settings_game.pf.forbid_90_deg);
|
||||||
if (train_on_res != nullptr) {
|
if (train_on_res != nullptr) {
|
||||||
CheckTrainsOnTrack(ftoti, ftoti.res.tile);
|
CheckTrainsOnTrack(ftoti, ftoti.res.tile);
|
||||||
|
@ -388,7 +388,7 @@ bool IsSafeWaitingPosition(const Train *v, TileIndex tile, Trackdir trackdir, bo
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check next tile. For performance reasons, we check for 90 degree turns ourself. */
|
/* Check next tile. For performance reasons, we check for 90 degree turns ourself. */
|
||||||
CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes);
|
CFollowTrackRail ft(v, GetAllCompatibleRailTypes(v->railtypes));
|
||||||
|
|
||||||
/* End of track? */
|
/* End of track? */
|
||||||
if (!ft.Follow(tile, trackdir)) {
|
if (!ft.Follow(tile, trackdir)) {
|
||||||
|
|
16
src/rail.cpp
16
src/rail.cpp
|
@ -262,11 +262,13 @@ RailTypes GetCompanyRailTypes(CompanyID company, bool introduces)
|
||||||
const RailVehicleInfo *rvi = &e->u.rail;
|
const RailVehicleInfo *rvi = &e->u.rail;
|
||||||
|
|
||||||
if (rvi->railveh_type != RAILVEH_WAGON) {
|
if (rvi->railveh_type != RAILVEH_WAGON) {
|
||||||
assert(rvi->railtype < RAILTYPE_END);
|
assert(rvi->railtypes.Any());
|
||||||
if (introduces) {
|
if (introduces) {
|
||||||
rts.Set(GetRailTypeInfo(rvi->railtype)->introduces_railtypes);
|
for (RailType rt : rvi->railtypes) {
|
||||||
|
rts.Set(GetRailTypeInfo(rt)->introduces_railtypes);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rts.Set(rvi->railtype);
|
rts.Set(rvi->railtypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -291,11 +293,13 @@ RailTypes GetRailTypes(bool introduces)
|
||||||
|
|
||||||
const RailVehicleInfo *rvi = &e->u.rail;
|
const RailVehicleInfo *rvi = &e->u.rail;
|
||||||
if (rvi->railveh_type != RAILVEH_WAGON) {
|
if (rvi->railveh_type != RAILVEH_WAGON) {
|
||||||
assert(rvi->railtype < RAILTYPE_END);
|
assert(rvi->railtypes.Any());
|
||||||
if (introduces) {
|
if (introduces) {
|
||||||
rts.Set(GetRailTypeInfo(rvi->railtype)->introduces_railtypes);
|
for (RailType rt : rvi->railtypes) {
|
||||||
|
rts.Set(GetRailTypeInfo(rt)->introduces_railtypes);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rts.Set(rvi->railtype);
|
rts.Set(rvi->railtypes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
50
src/rail.h
50
src/rail.h
|
@ -214,7 +214,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Acceleration type of this rail type
|
* Acceleration type of this rail type
|
||||||
*/
|
*/
|
||||||
uint8_t acceleration_type;
|
VehicleAccelerationModel acceleration_type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maximum speed for vehicles travelling on this rail type
|
* Maximum speed for vehicles travelling on this rail type
|
||||||
|
@ -317,6 +317,30 @@ inline RailType GetRailTypeInfoIndex(const RailTypeInfo *rti)
|
||||||
return static_cast<RailType>(index);
|
return static_cast<RailType>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all compatible railtypes for a set of railtypes.
|
||||||
|
* @param railtypes Set of railtypes to get the compatible railtypes from.
|
||||||
|
* @return Union of all compatible railtypes.
|
||||||
|
*/
|
||||||
|
inline RailTypes GetAllCompatibleRailTypes(RailTypes railtypes)
|
||||||
|
{
|
||||||
|
RailTypes compatible{};
|
||||||
|
for (RailType rt : railtypes) compatible |= GetRailTypeInfo(rt)->compatible_railtypes;
|
||||||
|
return compatible;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns all powered railtypes for a set of railtypes.
|
||||||
|
* @param railtypes Set of railtypes to get the powered railtypes from.
|
||||||
|
* @return Union of all powered railtypes.
|
||||||
|
*/
|
||||||
|
inline RailTypes GetAllPoweredRailTypes(RailTypes railtypes)
|
||||||
|
{
|
||||||
|
RailTypes powered{};
|
||||||
|
for (RailType rt : railtypes) powered |= GetRailTypeInfo(rt)->powered_railtypes;
|
||||||
|
return powered;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an engine of the given RailType can drive on a tile with a given
|
* Checks if an engine of the given RailType can drive on a tile with a given
|
||||||
* RailType. This would normally just be an equality check, but for electric
|
* RailType. This would normally just be an equality check, but for electric
|
||||||
|
@ -330,6 +354,18 @@ inline bool IsCompatibleRail(RailType enginetype, RailType tiletype)
|
||||||
return GetRailTypeInfo(enginetype)->compatible_railtypes.Test(tiletype);
|
return GetRailTypeInfo(enginetype)->compatible_railtypes.Test(tiletype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an engine of the given RailTypes can drive on a tile with a given
|
||||||
|
* RailType.
|
||||||
|
* @param enginetype The RailTypes of the engine we are considering.
|
||||||
|
* @param tiletype The RailType of the tile we are considering.
|
||||||
|
* @return Whether the engine can drive on this tile.
|
||||||
|
*/
|
||||||
|
inline bool IsCompatibleRail(RailTypes enginetype, RailType tiletype)
|
||||||
|
{
|
||||||
|
return GetAllCompatibleRailTypes(enginetype).Test(tiletype);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if an engine of the given RailType got power on a tile with a given
|
* Checks if an engine of the given RailType got power on a tile with a given
|
||||||
* RailType. This would normally just be an equality check, but for electric
|
* RailType. This would normally just be an equality check, but for electric
|
||||||
|
@ -343,6 +379,18 @@ inline bool HasPowerOnRail(RailType enginetype, RailType tiletype)
|
||||||
return GetRailTypeInfo(enginetype)->powered_railtypes.Test(tiletype);
|
return GetRailTypeInfo(enginetype)->powered_railtypes.Test(tiletype);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an engine of the given RailTypes got power on a tile with a given
|
||||||
|
* RailType.
|
||||||
|
* @param enginetype The RailTypes of the engine we are considering.
|
||||||
|
* @param tiletype The RailType of the tile we are considering.
|
||||||
|
* @return Whether the engine got power on this tile.
|
||||||
|
*/
|
||||||
|
inline bool HasPowerOnRail(RailTypes enginetype, RailType tiletype)
|
||||||
|
{
|
||||||
|
return GetAllPoweredRailTypes(enginetype).Test(tiletype);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Test if a RailType disallows build of level crossings.
|
* Test if a RailType disallows build of level crossings.
|
||||||
* @param rt The RailType to check.
|
* @param rt The RailType to check.
|
||||||
|
|
|
@ -1605,7 +1605,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_
|
||||||
Track track;
|
Track track;
|
||||||
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
|
while ((track = RemoveFirstTrack(&reserved)) != INVALID_TRACK) {
|
||||||
Train *v = GetTrainForReservation(tile, track);
|
Train *v = GetTrainForReservation(tile, track);
|
||||||
if (v != nullptr && !HasPowerOnRail(v->railtype, totype)) {
|
if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) {
|
||||||
/* No power on new rail type, reroute. */
|
/* No power on new rail type, reroute. */
|
||||||
FreeTrainTrackReservation(v);
|
FreeTrainTrackReservation(v);
|
||||||
vehicles_affected.push_back(v);
|
vehicles_affected.push_back(v);
|
||||||
|
@ -1691,7 +1691,7 @@ CommandCost CmdConvertRail(DoCommandFlags flags, TileIndex tile, TileIndex area_
|
||||||
Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
|
Track track = DiagDirToDiagTrack(GetTunnelBridgeDirection(tile));
|
||||||
if (HasTunnelBridgeReservation(tile)) {
|
if (HasTunnelBridgeReservation(tile)) {
|
||||||
Train *v = GetTrainForReservation(tile, track);
|
Train *v = GetTrainForReservation(tile, track);
|
||||||
if (v != nullptr && !HasPowerOnRail(v->railtype, totype)) {
|
if (v != nullptr && !HasPowerOnRail(v->railtypes, totype)) {
|
||||||
/* No power on new rail type, reroute. */
|
/* No power on new rail type, reroute. */
|
||||||
FreeTrainTrackReservation(v);
|
FreeTrainTrackReservation(v);
|
||||||
vehicles_affected.push_back(v);
|
vehicles_affected.push_back(v);
|
||||||
|
|
|
@ -250,11 +250,11 @@ protected: // These functions should not be called outside acceleration code.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to know the acceleration type of a vehicle.
|
* Allows to know the acceleration type of a vehicle.
|
||||||
* @return Zero, road vehicles always use a normal acceleration method.
|
* @return \c VehicleAccelerationModel::Normal, road vehicles always use a normal acceleration method.
|
||||||
*/
|
*/
|
||||||
inline int GetAccelerationType() const
|
inline VehicleAccelerationModel GetAccelerationType() const
|
||||||
{
|
{
|
||||||
return 0;
|
return VehicleAccelerationModel::Normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1333,10 +1333,10 @@ bool AfterLoadGame()
|
||||||
RailType min_rail = RAILTYPE_ELECTRIC;
|
RailType min_rail = RAILTYPE_ELECTRIC;
|
||||||
|
|
||||||
for (Train *v : Train::Iterate()) {
|
for (Train *v : Train::Iterate()) {
|
||||||
RailType rt = RailVehInfo(v->engine_type)->railtype;
|
RailTypes rts = RailVehInfo(v->engine_type)->railtypes;
|
||||||
|
|
||||||
v->railtype = rt;
|
v->railtypes = rts;
|
||||||
if (rt == RAILTYPE_ELECTRIC) min_rail = RAILTYPE_RAIL;
|
if (rts.Test(RAILTYPE_ELECTRIC)) min_rail = RAILTYPE_RAIL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .. so we convert the entire map from normal to elrail (so maintain "fairness") */
|
/* .. so we convert the entire map from normal to elrail (so maintain "fairness") */
|
||||||
|
|
|
@ -1050,12 +1050,13 @@ static bool LoadOldCompany(LoadgameState &ls, int num)
|
||||||
static uint32_t _old_order_ptr;
|
static uint32_t _old_order_ptr;
|
||||||
static uint16_t _old_next_ptr;
|
static uint16_t _old_next_ptr;
|
||||||
static typename VehicleID::BaseType _current_vehicle_id;
|
static typename VehicleID::BaseType _current_vehicle_id;
|
||||||
|
static RailType _old_railtype;
|
||||||
|
|
||||||
static const OldChunks vehicle_train_chunk[] = {
|
static const OldChunks vehicle_train_chunk[] = {
|
||||||
OCL_SVAR( OC_UINT8, Train, track ),
|
OCL_SVAR( OC_UINT8, Train, track ),
|
||||||
OCL_SVAR( OC_UINT8, Train, force_proceed ),
|
OCL_SVAR( OC_UINT8, Train, force_proceed ),
|
||||||
OCL_SVAR( OC_UINT16, Train, crash_anim_pos ),
|
OCL_SVAR( OC_UINT16, Train, crash_anim_pos ),
|
||||||
OCL_SVAR( OC_UINT8, Train, railtype ),
|
OCL_VAR ( OC_UINT8, 1, &_old_railtype),
|
||||||
|
|
||||||
OCL_NULL( 5 ), ///< Junk
|
OCL_NULL( 5 ), ///< Junk
|
||||||
|
|
||||||
|
@ -1296,7 +1297,7 @@ bool LoadOldVehicle(LoadgameState &ls, int num)
|
||||||
if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
|
if (v->spritenum / 2 >= lengthof(spriteset_rail)) return false;
|
||||||
v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
|
v->spritenum = spriteset_rail[v->spritenum / 2]; // adjust railway sprite set offset
|
||||||
/* Should be the original values for monorail / rail, can't use RailType constants */
|
/* Should be the original values for monorail / rail, can't use RailType constants */
|
||||||
Train::From(v)->railtype = static_cast<RailType>(type == 0x25 ? 1 : 0);
|
Train::From(v)->railtypes = RailTypes(static_cast<RailType>(type == 0x25 ? 1 : 0));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,6 +1358,10 @@ bool LoadOldVehicle(LoadgameState &ls, int num)
|
||||||
Debug(oldloader, 0, "Loading failed - vehicle-array is invalid");
|
Debug(oldloader, 0, "Loading failed - vehicle-array is invalid");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (v->type == VEH_TRAIN) {
|
||||||
|
Train::From(v)->railtypes = RailTypes(_old_railtype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) {
|
if (_old_order_ptr != 0 && _old_order_ptr != 0xFFFFFFFF) {
|
||||||
|
|
|
@ -403,6 +403,8 @@ enum SaveLoadVersion : uint16_t {
|
||||||
SLV_FIX_SCC_ENCODED_NEGATIVE, ///< 353 PR#14049 Fix encoding of negative parameters.
|
SLV_FIX_SCC_ENCODED_NEGATIVE, ///< 353 PR#14049 Fix encoding of negative parameters.
|
||||||
SLV_ORDERS_OWNED_BY_ORDERLIST, ///< 354 PR#13948 Orders stored in OrderList, pool removed.
|
SLV_ORDERS_OWNED_BY_ORDERLIST, ///< 354 PR#13948 Orders stored in OrderList, pool removed.
|
||||||
|
|
||||||
|
SLV_ENGINE_MULTI_RAILTYPE, ///< 355 PR#14357 Train engines can have multiple railtypes.
|
||||||
|
|
||||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -793,13 +793,16 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static RailType _old_railtype;
|
||||||
|
|
||||||
class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
|
class SlVehicleTrain : public DefaultSaveLoadHandler<SlVehicleTrain, Vehicle> {
|
||||||
public:
|
public:
|
||||||
static inline const SaveLoad description[] = {
|
static inline const SaveLoad description[] = {
|
||||||
SLEG_STRUCT("common", SlVehicleCommon),
|
SLEG_STRUCT("common", SlVehicleCommon),
|
||||||
SLE_VAR(Train, crash_anim_pos, SLE_UINT16),
|
SLE_VAR(Train, crash_anim_pos, SLE_UINT16),
|
||||||
SLE_VAR(Train, force_proceed, SLE_UINT8),
|
SLE_VAR(Train, force_proceed, SLE_UINT8),
|
||||||
SLE_VAR(Train, railtype, SLE_UINT8),
|
SLEG_CONDVAR("railtype", _old_railtype, SLE_UINT8, SL_MIN_VERSION, SLV_ENGINE_MULTI_RAILTYPE),
|
||||||
|
SLE_VAR(Train, railtypes, SLE_UINT64),
|
||||||
SLE_VAR(Train, track, SLE_UINT8),
|
SLE_VAR(Train, track, SLE_UINT8),
|
||||||
|
|
||||||
SLE_CONDVAR(Train, flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_100),
|
SLE_CONDVAR(Train, flags, SLE_FILE_U8 | SLE_VAR_U16, SLV_2, SLV_100),
|
||||||
|
@ -819,6 +822,10 @@ public:
|
||||||
{
|
{
|
||||||
if (v->type != VEH_TRAIN) return;
|
if (v->type != VEH_TRAIN) return;
|
||||||
SlObject(v, this->GetLoadDescription());
|
SlObject(v, this->GetLoadDescription());
|
||||||
|
|
||||||
|
if (IsSavegameVersionBefore(SLV_ENGINE_MULTI_RAILTYPE)) {
|
||||||
|
Train::From(v)->railtypes = RailTypes(_old_railtype);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixPointers(Vehicle *v) const override
|
void FixPointers(Vehicle *v) const override
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
* \li AICargo::CC_POTABLE
|
* \li AICargo::CC_POTABLE
|
||||||
* \li AICargo::CC_NON_POTABLE
|
* \li AICargo::CC_NON_POTABLE
|
||||||
* \li AIVehicleList_Waypoint
|
* \li AIVehicleList_Waypoint
|
||||||
|
* \li AIRail::GetAllRailTypes
|
||||||
*
|
*
|
||||||
* Other changes:
|
* Other changes:
|
||||||
* \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType
|
* \li AIBridge::GetBridgeID renamed to AIBridge::GetBridgeType
|
||||||
|
@ -35,6 +36,7 @@
|
||||||
* \li AIList instances can now be saved
|
* \li AIList instances can now be saved
|
||||||
* \li AIVehicleList_Station accepts an optional AIVehicle::VehicleType parameter
|
* \li AIVehicleList_Station accepts an optional AIVehicle::VehicleType parameter
|
||||||
* \li AIList instances can now be cloned
|
* \li AIList instances can now be cloned
|
||||||
|
* \li AIRail::GetRailType will only return the first RailType of an engine, use AIRail::GetAllRailTypes instead
|
||||||
*
|
*
|
||||||
* \b 14.0
|
* \b 14.0
|
||||||
*
|
*
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
* \li GSCargo::CC_NON_POTABLE
|
* \li GSCargo::CC_NON_POTABLE
|
||||||
* \li GSVehicleList_Waypoint
|
* \li GSVehicleList_Waypoint
|
||||||
* \li GSBaseStation::GetOwner
|
* \li GSBaseStation::GetOwner
|
||||||
|
* \li GSRail::GetAllRailTypes
|
||||||
*
|
*
|
||||||
* Other changes:
|
* Other changes:
|
||||||
* \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType
|
* \li GSBridge::GetBridgeID renamed to GSBridge::GetBridgeType
|
||||||
|
@ -36,6 +37,7 @@
|
||||||
* \li GSList instances can now be saved
|
* \li GSList instances can now be saved
|
||||||
* \li GSVehicleList_Station accepts an optional GSVehicle::VehicleType parameter
|
* \li GSVehicleList_Station accepts an optional GSVehicle::VehicleType parameter
|
||||||
* \li GSList instances can now be cloned
|
* \li GSList instances can now be cloned
|
||||||
|
* \li GSRail::GetRailType will only return the first RailType of an engine, use GSRail::GetAllRailTypes instead
|
||||||
*
|
*
|
||||||
* \b 14.0
|
* \b 14.0
|
||||||
*
|
*
|
||||||
|
|
|
@ -203,7 +203,7 @@
|
||||||
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
|
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
|
||||||
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
||||||
|
|
||||||
return ::IsCompatibleRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
|
return ::IsCompatibleRail(::RailVehInfo(engine_id)->railtypes, (::RailType)track_rail_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptEngine::HasPowerOnRail(EngineID engine_id, ScriptRail::RailType track_rail_type)
|
/* static */ bool ScriptEngine::HasPowerOnRail(EngineID engine_id, ScriptRail::RailType track_rail_type)
|
||||||
|
@ -212,7 +212,7 @@
|
||||||
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
|
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
|
||||||
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
||||||
|
|
||||||
return ::HasPowerOnRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
|
return ::HasPowerOnRail(::RailVehInfo(engine_id)->railtypes, (::RailType)track_rail_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptEngine::CanRunOnRoad(EngineID engine_id, ScriptRoad::RoadType road_type)
|
/* static */ bool ScriptEngine::CanRunOnRoad(EngineID engine_id, ScriptRoad::RoadType road_type)
|
||||||
|
@ -242,7 +242,15 @@
|
||||||
if (!IsValidEngine(engine_id)) return ScriptRail::RAILTYPE_INVALID;
|
if (!IsValidEngine(engine_id)) return ScriptRail::RAILTYPE_INVALID;
|
||||||
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return ScriptRail::RAILTYPE_INVALID;
|
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return ScriptRail::RAILTYPE_INVALID;
|
||||||
|
|
||||||
return (ScriptRail::RailType)(uint)::RailVehInfo(engine_id)->railtype;
|
return static_cast<ScriptRail::RailType>(::RailVehInfo(engine_id)->railtypes.GetNthSetBit(0).value_or(::RailType::INVALID_RAILTYPE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* static */ ScriptRail::RailTypes ScriptEngine::GetAllRailTypes(EngineID engine_id)
|
||||||
|
{
|
||||||
|
if (!IsValidEngine(engine_id)) return ScriptRail::INVALID_RAILTYPES;
|
||||||
|
if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return ScriptRail::INVALID_RAILTYPES;
|
||||||
|
|
||||||
|
return static_cast<ScriptRail::RailTypes>(::RailVehInfo(engine_id)->railtypes.base());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ScriptEngine::IsArticulated(EngineID engine_id)
|
/* static */ bool ScriptEngine::IsArticulated(EngineID engine_id)
|
||||||
|
|
|
@ -248,14 +248,24 @@ public:
|
||||||
static ScriptRoad::RoadType GetRoadType(EngineID engine_id);
|
static ScriptRoad::RoadType GetRoadType(EngineID engine_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the RailType of the engine.
|
* Get the first RailType of the engine.
|
||||||
|
* @note This will only return the first RailType of a multi-system engine. Use GetAllRailTypes to get all rail types of the engine.
|
||||||
* @param engine_id The engine to get the RailType of.
|
* @param engine_id The engine to get the RailType of.
|
||||||
* @pre IsValidEngine(engine_id).
|
* @pre IsValidEngine(engine_id).
|
||||||
* @pre GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL.
|
* @pre GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL.
|
||||||
* @return The RailType the engine has.
|
* @return The first RailType the engine has.
|
||||||
*/
|
*/
|
||||||
static ScriptRail::RailType GetRailType(EngineID engine_id);
|
static ScriptRail::RailType GetRailType(EngineID engine_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get all RailType's of the engine.
|
||||||
|
* @param engine_id The engine to get all RailTypes of.
|
||||||
|
* @pre IsValidEngine(engine_id).
|
||||||
|
* @pre GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL.
|
||||||
|
* @return All rail types of the engine.
|
||||||
|
*/
|
||||||
|
static ScriptRail::RailTypes GetAllRailTypes(EngineID engine_id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the engine is articulated.
|
* Check if the engine is articulated.
|
||||||
* @param engine_id The engine to check.
|
* @param engine_id The engine to check.
|
||||||
|
|
|
@ -49,6 +49,14 @@ public:
|
||||||
RAILTYPE_INVALID = ::INVALID_RAILTYPE, ///< Invalid RailType.
|
RAILTYPE_INVALID = ::INVALID_RAILTYPE, ///< Invalid RailType.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A bitmap with all possible rail types.
|
||||||
|
*/
|
||||||
|
enum RailTypes : int64_t {
|
||||||
|
/* Note: these values represent part of the in-game RailTypes enum */
|
||||||
|
INVALID_RAILTYPES = INT64_MAX, ///< Invalid RailTypes.
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A bitmap with all possible rail tracks on a tile.
|
* A bitmap with all possible rail tracks on a tile.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -270,7 +270,7 @@ void Squirrel::AddMethod(std::string_view method_name, SQFUNCTION proc, std::str
|
||||||
sq_newslot(this->vm, -3, SQFalse);
|
sq_newslot(this->vm, -3, SQFalse);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Squirrel::AddConst(std::string_view var_name, int value)
|
void Squirrel::AddConst(std::string_view var_name, SQInteger value)
|
||||||
{
|
{
|
||||||
ScriptAllocatorScope alloc_scope(this);
|
ScriptAllocatorScope alloc_scope(this);
|
||||||
|
|
||||||
|
|
|
@ -104,15 +104,21 @@ public:
|
||||||
* Adds a const to the stack. Depending on the current state this means
|
* Adds a const to the stack. Depending on the current state this means
|
||||||
* either a const to a class or to the global space.
|
* either a const to a class or to the global space.
|
||||||
*/
|
*/
|
||||||
void AddConst(std::string_view var_name, int value);
|
void AddConst(std::string_view var_name, SQInteger value);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a const to the stack. Depending on the current state this means
|
* Adds a const to the stack. Depending on the current state this means
|
||||||
* either a const to a class or to the global space.
|
* either a const to a class or to the global space.
|
||||||
*/
|
*/
|
||||||
void AddConst(std::string_view var_name, uint value) { this->AddConst(var_name, (int)value); }
|
void AddConst(std::string_view var_name, uint value) { this->AddConst(var_name, (SQInteger)value); }
|
||||||
|
|
||||||
void AddConst(std::string_view var_name, const ConvertibleThroughBase auto &value) { this->AddConst(var_name, static_cast<int>(value.base())); }
|
/**
|
||||||
|
* Adds a const to the stack. Depending on the current state this means
|
||||||
|
* either a const to a class or to the global space.
|
||||||
|
*/
|
||||||
|
void AddConst(std::string_view var_name, int value) { this->AddConst(var_name, (SQInteger)value); }
|
||||||
|
|
||||||
|
void AddConst(std::string_view var_name, const ConvertibleThroughBase auto &value) { this->AddConst(var_name, static_cast<SQInteger>(value.base())); }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a const to the stack. Depending on the current state this means
|
* Adds a const to the stack. Depending on the current state this means
|
||||||
|
|
|
@ -86,7 +86,7 @@ static const RailTypeInfo _original_railtypes[] = {
|
||||||
8,
|
8,
|
||||||
|
|
||||||
/* acceleration type */
|
/* acceleration type */
|
||||||
0,
|
VehicleAccelerationModel::Normal,
|
||||||
|
|
||||||
/* max speed */
|
/* max speed */
|
||||||
0,
|
0,
|
||||||
|
@ -188,7 +188,7 @@ static const RailTypeInfo _original_railtypes[] = {
|
||||||
12,
|
12,
|
||||||
|
|
||||||
/* acceleration type */
|
/* acceleration type */
|
||||||
0,
|
VehicleAccelerationModel::Normal,
|
||||||
|
|
||||||
/* max speed */
|
/* max speed */
|
||||||
0,
|
0,
|
||||||
|
@ -286,7 +286,7 @@ static const RailTypeInfo _original_railtypes[] = {
|
||||||
16,
|
16,
|
||||||
|
|
||||||
/* acceleration type */
|
/* acceleration type */
|
||||||
1,
|
VehicleAccelerationModel::Monorail,
|
||||||
|
|
||||||
/* max speed */
|
/* max speed */
|
||||||
0,
|
0,
|
||||||
|
@ -384,7 +384,7 @@ static const RailTypeInfo _original_railtypes[] = {
|
||||||
24,
|
24,
|
||||||
|
|
||||||
/* acceleration type */
|
/* acceleration type */
|
||||||
2,
|
VehicleAccelerationModel::Maglev,
|
||||||
|
|
||||||
/* max speed */
|
/* max speed */
|
||||||
0,
|
0,
|
||||||
|
|
24
src/train.h
24
src/train.h
|
@ -99,7 +99,7 @@ struct Train final : public GroundVehicle<Train, VEH_TRAIN> {
|
||||||
Train *other_multiheaded_part = nullptr;
|
Train *other_multiheaded_part = nullptr;
|
||||||
|
|
||||||
RailTypes compatible_railtypes{};
|
RailTypes compatible_railtypes{};
|
||||||
RailType railtype = INVALID_RAILTYPE;
|
RailTypes railtypes{};
|
||||||
|
|
||||||
TrackBits track{};
|
TrackBits track{};
|
||||||
TrainForceProceeding force_proceed{};
|
TrainForceProceeding force_proceed{};
|
||||||
|
@ -180,6 +180,15 @@ struct Train final : public GroundVehicle<Train, VEH_TRAIN> {
|
||||||
return this->gcache.cached_veh_length / 2 + (this->Next() != nullptr ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
|
return this->gcache.cached_veh_length / 2 + (this->Next() != nullptr ? this->Next()->gcache.cached_veh_length + 1 : 0) / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows to know the acceleration type of a vehicle.
|
||||||
|
* @return Acceleration type of the vehicle.
|
||||||
|
*/
|
||||||
|
inline VehicleAccelerationModel GetAccelerationType() const
|
||||||
|
{
|
||||||
|
return GetRailTypeInfo(GetRailType(this->tile))->acceleration_type;
|
||||||
|
}
|
||||||
|
|
||||||
protected: // These functions should not be called outside acceleration code.
|
protected: // These functions should not be called outside acceleration code.
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -189,7 +198,7 @@ protected: // These functions should not be called outside acceleration code.
|
||||||
inline uint16_t GetPower() const
|
inline uint16_t GetPower() const
|
||||||
{
|
{
|
||||||
/* Power is not added for articulated parts */
|
/* Power is not added for articulated parts */
|
||||||
if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtype, GetRailType(this->tile))) {
|
if (!this->IsArticulatedPart() && HasPowerOnRail(this->railtypes, GetRailType(this->tile))) {
|
||||||
uint16_t power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
|
uint16_t power = GetVehicleProperty(this, PROP_TRAIN_POWER, RailVehInfo(this->engine_type)->power);
|
||||||
/* Halve power for multiheaded parts */
|
/* Halve power for multiheaded parts */
|
||||||
if (this->IsMultiheaded()) power /= 2;
|
if (this->IsMultiheaded()) power /= 2;
|
||||||
|
@ -206,7 +215,7 @@ protected: // These functions should not be called outside acceleration code.
|
||||||
inline uint16_t GetPoweredPartPower(const Train *head) const
|
inline uint16_t GetPoweredPartPower(const Train *head) const
|
||||||
{
|
{
|
||||||
/* For powered wagons the engine defines the type of engine (i.e. railtype) */
|
/* For powered wagons the engine defines the type of engine (i.e. railtype) */
|
||||||
if (this->flags.Test(VehicleRailFlag::PoweredWagon) && HasPowerOnRail(head->railtype, GetRailType(this->tile))) {
|
if (this->flags.Test(VehicleRailFlag::PoweredWagon) && HasPowerOnRail(head->railtypes, GetRailType(this->tile))) {
|
||||||
return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
|
return RailVehInfo(this->gcache.first_engine)->pow_wag_power;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -298,15 +307,6 @@ protected: // These functions should not be called outside acceleration code.
|
||||||
return 15 * (512 + this->GetCurrentSpeed()) / 512;
|
return 15 * (512 + this->GetCurrentSpeed()) / 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Allows to know the acceleration type of a vehicle.
|
|
||||||
* @return Acceleration type of the vehicle.
|
|
||||||
*/
|
|
||||||
inline int GetAccelerationType() const
|
|
||||||
{
|
|
||||||
return GetRailTypeInfo(this->railtype)->acceleration_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the slope steepness used by this vehicle.
|
* Returns the slope steepness used by this vehicle.
|
||||||
* @return Slope steepness used by the vehicle.
|
* @return Slope steepness used by the vehicle.
|
||||||
|
|
|
@ -127,7 +127,7 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
||||||
|
|
||||||
/* update the 'first engine' */
|
/* update the 'first engine' */
|
||||||
u->gcache.first_engine = this == u ? EngineID::Invalid() : first_engine;
|
u->gcache.first_engine = this == u ? EngineID::Invalid() : first_engine;
|
||||||
u->railtype = rvi_u->railtype;
|
u->railtypes = rvi_u->railtypes;
|
||||||
|
|
||||||
if (u->IsEngine()) first_engine = u->engine_type;
|
if (u->IsEngine()) first_engine = u->engine_type;
|
||||||
|
|
||||||
|
@ -172,13 +172,13 @@ void Train::ConsistChanged(ConsistChangeFlags allowed_changes)
|
||||||
/* Do not count powered wagons for the compatible railtypes, as wagons always
|
/* Do not count powered wagons for the compatible railtypes, as wagons always
|
||||||
have railtype normal */
|
have railtype normal */
|
||||||
if (rvi_u->power > 0) {
|
if (rvi_u->power > 0) {
|
||||||
this->compatible_railtypes.Set(GetRailTypeInfo(u->railtype)->powered_railtypes);
|
this->compatible_railtypes.Set(GetAllPoweredRailTypes(u->railtypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Some electric engines can be allowed to run on normal rail. It happens to all
|
/* Some electric engines can be allowed to run on normal rail. It happens to all
|
||||||
* existing electric engines when elrails are disabled and then re-enabled */
|
* existing electric engines when elrails are disabled and then re-enabled */
|
||||||
if (u->flags.Test(VehicleRailFlag::AllowedOnNormalRail)) {
|
if (u->flags.Test(VehicleRailFlag::AllowedOnNormalRail)) {
|
||||||
u->railtype = RAILTYPE_RAIL;
|
u->railtypes.Set(RAILTYPE_RAIL);
|
||||||
u->compatible_railtypes.Set(RAILTYPE_RAIL);
|
u->compatible_railtypes.Set(RAILTYPE_RAIL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -639,7 +639,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlags flags, TileIndex tile, const
|
||||||
const RailVehicleInfo *rvi = &e->u.rail;
|
const RailVehicleInfo *rvi = &e->u.rail;
|
||||||
|
|
||||||
/* Check that the wagon can drive on the track in question */
|
/* Check that the wagon can drive on the track in question */
|
||||||
if (!IsCompatibleRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
|
if (!IsCompatibleRail(rvi->railtypes, GetRailType(tile))) return CMD_ERROR;
|
||||||
|
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
Train *v = new Train();
|
Train *v = new Train();
|
||||||
|
@ -674,7 +674,7 @@ static CommandCost CmdBuildRailWagon(DoCommandFlags flags, TileIndex tile, const
|
||||||
v->cargo_cap = rvi->capacity;
|
v->cargo_cap = rvi->capacity;
|
||||||
v->refit_cap = 0;
|
v->refit_cap = 0;
|
||||||
|
|
||||||
v->railtype = rvi->railtype;
|
v->railtypes = rvi->railtypes;
|
||||||
|
|
||||||
v->date_of_last_service = TimerGameEconomy::date;
|
v->date_of_last_service = TimerGameEconomy::date;
|
||||||
v->date_of_last_service_newgrf = TimerGameCalendar::date;
|
v->date_of_last_service_newgrf = TimerGameCalendar::date;
|
||||||
|
@ -741,7 +741,7 @@ static void AddRearEngineToMultiheadedTrain(Train *v)
|
||||||
u->cargo_subtype = v->cargo_subtype;
|
u->cargo_subtype = v->cargo_subtype;
|
||||||
u->cargo_cap = v->cargo_cap;
|
u->cargo_cap = v->cargo_cap;
|
||||||
u->refit_cap = v->refit_cap;
|
u->refit_cap = v->refit_cap;
|
||||||
u->railtype = v->railtype;
|
u->railtypes = v->railtypes;
|
||||||
u->engine_type = v->engine_type;
|
u->engine_type = v->engine_type;
|
||||||
u->date_of_last_service = v->date_of_last_service;
|
u->date_of_last_service = v->date_of_last_service;
|
||||||
u->date_of_last_service_newgrf = v->date_of_last_service_newgrf;
|
u->date_of_last_service_newgrf = v->date_of_last_service_newgrf;
|
||||||
|
@ -776,7 +776,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlags flags, TileIndex tile, const Engi
|
||||||
|
|
||||||
/* Check if depot and new engine uses the same kind of tracks *
|
/* Check if depot and new engine uses the same kind of tracks *
|
||||||
* We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
|
* We need to see if the engine got power on the tile to avoid electric engines in non-electric depots */
|
||||||
if (!HasPowerOnRail(rvi->railtype, GetRailType(tile))) return CMD_ERROR;
|
if (!HasPowerOnRail(rvi->railtypes, GetRailType(tile))) return CMD_ERROR;
|
||||||
|
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
DiagDirection dir = GetRailDepotDirection(tile);
|
DiagDirection dir = GetRailDepotDirection(tile);
|
||||||
|
@ -808,7 +808,7 @@ CommandCost CmdBuildRailVehicle(DoCommandFlags flags, TileIndex tile, const Engi
|
||||||
v->reliability_spd_dec = e->reliability_spd_dec;
|
v->reliability_spd_dec = e->reliability_spd_dec;
|
||||||
v->max_age = e->GetLifeLengthInDays();
|
v->max_age = e->GetLifeLengthInDays();
|
||||||
|
|
||||||
v->railtype = rvi->railtype;
|
v->railtypes = rvi->railtypes;
|
||||||
|
|
||||||
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
|
v->SetServiceInterval(Company::Get(_current_company)->settings.vehicle.servint_trains);
|
||||||
v->date_of_last_service = TimerGameEconomy::date;
|
v->date_of_last_service = TimerGameEconomy::date;
|
||||||
|
@ -2427,7 +2427,7 @@ void FreeTrainTrackReservation(const Train *v)
|
||||||
/* Don't free reservation if it's not ours. */
|
/* Don't free reservation if it's not ours. */
|
||||||
if (TracksOverlap(GetReservedTrackbits(tile) | TrackToTrackBits(TrackdirToTrack(td)))) return;
|
if (TracksOverlap(GetReservedTrackbits(tile) | TrackToTrackBits(TrackdirToTrack(td)))) return;
|
||||||
|
|
||||||
CFollowTrackRail ft(v, GetRailTypeInfo(v->railtype)->compatible_railtypes);
|
CFollowTrackRail ft(v, GetAllCompatibleRailTypes(v->railtypes));
|
||||||
while (ft.Follow(tile, td)) {
|
while (ft.Follow(tile, td)) {
|
||||||
tile = ft.new_tile;
|
tile = ft.new_tile;
|
||||||
TrackdirBits bits = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(tile));
|
TrackdirBits bits = ft.new_td_bits & TrackBitsToTrackdirBits(GetReservedTrackbits(tile));
|
||||||
|
@ -3083,7 +3083,7 @@ static inline void AffectSpeedByZChange(Train *v, int old_z)
|
||||||
{
|
{
|
||||||
if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) return;
|
if (old_z == v->z_pos || _settings_game.vehicle.train_acceleration_model != AM_ORIGINAL) return;
|
||||||
|
|
||||||
const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
|
const AccelerationSlowdownParams *asp = &_accel_slowdown[static_cast<int>(v->GetAccelerationType())];
|
||||||
|
|
||||||
if (old_z < v->z_pos) {
|
if (old_z < v->z_pos) {
|
||||||
v->cur_speed -= (v->cur_speed * asp->z_up >> 8);
|
v->cur_speed -= (v->cur_speed * asp->z_up >> 8);
|
||||||
|
@ -3490,7 +3490,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
|
||||||
|
|
||||||
if (chosen_dir != v->direction) {
|
if (chosen_dir != v->direction) {
|
||||||
if (prev == nullptr && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
|
if (prev == nullptr && _settings_game.vehicle.train_acceleration_model == AM_ORIGINAL) {
|
||||||
const AccelerationSlowdownParams *asp = &_accel_slowdown[GetRailTypeInfo(v->railtype)->acceleration_type];
|
const AccelerationSlowdownParams *asp = &_accel_slowdown[static_cast<int>(v->GetAccelerationType())];
|
||||||
DirDiff diff = DirDifference(v->direction, chosen_dir);
|
DirDiff diff = DirDifference(v->direction, chosen_dir);
|
||||||
v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? asp->small_turn : asp->large_turn) * v->cur_speed >> 8;
|
v->cur_speed -= (diff == DIRDIFF_45RIGHT || diff == DIRDIFF_45LEFT ? asp->small_turn : asp->large_turn) * v->cur_speed >> 8;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2810,7 +2810,7 @@ void Vehicle::ShowVisualEffect() const
|
||||||
IsDepotTile(v->tile) ||
|
IsDepotTile(v->tile) ||
|
||||||
IsTunnelTile(v->tile) ||
|
IsTunnelTile(v->tile) ||
|
||||||
(v->type == VEH_TRAIN &&
|
(v->type == VEH_TRAIN &&
|
||||||
!HasPowerOnRail(Train::From(v)->railtype, GetTileRailType(v->tile)))) {
|
!HasPowerOnRail(Train::From(v)->railtypes, GetTileRailType(v->tile)))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2596,7 +2596,7 @@ struct VehicleDetailsWindow : Window {
|
||||||
(v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) {
|
(v->type == VEH_ROAD && _settings_game.vehicle.roadveh_acceleration_model != AM_ORIGINAL)) {
|
||||||
const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
|
const GroundVehicleCache *gcache = v->GetGroundVehicleCache();
|
||||||
if (v->type == VEH_TRAIN && (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ||
|
if (v->type == VEH_TRAIN && (_settings_game.vehicle.train_acceleration_model == AM_ORIGINAL ||
|
||||||
GetRailTypeInfo(Train::From(v)->railtype)->acceleration_type == 2)) {
|
Train::From(v)->GetAccelerationType() == VehicleAccelerationModel::Maglev)) {
|
||||||
DrawString(tr, GetString(STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, gcache->cached_weight, gcache->cached_power, max_speed));
|
DrawString(tr, GetString(STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED, gcache->cached_weight, gcache->cached_power, max_speed));
|
||||||
} else {
|
} else {
|
||||||
DrawString(tr, GetString(STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE, gcache->cached_weight, gcache->cached_power, max_speed, gcache->cached_max_te));
|
DrawString(tr, GetString(STR_VEHICLE_INFO_WEIGHT_POWER_MAX_SPEED_MAX_TE, gcache->cached_weight, gcache->cached_power, max_speed, gcache->cached_max_te));
|
||||||
|
|
Loading…
Reference in New Issue