Improve handling of conditional order waiting loops
Do not leave station/depot/waypoint at all if conditional order loop would result in re-starting waiting/loading Only actually leave and update timetable at end of loop Rate-limit loop checks regardless of timetabled wait time
This commit is contained in:
@@ -3334,6 +3334,8 @@ void Vehicle::LeaveStation()
|
||||
delete this->cargo_payment;
|
||||
assert(this->cargo_payment == nullptr); // cleared by ~CargoPayment
|
||||
|
||||
ClrBit(this->vehicle_flags, VF_COND_ORDER_WAIT);
|
||||
|
||||
TileIndex station_tile = INVALID_TILE;
|
||||
|
||||
if (this->type == VEH_TRAIN) {
|
||||
@@ -3497,6 +3499,20 @@ void Vehicle::ResetRefitCaps()
|
||||
for (Vehicle *v = this; v != nullptr; v = v->Next()) v->refit_cap = v->cargo_cap;
|
||||
}
|
||||
|
||||
static bool ShouldVehicleContinueWaiting(Vehicle *v)
|
||||
{
|
||||
if (v->GetNumOrders() < 1) return false;
|
||||
|
||||
/* Rate-limit re-checking of conditional order loop */
|
||||
if (HasBit(v->vehicle_flags, VF_COND_ORDER_WAIT) && v->tick_counter % 32 != 0) return true;
|
||||
|
||||
/* If conditional orders lead back to this order, just keep waiting without leaving the order */
|
||||
bool loop = AdvanceOrderIndexDeferred(v, v->cur_implicit_order_index) == v->cur_implicit_order_index;
|
||||
FlushAdvanceOrderIndexDeferred(v, loop);
|
||||
if (loop) SetBit(v->vehicle_flags, VF_COND_ORDER_WAIT);
|
||||
return loop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle the loading of the vehicle; when not it skips through dummy
|
||||
* orders and does nothing in all other cases.
|
||||
@@ -3517,7 +3533,7 @@ void Vehicle::HandleLoading(bool mode)
|
||||
if (!mode && this->type != VEH_TRAIN) PayStationSharingFee(this, Station::Get(this->last_station_visited));
|
||||
|
||||
/* Not the first call for this tick, or still loading */
|
||||
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || (this->current_order_time < wait_time && this->current_order.GetLeaveType() != OLT_LEAVE_EARLY)) {
|
||||
if (mode || !HasBit(this->vehicle_flags, VF_LOADING_FINISHED) || (this->current_order_time < wait_time && this->current_order.GetLeaveType() != OLT_LEAVE_EARLY) || ShouldVehicleContinueWaiting(this)) {
|
||||
if (!mode && this->type == VEH_TRAIN && HasBit(Train::From(this)->flags, VRF_ADVANCE_IN_PLATFORM)) this->AdvanceLoadingInStation();
|
||||
return;
|
||||
}
|
||||
@@ -3559,8 +3575,12 @@ void Vehicle::HandleWaiting(bool stop_waiting, bool process_orders)
|
||||
if (!stop_waiting && this->current_order_time < wait_time && this->current_order.GetLeaveType() != OLT_LEAVE_EARLY) {
|
||||
return;
|
||||
}
|
||||
if (!stop_waiting && process_orders && ShouldVehicleContinueWaiting(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* When wait_time is expired, we move on. */
|
||||
ClrBit(this->vehicle_flags, VF_COND_ORDER_WAIT);
|
||||
UpdateVehicleTimetable(this, false);
|
||||
this->IncrementImplicitOrderIndex();
|
||||
this->current_order.MakeDummy();
|
||||
@@ -3668,6 +3688,7 @@ CommandCost Vehicle::SendToDepot(DoCommandFlag flags, DepotCommand command, Tile
|
||||
|
||||
if (flags & DC_EXEC) {
|
||||
if (this->current_order.IsAnyLoadingType()) this->LeaveStation();
|
||||
if (this->current_order.IsType(OT_WAITING)) this->HandleWaiting(true);
|
||||
|
||||
if (this->type == VEH_TRAIN) {
|
||||
for (Train *v = Train::From(this); v != nullptr; v = v->Next()) {
|
||||
@@ -4123,6 +4144,7 @@ void DumpVehicleFlagsGeneric(const Vehicle *v, T dump, U dump_header)
|
||||
dump('s', "VF_TIMETABLE_SEPARATION", HasBit(v->vehicle_flags, VF_TIMETABLE_SEPARATION));
|
||||
dump('a', "VF_AUTOMATE_TIMETABLE", HasBit(v->vehicle_flags, VF_AUTOMATE_TIMETABLE));
|
||||
dump('Q', "VF_HAVE_SLOT", HasBit(v->vehicle_flags, VF_HAVE_SLOT));
|
||||
dump('W', "VF_COND_ORDER_WAIT", HasBit(v->vehicle_flags, VF_COND_ORDER_WAIT));
|
||||
dump_header("vcf:", "cached_veh_flags:");
|
||||
dump('l', "VCF_LAST_VISUAL_EFFECT", HasBit(v->vcache.cached_veh_flags, VCF_LAST_VISUAL_EFFECT));
|
||||
dump('z', "VCF_GV_ZERO_SLOPE_RESIST", HasBit(v->vcache.cached_veh_flags, VCF_GV_ZERO_SLOPE_RESIST));
|
||||
|
Reference in New Issue
Block a user