Codechange: Use ticks for timetable start date
This commit is contained in:
		@@ -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"
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user