mirror of https://github.com/OpenTTD/OpenTTD.git
Codechange: Use ticks for timetable start date
This commit is contained in:
parent
3902acb13d
commit
d28caa3ced
|
@ -11,7 +11,7 @@
|
|||
#define BASE_CONSIST_H
|
||||
|
||||
#include "order_type.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "timer/timer_game_tick.h"
|
||||
|
||||
/** Various front vehicle properties that are preserved when autoreplacing, using order-backup or switching front engines within a consist. */
|
||||
struct BaseConsist {
|
||||
|
@ -20,7 +20,7 @@ struct BaseConsist {
|
|||
/* Used for timetabling. */
|
||||
uint32_t current_order_time; ///< How many ticks have passed since this order started.
|
||||
int32_t lateness_counter; ///< How many ticks late (or early if negative) this vehicle is.
|
||||
TimerGameCalendar::Date timetable_start; ///< When the vehicle is supposed to start the timetable.
|
||||
TimerGameTick::TickCounter timetable_start; ///< At what tick of TimerGameTick::counter the vehicle should start its timetable.
|
||||
|
||||
uint16_t service_interval; ///< The interval for (automatic) servicing; either in days or %.
|
||||
|
||||
|
|
|
@ -363,6 +363,7 @@ enum SaveLoadVersion : uint16_t {
|
|||
SLV_CARGO_TRAVELLED, ///< 319 PR#11283 CargoPacket now tracks how far it travelled inside a vehicle.
|
||||
|
||||
SLV_STATION_RATING_CHEAT, ///< 320 PR#11346 Add cheat to fix station ratings at 100%.
|
||||
SLV_TIMETABLE_START_TICKS, ///< 321 PR#11468 Convert timetable start from a date to ticks.
|
||||
|
||||
SL_MAX_VERSION, ///< Highest possible saveload version
|
||||
};
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "../roadveh.h"
|
||||
#include "../ship.h"
|
||||
#include "../aircraft.h"
|
||||
#include "../timetable.h"
|
||||
#include "../station_base.h"
|
||||
#include "../effectvehicle_base.h"
|
||||
#include "../company_base.h"
|
||||
|
@ -373,6 +374,16 @@ void AfterLoadVehicles(bool part_of_load)
|
|||
s->rotation_y_pos = s->y_pos;
|
||||
}
|
||||
}
|
||||
|
||||
if (IsSavegameVersionBefore(SLV_TIMETABLE_START_TICKS)) {
|
||||
/* Convert timetable start from a date to an absolute tick in TimerGameTick::counter. */
|
||||
for (Vehicle *v : Vehicle::Iterate()) {
|
||||
/* If the start date is 0, the vehicle is not waiting to start and can be ignored. */
|
||||
if (v->timetable_start == 0) continue;
|
||||
|
||||
v->timetable_start = GetStartTickFromDate(v->timetable_start);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CheckValidVehicles();
|
||||
|
@ -663,7 +674,8 @@ public:
|
|||
SLE_CONDVAR(Vehicle, current_order.wait_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, current_order.travel_time, SLE_UINT16, SLV_67, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, current_order.max_speed, SLE_UINT16, SLV_174, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, timetable_start, SLE_INT32, SLV_129, SL_MAX_VERSION),
|
||||
SLE_CONDVAR(Vehicle, timetable_start, SLE_FILE_I32 | SLE_VAR_U64, SLV_129, SLV_TIMETABLE_START_TICKS),
|
||||
SLE_CONDVAR(Vehicle, timetable_start, SLE_UINT64, SLV_TIMETABLE_START_TICKS, SL_MAX_VERSION),
|
||||
|
||||
SLE_CONDREF(Vehicle, orders, REF_ORDER, SL_MIN_VERSION, SLV_105),
|
||||
SLE_CONDREF(Vehicle, orders, REF_ORDERLIST, SLV_105, SL_MAX_VERSION),
|
||||
|
|
|
@ -16,6 +16,9 @@
|
|||
|
||||
static const TimerGameCalendar::Year MAX_TIMETABLE_START_YEARS = 15; ///< The maximum start date offset, in years.
|
||||
|
||||
TimerGameTick::TickCounter GetStartTickFromDate(TimerGameCalendar::Date start_date);
|
||||
TimerGameCalendar::Date GetDateFromStartTick(TimerGameTick::TickCounter start_tick);
|
||||
|
||||
void ShowTimetableWindow(const Vehicle *v);
|
||||
void UpdateVehicleTimetable(Vehicle *v, bool travelling);
|
||||
void SetTimetableParams(int param1, int param2, TimerGameTick::Ticks ticks);
|
||||
|
|
|
@ -21,6 +21,40 @@
|
|||
|
||||
#include "safeguards.h"
|
||||
|
||||
/**
|
||||
* Get the TimerGameTick::TickCounter tick of a given date.
|
||||
* @param start_date The date when the timetable starts.
|
||||
* @return The first tick of this date.
|
||||
*/
|
||||
TimerGameTick::TickCounter GetStartTickFromDate(TimerGameCalendar::Date start_date)
|
||||
{
|
||||
/* Calculate the offset in ticks from the current date. */
|
||||
TimerGameTick::Ticks tick_offset = (start_date - TimerGameCalendar::date).base() * Ticks::DAY_TICKS;
|
||||
|
||||
/* Compensate for the current date_fract. */
|
||||
tick_offset -= TimerGameCalendar::date_fract;
|
||||
|
||||
/* Return the current tick plus the offset. */
|
||||
return TimerGameTick::counter + tick_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a date from a given start tick of timetable.
|
||||
* @param start_tick The TimerGameTick::TickCounter when the timetable starts.
|
||||
* @return The date when we reach this tick.
|
||||
*/
|
||||
TimerGameCalendar::Date GetDateFromStartTick(TimerGameTick::TickCounter start_tick)
|
||||
{
|
||||
/* Calculate the offset in ticks from the current counter tick. */
|
||||
TimerGameTick::Ticks tick_offset = start_tick - TimerGameTick::counter;
|
||||
|
||||
/* Compensate for the current date_fract. */
|
||||
tick_offset += TimerGameCalendar::date_fract;
|
||||
|
||||
/* Return the current date plus the offset in days. */
|
||||
return TimerGameCalendar::date + (tick_offset / Ticks::DAY_TICKS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Change/update a particular timetable entry.
|
||||
* @param v The vehicle to change the timetable of.
|
||||
|
@ -300,10 +334,10 @@ static bool VehicleTimetableSorter(Vehicle * const &a, Vehicle * const &b)
|
|||
* @param flags Operation to perform.
|
||||
* @param veh_id Vehicle ID.
|
||||
* @param timetable_all Set to set timetable start for all vehicles sharing this order
|
||||
* @param start_date The timetable start date.
|
||||
* @param start_tick The TimerGameTick::counter tick when the timetable starts.
|
||||
* @return The error or cost of the operation.
|
||||
*/
|
||||
CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, TimerGameCalendar::Date start_date)
|
||||
CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick)
|
||||
{
|
||||
Vehicle *v = Vehicle::GetIfValid(veh_id);
|
||||
if (v == nullptr || !v->IsPrimaryVehicle() || v->orders == nullptr) return CMD_ERROR;
|
||||
|
@ -313,6 +347,8 @@ CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool tim
|
|||
|
||||
TimerGameTick::Ticks total_duration = v->orders->GetTimetableTotalDuration();
|
||||
|
||||
TimerGameCalendar::Date start_date = GetDateFromStartTick(start_tick);
|
||||
|
||||
/* Don't let a timetable start at an invalid date. */
|
||||
if (start_date < 0 || start_date > CalendarTime::MAX_DATE) return CMD_ERROR;
|
||||
|
||||
|
@ -351,7 +387,7 @@ CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool tim
|
|||
w->lateness_counter = 0;
|
||||
ClrBit(w->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
/* Do multiplication, then division to reduce rounding errors. */
|
||||
w->timetable_start = start_date + idx * total_duration / num_vehs / Ticks::DAY_TICKS;
|
||||
w->timetable_start = start_tick + (idx * total_duration / num_vehs);
|
||||
SetWindowDirty(WC_VEHICLE_TIMETABLE, w->index);
|
||||
++idx;
|
||||
}
|
||||
|
@ -444,7 +480,7 @@ void UpdateVehicleTimetable(Vehicle *v, bool travelling)
|
|||
just_started = !HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED);
|
||||
|
||||
if (v->timetable_start != 0) {
|
||||
v->lateness_counter = (TimerGameCalendar::date - v->timetable_start).base() * Ticks::DAY_TICKS + TimerGameCalendar::date_fract;
|
||||
v->lateness_counter = TimerGameTick::counter - v->timetable_start;
|
||||
v->timetable_start = 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -11,13 +11,13 @@
|
|||
#define TIMETABLE_CMD_H
|
||||
|
||||
#include "command_type.h"
|
||||
#include "timer/timer_game_calendar.h"
|
||||
#include "timer/timer_game_tick.h"
|
||||
|
||||
CommandCost CmdChangeTimetable(DoCommandFlag flags, VehicleID veh, VehicleOrderID order_number, ModifyTimetableFlags mtf, uint16_t data);
|
||||
CommandCost CmdBulkChangeTimetable(DoCommandFlag flags, VehicleID veh, ModifyTimetableFlags mtf, uint16_t data);
|
||||
CommandCost CmdSetVehicleOnTime(DoCommandFlag flags, VehicleID veh, bool apply_to_group);
|
||||
CommandCost CmdAutofillTimetable(DoCommandFlag flags, VehicleID veh, bool autofill, bool preserve_wait_time);
|
||||
CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, TimerGameCalendar::Date start_date);
|
||||
CommandCost CmdSetTimetableStart(DoCommandFlag flags, VehicleID veh_id, bool timetable_all, TimerGameTick::TickCounter start_tick);
|
||||
|
||||
DEF_CMD_TRAIT(CMD_CHANGE_TIMETABLE, CmdChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT)
|
||||
DEF_CMD_TRAIT(CMD_BULK_CHANGE_TIMETABLE, CmdBulkChangeTimetable, 0, CMDT_ROUTE_MANAGEMENT)
|
||||
|
|
|
@ -145,7 +145,7 @@ static void FillTimetableArrivalDepartureTable(const Vehicle *v, VehicleOrderID
|
|||
*/
|
||||
static void ChangeTimetableStartCallback(const Window *w, TimerGameCalendar::Date date, void *data)
|
||||
{
|
||||
Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (VehicleID)w->window_number, reinterpret_cast<std::uintptr_t>(data) != 0, date);
|
||||
Command<CMD_SET_TIMETABLE_START>::Post(STR_ERROR_CAN_T_TIMETABLE_VEHICLE, (VehicleID)w->window_number, reinterpret_cast<std::uintptr_t>(data) != 0, GetStartTickFromDate(date));
|
||||
}
|
||||
|
||||
|
||||
|
@ -494,7 +494,7 @@ struct TimetableWindow : Window {
|
|||
/* We are running towards the first station so we can start the
|
||||
* timetable at the given time. */
|
||||
SetDParam(0, STR_JUST_DATE_TINY);
|
||||
SetDParam(1, v->timetable_start);
|
||||
SetDParam(1, GetDateFromStartTick(v->timetable_start));
|
||||
DrawString(tr, STR_TIMETABLE_STATUS_START_AT);
|
||||
} else if (!HasBit(v->vehicle_flags, VF_TIMETABLE_STARTED)) {
|
||||
/* We aren't running on a timetable yet, so how can we be "on time"
|
||||
|
|
Loading…
Reference in New Issue