Initial implementation of tracerestrict speed restriction feature

This commit is contained in:
Jonathan G Rennison
2019-12-05 18:34:05 +00:00
parent 030e8bf762
commit aa8aae9a62
14 changed files with 182 additions and 6 deletions

View File

@@ -617,6 +617,9 @@ int Train::GetCurrentMaxSpeed() const
if (HasBit(this->flags, VRF_BREAKDOWN_SPEED)) {
max_speed = min(max_speed, this->GetBreakdownSpeed());
}
if (this->speed_restriction != 0) {
max_speed = min(max_speed, this->speed_restriction);
}
if (this->current_order.IsType(OT_LOADING_ADVANCE)) max_speed = min(max_speed, 15);
@@ -824,6 +827,7 @@ static CommandCost CmdBuildRailWagon(TileIndex tile, DoCommandFlag flags, const
v->track = TRACK_BIT_DEPOT;
v->vehstatus = VS_HIDDEN | VS_DEFPAL;
v->reverse_distance = 0;
v->speed_restriction = 0;
v->SetWagon();
@@ -969,6 +973,7 @@ CommandCost CmdBuildRailVehicle(TileIndex tile, DoCommandFlag flags, const Engin
v->last_station_visited = INVALID_STATION;
v->last_loading_station = INVALID_STATION;
v->reverse_distance = 0;
v->speed_restriction = 0;
v->engine_type = e->index;
v->gcache.first_engine = INVALID_ENGINE; // needs to be set before first callback
@@ -1668,6 +1673,7 @@ CommandCost CmdSellRailWagon(DoCommandFlag flags, Vehicle *t, uint16 data, uint3
/* Copy other important data from the front engine */
new_head->CopyVehicleConfigAndStatistics(first);
new_head->speed_restriction = first->speed_restriction;
GroupStatistics::CountVehicle(new_head, 1); // after copying over the profit
} else if (v->IsPrimaryVehicle() && data & (MAKE_ORDER_BACKUP_FLAG >> 20)) {
OrderBackup::Backup(v, user);
@@ -2268,6 +2274,20 @@ void ReverseTrainDirection(Train *v)
TryPathReserve(re_reserve_trains[i], true);
}
if (HasBit(v->flags, VRF_PENDING_SPEED_RESTRICTION)) {
auto range = pending_speed_restriction_change_map.equal_range(v->index);
for (auto it = range.first; it != range.second;) {
it->second.distance = (v->gcache.cached_total_length + (HasBit(it->second.flags, PSRCF_DIAGONAL) ? 8 : 4)) - it->second.distance;
if (it->second.distance == 0) {
v->speed_restriction = it->second.prev_speed;
it = pending_speed_restriction_change_map.erase(it);
} else {
std::swap(it->second.prev_speed, it->second.new_speed);
++it;
}
}
}
/* If we are inside a depot after reversing, don't bother with path reserving. */
if (v->track == TRACK_BIT_DEPOT) {
/* Can't be stuck here as inside a depot is always a safe tile. */
@@ -4099,7 +4119,7 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
const Trackdir dir = FindFirstTrackdir(trackdirbits);
if (HasSignalOnTrack(gp.new_tile, TrackdirToTrack(dir))) {
const TraceRestrictProgram *prog = GetExistingTraceRestrictProgram(gp.new_tile, TrackdirToTrack(dir));
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_REVERSE)) {
if (prog && prog->actions_used_flags & (TRPAUF_SLOT_ACQUIRE | TRPAUF_SLOT_RELEASE_FRONT | TRPAUF_REVERSE | TRPAUF_SPEED_RESTRICTION)) {
TraceRestrictProgramResult out;
TraceRestrictProgramInput input(gp.new_tile, dir, nullptr, nullptr);
input.permitted_slot_operations = TRPISP_ACQUIRE | TRPISP_RELEASE_FRONT;
@@ -4109,6 +4129,17 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
v->reverse_distance = v->gcache.cached_total_length + (IsDiagonalTrack(TrackdirToTrack(dir)) ? 16 : 8);
SetWindowDirty(WC_VEHICLE_VIEW, v->index);
}
if (out.flags & TRPRF_SPEED_RETRICTION_SET) {
SetBit(v->flags, VRF_PENDING_SPEED_RESTRICTION);
auto range = pending_speed_restriction_change_map.equal_range(v->index);
for (auto it = range.first; it != range.second; ++it) {
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (it->second.new_speed + 0xFFFF)) it->second.new_speed = out.speed_restriction;
}
uint16 flags = 0;
if (IsDiagonalTrack(TrackdirToTrack(dir))) SetBit(flags, PSRCF_DIAGONAL);
pending_speed_restriction_change_map.insert({ v->index, { (uint16) (v->gcache.cached_total_length + (HasBit(flags, PSRCF_DIAGONAL) ? 8 : 4)), out.speed_restriction, v->speed_restriction, flags } });
if ((uint16) (out.speed_restriction + 0xFFFF) < (uint16) (v->speed_restriction + 0xFFFF)) v->speed_restriction = out.speed_restriction;
}
}
}
}
@@ -4370,6 +4401,18 @@ bool TrainController(Train *v, Vehicle *nomove, bool reverse)
if (v->reverse_distance > 1) {
v->reverse_distance--;
}
if (HasBit(v->flags, VRF_PENDING_SPEED_RESTRICTION)) {
auto range = pending_speed_restriction_change_map.equal_range(v->index);
if (range.first == range.second) ClrBit(v->flags, VRF_PENDING_SPEED_RESTRICTION);
for (auto it = range.first; it != range.second;) {
if (--it->second.distance == 0) {
v->speed_restriction = it->second.new_speed;
it = pending_speed_restriction_change_map.erase(it);
} else {
++it;
}
}
}
/* update the Z position of the vehicle */
int old_z = v->UpdateInclination(gp.new_tile != gp.old_tile, false, v->track == TRACK_BIT_WORMHOLE);