From 669770f209074e0af61bdf8b84eba7ed06531b17 Mon Sep 17 00:00:00 2001 From: Andreas Schmitt Date: Sun, 20 Jun 2021 04:02:23 +0200 Subject: [PATCH] Fix a few issues and reset everything on start of new game --- src/date.cpp | 5 +++- src/misc.cpp | 4 ++- src/train_cmd.cpp | 68 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 62 insertions(+), 15 deletions(-) diff --git a/src/date.cpp b/src/date.cpp index 05cf97656f..40d35ddba6 100644 --- a/src/date.cpp +++ b/src/date.cpp @@ -39,6 +39,8 @@ YearMonthDay _game_load_cur_date_ymd; DateFract _game_load_date_fract; uint8 _game_load_tick_skip_counter; +extern void ClearOutOfDateSignalSpeedRestrictions(); + /** * Set the date. * @param date New date @@ -280,7 +282,8 @@ static void OnNewDay() if (!_settings_time.time_in_minutes || _settings_client.gui.date_with_time > 0) { SetWindowWidgetDirty(WC_STATUS_BAR, 0, WID_S_LEFT); } - EnginesDailyLoop(); + EnginesDailyLoop(); + ClearOutOfDateSignalSpeedRestrictions(); /* Refresh after possible snowline change */ SetWindowClassesDirty(WC_TOWN_VIEW); diff --git a/src/misc.cpp b/src/misc.cpp index b72d98ef9f..7741645fcd 100644 --- a/src/misc.cpp +++ b/src/misc.cpp @@ -43,6 +43,7 @@ extern TileIndex _cur_tileloop_tile; +extern void ClearAllSignalSpeedRestrictions(); extern void MakeNewgameSettingsLive(); void InitializeSound(); @@ -116,7 +117,8 @@ void InitializeGame(uint size_x, uint size_y, bool reset_date, bool reset_settin RebuildViewportKdtree(); FreeSignalPrograms(); - FreeSignalDependencies(); + FreeSignalDependencies(); + ClearAllSignalSpeedRestrictions(); ClearZoningCaches(); IntialiseOrderDestinationRefcountMap(); diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp index 5c4ebc8abd..1c982e5c42 100644 --- a/src/train_cmd.cpp +++ b/src/train_cmd.cpp @@ -90,6 +90,12 @@ struct SignalSpeedKey } }; +struct SignalSpeedValue +{ + uint16 train_speed; + DateTicksScaled time_stamp; +}; + struct SignalSpeedKeyHashFunc { std::size_t operator() (const SignalSpeedKey &key) const @@ -102,12 +108,6 @@ struct SignalSpeedKeyHashFunc } }; -struct SignalSpeedValue -{ - uint16 train_speed; - Date time_stamp; -}; - static std::unordered_map _signal_speeds(1 << 16); static void TryLongReserveChooseTrainTrackFromReservationEnd(Train *v, bool no_reserve_vehicle_tile = false); @@ -126,6 +126,46 @@ static void TrainEnterStation(Train *v, StationID station); static void UnreserveBridgeTunnelTile(TileIndex tile); static bool CheckTrainStayInWormHolePathReserve(Train *t, TileIndex tile); +/** Return the scaled date ticks by which the speed restriction + * at the current position of the train is going to be invalid */ +static DateTicksScaled GetSpeedRestrictionTimeout(const Train *t) +{ + const int64 look_ahead_distance = 16; // In tiles + const int64 velocity = std::max(25, t->cur_speed); + + // This is a guess. I cannot figure out how the game actually calculates ticks_per_tile. + // If anybody has the correct value here, let me know. + const int64 ticks_per_tile = 2232 / velocity; + + const int64 ticks = ticks_per_tile * look_ahead_distance; + + return _scaled_date_ticks + ticks; +} + +/** Checks if the timeout of the specified signal speed restriction value has passed */ +static bool IsOutOfDate(const SignalSpeedValue& value) +{ + return _scaled_date_ticks > value.time_stamp; +} + +/** Removes all speed restrictions from all signals */ +void ClearAllSignalSpeedRestrictions() +{ + _signal_speeds.clear(); +} + +/** Removes all speed restrictions which have passed their timeout from all signals */ +void ClearOutOfDateSignalSpeedRestrictions() +{ + for(auto key_value_pair = _signal_speeds.begin(); key_value_pair != _signal_speeds.end(); ) { + if (IsOutOfDate(key_value_pair->second)) { + key_value_pair = _signal_speeds.erase(key_value_pair); + } else { + ++key_value_pair; + } + } +} + inline void ClearLookAheadIfInvalid(Train *v) { if (v->lookahead != nullptr && !ValidateLookAhead(v)) v->lookahead.reset(); @@ -988,10 +1028,10 @@ static void AdvanceLookAheadPosition(Train *v) /** * Calculates the maximum speed based on any train in front of this train. */ -int Train::GetAtcMaxSpeed() const +int32 Train::GetAtcMaxSpeed() const { if (!(this->vehstatus & VS_CRASHED) && _settings_game.vehicle.train_speed_adaption && this->signal_speed_restriction != 0) { - return std::max(25, this->signal_speed_restriction); + return std::max(25, this->signal_speed_restriction); } return INT32_MAX; @@ -5564,12 +5604,14 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) const auto found_speed_restriction = _signal_speeds.find(speed_key); if (found_speed_restriction != _signal_speeds.end()) { - if (_date - found_speed_restriction->second.time_stamp < 6) { - v->signal_speed_restriction = std::max(25, found_speed_restriction->second.train_speed); - } else { + if (IsOutOfDate(found_speed_restriction->second)) { _signal_speeds.erase(speed_key); v->signal_speed_restriction = 0; + } else { + v->signal_speed_restriction = std::max(25, found_speed_restriction->second.train_speed); } + } else { + v->signal_speed_restriction = 0; } } @@ -5622,8 +5664,8 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse) speed_key.last_passing_train_dir = v->GetVehicleTrackdir() }; SignalSpeedValue speed_value = { - speed_value.train_speed = v->First()->GetDisplaySpeed(), - speed_value.time_stamp = _date + speed_value.train_speed = v->First()->cur_speed, + speed_value.time_stamp = GetSpeedRestrictionTimeout(v->First()) }; _signal_speeds[speed_key] = speed_value;