mirror of
https://github.com/JGRennison/OpenTTD-patches.git
synced 2024-11-11 13:10:45 +00:00
Departures: Allow timetabled depot orders to be calling points
This commit is contained in:
parent
27f8cfba22
commit
7fd1d5e54d
@ -45,6 +45,13 @@ static constexpr Ticks INVALID_DEPARTURE_TICKS = INT32_MIN;
|
|||||||
using ScheduledDispatchCache = btree::btree_map<const DispatchSchedule *, btree::btree_set<StateTicks>>;
|
using ScheduledDispatchCache = btree::btree_map<const DispatchSchedule *, btree::btree_set<StateTicks>>;
|
||||||
using ScheduledDispatchVehicleRecords = btree::btree_map<std::pair<uint, VehicleID>, LastDispatchRecord>;
|
using ScheduledDispatchVehicleRecords = btree::btree_map<std::pair<uint, VehicleID>, LastDispatchRecord>;
|
||||||
|
|
||||||
|
CallAtTargetID CallAtTargetID::FromOrder(const Order *order)
|
||||||
|
{
|
||||||
|
uint32_t id = order->GetDestination();
|
||||||
|
if (order->IsType(OT_GOTO_DEPOT)) id |= DEPOT_TAG;
|
||||||
|
return CallAtTargetID(id);
|
||||||
|
}
|
||||||
|
|
||||||
struct ArrivalHistoryEntry {
|
struct ArrivalHistoryEntry {
|
||||||
const Order *order;
|
const Order *order;
|
||||||
Ticks offset;
|
Ticks offset;
|
||||||
@ -323,7 +330,7 @@ static void ScheduledDispatchDepartureLocalFix(DepartureList &departure_list)
|
|||||||
|
|
||||||
static void ScheduledDispatchSmartTerminusDetection(DepartureList &departure_list, Ticks loop_duration = 0)
|
static void ScheduledDispatchSmartTerminusDetection(DepartureList &departure_list, Ticks loop_duration = 0)
|
||||||
{
|
{
|
||||||
btree::btree_map<StationID, StateTicks> earliest_seen;
|
btree::btree_map<CallAtTargetID, StateTicks> earliest_seen;
|
||||||
|
|
||||||
auto check_departure = [&](Departure *d) {
|
auto check_departure = [&](Departure *d) {
|
||||||
size_t calling_at_size = d->calling_at.size();
|
size_t calling_at_size = d->calling_at.size();
|
||||||
@ -336,12 +343,12 @@ static void ScheduledDispatchSmartTerminusDetection(DepartureList &departure_lis
|
|||||||
|
|
||||||
while (calling_at_size >= 2) {
|
while (calling_at_size >= 2) {
|
||||||
if (d->terminus.scheduled_tick != 0) {
|
if (d->terminus.scheduled_tick != 0) {
|
||||||
auto iter = earliest_seen.find(d->terminus.station);
|
auto iter = earliest_seen.find(d->terminus.target);
|
||||||
if (iter != earliest_seen.end() && iter->second <= d->terminus.scheduled_tick) {
|
if (iter != earliest_seen.end() && iter->second <= d->terminus.scheduled_tick) {
|
||||||
/* Terminus can be reached at same or earlier time on a later vehicle */
|
/* Terminus can be reached at same or earlier time on a later vehicle */
|
||||||
calling_at_size--;
|
calling_at_size--;
|
||||||
size_t new_terminus_offset = calling_at_size - 1;
|
size_t new_terminus_offset = calling_at_size - 1;
|
||||||
d->terminus = CallAt(d->calling_at[new_terminus_offset]);
|
d->terminus = d->calling_at[new_terminus_offset];
|
||||||
|
|
||||||
auto remove_via = [&](StationID st) {
|
auto remove_via = [&](StationID st) {
|
||||||
if (d->via2 == st) d->via2 = INVALID_STATION;
|
if (d->via2 == st) d->via2 = INVALID_STATION;
|
||||||
@ -350,7 +357,9 @@ static void ScheduledDispatchSmartTerminusDetection(DepartureList &departure_lis
|
|||||||
d->via2 = INVALID_STATION;
|
d->via2 = INVALID_STATION;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
remove_via(d->terminus.station);
|
if (d->terminus.target.IsStationID()) {
|
||||||
|
remove_via(d->terminus.target.GetStationID());
|
||||||
|
}
|
||||||
for (const RemoveVia &rv : d->remove_vias) {
|
for (const RemoveVia &rv : d->remove_vias) {
|
||||||
if (rv.calling_at_offset == new_terminus_offset) {
|
if (rv.calling_at_offset == new_terminus_offset) {
|
||||||
remove_via(rv.via);
|
remove_via(rv.via);
|
||||||
@ -364,7 +373,7 @@ static void ScheduledDispatchSmartTerminusDetection(DepartureList &departure_lis
|
|||||||
|
|
||||||
for (const CallAt &c : d->calling_at) {
|
for (const CallAt &c : d->calling_at) {
|
||||||
if (c.scheduled_tick != 0) {
|
if (c.scheduled_tick != 0) {
|
||||||
StateTicks &seen = earliest_seen[c.station];
|
StateTicks &seen = earliest_seen[c.target];
|
||||||
if (seen == 0 || c.scheduled_tick < seen) seen = c.scheduled_tick;
|
if (seen == 0 || c.scheduled_tick < seen) seen = c.scheduled_tick;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -571,10 +580,11 @@ static void GetDepartureCandidateOrderDatesFromVehicle(std::vector<OrderDate> &n
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsStationIDCallingPointOrder(const Order *order)
|
static bool IsCallingPointTargetOrder(const Order *order)
|
||||||
{
|
{
|
||||||
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_IMPLICIT)) && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) return true;
|
if ((order->IsType(OT_GOTO_STATION) || order->IsType(OT_IMPLICIT)) && (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION) == 0) return true;
|
||||||
if (order->IsType(OT_GOTO_WAYPOINT) && order->IsWaitTimetabled()) return true;
|
if (order->IsType(OT_GOTO_WAYPOINT) && order->IsWaitTimetabled()) return true;
|
||||||
|
if (order->IsType(OT_GOTO_DEPOT) && ((order->GetDepotActionType() & ODATFB_NEAREST_DEPOT) == 0) && (order->IsWaitTimetabled() || (order->GetDepotActionType() & ODATFB_HALT) != 0)) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -636,9 +646,9 @@ bool DepartureViaTerminusState::CheckOrder(const Vehicle *v, Departure *d, const
|
|||||||
|
|
||||||
bool DepartureViaTerminusState::HandleCallingPoint(Departure *d, const Order *order, CallAt c, DepartureCallingSettings calling_settings)
|
bool DepartureViaTerminusState::HandleCallingPoint(Departure *d, const Order *order, CallAt c, DepartureCallingSettings calling_settings)
|
||||||
{
|
{
|
||||||
if (!IsStationIDCallingPointOrder(order)) return false;
|
if (!IsCallingPointTargetOrder(order)) return false;
|
||||||
|
|
||||||
if (order->IsType(OT_GOTO_WAYPOINT)) {
|
if (order->IsType(OT_GOTO_WAYPOINT) || order->IsType(OT_GOTO_DEPOT)) {
|
||||||
if (!calling_settings.ShowAllStops()) return false;
|
if (!calling_settings.ShowAllStops()) return false;
|
||||||
} else {
|
} else {
|
||||||
if (!calling_settings.ShowAllStops() && order->GetUnloadType() == OUFB_NO_UNLOAD) return false;
|
if (!calling_settings.ShowAllStops() && order->GetUnloadType() == OUFB_NO_UNLOAD) return false;
|
||||||
@ -650,6 +660,11 @@ bool DepartureViaTerminusState::HandleCallingPoint(Departure *d, const Order *or
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
d->terminus = c;
|
||||||
|
d->calling_at.push_back(c);
|
||||||
|
|
||||||
|
if (order->IsType(OT_GOTO_DEPOT)) return (order->GetDepotActionType() & ODATFB_HALT) != 0;
|
||||||
|
|
||||||
/* Add the station to the calling at list and make it the candidate terminus. */
|
/* Add the station to the calling at list and make it the candidate terminus. */
|
||||||
if (d->via == INVALID_STATION && pending_via != INVALID_STATION) {
|
if (d->via == INVALID_STATION && pending_via != INVALID_STATION) {
|
||||||
d->via = this->pending_via;
|
d->via = this->pending_via;
|
||||||
@ -658,8 +673,6 @@ bool DepartureViaTerminusState::HandleCallingPoint(Departure *d, const Order *or
|
|||||||
if (d->via == INVALID_STATION && this->candidate_via == (StationID)order->GetDestination()) {
|
if (d->via == INVALID_STATION && this->candidate_via == (StationID)order->GetDestination()) {
|
||||||
d->via = (StationID)order->GetDestination();
|
d->via = (StationID)order->GetDestination();
|
||||||
}
|
}
|
||||||
d->terminus = c;
|
|
||||||
d->calling_at.push_back(c);
|
|
||||||
|
|
||||||
/* If we unload all at this station and departure load tests are not disabled, then it is the terminus. */
|
/* If we unload all at this station and departure load tests are not disabled, then it is the terminus. */
|
||||||
if (order->GetType() == OT_GOTO_STATION && order->GetUnloadType() == OUFB_UNLOAD && !calling_settings.DepartureNoLoadTest()) {
|
if (order->GetType() == OT_GOTO_STATION && order->GetUnloadType() == OUFB_UNLOAD && !calling_settings.DepartureNoLoadTest()) {
|
||||||
@ -692,7 +705,7 @@ static bool ProcessArrivalHistory(Departure *d, std::span<ArrivalHistoryEntry> a
|
|||||||
for (uint i = 0; i < (uint)arrival_history.size(); i++) {
|
for (uint i = 0; i < (uint)arrival_history.size(); i++) {
|
||||||
const Order *o = arrival_history[i].order;
|
const Order *o = arrival_history[i].order;
|
||||||
|
|
||||||
if (IsStationIDCallingPointOrder(o)) {
|
if (IsCallingPointTargetOrder(o)) {
|
||||||
if (source.StationMatches(o->GetDestination())) {
|
if (source.StationMatches(o->GetDestination())) {
|
||||||
/* Same as source order, remove all possible origins */
|
/* Same as source order, remove all possible origins */
|
||||||
possible_origins.clear();
|
possible_origins.clear();
|
||||||
@ -707,7 +720,7 @@ static bool ProcessArrivalHistory(Departure *d, std::span<ArrivalHistoryEntry> a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (o->IsType(OT_GOTO_WAYPOINT)) {
|
if (o->IsType(OT_GOTO_WAYPOINT) || o->IsType(OT_GOTO_DEPOT)) {
|
||||||
if (calling_settings.ShowAllStops()) possible_origins.push_back({ o->GetDestination(), i });
|
if (calling_settings.ShowAllStops()) possible_origins.push_back({ o->GetDestination(), i });
|
||||||
} else {
|
} else {
|
||||||
if (calling_settings.ShowAllStops() || o->GetLoadType() != OLFB_NO_LOAD) possible_origins.push_back({ o->GetDestination(), i });
|
if (calling_settings.ShowAllStops() || o->GetLoadType() != OLFB_NO_LOAD) possible_origins.push_back({ o->GetDestination(), i });
|
||||||
@ -742,19 +755,19 @@ static bool ProcessArrivalHistory(Departure *d, std::span<ArrivalHistoryEntry> a
|
|||||||
|
|
||||||
auto make_call_at = [&](const ArrivalHistoryEntry &entry) -> CallAt {
|
auto make_call_at = [&](const ArrivalHistoryEntry &entry) -> CallAt {
|
||||||
if (entry.offset == INVALID_DEPARTURE_TICKS) {
|
if (entry.offset == INVALID_DEPARTURE_TICKS) {
|
||||||
return CallAt((StationID)entry.order->GetDestination());
|
return CallAt(entry.order);
|
||||||
} else {
|
} else {
|
||||||
return CallAt((StationID)entry.order->GetDestination(), entry.offset + arrival_offset);
|
return CallAt(entry.order, entry.offset + arrival_offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (uint i = origin_arrival_history_index + 1; i < (uint)arrival_history.size(); i++) {
|
for (uint i = origin_arrival_history_index + 1; i < (uint)arrival_history.size(); i++) {
|
||||||
const Order *o = arrival_history[i].order;
|
const Order *o = arrival_history[i].order;
|
||||||
if (IsStationIDCallingPointOrder(o)) {
|
if (IsCallingPointTargetOrder(o)) {
|
||||||
check_order(o);
|
check_order(o);
|
||||||
if (o->IsType(OT_GOTO_STATION) && (o->GetLoadType() != OLFB_NO_LOAD || calling_settings.ShowAllStops())) {
|
if (o->IsType(OT_GOTO_STATION) && (o->GetLoadType() != OLFB_NO_LOAD || calling_settings.ShowAllStops())) {
|
||||||
d->calling_at.push_back(make_call_at(arrival_history[i]));
|
d->calling_at.push_back(make_call_at(arrival_history[i]));
|
||||||
} else if (o->IsType(OT_GOTO_WAYPOINT) && calling_settings.ShowAllStops()) {
|
} else if ((o->IsType(OT_GOTO_WAYPOINT) || o->IsType(OT_GOTO_DEPOT))&& calling_settings.ShowAllStops()) {
|
||||||
d->calling_at.push_back(make_call_at(arrival_history[i]));
|
d->calling_at.push_back(make_call_at(arrival_history[i]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -880,7 +893,7 @@ static DepartureList MakeDepartureListLiveMode(DepartureOrderDestinationDetector
|
|||||||
order = lod.v->orders->GetNext(order);
|
order = lod.v->orders->GetNext(order);
|
||||||
StateTicks departure_tick = d->scheduled_tick;
|
StateTicks departure_tick = d->scheduled_tick;
|
||||||
bool travel_time_required = true;
|
bool travel_time_required = true;
|
||||||
CallAt c = CallAt((StationID)order->GetDestination(), departure_tick);
|
CallAt c = CallAt(order, departure_tick);
|
||||||
for (uint i = order_iteration_limit; i > 0; --i) {
|
for (uint i = order_iteration_limit; i > 0; --i) {
|
||||||
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
||||||
if (order == lod.order) {
|
if (order == lod.order) {
|
||||||
@ -927,7 +940,7 @@ static DepartureList MakeDepartureListLiveMode(DepartureOrderDestinationDetector
|
|||||||
}
|
}
|
||||||
if (c.scheduled_tick != 0) c.scheduled_tick = departure_tick;
|
if (c.scheduled_tick != 0) c.scheduled_tick = departure_tick;
|
||||||
|
|
||||||
c.station = (StationID)order->GetDestination();
|
c.target = CallAtTargetID::FromOrder(order);
|
||||||
|
|
||||||
/* We're not interested in this order any further if we're not calling at it. */
|
/* We're not interested in this order any further if we're not calling at it. */
|
||||||
if (via_state.HandleCallingPoint(d, order, c, calling_settings)) break;
|
if (via_state.HandleCallingPoint(d, order, c, calling_settings)) break;
|
||||||
@ -1013,7 +1026,7 @@ static DepartureList MakeDepartureListLiveMode(DepartureOrderDestinationDetector
|
|||||||
|
|
||||||
cumul += o->GetTravelTime() + o->GetWaitTime();
|
cumul += o->GetTravelTime() + o->GetWaitTime();
|
||||||
|
|
||||||
if (o->GetType() == OT_GOTO_STATION || o->GetType() == OT_IMPLICIT || (o->IsType(OT_GOTO_WAYPOINT) && o->IsWaitTimetabled())) {
|
if (IsCallingPointTargetOrder(o)) {
|
||||||
new_history.push_back({ o, cumul });
|
new_history.push_back({ o, cumul });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1266,7 +1279,7 @@ void DepartureListScheduleModeSlotEvaluator::EvaluateFromSourceOrder(const Order
|
|||||||
|
|
||||||
order = this->v->orders->GetNext(order);
|
order = this->v->orders->GetNext(order);
|
||||||
bool travel_time_required = true;
|
bool travel_time_required = true;
|
||||||
CallAt c = CallAt((StationID)order->GetDestination(), departure_tick);
|
CallAt c = CallAt(order, departure_tick);
|
||||||
for (uint i = order_iteration_limit; i > 0; --i) {
|
for (uint i = order_iteration_limit; i > 0; --i) {
|
||||||
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
/* If we reach the order at which the departure occurs again, then use the departure station as the terminus. */
|
||||||
if (order == source_order) {
|
if (order == source_order) {
|
||||||
@ -1313,7 +1326,7 @@ void DepartureListScheduleModeSlotEvaluator::EvaluateFromSourceOrder(const Order
|
|||||||
c.scheduled_tick = 0;
|
c.scheduled_tick = 0;
|
||||||
}
|
}
|
||||||
if (c.scheduled_tick != 0) c.scheduled_tick = departure_tick;
|
if (c.scheduled_tick != 0) c.scheduled_tick = departure_tick;
|
||||||
c.station = (StationID)order->GetDestination();
|
c.target = CallAtTargetID::FromOrder(order);
|
||||||
|
|
||||||
/* We're not interested in this order any further if we're not calling at it. */
|
/* We're not interested in this order any further if we're not calling at it. */
|
||||||
if (via_state.HandleCallingPoint(&d, order, c, this->calling_settings)) break;
|
if (via_state.HandleCallingPoint(&d, order, c, this->calling_settings)) break;
|
||||||
@ -1579,8 +1592,8 @@ static DepartureList MakeDepartureListScheduleMode(DepartureOrderDestinationDete
|
|||||||
|
|
||||||
std::sort(result.begin(), result.end(), [](std::unique_ptr<Departure> &a, std::unique_ptr<Departure> &b) -> bool {
|
std::sort(result.begin(), result.end(), [](std::unique_ptr<Departure> &a, std::unique_ptr<Departure> &b) -> bool {
|
||||||
if (a->scheduled_tick == b->scheduled_tick) {
|
if (a->scheduled_tick == b->scheduled_tick) {
|
||||||
return std::tie(a->terminus.station, a->terminus.scheduled_tick, a->vehicle->index)
|
return std::tie(a->terminus.target, a->terminus.scheduled_tick, a->vehicle->index)
|
||||||
< std::tie(b->terminus.station, b->terminus.scheduled_tick, b->vehicle->index);
|
< std::tie(b->terminus.target, b->terminus.scheduled_tick, b->vehicle->index);
|
||||||
}
|
}
|
||||||
return a->scheduled_tick < b->scheduled_tick;
|
return a->scheduled_tick < b->scheduled_tick;
|
||||||
});
|
});
|
||||||
|
@ -821,15 +821,21 @@ uint DeparturesWindow::GetMinWidth() const
|
|||||||
return result + ScaleGUITrad(140);
|
return result + ScaleGUITrad(140);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Uses 2 parameters */
|
/* Uses 3 parameters */
|
||||||
static void FillBaseStationDParam(size_t n, StationID id)
|
static void FillCallingAtTargetDParam(size_t n, const Departure *d, CallAtTargetID target)
|
||||||
{
|
{
|
||||||
if (Waypoint::IsValidID(id)) {
|
if (target.IsStationID()) {
|
||||||
SetDParam(n, STR_WAYPOINT_NAME);
|
if (Waypoint::IsValidID(target.GetStationID())) {
|
||||||
|
SetDParam(n, STR_WAYPOINT_NAME);
|
||||||
|
} else {
|
||||||
|
SetDParam(n, STR_STATION_NAME);
|
||||||
|
}
|
||||||
|
SetDParam(n + 1, target.GetStationID());
|
||||||
} else {
|
} else {
|
||||||
SetDParam(n, STR_STATION_NAME);
|
SetDParam(n, STR_DEPOT_NAME);
|
||||||
|
SetDParam(n + 1, d->vehicle->type);
|
||||||
|
SetDParam(n + 2, target.GetDepotDestinationID());
|
||||||
}
|
}
|
||||||
SetDParam(n + 1, id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -938,7 +944,7 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->terminus == INVALID_STATION) continue;
|
if (!d->terminus.IsValid()) continue;
|
||||||
|
|
||||||
if (time_width > 0) {
|
if (time_width > 0) {
|
||||||
StringID time_str;
|
StringID time_str;
|
||||||
@ -1011,10 +1017,12 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
/* The icons to show with the destination and via stations. */
|
/* The icons to show with the destination and via stations. */
|
||||||
StringID icon = STR_DEPARTURES_STATION_NONE;
|
StringID icon = STR_DEPARTURES_STATION_NONE;
|
||||||
|
|
||||||
if (_settings_client.gui.departure_destination_type) {
|
if (_settings_client.gui.departure_destination_type && d->terminus.target.IsStationID()) {
|
||||||
Station *t = Station::Get(d->terminus.station);
|
Station *t = Station::GetIfValid(d->terminus.target.GetStationID());
|
||||||
|
|
||||||
if (t->facilities & FACIL_DOCK &&
|
if (t == nullptr) {
|
||||||
|
/* No icon change */
|
||||||
|
} else if (t->facilities & FACIL_DOCK &&
|
||||||
t->facilities & FACIL_AIRPORT &&
|
t->facilities & FACIL_AIRPORT &&
|
||||||
d->vehicle->type != VEH_SHIP &&
|
d->vehicle->type != VEH_SHIP &&
|
||||||
d->vehicle->type != VEH_AIRCRAFT) {
|
d->vehicle->type != VEH_AIRCRAFT) {
|
||||||
@ -1030,11 +1038,11 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
|
|
||||||
StationID via = d->via;
|
StationID via = d->via;
|
||||||
StationID via2 = d->via2;
|
StationID via2 = d->via2;
|
||||||
if (via == d->terminus.station || this->source.StationMatches(via)) {
|
if (d->terminus.target.MatchesStationID(via) || this->source.StationMatches(via)) {
|
||||||
via = via2;
|
via = via2;
|
||||||
via2 = INVALID_STATION;
|
via2 = INVALID_STATION;
|
||||||
}
|
}
|
||||||
if (via2 == d->terminus.station || this->source.StationMatches(via2)) via2 = INVALID_STATION;
|
if (d->terminus.target.MatchesStationID(via2) || this->source.StationMatches(via2)) via2 = INVALID_STATION;
|
||||||
|
|
||||||
/* Arrival time */
|
/* Arrival time */
|
||||||
if (arrival_time_width != 0 && d->terminus.scheduled_tick != 0) {
|
if (arrival_time_width != 0 && d->terminus.scheduled_tick != 0) {
|
||||||
@ -1057,8 +1065,8 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
|
|
||||||
if (via == INVALID_STATION) {
|
if (via == INVALID_STATION) {
|
||||||
/* Only show the terminus. */
|
/* Only show the terminus. */
|
||||||
FillBaseStationDParam(0, d->terminus.station);
|
FillCallingAtTargetDParam(0, d, d->terminus.target);
|
||||||
SetDParam(2, icon);
|
SetDParam(3, icon);
|
||||||
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS);
|
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS);
|
||||||
} else {
|
} else {
|
||||||
auto set_via_dparams = [&](uint offset) {
|
auto set_via_dparams = [&](uint offset) {
|
||||||
@ -1096,16 +1104,16 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
SetDParam(offset, SPECSTR_TEMP_START);
|
SetDParam(offset, SPECSTR_TEMP_START);
|
||||||
};
|
};
|
||||||
/* Show the terminus and the via station. */
|
/* Show the terminus and the via station. */
|
||||||
FillBaseStationDParam(0, d->terminus.station);
|
FillCallingAtTargetDParam(0, d, d->terminus.target);
|
||||||
SetDParam(2, icon);
|
SetDParam(3, icon);
|
||||||
set_via_dparams(3);
|
set_via_dparams(4);
|
||||||
int text_width = (GetStringBoundingBox(STR_DEPARTURES_TERMINUS_VIA_STATION)).width;
|
int text_width = (GetStringBoundingBox(STR_DEPARTURES_TERMINUS_VIA_STATION)).width;
|
||||||
|
|
||||||
if (dest_left + text_width < dest_right) {
|
if (dest_left + text_width < dest_right) {
|
||||||
/* They will both fit, so show them both. */
|
/* They will both fit, so show them both. */
|
||||||
FillBaseStationDParam(0, d->terminus.station);
|
FillCallingAtTargetDParam(0, d, d->terminus.target);
|
||||||
SetDParam(2, icon);
|
SetDParam(3, icon);
|
||||||
set_via_dparams(3);
|
set_via_dparams(4);
|
||||||
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION);
|
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS_VIA_STATION);
|
||||||
} else {
|
} else {
|
||||||
/* They won't both fit, so switch between showing the terminus and the via station approximately every 4 seconds. */
|
/* They won't both fit, so switch between showing the terminus and the via station approximately every 4 seconds. */
|
||||||
@ -1113,8 +1121,8 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
set_via_dparams(0);
|
set_via_dparams(0);
|
||||||
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_VIA);
|
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_VIA);
|
||||||
} else {
|
} else {
|
||||||
FillBaseStationDParam(0, d->terminus.station);
|
FillCallingAtTargetDParam(0, d, d->terminus.target);
|
||||||
SetDParam(2, icon);
|
SetDParam(3, icon);
|
||||||
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS_VIA);
|
DrawString(dest_left, dest_right, y + 1, STR_DEPARTURES_TERMINUS_VIA);
|
||||||
}
|
}
|
||||||
this->scroll_refresh = true;
|
this->scroll_refresh = true;
|
||||||
@ -1197,23 +1205,23 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
/* STR_DEPARTURES_CALLING_AT_LAST_STATION :{STATION} & {RAW_STRING}*/
|
/* STR_DEPARTURES_CALLING_AT_LAST_STATION :{STATION} & {RAW_STRING}*/
|
||||||
std::string buffer;
|
std::string buffer;
|
||||||
|
|
||||||
/* Uses 3 or 4 parameters */
|
/* Uses 4 or 5 parameters */
|
||||||
auto fill_calling_at_dparam = [&](size_t n, const CallAt &c) {
|
auto fill_calling_at_dparam = [&](size_t n, const CallAt &c) {
|
||||||
if (c.scheduled_tick != 0 && arrival_time_width > 0) {
|
if (c.scheduled_tick != 0 && arrival_time_width > 0) {
|
||||||
SetDParam(n, STR_DEPARTURES_CALLING_AT_STATION_WITH_TIME);
|
SetDParam(n, STR_DEPARTURES_CALLING_AT_STATION_WITH_TIME);
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
FillBaseStationDParam(n, c.station);
|
FillCallingAtTargetDParam(n, d, c.target);
|
||||||
SetDParam(n + 2, c.scheduled_tick);
|
SetDParam(n + 3, c.scheduled_tick);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (d->calling_at.size() != 0) {
|
if (d->calling_at.size() != 0) {
|
||||||
fill_calling_at_dparam(0, d->calling_at[0]);
|
fill_calling_at_dparam(0, d->calling_at[0]);
|
||||||
std::string calling_at_buffer = GetString(STR_JUST_STRING3);
|
std::string calling_at_buffer = GetString(STR_JUST_STRING4);
|
||||||
|
|
||||||
const CallAt *continues_to = nullptr;
|
const CallAt *continues_to = nullptr;
|
||||||
|
|
||||||
if (d->calling_at[0].station == d->terminus.station && d->calling_at.size() > 1) {
|
if (d->calling_at[0].target == d->terminus.target && d->calling_at.size() > 1) {
|
||||||
continues_to = &(d->calling_at[d->calling_at.size() - 1]);
|
continues_to = &(d->calling_at[d->calling_at.size() - 1]);
|
||||||
} else if (d->calling_at.size() > 1) {
|
} else if (d->calling_at.size() > 1) {
|
||||||
/* There's more than one stop. */
|
/* There's more than one stop. */
|
||||||
@ -1221,8 +1229,8 @@ void DeparturesWindow::DrawDeparturesListItems(const Rect &r) const
|
|||||||
uint i;
|
uint i;
|
||||||
/* For all but the last station, write out ", <station>". */
|
/* For all but the last station, write out ", <station>". */
|
||||||
for (i = 1; i < d->calling_at.size() - 1; ++i) {
|
for (i = 1; i < d->calling_at.size() - 1; ++i) {
|
||||||
StationID s = d->calling_at[i].station;
|
CallAtTargetID target = d->calling_at[i].target;
|
||||||
if (s == d->terminus.station) {
|
if (target == d->terminus.target) {
|
||||||
continues_to = &(d->calling_at[d->calling_at.size() - 1]);
|
continues_to = &(d->calling_at[d->calling_at.size() - 1]);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -39,17 +39,44 @@ enum DeparturesSourceMode : uint8_t {
|
|||||||
DSM_END
|
DSM_END
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct CallAtTargetID {
|
||||||
|
private:
|
||||||
|
static constexpr uint32_t DEPOT_TAG = 1 << 31;
|
||||||
|
|
||||||
|
uint32_t id;
|
||||||
|
|
||||||
|
constexpr CallAtTargetID(uint32_t id) : id(id) {}
|
||||||
|
|
||||||
|
public:
|
||||||
|
constexpr CallAtTargetID() : id(INVALID_STATION) {}
|
||||||
|
|
||||||
|
static CallAtTargetID FromOrder(const Order *order);
|
||||||
|
static constexpr CallAtTargetID FromStation(StationID station) { return CallAtTargetID(station); }
|
||||||
|
|
||||||
|
inline bool IsValid() const { return id != INVALID_STATION; }
|
||||||
|
inline bool IsStationID() const { return (id & DEPOT_TAG) == 0; }
|
||||||
|
inline StationID GetStationID() const { return (StationID)this->id; }
|
||||||
|
inline DestinationID GetDepotDestinationID() const { return this->id & ~DEPOT_TAG; }
|
||||||
|
inline bool MatchesStationID(StationID st) const { return this->IsStationID() && st == this->GetStationID(); }
|
||||||
|
|
||||||
|
bool operator==(const CallAtTargetID& c) const = default;
|
||||||
|
auto operator<=>(const CallAtTargetID& c) const = default;
|
||||||
|
};
|
||||||
|
|
||||||
struct CallAt {
|
struct CallAt {
|
||||||
StationID station;
|
CallAtTargetID target;
|
||||||
StateTicks scheduled_tick;
|
StateTicks scheduled_tick;
|
||||||
|
|
||||||
CallAt(const StationID& s) : station(s), scheduled_tick(0) { }
|
CallAt(CallAtTargetID target) : target(target), scheduled_tick(0) {}
|
||||||
CallAt(const StationID& s, StateTicks t) : station(s), scheduled_tick(t) { }
|
CallAt(CallAtTargetID target, StateTicks t) : target(target), scheduled_tick(t) {}
|
||||||
CallAt(const CallAt& c) : station(c.station), scheduled_tick(c.scheduled_tick) { }
|
CallAt(const Order *order) : target(CallAtTargetID::FromOrder(order)), scheduled_tick(0) {}
|
||||||
|
CallAt(const Order *order, StateTicks t) : target(CallAtTargetID::FromOrder(order)), scheduled_tick(t) {}
|
||||||
|
|
||||||
|
inline bool IsValid() const { return this->target.IsValid(); }
|
||||||
|
|
||||||
inline bool operator==(const CallAt& c) const
|
inline bool operator==(const CallAt& c) const
|
||||||
{
|
{
|
||||||
return this->station == c.station;
|
return this->target == c.target;
|
||||||
}
|
}
|
||||||
|
|
||||||
CallAt& operator=(const CallAt& c) = default;
|
CallAt& operator=(const CallAt& c) = default;
|
||||||
@ -72,7 +99,7 @@ struct Departure {
|
|||||||
Ticks lateness = 0; ///< How delayed the departure is expected to be
|
Ticks lateness = 0; ///< How delayed the departure is expected to be
|
||||||
StationID via = INVALID_STATION; ///< The station the departure should list as going via
|
StationID via = INVALID_STATION; ///< The station the departure should list as going via
|
||||||
StationID via2 = INVALID_STATION; ///< Secondary station the departure should list as going via
|
StationID via2 = INVALID_STATION; ///< Secondary station the departure should list as going via
|
||||||
CallAt terminus = INVALID_STATION; ///< The station at which the vehicle will terminate following this departure
|
CallAt terminus = CallAtTargetID(); ///< The station at which the vehicle will terminate following this departure
|
||||||
std::vector<CallAt> calling_at; ///< The stations both called at and unloaded at by the vehicle after this departure before it terminates
|
std::vector<CallAt> calling_at; ///< The stations both called at and unloaded at by the vehicle after this departure before it terminates
|
||||||
std::vector<RemoveVia> remove_vias; ///< Vias to remove when using smart terminus.
|
std::vector<RemoveVia> remove_vias; ///< Vias to remove when using smart terminus.
|
||||||
DepartureStatus status{}; ///< Whether the vehicle has arrived yet for this departure
|
DepartureStatus status{}; ///< Whether the vehicle has arrived yet for this departure
|
||||||
|
@ -1368,19 +1368,19 @@ STR_DEPARTURES_TIME :{COLOUR}{STRING
|
|||||||
STR_DEPARTURES_TIME_DEP :{COLOUR}{STRING1} {GREEN}{UP_ARROW}
|
STR_DEPARTURES_TIME_DEP :{COLOUR}{STRING1} {GREEN}{UP_ARROW}
|
||||||
STR_DEPARTURES_TIME_ARR :{COLOUR}{STRING1} {RED}{DOWN_ARROW}
|
STR_DEPARTURES_TIME_ARR :{COLOUR}{STRING1} {RED}{DOWN_ARROW}
|
||||||
STR_DEPARTURES_TIME_BOTH :{COLOUR}{STRING1} {RED}{DOWN_ARROW} {COLOUR}{STRING1} {GREEN}{UP_ARROW}
|
STR_DEPARTURES_TIME_BOTH :{COLOUR}{STRING1} {RED}{DOWN_ARROW} {COLOUR}{STRING1} {GREEN}{UP_ARROW}
|
||||||
STR_DEPARTURES_TERMINUS :{ORANGE}{STRING1}{STRING}
|
STR_DEPARTURES_TERMINUS :{ORANGE}{STRING2}{STRING}
|
||||||
STR_DEPARTURES_TERMINUS_VIA_STATION :{ORANGE}{STRING1}{STRING} via {STRING}
|
STR_DEPARTURES_TERMINUS_VIA_STATION :{ORANGE}{STRING2}{STRING} via {STRING}
|
||||||
STR_DEPARTURES_TERMINUS_VIA :{ORANGE}{STRING1}{STRING} via
|
STR_DEPARTURES_TERMINUS_VIA :{ORANGE}{STRING2}{STRING} via
|
||||||
STR_DEPARTURES_VIA :{ORANGE}via {STRING}
|
STR_DEPARTURES_VIA :{ORANGE}via {STRING}
|
||||||
STR_DEPARTURES_TOC :{ORANGE}{COMPANY}
|
STR_DEPARTURES_TOC :{ORANGE}{COMPANY}
|
||||||
STR_DEPARTURES_GROUP :{ORANGE}{GROUP}
|
STR_DEPARTURES_GROUP :{ORANGE}{GROUP}
|
||||||
STR_DEPARTURES_VEH :{ORANGE}{VEHICLE}
|
STR_DEPARTURES_VEH :{ORANGE}{VEHICLE}
|
||||||
STR_DEPARTURES_CALLING_AT :{ORANGE}Calling at:
|
STR_DEPARTURES_CALLING_AT :{ORANGE}Calling at:
|
||||||
STR_DEPARTURES_CALLING_AT_STATION :{RAW_STRING}, {STRING3}
|
STR_DEPARTURES_CALLING_AT_STATION :{RAW_STRING}, {STRING4}
|
||||||
STR_DEPARTURES_CALLING_AT_LAST_STATION :{RAW_STRING} and {STRING3}
|
STR_DEPARTURES_CALLING_AT_LAST_STATION :{RAW_STRING} and {STRING4}
|
||||||
STR_DEPARTURES_CALLING_AT_LIST :{ORANGE}{RAW_STRING}.
|
STR_DEPARTURES_CALLING_AT_LIST :{ORANGE}{RAW_STRING}.
|
||||||
STR_DEPARTURES_CALLING_AT_LIST_SMART_TERMINUS :{ORANGE}{RAW_STRING}. This service continues to {STRING3}.
|
STR_DEPARTURES_CALLING_AT_LIST_SMART_TERMINUS :{ORANGE}{RAW_STRING}. This service continues to {STRING4}.
|
||||||
STR_DEPARTURES_CALLING_AT_STATION_WITH_TIME :{STRING1} ({TT_TIME_ABS})
|
STR_DEPARTURES_CALLING_AT_STATION_WITH_TIME :{STRING2} ({TT_TIME_ABS})
|
||||||
STR_DEPARTURES_TINY :{TINY_FONT}{STRING2}
|
STR_DEPARTURES_TINY :{TINY_FONT}{STRING2}
|
||||||
STR_DEPARTURES_VIA_DESCRIPTOR :{STRING1}{STRING}
|
STR_DEPARTURES_VIA_DESCRIPTOR :{STRING1}{STRING}
|
||||||
STR_DEPARTURES_VIA_AND :{STRING} and {STRING}
|
STR_DEPARTURES_VIA_AND :{STRING} and {STRING}
|
||||||
|
Loading…
Reference in New Issue
Block a user