summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lang/english.txt8
-rw-r--r--src/order_base.h3
-rw-r--r--src/order_cmd.cpp2
-rw-r--r--src/order_type.h1
-rw-r--r--src/roadveh_cmd.cpp4
-rw-r--r--src/saveload/order_sl.cpp1
-rw-r--r--src/saveload/saveload.cpp3
-rw-r--r--src/script/api/game/game_window.hpp.sq2
-rw-r--r--src/script/api/script_window.hpp2
-rw-r--r--src/ship_cmd.cpp1
-rw-r--r--src/timetable_cmd.cpp15
-rw-r--r--src/timetable_gui.cpp62
-rw-r--r--src/train_cmd.cpp3
-rw-r--r--src/vehicle.cpp2
-rw-r--r--src/widgets/timetable_widget.h2
15 files changed, 96 insertions, 15 deletions
diff --git a/src/lang/english.txt b/src/lang/english.txt
index 77bfeb5c1..655df00ed 100644
--- a/src/lang/english.txt
+++ b/src/lang/english.txt
@@ -3442,7 +3442,9 @@ STR_TIMETABLE_TOOLTIP :{BLACK}Timetabl
STR_TIMETABLE_NO_TRAVEL :No travel
STR_TIMETABLE_NOT_TIMETABLEABLE :Travel (automatic; timetabled by next manual order)
STR_TIMETABLE_TRAVEL_NOT_TIMETABLED :Travel (not timetabled)
+STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED :Travel with at most {2:VELOCITY} (not timetabled)
STR_TIMETABLE_TRAVEL_FOR :Travel for {STRING1}
+STR_TIMETABLE_TRAVEL_FOR_SPEED :Travel for {STRING1} with at most {2:VELOCITY}
STR_TIMETABLE_STAY_FOR :and stay for {STRING1}
STR_TIMETABLE_AND_TRAVEL_FOR :and travel for {STRING1}
STR_TIMETABLE_DAYS :{COMMA} day{P "" s}
@@ -3466,6 +3468,12 @@ STR_TIMETABLE_WAIT_TIME_TOOLTIP :{BLACK}Change t
STR_TIMETABLE_CLEAR_TIME :{BLACK}Clear Time
STR_TIMETABLE_CLEAR_TIME_TOOLTIP :{BLACK}Clear the amount of time for the highlighted order
+STR_TIMETABLE_CHANGE_SPEED :{BLACK}Change Speed Limit
+STR_TIMETABLE_CHANGE_SPEED_TOOLTIP :{BLACK}Change the maximum travel speed of the highlighted order
+
+STR_TIMETABLE_CLEAR_SPEED :{BLACK}Clear Speed Limit
+STR_TIMETABLE_CLEAR_SPEED_TOOLTIP :{BLACK}Clear the maximum travel speed of the highlighted order
+
STR_TIMETABLE_RESET_LATENESS :{BLACK}Reset Late Counter
STR_TIMETABLE_RESET_LATENESS_TOOLTIP :{BLACK}Reset the lateness counter, so the vehicle will be on time
diff --git a/src/order_base.h b/src/order_base.h
index eaf050cbd..82e1371ee 100644
--- a/src/order_base.h
+++ b/src/order_base.h
@@ -49,8 +49,9 @@ public:
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.
+ uint16 max_speed; ///< How fast the vehicle may go on the way to the destination.
- Order() : refit_cargo(CT_NO_REFIT) {}
+ Order() : refit_cargo(CT_NO_REFIT), max_speed(UINT16_MAX) {}
~Order();
Order(uint32 packed);
diff --git a/src/order_cmd.cpp b/src/order_cmd.cpp
index 824d82045..6846c7af5 100644
--- a/src/order_cmd.cpp
+++ b/src/order_cmd.cpp
@@ -241,6 +241,7 @@ Order::Order(uint32 packed)
this->refit_subtype = 0;
this->wait_time = 0;
this->travel_time = 0;
+ this->max_speed = UINT16_MAX;
}
/**
@@ -281,6 +282,7 @@ void Order::AssignOrder(const Order &other)
this->wait_time = other.wait_time;
this->travel_time = other.travel_time;
+ this->max_speed = other.max_speed;
}
/**
diff --git a/src/order_type.h b/src/order_type.h
index 0099c67c9..44f93218b 100644
--- a/src/order_type.h
+++ b/src/order_type.h
@@ -169,6 +169,7 @@ enum OrderDepotAction {
enum ModifyTimetableFlags {
MTF_WAIT_TIME, ///< Set wait time.
MTF_TRAVEL_TIME, ///< Set travel time.
+ MTF_TRAVEL_SPEED, ///< Set max travel speed.
MTF_END
};
template <> struct EnumPropsT<ModifyTimetableFlags> : MakeEnumPropsT<ModifyTimetableFlags, byte, MTF_WAIT_TIME, MTF_END, MTF_END, 2> {};
diff --git a/src/roadveh_cmd.cpp b/src/roadveh_cmd.cpp
index 0c0157ab1..6a8225050 100644
--- a/src/roadveh_cmd.cpp
+++ b/src/roadveh_cmd.cpp
@@ -416,7 +416,7 @@ void RoadVehicle::UpdateDeltaXY(Direction direction)
*/
inline int RoadVehicle::GetCurrentMaxSpeed() const
{
- if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) return this->vcache.cached_max_speed;
+ if (_settings_game.vehicle.roadveh_acceleration_model == AM_ORIGINAL) return min(this->vcache.cached_max_speed, this->current_order.max_speed * 2);
int max_speed = this->vcache.cached_max_speed;
@@ -430,7 +430,7 @@ inline int RoadVehicle::GetCurrentMaxSpeed() const
}
}
- return max_speed;
+ return min(max_speed, this->current_order.max_speed * 2);
}
/**
diff --git a/src/saveload/order_sl.cpp b/src/saveload/order_sl.cpp
index e60c35d8d..0437a2d7a 100644
--- a/src/saveload/order_sl.cpp
+++ b/src/saveload/order_sl.cpp
@@ -110,6 +110,7 @@ const SaveLoad *GetOrderDescription()
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),
+ SLE_CONDVAR(Order, max_speed, SLE_UINT16, 172, 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/saveload/saveload.cpp b/src/saveload/saveload.cpp
index eb9c38a28..f768ce685 100644
--- a/src/saveload/saveload.cpp
+++ b/src/saveload/saveload.cpp
@@ -235,8 +235,9 @@
* 169 23816
* 170 23826
* 171 23835
+ * 172 23947
*/
-extern const uint16 SAVEGAME_VERSION = 171; ///< Current savegame version of OpenTTD.
+extern const uint16 SAVEGAME_VERSION = 172; ///< Current savegame version of OpenTTD.
SavegameType _savegame_type; ///< type of savegame we are loading
diff --git a/src/script/api/game/game_window.hpp.sq b/src/script/api/game/game_window.hpp.sq
index 395a60c6d..37317fce9 100644
--- a/src/script/api/game/game_window.hpp.sq
+++ b/src/script/api/game/game_window.hpp.sq
@@ -1107,6 +1107,8 @@ void SQGSWindow_Register(Squirrel *engine)
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_VT_SHARED_ORDER_LIST, "WID_VT_SHARED_ORDER_LIST");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_VT_ARRIVAL_DEPARTURE_SELECTION, "WID_VT_ARRIVAL_DEPARTURE_SELECTION");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_VT_EXPECTED_SELECTION, "WID_VT_EXPECTED_SELECTION");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_VT_CHANGE_SPEED, "WID_VT_CHANGE_SPEED");
+ SQGSWindow.DefSQConst(engine, ScriptWindow::WID_VT_CLEAR_SPEED, "WID_VT_CLEAR_SPEED");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_PAUSE, "WID_TN_PAUSE");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_FAST_FORWARD, "WID_TN_FAST_FORWARD");
SQGSWindow.DefSQConst(engine, ScriptWindow::WID_TN_SETTINGS, "WID_TN_SETTINGS");
diff --git a/src/script/api/script_window.hpp b/src/script/api/script_window.hpp
index b31c738f0..99f8313f7 100644
--- a/src/script/api/script_window.hpp
+++ b/src/script/api/script_window.hpp
@@ -2154,6 +2154,8 @@ public:
WID_VT_SHARED_ORDER_LIST = ::WID_VT_SHARED_ORDER_LIST, ///< Show the shared order list.
WID_VT_ARRIVAL_DEPARTURE_SELECTION = ::WID_VT_ARRIVAL_DEPARTURE_SELECTION, ///< Disable/hide the arrival departure panel.
WID_VT_EXPECTED_SELECTION = ::WID_VT_EXPECTED_SELECTION, ///< Disable/hide the expected selection button.
+ WID_VT_CHANGE_SPEED = ::WID_VT_CHANGE_SPEED, ///< Change speed limit button.
+ WID_VT_CLEAR_SPEED = ::WID_VT_CLEAR_SPEED, ///< Clear speed limit button.
};
/** Widgets of the #MainToolbarWindow class. */
diff --git a/src/ship_cmd.cpp b/src/ship_cmd.cpp
index dc76d9451..ebb6d9bff 100644
--- a/src/ship_cmd.cpp
+++ b/src/ship_cmd.cpp
@@ -342,6 +342,7 @@ static bool ShipAccelerate(Vehicle *v)
byte t;
spd = min(v->cur_speed + 1, v->vcache.cached_max_speed);
+ spd = min(spd, v->current_order.max_speed * 2);
/* updates statusbar only if speed have changed to save CPU time */
if (spd != v->cur_speed) {
diff --git a/src/timetable_cmd.cpp b/src/timetable_cmd.cpp
index d360d8190..5be51c37b 100644
--- a/src/timetable_cmd.cpp
+++ b/src/timetable_cmd.cpp
@@ -42,6 +42,10 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
order->travel_time = val;
break;
+ case MTF_TRAVEL_SPEED:
+ order->max_speed = val;
+ break;
+
default:
NOT_REACHED();
}
@@ -58,6 +62,10 @@ static void ChangeTimetable(Vehicle *v, VehicleOrderID order_number, uint16 val,
v->current_order.travel_time = val;
break;
+ case MTF_TRAVEL_SPEED:
+ v->current_order.max_speed = val;
+ break;
+
default:
NOT_REACHED();
}
@@ -98,6 +106,7 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
int wait_time = order->wait_time;
int travel_time = order->travel_time;
+ int max_speed = order->max_speed;
switch (mtf) {
case MTF_WAIT_TIME:
wait_time = GB(p2, 0, 16);
@@ -107,6 +116,10 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
travel_time = GB(p2, 0, 16);
break;
+ case MTF_TRAVEL_SPEED:
+ max_speed = GB(p2, 0, 16);
+ break;
+
default:
NOT_REACHED();
}
@@ -125,10 +138,12 @@ CommandCost CmdChangeTimetable(TileIndex tile, DoCommandFlag flags, uint32 p1, u
}
if (travel_time != order->travel_time && order->IsType(OT_CONDITIONAL)) return CMD_ERROR;
+ if (max_speed != order->max_speed && (order->IsType(OT_CONDITIONAL) || v->type == VEH_AIRCRAFT)) return CMD_ERROR;
if (flags & DC_EXEC) {
if (wait_time != order->wait_time) ChangeTimetable(v, order_number, wait_time, MTF_WAIT_TIME);
if (travel_time != order->travel_time) ChangeTimetable(v, order_number, travel_time, MTF_TRAVEL_TIME);
+ if (max_speed != order->max_speed) ChangeTimetable(v, order_number, max_speed, MTF_TRAVEL_SPEED);
}
return CommandCost();
diff --git a/src/timetable_gui.cpp b/src/timetable_gui.cpp
index 287386d72..41c61d347 100644
--- a/src/timetable_gui.cpp
+++ b/src/timetable_gui.cpp
@@ -162,6 +162,7 @@ struct TimetableWindow : Window {
uint deparr_time_width; ///< The width of the departure/arrival time
uint deparr_abbr_width; ///< The width of the departure/arrival abbreviation
Scrollbar *vscroll;
+ bool query_is_speed_query; ///< The currently open query window is a speed query and not a time query.
TimetableWindow(const WindowDesc *desc, WindowNumber window_number) :
Window(),
@@ -319,9 +320,12 @@ struct TimetableWindow : Window {
disable = order == NULL || ((!order->IsType(OT_GOTO_STATION) || (order->GetNonStopType() & ONSF_NO_STOP_AT_DESTINATION_STATION)) && !order->IsType(OT_CONDITIONAL));
}
}
+ bool disable_speed = disable || selected % 2 != 1 || v->type == VEH_AIRCRAFT;
this->SetWidgetDisabledState(WID_VT_CHANGE_TIME, disable);
this->SetWidgetDisabledState(WID_VT_CLEAR_TIME, disable);
+ this->SetWidgetDisabledState(WID_VT_CHANGE_SPEED, disable_speed);
+ this->SetWidgetDisabledState(WID_VT_CLEAR_SPEED, disable_speed);
this->SetWidgetDisabledState(WID_VT_SHARED_ORDER_LIST, !v->IsOrderListShared());
this->EnableWidget(WID_VT_START_DATE);
@@ -331,6 +335,8 @@ struct TimetableWindow : Window {
this->DisableWidget(WID_VT_START_DATE);
this->DisableWidget(WID_VT_CHANGE_TIME);
this->DisableWidget(WID_VT_CLEAR_TIME);
+ this->DisableWidget(WID_VT_CHANGE_SPEED);
+ this->DisableWidget(WID_VT_CLEAR_SPEED);
this->DisableWidget(WID_VT_RESET_LATENESS);
this->DisableWidget(WID_VT_AUTOFILL);
this->DisableWidget(WID_VT_SHARED_ORDER_LIST);
@@ -391,11 +397,12 @@ struct TimetableWindow : Window {
string = STR_TIMETABLE_NOT_TIMETABLEABLE;
colour = ((i == selected) ? TC_SILVER : TC_GREY) | TC_NO_SHADE;
} else if (order->travel_time == 0) {
- string = STR_TIMETABLE_TRAVEL_NOT_TIMETABLED;
+ string = order->max_speed != UINT16_MAX ? STR_TIMETABLE_TRAVEL_NOT_TIMETABLED_SPEED : STR_TIMETABLE_TRAVEL_NOT_TIMETABLED;
} else {
SetTimetableParams(0, 1, order->travel_time);
- string = STR_TIMETABLE_TRAVEL_FOR;
+ string = order->max_speed != UINT16_MAX ? STR_TIMETABLE_TRAVEL_FOR_SPEED : STR_TIMETABLE_TRAVEL_FOR;
}
+ SetDParam(2, order->max_speed);
DrawString(rtl ? r.left + WD_FRAMERECT_LEFT : middle, rtl ? middle : r.right - WD_FRAMERECT_LEFT, y, string, colour);
@@ -490,10 +497,10 @@ struct TimetableWindow : Window {
}
}
- static inline uint32 PackTimetableArgs(const Vehicle *v, uint selected)
+ static inline uint32 PackTimetableArgs(const Vehicle *v, uint selected, bool speed)
{
uint order_number = (selected + 1) / 2;
- ModifyTimetableFlags mtf = (selected % 2 == 1) ? MTF_TRAVEL_TIME : MTF_WAIT_TIME;
+ ModifyTimetableFlags mtf = (selected % 2 == 1) ? (speed ? MTF_TRAVEL_SPEED : MTF_TRAVEL_TIME) : MTF_WAIT_TIME;
if (order_number >= v->GetNumOrders()) order_number = 0;
@@ -540,16 +547,43 @@ struct TimetableWindow : Window {
}
}
+ this->query_is_speed_query = false;
ShowQueryString(current, STR_TIMETABLE_CHANGE_TIME, 31, this, CS_NUMERAL, QSF_NONE);
break;
}
- case WID_VT_CLEAR_TIME: { // Clear waiting time button.
- uint32 p1 = PackTimetableArgs(v, this->sel_index);
+ case WID_VT_CHANGE_SPEED: { // Change max speed button.
+ int selected = this->sel_index;
+ VehicleOrderID real = (selected + 1) / 2;
+
+ if (real >= v->GetNumOrders()) real = 0;
+
+ StringID current = STR_EMPTY;
+ const Order *order = v->GetOrder(real);
+ if (order != NULL) {
+ if (order->max_speed != UINT16_MAX) {
+ SetDParam(0, ConvertKmhishSpeedToDisplaySpeed(order->max_speed));
+ current = STR_JUST_INT;
+ }
+ }
+
+ this->query_is_speed_query = true;
+ ShowQueryString(current, STR_TIMETABLE_CHANGE_SPEED, 31, this, CS_NUMERAL, QSF_NONE);
+ break;
+ }
+
+ case WID_VT_CLEAR_TIME: { // Clear waiting time.
+ uint32 p1 = PackTimetableArgs(v, this->sel_index, false);
DoCommandP(0, p1, 0, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
break;
}
+ case WID_VT_CLEAR_SPEED: { // Clear max speed button.
+ uint32 p1 = PackTimetableArgs(v, this->sel_index, true);
+ DoCommandP(0, p1, UINT16_MAX, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
+ break;
+ }
+
case WID_VT_RESET_LATENESS: // Reset the vehicle's late counter.
DoCommandP(0, v->index, 0, CMD_SET_VEHICLE_ON_TIME | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
break;
@@ -580,12 +614,16 @@ struct TimetableWindow : Window {
const Vehicle *v = this->vehicle;
- uint32 p1 = PackTimetableArgs(v, this->sel_index);
+ uint32 p1 = PackTimetableArgs(v, this->sel_index, this->query_is_speed_query);
- uint64 time = StrEmpty(str) ? 0 : strtoul(str, NULL, 10);
- if (!_settings_client.gui.timetable_in_ticks) time *= DAY_TICKS;
+ uint64 val = StrEmpty(str) ? 0 : strtoul(str, NULL, 10);
+ if (this->query_is_speed_query) {
+ val = ConvertDisplaySpeedToKmhishSpeed(val);
+ } else {
+ if (!_settings_client.gui.timetable_in_ticks) val *= DAY_TICKS;
+ }
- uint32 p2 = minu(time, UINT16_MAX);
+ uint32 p2 = minu(val, UINT16_MAX);
DoCommandP(0, p1, p2, CMD_CHANGE_TIMETABLE | CMD_MSG(STR_ERROR_CAN_T_TIMETABLE_VEHICLE));
}
@@ -629,6 +667,10 @@ static const NWidgetPart _nested_timetable_widgets[] = {
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_TIME), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CLEAR_TIME, STR_TIMETABLE_CLEAR_TIME_TOOLTIP),
EndContainer(),
NWidget(NWID_VERTICAL, NC_EQUALSIZE),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CHANGE_SPEED), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CHANGE_SPEED, STR_TIMETABLE_CHANGE_SPEED_TOOLTIP),
+ NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_CLEAR_SPEED), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_CLEAR_SPEED, STR_TIMETABLE_CLEAR_SPEED_TOOLTIP),
+ EndContainer(),
+ NWidget(NWID_VERTICAL, NC_EQUALSIZE),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_START_DATE), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_STARTING_DATE, STR_TIMETABLE_STARTING_DATE_TOOLTIP),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_VT_RESET_LATENESS), SetResize(1, 0), SetFill(1, 1), SetDataTip(STR_TIMETABLE_RESET_LATENESS, STR_TIMETABLE_RESET_LATENESS_TOOLTIP),
EndContainer(),
diff --git a/src/train_cmd.cpp b/src/train_cmd.cpp
index 35127ae7f..4473c5265 100644
--- a/src/train_cmd.cpp
+++ b/src/train_cmd.cpp
@@ -404,6 +404,7 @@ int Train::GetCurrentMaxSpeed() const
}
}
+ max_speed = min(max_speed, this->current_order.max_speed);
return min(max_speed, this->gcache.cached_max_track_speed);
}
@@ -2748,7 +2749,7 @@ int Train::UpdateSpeed()
switch (_settings_game.vehicle.train_acceleration_model) {
default: NOT_REACHED();
case AM_ORIGINAL:
- return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, this->gcache.cached_max_track_speed);
+ return this->DoUpdateSpeed(this->acceleration * (this->GetAccelerationStatus() == AS_BRAKE ? -4 : 2), 0, min(this->gcache.cached_max_track_speed, this->current_order.max_speed));
case AM_REALISTIC:
return this->DoUpdateSpeed(this->GetAcceleration(), this->GetAccelerationStatus() == AS_BRAKE ? 0 : 2, this->GetCurrentMaxSpeed());
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index f40f5070e..c6abc3f25 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -2202,7 +2202,9 @@ void Vehicle::ShowVisualEffect() const
}
max_speed = min(max_speed, t->gcache.cached_max_track_speed);
+ max_speed = min(max_speed, this->current_order.max_speed);
}
+ if (this->type == VEH_ROAD || this->type == VEH_SHIP) max_speed = min(max_speed, this->current_order.max_speed * 2);
const Vehicle *v = this;
diff --git a/src/widgets/timetable_widget.h b/src/widgets/timetable_widget.h
index 1661bb219..09beb6167 100644
--- a/src/widgets/timetable_widget.h
+++ b/src/widgets/timetable_widget.h
@@ -29,6 +29,8 @@ enum VehicleTimetableWidgets {
WID_VT_SHARED_ORDER_LIST, ///< Show the shared order list.
WID_VT_ARRIVAL_DEPARTURE_SELECTION, ///< Disable/hide the arrival departure panel.
WID_VT_EXPECTED_SELECTION, ///< Disable/hide the expected selection button.
+ WID_VT_CHANGE_SPEED, ///< Change speed limit button.
+ WID_VT_CLEAR_SPEED, ///< Clear speed limit button.
};
#endif /* WIDGETS_TIMETABLE_WIDGET_H */