diff --git a/config.lib b/config.lib index b381f6048b..b41306d327 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 a439556d21..931fe7fb7f 100644 --- a/projects/openttd.vcproj +++ b/projects/openttd.vcproj @@ -653,6 +653,9 @@ + + @@ -789,6 +792,9 @@ + + @@ -844,6 +850,9 @@ + + diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index f3129305a8..33092e6f6a 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -1099,6 +1099,10 @@ RelativePath=".\..\src\tile.h" > + + @@ -1279,6 +1283,10 @@ RelativePath=".\..\src\terraform_gui.cpp" > + + @@ -1351,6 +1359,10 @@ RelativePath=".\..\src\station_cmd.cpp" > + + diff --git a/source.list b/source.list index 6445d213bc..fc613bc5e9 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 6a190ef083..b92039ed5d 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 8b814d034b..a400307dcb 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 c269ed43d9..6f20147650 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 ea492f0a41..dd9a1ba846 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 460f29bd67..a768da3bd4 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 3a2ddb1f34..9703989e82 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 f33bfb4d28..7b14f912fc 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 116b67df13..d769162f9c 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 5688b47c07..e0757429ef 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 23b987bf0e..36be798ee8 100644 --- a/src/saveload.cpp +++ b/src/saveload.cpp @@ -29,7 +29,7 @@ #include #include -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 bd8c094f92..f0454ad736 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 bb0a25e43e..000d50f2c9 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 90edf47198..23ca3b3370 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 0aca1b08d4..065e6db02f 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 4277f51117..a45ef3e6e0 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 10c34823be..c00c3fe4a5 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 549e04e11a..c40017879f 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;