Add feature: realistic train braking

Add setting to select train braking model.
This commit is contained in:
Jonathan G Rennison
2021-01-25 02:33:14 +00:00
parent 2b02318c7e
commit ed0ffb6220
37 changed files with 2556 additions and 291 deletions

View File

@@ -68,6 +68,8 @@
#include "string_func.h"
#include "debug.h"
#include "zoning.h"
#include "vehicle_func.h"
#include "scope_info.h"
#include "void_map.h"
#include "station_base.h"
@@ -958,7 +960,10 @@ static bool UpdateConsists(int32 p1)
{
for (Train *t : Train::Iterate()) {
/* Update the consist of all trains so the maximum speed is set correctly. */
if (t->IsFrontEngine() || t->IsFreeWagon()) t->ConsistChanged(CCF_TRACK);
if (t->IsFrontEngine() || t->IsFreeWagon()) {
t->ConsistChanged(CCF_TRACK);
if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY);
}
}
InvalidateWindowClassesData(WC_BUILD_VEHICLE, 0);
return true;
@@ -1059,6 +1064,7 @@ static bool TrainAccelerationModelChanged(int32 p1)
if (t->IsFrontEngine()) {
t->tcache.cached_max_curve_speed = t->GetCurveSpeedLimit();
t->UpdateAcceleration();
if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY);
}
}
@@ -1070,6 +1076,86 @@ static bool TrainAccelerationModelChanged(int32 p1)
return true;
}
static bool TrainBrakingModelChanged(int32 p1)
{
for (Train *t : Train::Iterate()) {
if (t->IsFrontEngine()) {
t->UpdateAcceleration();
}
}
if (p1 == TBM_REALISTIC && (_game_mode == GM_NORMAL || _game_mode == GM_EDITOR)) {
for (TileIndex t = 0; t < MapSize(); t++) {
if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == RAIL_TILE_SIGNALS) {
uint signals = GetPresentSignals(t);
if ((signals & 0x3) & ((signals & 0x3) - 1) || (signals & 0xC) & ((signals & 0xC) - 1)) {
/* Signals in both directions */
ShowErrorMessage(STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED, INVALID_STRING_ID, WL_ERROR);
return false;
}
if (((signals & 0x3) && IsSignalTypeUnsuitableForRealisticBraking(GetSignalType(t, TRACK_LOWER))) ||
((signals & 0xC) && IsSignalTypeUnsuitableForRealisticBraking(GetSignalType(t, TRACK_UPPER)))) {
/* Banned signal types present */
ShowErrorMessage(STR_CONFIG_SETTING_REALISTIC_BRAKING_SIGNALS_NOT_ALLOWED, INVALID_STRING_ID, WL_ERROR);
return false;
}
}
}
for (TileIndex t = 0; t < MapSize(); t++) {
if (IsTileType(t, MP_RAILWAY) && GetRailTileType(t) == RAIL_TILE_SIGNALS) {
TrackBits bits = GetTrackBits(t);
do {
Track track = RemoveFirstTrack(&bits);
if (HasSignalOnTrack(t, track) && GetSignalType(t, track) == SIGTYPE_NORMAL && HasBit(GetRailReservationTrackBits(t), track)) {
if (EnsureNoTrainOnTrackBits(t, TrackToTrackBits(track)).Succeeded()) {
UnreserveTrack(t, track);
}
}
} while (bits != TRACK_BIT_NONE);
}
}
Train *v_cur = nullptr;
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
extern bool _long_reserve_disabled;
_long_reserve_disabled = true;
for (Train *v : Train::Iterate()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, v->current_order.GetType() != OT_LOADING, HasStationTileRail(v->tile));
}
_long_reserve_disabled = false;
for (Train *v : Train::Iterate()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) continue;
TryPathReserve(v, v->current_order.GetType() != OT_LOADING, HasStationTileRail(v->tile));
if (v->lookahead != nullptr) SetBit(v->lookahead->flags, TRLF_APPLY_ADVISORY);
}
} else if (p1 == TBM_ORIGINAL && (_game_mode == GM_NORMAL || _game_mode == GM_EDITOR)) {
Train *v_cur = nullptr;
SCOPE_INFO_FMT([&v_cur], "TrainBrakingModelChanged: %s", scope_dumper().VehicleInfo(v_cur));
for (Train *v : Train::Iterate()) {
v_cur = v;
if (!v->IsPrimaryVehicle() || (v->vehstatus & VS_CRASHED) != 0 || HasBit(v->subtype, GVSF_VIRTUAL) || v->track == TRACK_BIT_DEPOT) {
v->lookahead.reset();
continue;
}
if (!HasBit(v->flags, VRF_TRAIN_STUCK)) {
_settings_game.vehicle.train_braking_model = TBM_REALISTIC;
FreeTrainTrackReservation(v);
_settings_game.vehicle.train_braking_model = p1;
TryPathReserve(v, v->current_order.GetType() != OT_LOADING, HasStationTileRail(v->tile));
} else {
v->lookahead.reset();
}
}
}
UpdateAllBlockSignals();
InvalidateWindowData(WC_BUILD_SIGNAL, 0);
return true;
}
/**
* This function updates the train acceleration cache after a steepness change.
* @param p1 Callback parameter.
@@ -1078,7 +1164,10 @@ static bool TrainAccelerationModelChanged(int32 p1)
static bool TrainSlopeSteepnessChanged(int32 p1)
{
for (Train *t : Train::Iterate()) {
if (t->IsFrontEngine()) t->CargoChanged();
if (t->IsFrontEngine()) {
t->CargoChanged();
if (t->lookahead != nullptr) SetBit(t->lookahead->flags, TRLF_APPLY_ADVISORY);
}
}
return true;