Realistic braking: Cache train overall z position

Refresh cache at a variable rate depending on train length and
weight distribution
pull/393/head
Jonathan G Rennison 2 years ago
parent c238bd5012
commit 99ee4b13ce

@ -931,6 +931,8 @@ void TryCreateLookAheadForTrainInTunnelBridge(Train *t)
t->lookahead->reservation_end_position = GetTileMarginInFrontOfTrain(t);
t->lookahead->flags = 0;
t->lookahead->speed_restriction = t->speed_restriction;
t->lookahead->cached_zpos = t->CalculateOverallZPos();
t->lookahead->zpos_refresh_remaining = t->GetZPosCacheUpdateInterval();
if (IsTunnel(t->tile) && Tunnel::GetByTile(t->tile)->is_chunnel) SetBit(t->lookahead->flags, TRLF_CHUNNEL);
if (IsTunnelBridgeSignalSimulationEntrance(t->tile)) {
@ -1002,6 +1004,8 @@ void FillTrainReservationLookAhead(Train *v)
v->lookahead->tunnel_bridge_reserved_tiles = 0;
v->lookahead->flags = 0;
v->lookahead->speed_restriction = v->speed_restriction;
v->lookahead->cached_zpos = v->CalculateOverallZPos();
v->lookahead->zpos_refresh_remaining = v->GetZPosCacheUpdateInterval();
FillLookAheadCurveDataFromTrainPosition(v);
tile = v->tile;
trackdir = v->GetVehicleTrackdir();

@ -90,6 +90,8 @@ struct TrainReservationLookAhead {
uint16 speed_restriction;
std::deque<TrainReservationLookAheadItem> items;
std::deque<TrainReservationLookAheadCurve> curves;
int32 cached_zpos = 0; ///< Cached z position as used in TrainDecelerationStats
uint8 zpos_refresh_remaining = 0; ///< Remaining position updates before next refresh of cached_zpos
int32 RealEndPosition() const
{

@ -3956,6 +3956,15 @@ bool AfterLoadGame()
}
}
if (!SlXvIsFeaturePresent(XSLFI_REALISTIC_TRAIN_BRAKING, 6) && _settings_game.vehicle.train_braking_model == TBM_REALISTIC) {
for (Train *t : Train::Iterate()) {
if (t->lookahead != nullptr) {
t->lookahead->cached_zpos = t->CalculateOverallZPos();
t->lookahead->zpos_refresh_remaining = t->GetZPosCacheUpdateInterval();
}
}
}
if (SlXvIsFeatureMissing(XSLFI_INFLATION_FIXED_DATES)) {
_settings_game.economy.inflation_fixed_dates = !IsSavegameVersionBefore(SLV_GS_INDUSTRY_CONTROL);
}

@ -151,7 +151,7 @@ const SlxiSubChunkInfo _sl_xv_sub_chunk_infos[] = {
{ XSLFI_ANIMATED_TILE_EXTRA, XSCF_NULL, 1, 1, "animated_tile_extra", nullptr, nullptr, nullptr },
{ XSLFI_NEWGRF_INFO_EXTRA, XSCF_NULL, 1, 1, "newgrf_info_extra", nullptr, nullptr, nullptr },
{ XSLFI_INDUSTRY_CARGO_ADJ, XSCF_IGNORABLE_UNKNOWN, 1, 1, "industry_cargo_adj", nullptr, nullptr, nullptr },
{ XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 5, 5, "realistic_train_braking", nullptr, nullptr, "VLKA" },
{ XSLFI_REALISTIC_TRAIN_BRAKING,XSCF_NULL, 6, 6, "realistic_train_braking", nullptr, nullptr, "VLKA" },
{ XSLFI_INFLATION_FIXED_DATES, XSCF_IGNORABLE_ALL, 1, 1, "inflation_fixed_dates", nullptr, nullptr, nullptr },
{ XSLFI_WATER_FLOODING, XSCF_NULL, 2, 2, "water_flooding", nullptr, nullptr, nullptr },
{ XSLFI_MORE_HOUSES, XSCF_NULL, 2, 2, "more_houses", nullptr, nullptr, nullptr },

@ -1392,6 +1392,8 @@ const SaveLoadTable GetVehicleLookAheadDescription()
SLE_VAR(TrainReservationLookAhead, flags, SLE_UINT16),
SLE_VAR(TrainReservationLookAhead, speed_restriction, SLE_UINT16),
SLE_CONDVAR_X(TrainReservationLookAhead, next_extend_position, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 5)),
SLE_CONDVAR_X(TrainReservationLookAhead, cached_zpos, SLE_INT32, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 6)),
SLE_CONDVAR_X(TrainReservationLookAhead, zpos_refresh_remaining, SLE_UINT8, SL_MIN_VERSION, SL_MAX_VERSION, SlXvFeatureTest(XSLFTO_AND, XSLFI_REALISTIC_TRAIN_BRAKING, 6)),
};
return _vehicle_look_ahead_desc;

@ -211,7 +211,7 @@ class NIHVehicle : public NIHelper {
if (t->lookahead != nullptr) {
output.print(" Look ahead:");
const TrainReservationLookAhead &l = *t->lookahead;
TrainDecelerationStats stats(t);
TrainDecelerationStats stats(t, l.cached_zpos);
auto print_braking_speed = [&](int position, int end_speed, int end_z) {
if (!t->UsingRealisticBraking()) return;
@ -229,6 +229,11 @@ class NIHVehicle : public NIHelper {
}
output.print(buffer);
const int overall_zpos = t->CalculateOverallZPos();
seprintf(buffer, lastof(buffer), " Cached zpos: %u (actual: %u, delta: %d), positions to refresh: %u",
l.cached_zpos, overall_zpos, (l.cached_zpos - overall_zpos), l.zpos_refresh_remaining);
output.print(buffer);
b = buffer + seprintf(buffer, lastof(buffer), " Reservation ends at %X (%u x %u), trackdir: %02X, z: %d",
l.reservation_end_tile, TileX(l.reservation_end_tile), TileY(l.reservation_end_tile), l.reservation_end_trackdir, l.reservation_end_z);
if (HasBit(l.flags, TRLF_DEPOT_END)) {

@ -212,6 +212,13 @@ public:
int GetCurrentMaxSpeed() const;
uint8 GetZPosCacheUpdateInterval() const
{
return Clamp<uint16>(std::min<uint16>(this->gcache.cached_total_length / 4, this->tcache.cached_centre_mass / 2), 2, 32);
}
uint32 CalculateOverallZPos() const;
bool UsingRealisticBraking() const { return this->tcache.cached_tflags & TCF_RL_BRAKING; }
/**
@ -494,7 +501,7 @@ struct TrainDecelerationStats {
int z_pos;
const Train *t;
TrainDecelerationStats(const Train *t);
TrainDecelerationStats(const Train *t, int z_pos);
};
CommandCost CmdMoveRailVehicle(TileIndex, DoCommandFlag , uint32, uint32, const char *);

@ -807,19 +807,11 @@ int PredictStationStoppingLocation(const Train *v, const Order *order, int stati
return stop + adjust;
}
TrainDecelerationStats::TrainDecelerationStats(const Train *t)
TrainDecelerationStats::TrainDecelerationStats(const Train *t, int z_pos)
{
this->deceleration_x2 = 2 * t->tcache.cached_deceleration;
this->uncapped_deceleration_x2 = 2 * t->tcache.cached_uncapped_decel;
if (likely(HasBit(t->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST))) {
this->z_pos = t->z_pos;
} else {
int64 sum = 0;
for (const Train *u = t; u != nullptr; u = u->Next()) {
sum += ((int)u->z_pos * (int)u->tcache.cached_veh_weight);
}
this->z_pos = sum / t->gcache.cached_weight;
}
this->z_pos = z_pos;
this->t = t;
}
@ -977,6 +969,7 @@ static void ApplyLookAheadItem(const Train *v, const TrainReservationLookAheadIt
static void AdvanceLookAheadPosition(Train *v)
{
v->lookahead->current_position++;
if (v->lookahead->zpos_refresh_remaining > 0) v->lookahead->zpos_refresh_remaining--;
if (v->lookahead->current_position > v->lookahead->reservation_end_position + 8) {
/* Beyond end of lookahead, delete it, it will be recreated later with a new reservation */
@ -1102,7 +1095,11 @@ Train::MaxSpeedInfo Train::GetCurrentMaxSpeedInfoInternal(bool update_state) con
if (this->UsingRealisticBraking()) {
if (this->lookahead != nullptr) {
TrainDecelerationStats stats(this);
if (update_state && this->lookahead->zpos_refresh_remaining == 0) {
this->lookahead->cached_zpos = this->CalculateOverallZPos();
this->lookahead->zpos_refresh_remaining = this->GetZPosCacheUpdateInterval();
}
TrainDecelerationStats stats(this, this->lookahead->cached_zpos);
if (HasBit(this->lookahead->flags, TRLF_DEPOT_END)) {
LimitSpeedFromLookAhead(max_speed, stats, this->lookahead->current_position, this->lookahead->reservation_end_position - TILE_SIZE, 61, this->lookahead->reservation_end_z - stats.z_pos);
} else {
@ -1135,6 +1132,19 @@ int Train::GetCurrentMaxSpeed() const
return std::min(info.strict_max_speed, info.advisory_max_speed);
}
uint32 Train::CalculateOverallZPos() const
{
if (likely(HasBit(this->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST))) {
return this->z_pos;
} else {
int64 sum = 0;
for (const Train *u = this; u != nullptr; u = u->Next()) {
sum += ((int)u->z_pos * (int)u->tcache.cached_veh_weight);
}
return sum / this->gcache.cached_weight;
}
}
/** Update acceleration of the train from the cached power and weight. */
void Train::UpdateAcceleration()
{
@ -3980,7 +3990,7 @@ static bool IsReservationLookAheadLongEnough(const Train *v, const ChooseTrainTr
if (v->lookahead->reservation_end_position >= v->lookahead->current_position + v->reverse_distance - 1) return true;
}
TrainDecelerationStats stats(v);
TrainDecelerationStats stats(v, v->lookahead->cached_zpos);
bool found_signal = false;
int signal_speed = 0;
@ -5231,7 +5241,7 @@ inline void DecreaseReverseDistance(Train *v)
int ReversingDistanceTargetSpeed(const Train *v)
{
if (v->UsingRealisticBraking()) {
TrainDecelerationStats stats(v);
TrainDecelerationStats stats(v, v->lookahead != nullptr ? v->lookahead->cached_zpos : v->CalculateOverallZPos());
return GetRealisticBrakingSpeedForDistance(stats, v->reverse_distance - 1, 0, 0);
}
int target_speed;

@ -3418,6 +3418,7 @@ void Vehicle::LeaveStation()
}
SetBit(Train::From(this)->flags, VRF_LEAVING_STATION);
if (Train::From(this)->lookahead != nullptr) Train::From(this)->lookahead->zpos_refresh_remaining = 0;
}
if (this->type == VEH_ROAD && !(this->vehstatus & VS_CRASHED)) {
/* Trigger road stop animation */
@ -3477,6 +3478,7 @@ void Vehicle::AdvanceLoadingInStation()
HideFillingPercent(&this->fill_percent_te_id);
this->current_order.MakeLoadingAdvance(this->last_station_visited);
this->current_order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
if (Train::From(this)->lookahead != nullptr) Train::From(this)->lookahead->zpos_refresh_remaining = 0;
this->MarkDirty();
}

Loading…
Cancel
Save