Fix a few issues and reset everything on start of new game

This commit is contained in:
Andreas Schmitt
2021-06-20 04:02:23 +02:00
parent 86cfefba08
commit 669770f209
3 changed files with 62 additions and 15 deletions

View File

@@ -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<SignalSpeedKey, SignalSpeedValue, SignalSpeedKeyHashFunc> _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<int64>(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<int>(25, this->signal_speed_restriction);
return std::max<int32>(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<uint16>(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<uint16>(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;