summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--config.lib16
-rw-r--r--projects/openttd.vcproj9
-rw-r--r--projects/openttd_vs80.vcproj12
-rw-r--r--source.list3
-rw-r--r--src/aircraft_cmd.cpp3
-rw-r--r--src/command.cpp4
-rw-r--r--src/command.h2
-rw-r--r--src/lang/english.txt27
-rw-r--r--src/openttd.h1
-rw-r--r--src/order.h7
-rw-r--r--src/order_cmd.cpp20
-rw-r--r--src/order_gui.cpp47
-rw-r--r--src/roadveh_cmd.cpp3
-rw-r--r--src/saveload.cpp2
-rw-r--r--src/settings.cpp4
-rw-r--r--src/settings_gui.cpp6
-rw-r--r--src/ship_cmd.cpp4
-rw-r--r--src/train_cmd.cpp6
-rw-r--r--src/variables.h3
-rw-r--r--src/vehicle.cpp17
-rw-r--r--src/vehicle.h4
21 files changed, 167 insertions, 33 deletions
diff --git a/config.lib b/config.lib
index b381f6048..b41306d32 100644
--- a/config.lib
+++ b/config.lib
@@ -315,13 +315,13 @@ check_params() {
exit 1
fi
# cpu_type can be either 32 or 64
- if [ -z "`echo $cpu_type | grep '^32$\|^64$\|^DETECT$'`" ]; then
+ if [ -z "`echo $cpu_type | egrep '^(32|64|DETECT)$'`" ]; then
echo "configure: error: invalid option --cpu-type=$cpu_type"
echo " Available options are: --cpu-type[=DETECT|32|64]"
exit 1
fi
# enable_debug should be between 0 and 4
- if [ -z "`echo $enable_debug | grep '^[0123]$'`" ]; then
+ if [ -z "`echo $enable_debug | egrep '^[0123]$'`" ]; then
echo "configure: error: invalid option --enable-debug=$enable_debug"
echo " Available options are: --enable-debug[=0123]"
exit 1
@@ -1512,11 +1512,11 @@ detect_library() {
log 2 "detecting $2"
if [ "$1" = "1" ] || [ "$1" = "" ] || [ "$1" = "2" ]; then
- eval "$2=`ls -1 /usr/include/*.h 2>/dev/null | grep \"\/$4\$\"`"
+ eval "$2=`ls -1 /usr/include/*.h 2>/dev/null | egrep \"\/$4\$\"`"
eval "res=\$$2"
if [ -z "$res" ]; then
log 2 " trying /usr/include/$4... no"
- eval "$2=`ls -1 /usr/local/include/*.h 2>/dev/null | grep \"\/$4\$\"`"
+ eval "$2=`ls -1 /usr/local/include/*.h 2>/dev/null | egrep \"\/$4\$\"`"
fi
eval "res=\$$2"
if [ -z "$res" ]; then
@@ -1528,16 +1528,16 @@ detect_library() {
eval "res=\$$2"
log 2 " trying $res... found"
# Now find the static lib, if needed
- eval "$2=`ls /lib/*.a 2>/dev/null | grep \"\/$3\$\"`"
+ eval "$2=`ls /lib/*.a 2>/dev/null | egrep \"\/$3\$\"`"
eval "res=\$$2"
if [ -z "$res" ]; then
log 2 " trying /lib/$3... no"
- eval "$2=`ls /usr/lib/*.a 2>/dev/null | grep \"\/$3\$\"`"
+ eval "$2=`ls /usr/lib/*.a 2>/dev/null | egrep \"\/$3\$\"`"
fi
eval "res=\$$2"
if [ -z "$res" ]; then
log 2 " trying /usr/lib/$3... no"
- eval "$2=`ls /usr/local/lib/*.a 2>/dev/null | grep \"\/$3\$\"`"
+ eval "$2=`ls /usr/local/lib/*.a 2>/dev/null | egrep \"\/$3\$\"`"
fi
eval "res=\$$2"
if [ -z "$res" ]; then
@@ -1913,7 +1913,7 @@ make_sed() {
# FOUR_BYTE_BOOL is needed, because C++ uses 4byte for a bool on PPC, where
# we use 1 byte per bool normally in C part. So convert that last one to 4
# bytes too, but only for PPC.
- ppc=`$cc_host -dumpmachine | grep "powerpc\|ppc"`
+ ppc=`$cc_host -dumpmachine | egrep "powerpc|ppc"`
if [ -n "$ppc" ]; then
T_CFLAGS="$CFLAGS -DFOUR_BYTE_BOOL"
osx_sysroot_version=10.3.9
diff --git a/projects/openttd.vcproj b/projects/openttd.vcproj
index a439556d2..931fe7fb7 100644
--- a/projects/openttd.vcproj
+++ b/projects/openttd.vcproj
@@ -654,6 +654,9 @@
RelativePath=".\..\src\tile.h">
</File>
<File
+ RelativePath=".\..\src\timetable.h">
+ </File>
+ <File
RelativePath=".\..\src\town.h">
</File>
<File
@@ -790,6 +793,9 @@
RelativePath=".\..\src\terraform_gui.cpp">
</File>
<File
+ RelativePath=".\..\src\timetable_gui.cpp">
+ </File>
+ <File
RelativePath=".\..\src\town_gui.cpp">
</File>
<File
@@ -845,6 +851,9 @@
RelativePath=".\..\src\station_cmd.cpp">
</File>
<File
+ RelativePath=".\..\src\timetable_cmd.cpp">
+ </File>
+ <File
RelativePath=".\..\src\town_cmd.cpp">
</File>
<File
diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj
index f3129305a..33092e6f6 100644
--- a/projects/openttd_vs80.vcproj
+++ b/projects/openttd_vs80.vcproj
@@ -1100,6 +1100,10 @@
>
</File>
<File
+ RelativePath=".\..\src\timetable.h"
+ >
+ </File>
+ <File
RelativePath=".\..\src\town.h"
>
</File>
@@ -1280,6 +1284,10 @@
>
</File>
<File
+ RelativePath=".\..\src\timetable_gui.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\town_gui.cpp"
>
</File>
@@ -1352,6 +1360,10 @@
>
</File>
<File
+ RelativePath=".\..\src\timetable_cmd.cpp"
+ >
+ </File>
+ <File
RelativePath=".\..\src\town_cmd.cpp"
>
</File>
diff --git a/source.list b/source.list
index 6445d213b..fc613bc5e 100644
--- a/source.list
+++ b/source.list
@@ -185,6 +185,7 @@ string.h
tgp.h
thread.h
tile.h
+timetable.h
town.h
train.h
transparency_gui.h
@@ -231,6 +232,7 @@ smallmap_gui.cpp
station_gui.cpp
subsidy_gui.cpp
terraform_gui.cpp
+timetable_gui.cpp
town_gui.cpp
train_gui.cpp
transparency_gui.cpp
@@ -250,6 +252,7 @@ road_cmd.cpp
roadveh_cmd.cpp
ship_cmd.cpp
station_cmd.cpp
+timetable_cmd.cpp
town_cmd.cpp
train_cmd.cpp
tree_cmd.cpp
diff --git a/src/aircraft_cmd.cpp b/src/aircraft_cmd.cpp
index 6a190ef08..b92039ed5 100644
--- a/src/aircraft_cmd.cpp
+++ b/src/aircraft_cmd.cpp
@@ -14,6 +14,7 @@
#include "map.h"
#include "tile.h"
#include "vehicle.h"
+#include "timetable.h"
#include "depot.h"
#include "engine.h"
#include "command.h"
@@ -1349,6 +1350,7 @@ static void ProcessAircraftOrder(Vehicle *v)
if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
!VehicleNeedsService(v)) {
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
}
break;
@@ -2086,6 +2088,7 @@ static bool AirportFindFreeHelipad(Vehicle *v, const AirportFTAClass *apc)
static void AircraftEventHandler(Vehicle *v, int loop)
{
v->tick_counter++;
+ v->current_order_time++;
if (v->vehstatus & VS_CRASHED) {
HandleCrashedAircraft(v);
diff --git a/src/command.cpp b/src/command.cpp
index 8b814d034..a400307dc 100644
--- a/src/command.cpp
+++ b/src/command.cpp
@@ -177,6 +177,8 @@ DEF_COMMAND(CmdRemoveAllVehiclesGroup);
DEF_COMMAND(CmdSetGroupReplaceProtection);
DEF_COMMAND(CmdMoveOrder);
+DEF_COMMAND(CmdChangeTimetable);
+DEF_COMMAND(CmdSetVehicleOnTime);
/* The master command table */
static const Command _command_proc_table[] = {
@@ -331,6 +333,8 @@ static const Command _command_proc_table[] = {
{CmdRemoveAllVehiclesGroup, 0}, /* 125 */
{CmdSetGroupReplaceProtection, 0}, /* 126 */
{CmdMoveOrder, 0}, /* 127 */
+ {CmdChangeTimetable, 0}, /* 128 */
+ {CmdSetVehicleOnTime, 0}, /* 129 */
};
/* This function range-checks a cmd, and checks if the cmd is not NULL */
diff --git a/src/command.h b/src/command.h
index c269ed43d..6f2014765 100644
--- a/src/command.h
+++ b/src/command.h
@@ -153,6 +153,8 @@ enum {
CMD_SET_GROUP_REPLACE_PROTECTION = 126,
CMD_MOVE_ORDER = 127,
+ CMD_CHANGE_TIMETABLE = 128,
+ CMD_SET_VEHICLE_ON_TIME = 129,
};
enum {
diff --git a/src/lang/english.txt b/src/lang/english.txt
index ea492f0a4..dd9a1ba84 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -1103,6 +1103,8 @@ STR_CONFIG_PATCHES_SCROLLWHEEL_OFF :Off
STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER :{LTBLUE}Map scrollwheel speed: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME :{LTBLUE}Automatically pause when starting a new game: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS :{LTBLUE}Use the advanced vehicle list: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_TIMETABLE_ALLOW :{LTBLUE}Enable timetabling for vehicles: {ORANGE}{STRING1}
+STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS :{LTBLUE}Show timetable in ticks rather than days: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_MAX_TRAINS :{LTBLUE}Max trains per player: {ORANGE}{STRING1}
STR_CONFIG_PATCHES_MAX_ROADVEH :{LTBLUE}Max road vehicles per player: {ORANGE}{STRING1}
@@ -2607,6 +2609,13 @@ STR_SERVICE_AT_TRAIN_DEPOT :Service at {TOW
STR_880F_GO_NON_STOP_TO_TRAIN_DEPOT :Go non-stop to {TOWN} Train Depot
STR_SERVICE_NON_STOP_AT_TRAIN_DEPOT :Service non-stop at {TOWN} Train Depot
+STR_TIMETABLE_GO_TO :{STRING1} {STRING2}
+STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Travel (not timetabled)
+STR_TIMETABLE_TRAVEL_FOR :Travel for {STRING1}
+STR_TIMETABLE_STAY_FOR :and stay for {STRING1}
+STR_TIMETABLE_DAYS :{COMMA} day{P "" s}
+STR_TIMETABLE_TICKS :{COMMA} tick{P "" s}
+
STR_HEADING_FOR_TRAIN_DEPOT :{ORANGE}Heading for {TOWN} Train Depot
STR_HEADING_FOR_TRAIN_DEPOT_VEL :{ORANGE}Heading for {TOWN} Train Depot, {VELOCITY}
STR_HEADING_FOR_TRAIN_DEPOT_SERVICE :{LTBLUE}Service at {TOWN} Train Depot
@@ -2648,6 +2657,8 @@ STR_8828_UNLOAD :{BLACK}Unload
STR_REFIT :{BLACK}Refit
STR_REFIT_TIP :{BLACK}Select what cargo type to refit to in this order. Control click to remove refit instruction
STR_REFIT_ORDER :(Refit to {STRING})
+STR_TIMETABLE_VIEW :{BLACK}Timetable
+STR_TIMETABLE_VIEW_TOOLTIP :{BLACK}Switch to the timetable view
STR_8829_ORDERS :{WHITE}{VEHICLE} (Orders)
STR_882A_END_OF_ORDERS :{SETX 10}- - End of Orders - -
STR_FULLLOAD_OR_SERVICE :{SKIP}{SKIP}{STRING}
@@ -2704,6 +2715,10 @@ STR_8855_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the
STR_8856_INSERT_A_NEW_ORDER_BEFORE :{BLACK}Insert a new order before the highlighted order, or add to end of list
STR_8857_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to wait for a full load
STR_8858_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to unload
+STR_TIMETABLE_TOOLTIP :{BLACK}Timetable - click on an order to highlight it.
+STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change the amount of time that the highlighted order should take
+STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order
+STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time
STR_SERVICE_HINT :{BLACK}Skip this order unless a service is needed
STR_VEHICLE_INFO_COST_WEIGHT_SPEED_POWER :{BLACK}Cost: {CURRENCY} Weight: {WEIGHT_S}{}Speed: {VELOCITY} Power: {POWER}{}Running Cost: {CURRENCY}/yr{}Capacity: {CARGO}
STR_885C_BROKEN_DOWN :{RED}Broken down
@@ -2725,6 +2740,8 @@ STR_886A_RENAME_TRAIN_VEHICLE_TYPE :{WHITE}Rename t
STR_886B_CAN_T_RENAME_TRAIN_VEHICLE :{WHITE}Can't rename train vehicle type...
STR_886D_MAKE_THE_HIGHLIGHTED_ORDER :{BLACK}Make the highlighted order force the vehicle to dump cargo
STR_886F_TRANSFER :{BLACK}Transfer
+STR_CLEAR_TIME :{BLACK}Clear Time
+STR_RESET_LATENESS :{BLACK}Reset Late Counter
STR_TRAIN_STOPPING :{RED}Stopping
STR_TRAIN_STOPPING_VEL :{RED}Stopping, {VELOCITY}
@@ -2736,6 +2753,14 @@ STR_NEW_VEHICLE_NOW_AVAILABLE :{BLACK}{BIGFONT
STR_NEW_VEHICLE_TYPE :{BLACK}{BIGFONT}{STRING}
STR_NEW_VEHICLE_NOW_AVAILABLE_WITH_TYPE :{BLACK}New {STRING} now available! - {STRING}
+STR_CAN_T_TIMETABLE_VEHICLE :{WHITE}Can't timetable vehicle...
+STR_TIMETABLE_ONLY_WAIT_AT_STATIONS :{WHITE}Vehicles can only wait at stations.
+STR_TIMETABLE_NOT_STOPPING_HERE :{WHITE}This vehicle is not stopping at this station.
+STR_TIMETABLE_CHANGE_TIME :{BLACK}Change Time
+STR_TIMETABLE_STATUS_ON_TIME :This vehicle is currently running on time
+STR_TIMETABLE_STATUS_LATE :This vehicle is currently running {STRING1} late
+STR_TIMETABLE_STATUS_EARLY :This vehicle is currently running {STRING1} early
+
##id 0x9000
STR_9000_ROAD_VEHICLE_IN_THE_WAY :{WHITE}Road vehicle in the way
STR_9001_ROAD_VEHICLES :{WHITE}{COMPANY} - {COMMA} Road Vehicle{P "" s}
@@ -2947,6 +2972,8 @@ STR_A042_CAN_T_REFIT_AIRCRAFT :{WHITE}Can't re
STR_GO_TO_AIRPORT_HANGAR :Go to {STATION} Hangar
SERVICE_AT_AIRPORT_HANGAR :Service at {STATION} Hangar
+STR_TIMETABLE_TITLE :{WHITE}{VEHICLE} (Timetable)
+
##id 0xB000
STR_B000_ZEPPELIN_DISASTER_AT :{BLACK}{BIGFONT}Zeppelin disaster at {STATION}!
STR_B001_ROAD_VEHICLE_DESTROYED :{BLACK}{BIGFONT}Road vehicle destroyed in 'UFO' collision!
diff --git a/src/openttd.h b/src/openttd.h
index 460f29bd6..a768da3bd 100644
--- a/src/openttd.h
+++ b/src/openttd.h
@@ -570,6 +570,7 @@ enum WindowClass {
WC_GENERATE_PROGRESS_WINDOW,
WC_CONFIRM_POPUP_QUERY,
WC_TRANSPARENCY_TOOLBAR,
+ WC_VEHICLE_TIMETABLE,
};
diff --git a/src/order.h b/src/order.h
index 3a2ddb1f3..9703989e8 100644
--- a/src/order.h
+++ b/src/order.h
@@ -86,7 +86,7 @@ enum {
/* If you change this, keep in mind that it is saved on 3 places:
* - Load_ORDR, all the global orders
* - Vehicle -> current_order
- * - REF_SHEDULE (all REFs are currently limited to 16 bits!!)
+ * - REF_ORDER (all REFs are currently limited to 16 bits!!)
*/
struct Order {
Order *next; ///< Pointer to next order. If NULL, end of list
@@ -100,6 +100,9 @@ struct Order {
CargoID refit_cargo; // Refit CargoID
byte refit_subtype; // Refit subtype
+ uint16 wait_time; ///< How long in ticks to wait at the destination.
+ uint16 travel_time; ///< How long in ticks the journey to this destination should take.
+
bool IsValid() const;
void Free();
void FreeChain();
@@ -197,6 +200,8 @@ static inline Order UnpackOrder(uint32 packed)
order.index = 0; // avoid compiler warning
order.refit_cargo = CT_NO_REFIT;
order.refit_subtype = 0;
+ order.wait_time = 0;
+ order.travel_time = 0;
return order;
}
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index f33bfb4d2..7b14f912f 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -48,6 +48,8 @@ Order UnpackOldOrder(uint16 packed)
order.refit_cargo = CT_NO_REFIT;
order.refit_subtype = 0;
+ order.wait_time = 0;
+ order.travel_time = 0;
order.index = 0; // avoid compiler warning
// Sanity check
@@ -75,6 +77,8 @@ static Order UnpackVersion4Order(uint16 packed)
order.index = 0; // avoid compiler warning
order.refit_cargo = CT_NO_REFIT;
order.refit_subtype = 0;
+ order.wait_time = 0;
+ order.travel_time = 0;
return order;
}
@@ -85,8 +89,9 @@ static Order UnpackVersion4Order(uint16 packed)
*/
void InvalidateVehicleOrder(const Vehicle *v)
{
- InvalidateWindow(WC_VEHICLE_VIEW, v->index);
- InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+ InvalidateWindow(WC_VEHICLE_VIEW, v->index);
+ InvalidateWindow(WC_VEHICLE_ORDERS, v->index);
+ InvalidateWindow(WC_VEHICLE_TIMETABLE, v->index);
}
/**
@@ -127,6 +132,8 @@ static Order *AllocateOrder()
order->next = NULL;
order->refit_cargo = CT_NO_REFIT;
order->refit_subtype = 0;
+ order->wait_time = 0;
+ order->travel_time = 0;
return order;
}
@@ -152,6 +159,9 @@ void AssignOrder(Order *order, Order data)
order->refit_cargo = data.refit_cargo;
order->refit_subtype = data.refit_subtype;
+
+ order->wait_time = data.wait_time;
+ order->travel_time = data.travel_time;
}
@@ -1315,8 +1325,10 @@ static const SaveLoad _order_desc[] = {
SLE_VAR(Order, flags, SLE_UINT8),
SLE_VAR(Order, dest, SLE_UINT16),
SLE_REF(Order, next, REF_ORDER),
- SLE_CONDVAR(Order, refit_cargo, SLE_UINT8, 36, SL_MAX_VERSION),
- SLE_CONDVAR(Order, refit_subtype, SLE_UINT8, 36, SL_MAX_VERSION),
+ SLE_CONDVAR(Order, refit_cargo, SLE_UINT8, 36, SL_MAX_VERSION),
+ SLE_CONDVAR(Order, refit_subtype, SLE_UINT8, 36, SL_MAX_VERSION),
+ SLE_CONDVAR(Order, wait_time, SLE_UINT16, 67, SL_MAX_VERSION),
+ SLE_CONDVAR(Order, travel_time, SLE_UINT16, 67, SL_MAX_VERSION),
/* Leftover from the minor savegame version stuff
* We will never use those free bytes, but we have to keep this line to allow loading of old savegames */
diff --git a/src/order_gui.cpp b/src/order_gui.cpp
index 116b67df1..d769162f9 100644
--- a/src/order_gui.cpp
+++ b/src/order_gui.cpp
@@ -24,11 +24,13 @@
#include "train.h"
#include "water_map.h"
#include "vehicle_gui.h"
+#include "timetable.h"
#include "cargotype.h"
enum OrderWindowWidgets {
ORDER_WIDGET_CLOSEBOX = 0,
ORDER_WIDGET_CAPTION,
+ ORDER_WIDGET_TIMETABLE_VIEW,
ORDER_WIDGET_ORDER_LIST,
ORDER_WIDGET_SCROLLBAR,
ORDER_WIDGET_SKIP,
@@ -540,6 +542,13 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
assert(w->widget[ORDER_WIDGET_REFIT].bottom == w->widget[ORDER_WIDGET_UNLOAD].bottom);
assert(w->widget[ORDER_WIDGET_REFIT].display_flags == w->widget[ORDER_WIDGET_UNLOAD].display_flags);
}
+
+ if (_patches.timetabling) {
+ w->widget[ORDER_WIDGET_CAPTION].right -= 61;
+ } else {
+ HideWindowWidget(w, ORDER_WIDGET_TIMETABLE_VIEW);
+ }
+
break;
case WE_PAINT:
@@ -623,6 +632,11 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
case ORDER_WIDGET_TRANSFER:
OrderClick_Transfer(w, v);
break;
+
+ case ORDER_WIDGET_TIMETABLE_VIEW:
+ ShowTimetableWindow(v);
+ break;
+
case ORDER_WIDGET_SHARED_ORDER_LIST:
ShowVehicleListWindow(v);
break;
@@ -733,6 +747,7 @@ static void OrdersWndProc(Window *w, WindowEvent *e)
static const Widget _orders_train_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // ORDER_WIDGET_CLOSEBOX
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 398, 0, 13, STR_8829_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, // ORDER_WIDGET_CAPTION
+ { WWT_PUSHTXTBTN, RESIZE_LR, 14, 338, 398, 0, 13, STR_TIMETABLE_VIEW, STR_TIMETABLE_VIEW_TOOLTIP}, // ORDER_WIDGET_TIMETABLE_VIEW
{ WWT_PANEL, RESIZE_RB, 14, 0, 386, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
@@ -769,6 +784,7 @@ static const WindowDesc _orders_train_desc = {
static const Widget _orders_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // ORDER_WIDGET_CLOSEBOX
{ WWT_CAPTION, RESIZE_RIGHT, 14, 11, 409, 0, 13, STR_8829_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, // ORDER_WIDGET_CAPTION
+ { WWT_PUSHTXTBTN, RESIZE_LR, 14, 349, 409, 0, 13, STR_TIMETABLE_VIEW, STR_TIMETABLE_VIEW_TOOLTIP}, // ORDER_WIDGET_TIMETABLE_VIEW
{ WWT_PANEL, RESIZE_RB, 14, 0, 397, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
@@ -803,27 +819,28 @@ static const WindowDesc _orders_desc = {
* Widget definition for competitor orders
*/
static const Widget _other_orders_widgets[] = {
- { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // ORDER_WIDGET_CLOSEBOX
- { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 331, 0, 13, STR_A00B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, // ORDER_WIDGET_CAPTION
+ { WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW}, // ORDER_WIDGET_CLOSEBOX
+ { WWT_CAPTION, RESIZE_RIGHT, 14, 11, 331, 0, 13, STR_A00B_ORDERS, STR_018C_WINDOW_TITLE_DRAG_THIS}, // ORDER_WIDGET_CAPTION
+ { WWT_PUSHTXTBTN, RESIZE_LR, 14, 271, 331, 0, 13, STR_TIMETABLE_VIEW, STR_TIMETABLE_VIEW_TOOLTIP}, // ORDER_WIDGET_TIMETABLE_VIEW
- { WWT_PANEL, RESIZE_RB, 14, 0, 319, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
+ { WWT_PANEL, RESIZE_RB, 14, 0, 319, 14, 75, 0x0, STR_8852_ORDERS_LIST_CLICK_ON_ORDER}, // ORDER_WIDGET_ORDER_LIST
- { WWT_SCROLLBAR, RESIZE_LRB, 14, 320, 331, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // ORDER_WIDGET_SCROLLBAR
+ { WWT_SCROLLBAR, RESIZE_LRB, 14, 320, 331, 14, 75, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST}, // ORDER_WIDGET_SCROLLBAR
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SKIP
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_DELETE
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_NON_STOP
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_GOTO
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_FULL_LOAD
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_UNLOAD
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_REFIT
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_TRANSFER
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SKIP
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_DELETE
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_NON_STOP
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_GOTO
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_FULL_LOAD
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_UNLOAD
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_REFIT
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_TRANSFER
- { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SHARED_ORDER_LIST
+ { WWT_EMPTY, RESIZE_NONE, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_SHARED_ORDER_LIST
- { WWT_PANEL, RESIZE_RTB, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR
+ { WWT_PANEL, RESIZE_RTB, 14, 0, 319, 76, 87, 0x0, STR_NULL}, // ORDER_WIDGET_RESIZE_BAR
- { WWT_RESIZEBOX, RESIZE_LRTB, 14, 320, 331, 76, 87, 0x0, STR_RESIZE_BUTTON}, // ORDER_WIDGET_RESIZE
+ { WWT_RESIZEBOX, RESIZE_LRTB, 14, 320, 331, 76, 87, 0x0, STR_RESIZE_BUTTON}, // ORDER_WIDGET_RESIZE
{ WIDGETS_END},
};
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 5688b47c0..e0757429e 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -14,6 +14,7 @@
#include "map.h"
#include "tile.h"
#include "vehicle.h"
+#include "timetable.h"
#include "engine.h"
#include "command.h"
#include "station.h"
@@ -758,6 +759,7 @@ static void ProcessRoadVehOrder(Vehicle *v)
if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
!VehicleNeedsService(v)) {
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
}
break;
@@ -1784,6 +1786,7 @@ static void RoadVehController(Vehicle *v)
{
/* decrease counters */
v->tick_counter++;
+ v->current_order_time++;
if (v->u.road.reverse_ctr != 0) v->u.road.reverse_ctr--;
/* handle crashed */
diff --git a/src/saveload.cpp b/src/saveload.cpp
index 23b987bf0..36be798ee 100644
--- a/src/saveload.cpp
+++ b/src/saveload.cpp
@@ -29,7 +29,7 @@
#include <setjmp.h>
#include <list>
-extern const uint16 SAVEGAME_VERSION = 66;
+extern const uint16 SAVEGAME_VERSION = 67;
uint16 _sl_version; ///< the major savegame version identifier
byte _sl_minor_version; ///< the minor savegame version, DO NOT USE!
diff --git a/src/settings.cpp b/src/settings.cpp
index bd8c094f9..f0454ad73 100644
--- a/src/settings.cpp
+++ b/src/settings.cpp
@@ -1348,7 +1348,8 @@ const SettingDesc _patch_settings[] = {
SDT_VAR(Patches, scrollwheel_scrolling,SLE_UINT8,S,MS, 0, 0, 2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING, NULL),
SDT_VAR(Patches,scrollwheel_multiplier,SLE_UINT8,S, 0, 5, 1, 15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,NULL),
SDT_BOOL(Patches, pause_on_newgame, S, 0, false, STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME, NULL),
- SDT_BOOL(Patches, advanced_vehicle_list, S, 0, true, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS, NULL),
+ SDT_BOOL(Patches, advanced_vehicle_list, S, 0, true, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS, NULL),
+ SDT_BOOL(Patches, timetable_in_ticks, S, 0, false, STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS, NULL),
/***************************************************************************/
/* Construction section of the GUI-configure patches window */
@@ -1394,6 +1395,7 @@ const SettingDesc _patch_settings[] = {
SDT_BOOL(Patches, wagon_speed_limits, 0, 0, true, STR_CONFIG_PATCHES_WAGONSPEEDLIMITS, NULL),
SDT_CONDBOOL(Patches, disable_elrails, 38, SL_MAX_VERSION, 0, 0, false, STR_CONFIG_PATCHES_DISABLE_ELRAILS, SettingsDisableElrail),
SDT_CONDVAR(Patches, freight_trains, SLE_UINT8, 39, SL_MAX_VERSION, 0, 0, 1, 1, 255, 1, STR_CONFIG_PATCHES_FREIGHT_TRAINS, NULL),
+ SDT_CONDBOOL(Patches, timetabling, 67, SL_MAX_VERSION, 0, 0, true, STR_CONFIG_PATCHES_TIMETABLE_ALLOW, NULL),
/***************************************************************************/
/* Station section of the GUI-configure patches window */
diff --git a/src/settings_gui.cpp b/src/settings_gui.cpp
index bb0a25e43..000d50f2c 100644
--- a/src/settings_gui.cpp
+++ b/src/settings_gui.cpp
@@ -652,6 +652,7 @@ static const char *_patches_ui[] = {
"scrollwheel_multiplier",
"pause_on_newgame",
"advanced_vehicle_list",
+ "timetable_in_ticks",
};
static const char *_patches_construction[] = {
@@ -735,6 +736,7 @@ static const char *_patches_vehicles[] = {
"wagon_speed_limits",
"disable_elrails",
"freight_trains",
+ "timetabling",
};
struct PatchEntry {
@@ -977,7 +979,7 @@ static const Widget _patches_selection_widgets[] = {
{ WWT_CLOSEBOX, RESIZE_NONE, 10, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
{ WWT_CAPTION, RESIZE_NONE, 10, 11, 369, 0, 13, STR_CONFIG_PATCHES_CAPTION, STR_018C_WINDOW_TITLE_DRAG_THIS},
{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 14, 41, 0x0, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 370, 0x0, STR_NULL},
+{ WWT_PANEL, RESIZE_NONE, 10, 0, 369, 42, 380, 0x0, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 3, 10, 96, 16, 27, STR_CONFIG_PATCHES_GUI, STR_NULL},
{ WWT_TEXTBTN, RESIZE_NONE, 3, 97, 183, 16, 27, STR_CONFIG_PATCHES_CONSTRUCTION, STR_NULL},
@@ -989,7 +991,7 @@ static const Widget _patches_selection_widgets[] = {
};
static const WindowDesc _patches_selection_desc = {
- WDP_CENTER, WDP_CENTER, 370, 371,
+ WDP_CENTER, WDP_CENTER, 370, 381,
WC_GAME_OPTIONS, WC_NONE,
WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
_patches_selection_widgets,
diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp
index 90edf4719..23ca3b337 100644
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -11,6 +11,7 @@
#include "map.h"
#include "tile.h"
#include "vehicle.h"
+#include "timetable.h"
#include "command.h"
#include "pathfind.h"
#include "station_map.h"
@@ -258,6 +259,7 @@ static void ProcessShipOrder(Vehicle *v)
if (v->current_order.flags & OF_SERVICE_IF_NEEDED &&
!VehicleNeedsService(v)) {
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
}
break;
@@ -648,6 +650,7 @@ static void ShipController(Vehicle *v)
TrackBits tracks;
v->tick_counter++;
+ v->current_order_time++;
if (v->breakdown_ctr != 0) {
if (v->breakdown_ctr <= 2) {
@@ -695,6 +698,7 @@ static void ShipController(Vehicle *v)
* next order */
v->cur_order_index++;
v->current_order.type = OT_DUMMY;
+ UpdateVehicleTimetable(v, true);
InvalidateVehicleOrder(v);
} else {
/* Non-buoy orders really need to reach the tile */
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 0aca1b08d..065e6db02 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -15,6 +15,7 @@
#include "tile.h"
#include "tunnel_map.h"
#include "vehicle.h"
+#include "timetable.h"
#include "articulated_vehicles.h"
#include "command.h"
#include "pathfind.h"
@@ -2380,6 +2381,7 @@ static bool ProcessTrainOrder(Vehicle *v)
if ((v->current_order.flags & OF_SERVICE_IF_NEEDED) &&
!VehicleNeedsService(v)) {
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
}
break;
@@ -2395,6 +2397,7 @@ static bool ProcessTrainOrder(Vehicle *v)
if (v->current_order.type == OT_GOTO_WAYPOINT && v->tile == v->dest_tile) {
v->cur_order_index++;
at_waypoint = true;
+ UpdateVehicleTimetable(v, true);
}
/* check if we've reached a non-stop station while TTDPatch nonstop is enabled.. */
@@ -2403,6 +2406,7 @@ static bool ProcessTrainOrder(Vehicle *v)
IsTileType(v->tile, MP_STATION) &&
v->current_order.dest == GetStationIndex(v->tile)) {
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
}
/* Get the current order */
@@ -3296,6 +3300,8 @@ void Train_Tick(Vehicle *v)
v->tick_counter++;
if (IsFrontEngine(v)) {
+ v->current_order_time++;
+
TrainLocoHandler(v, false);
/* make sure vehicle wasn't deleted. */
diff --git a/src/variables.h b/src/variables.h
index 4277f5111..a45ef3e6e 100644
--- a/src/variables.h
+++ b/src/variables.h
@@ -235,6 +235,9 @@ struct Patches {
bool pause_on_newgame; ///< Whether to start new games paused or not.
TownLayoutByte town_layout; ///< Select town layout
+
+ bool timetabling; ///< Whether to allow timetabling.
+ bool timetable_in_ticks; ///< Whether to show the timetable in ticks rather than days.
};
VARDEF Patches _patches;
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index 10c34823b..c00c3fe4a 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -15,6 +15,7 @@
#include "map.h"
#include "tile.h"
#include "vehicle.h"
+#include "timetable.h"
#include "gfx.h"
#include "viewport.h"
#include "news.h"
@@ -2335,6 +2336,7 @@ void VehicleEnterDepot(Vehicle *v)
if (HASBIT(t.flags, OFB_PART_OF_ORDERS)) {
/* Part of orders */
v->cur_order_index++;
+ UpdateVehicleTimetable(v, true);
} else if (HASBIT(t.flags, OFB_HALT_IN_DEPOT)) {
/* Force depot visit */
v->vehstatus |= VS_STOPPED;
@@ -2787,6 +2789,10 @@ extern const SaveLoad _common_veh_desc[] = {
SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, refit_cargo), SLE_UINT8, 36, SL_MAX_VERSION),
SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, refit_subtype), SLE_UINT8, 36, SL_MAX_VERSION),
+ /* Timetable in current order */
+ SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, wait_time), SLE_UINT16, 67, SL_MAX_VERSION),
+ SLE_CONDVARX(cpp_offsetof(Vehicle, current_order) + cpp_offsetof(Order, travel_time), SLE_UINT16, 67, SL_MAX_VERSION),
+
SLE_REF(Vehicle, orders, REF_ORDER),
SLE_CONDVAR(Vehicle, age, SLE_FILE_U16 | SLE_VAR_I32, 0, 30),
@@ -2828,6 +2834,9 @@ extern const SaveLoad _common_veh_desc[] = {
SLE_CONDVAR(Vehicle, group_id, SLE_UINT16, 60, SL_MAX_VERSION),
+ SLE_CONDVAR(Vehicle, current_order_time, SLE_UINT32, 67, SL_MAX_VERSION),
+ SLE_CONDVAR(Vehicle, lateness_counter, SLE_INT32, 67, SL_MAX_VERSION),
+
/* reserve extra space in savegame here. (currently 10 bytes) */
SLE_CONDNULL(10, 2, SL_MAX_VERSION),
@@ -3070,6 +3079,7 @@ void Vehicle::BeginLoading()
* whether the train is lost or not; not marking a train lost
* that arrives at random stations is bad. */
this->current_order.flags |= OF_NON_STOP;
+ UpdateVehicleTimetable(this, true);
} else {
/* This is just an unordered intermediate stop */
this->current_order.flags = 0;
@@ -3096,6 +3106,8 @@ void Vehicle::LeaveStation()
current_order.type = OT_LEAVESTATION;
current_order.flags = 0;
GetStation(this->last_station_visited)->loading_vehicles.remove(this);
+
+ UpdateVehicleTimetable(this, false);
}
@@ -3103,8 +3115,11 @@ void Vehicle::HandleLoading(bool mode)
{
switch (this->current_order.type) {
case OT_LOADING: {
+ uint wait_time = max(this->current_order.wait_time - this->lateness_counter, 0);
+
/* Not the first call for this tick, or still loading */
- if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED)) return;
+ if (mode || !HASBIT(this->vehicle_flags, VF_LOADING_FINISHED) ||
+ (_patches.timetabling && this->current_order_time < wait_time)) return;
this->PlayLeaveStationSound();
diff --git a/src/vehicle.h b/src/vehicle.h
index 549e04e11..c40017879 100644
--- a/src/vehicle.h
+++ b/src/vehicle.h
@@ -320,6 +320,10 @@ struct Vehicle {
GroupID group_id; ///< Index of group Pool array
+ /* Used for timetabling. */
+ uint32 current_order_time; ///< How many ticks have passed since this order started.
+ int32 lateness_counter; ///< How many ticks late (or early if negative) this vehicle is.
+
union {
VehicleRail rail;
VehicleAir air;