Initial implementation of tracerestrict speed restriction feature
This commit is contained in:
@@ -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);
|
||||
|
Reference in New Issue
Block a user