Merge remote-tracking branch 'upstream/master'

This commit is contained in:
dP
2025-09-28 02:33:49 +05:00
926 changed files with 37902 additions and 27369 deletions

View File

@@ -27,6 +27,7 @@
#include "settings_type.h"
#include "timetable_cmd.h"
#include "timetable.h"
#include "core/string_consumer.hpp"
#include "widgets/timetable_widget.h"
@@ -103,15 +104,15 @@ bool VehicleIsAboveLatenessThreshold(TimerGameTick::Ticks ticks, bool round_to_d
* @param travelling whether we are interested in the travel or the wait part.
* @return true if the travel/wait time can be used.
*/
static bool CanDetermineTimeTaken(const Order *order, bool travelling)
static bool CanDetermineTimeTaken(const Order &order, bool travelling)
{
/* Current order is conditional */
if (order->IsType(OT_CONDITIONAL) || order->IsType(OT_IMPLICIT)) return false;
if (order.IsType(OT_CONDITIONAL) || order.IsType(OT_IMPLICIT)) return false;
/* No travel time and we have not already finished travelling */
if (travelling && !order->IsTravelTimetabled()) return false;
if (travelling && !order.IsTravelTimetabled()) return false;
/* No wait time but we are loading at this timetabled station */
if (!travelling && !order->IsWaitTimetabled() && order->IsType(OT_GOTO_STATION) &&
!(order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
if (!travelling && !order.IsWaitTimetabled() && order.IsType(OT_GOTO_STATION) &&
!(order.GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) {
return false;
}
@@ -140,7 +141,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
TimerGameTick::Ticks sum = offset;
VehicleOrderID i = start;
const Order *order = v->GetOrder(i);
auto orders = v->Orders();
/* Cyclically loop over all orders until we reach the current one again.
* As we may start at the current order, do a post-checking loop */
@@ -148,48 +149,30 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
/* Automatic orders don't influence the overall timetable;
* they just add some untimetabled entries, but the time till
* the next non-implicit order can still be known. */
if (!order->IsType(OT_IMPLICIT)) {
if (!orders[i].IsType(OT_IMPLICIT)) {
if (travelling || i != start) {
if (!CanDetermineTimeTaken(order, true)) return;
sum += order->GetTimetabledTravel();
if (!CanDetermineTimeTaken(orders[i], true)) return;
sum += orders[i].GetTimetabledTravel();
table[i].arrival = sum;
}
if (!CanDetermineTimeTaken(order, false)) return;
sum += order->GetTimetabledWait();
if (!CanDetermineTimeTaken(orders[i], false)) return;
sum += orders[i].GetTimetabledWait();
table[i].departure = sum;
}
++i;
order = order->next;
if (i >= v->GetNumOrders()) {
i = 0;
assert(order == nullptr);
order = v->orders->GetFirstOrder();
}
i = v->orders->GetNext(i);
} while (i != start);
/* When loading at a scheduled station we still have to treat the
* travelling part of the first order. */
if (!travelling) {
if (!CanDetermineTimeTaken(order, true)) return;
sum += order->GetTimetabledTravel();
if (!CanDetermineTimeTaken(orders[i], true)) return;
sum += orders[i].GetTimetabledTravel();
table[i].arrival = sum;
}
}
/**
* Callback for when a time has been chosen to start the time table
* @param w the window related to the setting of the date
* @param date the actually chosen date
*/
static void ChangeTimetableStartCallback(const Window *w, TimerGameEconomy::Date date, void *data)
{
Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, w->window_number, reinterpret_cast<std::uintptr_t>(data) != 0, GetStartTickFromDate(date));
}
struct TimetableWindow : Window {
int sel_index = -1;
VehicleTimetableWidgets query_widget{}; ///< Which button was clicked to open the query text input?
@@ -261,7 +244,7 @@ struct TimetableWindow : Window {
case WID_VT_ARRIVAL_DEPARTURE_SELECTION:
case WID_VT_TIMETABLE_PANEL:
resize.height = GetCharacterHeight(FS_NORMAL);
fill.height = resize.height = GetCharacterHeight(FS_NORMAL);
size.height = 8 * resize.height + padding.height;
break;
@@ -446,6 +429,7 @@ struct TimetableWindow : Window {
void DrawTimetablePanel(const Rect &r) const
{
const Vehicle *v = this->vehicle;
if (v->GetNumOrders() == 0) return;
Rect tr = r.Shrink(WidgetDimensions::scaled.framerect);
int i = this->vscroll->GetPosition();
VehicleOrderID order_id = (i + 1) / 2;
@@ -456,25 +440,18 @@ struct TimetableWindow : Window {
int index_column_width = GetStringBoundingBox(GetString(STR_ORDER_INDEX, GetParamMaxValue(v->GetNumOrders(), 2))).width + 2 * GetSpriteSize(rtl ? SPR_ARROW_RIGHT : SPR_ARROW_LEFT).width + WidgetDimensions::scaled.hsep_normal;
int middle = rtl ? tr.right - index_column_width : tr.left + index_column_width;
const Order *order = v->GetOrder(order_id);
while (order != nullptr) {
auto orders = v->Orders();
while (true) {
/* Don't draw anything if it extends past the end of the window. */
if (!this->vscroll->IsVisible(i)) break;
if (i % 2 == 0) {
DrawOrderString(v, order, order_id, tr.top, i == selected, true, tr.left, middle, tr.right);
order_id++;
if (order_id >= v->GetNumOrders()) {
order = v->GetOrder(0);
final_order = true;
} else {
order = order->next;
}
DrawOrderString(v, &orders[order_id], order_id, tr.top, i == selected, true, tr.left, middle, tr.right);
if (v->orders->GetNext(order_id) == 0) final_order = true;
order_id = v->orders->GetNext(order_id);
} else {
TextColour colour;
std::string string = GetTimetableTravelString(*order, i, colour);
std::string string = GetTimetableTravelString(orders[order_id], i, colour);
DrawString(rtl ? tr.left : middle, rtl ? middle : tr.right, tr.top, string, colour);
@@ -663,7 +640,11 @@ struct TimetableWindow : Window {
this->change_timetable_all = citymania::_fn_mod;
ShowQueryString({}, STR_TIMETABLE_START_SECONDS_QUERY, 6, this, CS_NUMERAL, QueryStringFlag::AcceptUnchanged);
} else {
ShowSetDateWindow(this, v->index.base(), TimerGameEconomy::date, TimerGameEconomy::year, TimerGameEconomy::year + MAX_TIMETABLE_START_YEARS, ChangeTimetableStartCallback, reinterpret_cast<void*>(static_cast<uintptr_t>(citymania::_fn_mod)));
ShowSetDateWindow(this, v->index.base(), TimerGameEconomy::date, TimerGameEconomy::year, TimerGameEconomy::year + MAX_TIMETABLE_START_YEARS,
[ctrl=citymania::_fn_mod](const Window *w, TimerGameEconomy::Date date) {
Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, w->window_number, ctrl, GetStartTickFromDate(date));
}
);
}
break;
@@ -757,7 +738,7 @@ struct TimetableWindow : Window {
if (!str.has_value()) return;
const Vehicle *v = this->vehicle;
uint64_t val = str->empty() ? 0 : std::strtoul(str->c_str(), nullptr, 10);
uint64_t val = ParseInteger<uint64_t>(*str, 10, true).value_or(0);
auto [order_id, mtf] = PackTimetableArgs(v, this->sel_index, query_widget == WID_VT_CHANGE_SPEED);
switch (query_widget) {
@@ -811,7 +792,7 @@ struct TimetableWindow : Window {
/**
* In real-time mode, the timetable GUI shows relative times and needs to be redrawn every second.
*/
IntervalTimer<TimerGameTick> redraw_interval = { { TimerGameTick::Priority::NONE, Ticks::TICKS_PER_SECOND }, [this](auto) {
const IntervalTimer<TimerGameTick> redraw_interval = { { TimerGameTick::Priority::NONE, Ticks::TICKS_PER_SECOND }, [this](auto) {
if (_settings_client.gui.timetable_mode == TimetableMode::Seconds) {
this->SetDirty();
}