Add no unload option to station order modifier hotkey actions

This commit is contained in:
dP
2025-10-01 01:32:53 +05:00
parent 9a3e78d464
commit 0ba1ed61a5
7 changed files with 169 additions and 144 deletions

View File

@@ -73,6 +73,16 @@ This is usable for any OpenTTD servers
== CHANGELOG ==
*** 14.1 ***
- Fixed polyrail endpoint update when removing rail.
- Fixed industry blinking rate on minimap.
- Fixed APM and average APM counters.
- Fixed cargo ID in industry chains window and make it use newgrf_developer_tools setting.
- Reimplemented all station building tools hopefully fixing all the old bugs.
- Made industries on the minimap blink with color similar to the industry colour instead of just white.
- Added settings to configure modifier keys for depot orders.
- Added no unload option to station order modifier hotkey actions.
*** 14.0 ***
- Fixed graphs with cargo selection.
- Fixed measurement tooltips.

View File

@@ -8,6 +8,7 @@
#include "../sound_func.h"
#include "../tilehighlight_func.h"
#include "../viewport_func.h"
#include "../vehicle_base.h"
#include "../window_func.h"
#include "../window_gui.h"
#include "../window_type.h"
@@ -81,11 +82,11 @@ bool HasSeparateRemoveMod() {
}
void UpdateModKeys(bool shift_pressed, bool ctrl_pressed, bool alt_pressed, bool command_pressed) {
bool mod_pressed[(size_t)ModKey::END] = {false};
if (shift_pressed) mod_pressed[(size_t)ModKey::SHIFT] = true;
if (ctrl_pressed) mod_pressed[(size_t)ModKey::CTRL] = true;
if (alt_pressed) mod_pressed[(size_t)ModKey::ALT] = true;
if (command_pressed) mod_pressed[(size_t)ModKey::COMMAND] = true;
bool mod_pressed[(size_t)ModKey::End] = {false};
if (shift_pressed) mod_pressed[(size_t)ModKey::Shift] = true;
if (ctrl_pressed) mod_pressed[(size_t)ModKey::Ctrl] = true;
if (alt_pressed) mod_pressed[(size_t)ModKey::Alt] = true;
if (command_pressed) mod_pressed[(size_t)ModKey::Command] = true;
bool fn_mod_prev = _fn_mod;
bool remove_mod_prev = _remove_mod;
_fn_mod = mod_pressed[(size_t)_settings_client.gui.cm_fn_mod];
@@ -287,4 +288,86 @@ void CountHotkeyStats(const HotkeyList *list, int hotkey) {
_game_session_stats.cm.hotkeys[key]++;
}
static StationOrderModAction GetStationOrderModAction()
{
if (_ctrl_pressed) {
if (_shift_pressed)
return (StationOrderModAction)_settings_client.gui.cm_ctrl_shift_station_mod;
else if (_alt_pressed)
return (StationOrderModAction)_settings_client.gui.cm_alt_ctrl_station_mod;
else
return (StationOrderModAction)_settings_client.gui.cm_ctrl_station_mod;
} else if (_shift_pressed) {
if (_alt_pressed)
return (StationOrderModAction)_settings_client.gui.cm_alt_shift_station_mod;
else
return (StationOrderModAction)_settings_client.gui.cm_shift_station_mod;
} else if (_alt_pressed)
return (StationOrderModAction)_settings_client.gui.cm_alt_station_mod;
return StationOrderModAction::None;
}
DepotOrderModAction GetDepotOrderModAction() {
if (_ctrl_pressed) {
if (_shift_pressed) return (DepotOrderModAction)_settings_client.gui.cm_ctrl_shift_depot_mod;
else return (DepotOrderModAction)_settings_client.gui.cm_ctrl_depot_mod;
} else if (_shift_pressed) {
return (DepotOrderModAction)_settings_client.gui.cm_shift_depot_mod;
}
return DepotOrderModAction::None;
}
StationModOrders GetStationModOrders(const Vehicle *v)
{
StationModOrders res = {
OLF_LOAD_IF_POSSIBLE,
OUF_UNLOAD_IF_POSSIBLE,
FeederOrderMod::None,
};
switch(GetStationOrderModAction()) {
case StationOrderModAction::None:
break;
case StationOrderModAction::FullLoad:
res.load = OLF_FULL_LOAD_ANY;
break;
case StationOrderModAction::Transfer:
res.unload = OUFB_TRANSFER;
if (_settings_client.gui.cm_no_loading_on_transfer_order)
res.load = OLFB_NO_LOAD;
break;
case StationOrderModAction::UnloadAll:
res.unload = OUFB_UNLOAD;
if (_settings_client.gui.cm_no_loading_on_unload_order)
res.load = OLFB_NO_LOAD;
break;
case StationOrderModAction::FeederLoad:
if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::Load;
res.unload = OUFB_NO_UNLOAD;
res.load = OLF_FULL_LOAD_ANY;
break;
case StationOrderModAction::FeederUnload:
if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::Unload;
res.unload = OUFB_TRANSFER;
res.load = OLFB_NO_LOAD;
break;
case StationOrderModAction::NoLoad:
res.load = OLFB_NO_LOAD;
break;
case StationOrderModAction::NoUnload:
res.unload = OUFB_NO_UNLOAD;
break;
default: NOT_REACHED();
}
return res;
}
} // namespace citymania

View File

@@ -2,8 +2,11 @@
#define CMEXT_HOTKEYS_HPP
#include "../hotkeys.h"
#include "../order_type.h"
#include "../window_type.h"
struct Vehicle;
namespace citymania {
extern bool _fn_mod;
@@ -33,6 +36,40 @@ std::pair<uint32, uint32> GetEPM();
bool ChooseSignalDragBehaviour();
void CountHotkeyStats(const HotkeyList *list, int hotkey);
enum class FeederOrderMod {
None,
Load,
Unload,
};
enum class StationOrderModAction : uint8_t {
None = 0,
FullLoad,
Transfer,
UnloadAll,
FeederLoad,
FeederUnload,
NoLoad,
NoUnload,
};
enum class DepotOrderModAction : uint8_t {
None = 0,
Service,
Stop,
Unbunch,
};
struct StationModOrders {
OrderLoadFlags load;
OrderUnloadFlags unload;
FeederOrderMod mod;
};
DepotOrderModAction GetDepotOrderModAction();
StationModOrders GetStationModOrders(const Vehicle *v);
} // namespace citymania
#endif

View File

@@ -11,13 +11,13 @@
namespace citymania {
enum class ModKey : uint8 {
NONE = 0,
SHIFT = 1,
CTRL = 2,
ALT = 3,
COMMAND = 4,
END,
enum class ModKey : uint8_t {
None = 0,
Shift = 1,
Ctrl = 2,
Alt = 3,
Command = 4,
End,
};
struct EconomySettings {

View File

@@ -6234,6 +6234,7 @@ CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_UNLOAD_ALL :Force unload of
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_LOAD :Feeder Load (replace first order)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_UNLOAD :Feeder Unload (replace last order)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_LOAD :Do not load any cargo
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_UNLOAD :Do not unload any cargo
CM_STR_CONFIG_SETTING_DEPOT_MOD_CTRL :Ctrl+click depot: {STRING2}
CM_STR_CONFIG_SETTING_DEPOT_MOD_SHIFT :Shift+click depot: {STRING2}

View File

@@ -181,82 +181,6 @@ static const StringID _order_conditional_condition[] = {
INVALID_STRING_ID,
};
enum class FeederOrderMod{
NONE,
LOAD,
UNLOAD
};
struct OrdersFromSettings {
OrderLoadFlags load;
OrderUnloadFlags unload;
FeederOrderMod mod;
};
enum GetOrderFromSettingsTypes {
GOFS_NONE = 0,
GOFS_FULL,
GOFS_XFER,
GOFS_UNLOAD,
GOFS_FEEDLOAD,
GOFS_FEEDUNLOAD,
GOFS_NOLOAD
};
#define GOFSFEEDER_ORDERMOD_RESET gofsfeeder_ordermod = GOFS_FEEDER_NULL
/* fetch and compute orders set from settings */
static OrdersFromSettings GetOrdersFromSettings(const Vehicle *v, uint8 setting)
{
OrdersFromSettings res = {
OLF_LOAD_IF_POSSIBLE,
OUF_UNLOAD_IF_POSSIBLE,
FeederOrderMod::NONE
};
switch(setting) {
case GOFS_FEEDLOAD:
if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::LOAD;
res.unload = OUFB_NO_UNLOAD;
res.load = OLF_FULL_LOAD_ANY;
break;
case GOFS_FULL:
res.load = OLF_FULL_LOAD_ANY;
break;
case GOFS_UNLOAD:
res.unload = OUFB_UNLOAD;
if (_settings_client.gui.cm_no_loading_on_unload_order)
res.load = OLFB_NO_LOAD;
break;
case GOFS_FEEDUNLOAD:
if (v->GetNumOrders() > 0) res.mod = FeederOrderMod::UNLOAD;
res.unload = OUFB_TRANSFER;
res.load = OLFB_NO_LOAD;
break;
case GOFS_XFER:
res.unload = OUFB_TRANSFER;
if (_settings_client.gui.cm_no_loading_on_transfer_order)
res.load = OLFB_NO_LOAD;
break;
case GOFS_NOLOAD:
res.load = OLFB_NO_LOAD;
break;
case GOFS_NONE:
break;
default: NOT_REACHED();
}
return res;
}
extern uint ConvertSpeedToDisplaySpeed(uint speed, VehicleType type);
extern uint ConvertDisplaySpeedToSpeed(uint speed, VehicleType type);
@@ -477,7 +401,7 @@ void DrawOrderString(const Vehicle *v, const Order *order, int order_index, int
* @param tile Tile being queried.
* @return The order associated to vehicle v in given tile (or empty order if vehicle can do nothing in the tile).
*/
static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
static std::pair<Order, citymania::FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, TileIndex tile)
{
/* Hack-ish; unpack order 0, so everything gets initialised with either zero
* or a suitable default value for the variable. Then also override the index
@@ -491,18 +415,10 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
ODTFB_PART_OF_ORDERS,
(_settings_client.gui.new_nonstop && v->IsGroundVehicle()) ? ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS : ONSF_STOP_EVERYWHERE);
uint8 os = 0;
if (_ctrl_pressed) {
if (_shift_pressed) os = _settings_client.gui.cm_ctrl_shift_depot_mod;
else os = _settings_client.gui.cm_ctrl_depot_mod;
} else if (_shift_pressed) {
os = _settings_client.gui.cm_shift_depot_mod;
}
switch (os) {
case 1: order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() | ODTFB_SERVICE)); break;
case 2: order.SetDepotActionType(ODATFB_HALT); break;
case 3: order.SetDepotActionType(ODATFB_UNBUNCH); break;
switch (citymania::GetDepotOrderModAction()) {
case citymania::DepotOrderModAction::Service: order.SetDepotOrderType((OrderDepotTypeFlags)(order.GetDepotOrderType() | ODTFB_SERVICE)); break;
case citymania::DepotOrderModAction::Stop: order.SetDepotActionType(ODATFB_HALT); break;
case citymania::DepotOrderModAction::Unbunch: order.SetDepotActionType(ODATFB_UNBUNCH); break;
default: break;
}
@@ -526,14 +442,14 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
/* Return an empty order to bail out. */
if (failed) {
order.Free();
return {order, FeederOrderMod::NONE};;
return {order, citymania::FeederOrderMod::None};
}
/* Now we are allowed to set the action type. */
// order.SetDepotActionType(ODATFB_UNBUNCH);
}
return {order, FeederOrderMod::NONE};
return {order, citymania::FeederOrderMod::None};
}
/* check rail waypoint */
@@ -542,13 +458,13 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
IsTileOwner(tile, _local_company)) {
order.MakeGoToWaypoint(GetStationIndex(tile));
if (_settings_client.gui.new_nonstop != citymania::_fn_mod) order.SetNonStopType(ONSF_NO_STOP_AT_ANY_STATION);
return std::make_pair(order, FeederOrderMod::NONE);
return {order, citymania::FeederOrderMod::None};
}
/* check buoy (no ownership) */
if (IsBuoyTile(tile) && v->type == VEH_SHIP) {
order.MakeGoToWaypoint(GetStationIndex(tile));
return std::make_pair(order, FeederOrderMod::NONE);
return std::make_pair(order, citymania::FeederOrderMod::None);
}
/* check for station or industry with neutral station */
@@ -573,44 +489,22 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
if (st->facilities & facil) {
order.MakeGoToStation(st->index);
uint8 os = 0xff;
if (_ctrl_pressed) {
if (_shift_pressed)
os = _settings_client.gui.cm_ctrl_shift_station_mod;
else if (_alt_pressed)
os = _settings_client.gui.cm_alt_ctrl_station_mod;
else
os = _settings_client.gui.cm_ctrl_station_mod;
}
else if (_shift_pressed) {
if (_alt_pressed)
os = _settings_client.gui.cm_alt_shift_station_mod;
else
os = _settings_client.gui.cm_shift_station_mod;
}
else if (_alt_pressed)
os = _settings_client.gui.cm_alt_station_mod;
auto feeder_mod = FeederOrderMod::NONE;
if (os != 0xff) {
auto ofs = GetOrdersFromSettings(v, os);
if (ofs.load != (enum OrderLoadFlags)-1)
order.SetLoadType(ofs.load);
if (ofs.unload != (enum OrderUnloadFlags)-1)
order.SetUnloadType(ofs.unload);
feeder_mod = ofs.mod;
}
auto feeder_mod = citymania::FeederOrderMod::None;
auto ofs = citymania::GetStationModOrders(v);
order.SetLoadType(ofs.load);
order.SetUnloadType(ofs.unload);
feeder_mod = ofs.mod;
if (_settings_client.gui.new_nonstop && v->IsGroundVehicle()) order.SetNonStopType(ONSF_NO_STOP_AT_INTERMEDIATE_STATIONS);
order.SetStopLocation(v->type == VEH_TRAIN ? (OrderStopLocation)(_settings_client.gui.stop_location) : OSL_PLATFORM_FAR_END);
return std::make_pair(order, feeder_mod);
return {order, feeder_mod};
}
}
}
/* not found */
order.Free();
return std::make_pair(order, FeederOrderMod::NONE);
return {order, citymania::FeederOrderMod::None};
}
/** Hotkeys for order window. */
@@ -1662,8 +1556,8 @@ public:
auto feeder_mod = res.second;
if (cmd.IsType(OT_NOTHING)) return;
if (feeder_mod != FeederOrderMod::NONE) {
if (feeder_mod == FeederOrderMod::LOAD) {
if (feeder_mod != citymania::FeederOrderMod::None) {
if (feeder_mod == citymania::FeederOrderMod::Load) {
if (citymania::cmd::InsertOrder(this->vehicle->tile, this->vehicle->index, 1, cmd)
.with_error(STR_ERROR_CAN_T_INSERT_NEW_ORDER)
.set_auto()
@@ -1674,7 +1568,7 @@ public:
.post();
}
} else if (feeder_mod == FeederOrderMod::UNLOAD) { // still flushes the whole order table
} else if (feeder_mod == citymania::FeederOrderMod::Unload) { // still flushes the whole order table
if (citymania::cmd::InsertOrder(this->vehicle->tile, this->vehicle->index, this->vehicle->GetNumOrders(), cmd)
.with_error(STR_ERROR_CAN_T_INSERT_NEW_ORDER)
.set_auto()

View File

@@ -2,7 +2,7 @@
static void cm_v_RedrawStatusBar(int32 new_value);
static void cm_v_RedrawGraphs(int32 new_value);
static std::initializer_list<const char*> _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load"};
static std::initializer_list<const char*> _station_mod_actions{"nothing", "full_load", "transfer", "unload_all", "feeder_load", "feeder_unload", "no_load", "no_unload"};
static std::initializer_list<const char*> _depot_mod_actions{"nothing", "service", "stop", "unbunch"};
static std::initializer_list<const char*> _mod_keys{"none", "shift", "ctrl", "alt", "command"};
static std::initializer_list<const char*> _shaded_tree_options{"always_off", "always_on", "as_server"};
@@ -67,7 +67,7 @@ var = gui.cm_ctrl_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 1
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
@@ -78,7 +78,7 @@ var = gui.cm_shift_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 0
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
@@ -89,7 +89,7 @@ var = gui.cm_ctrl_shift_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 2
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
@@ -100,7 +100,7 @@ var = gui.cm_alt_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 4
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
@@ -111,7 +111,7 @@ var = gui.cm_alt_shift_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 3
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
@@ -122,7 +122,7 @@ var = gui.cm_alt_ctrl_station_mod
type = SLE_UINT8
flags = SF_NOT_IN_SAVE | SF_NO_NETWORK_SYNC | SF_GUI_DROPDOWN | CM_SF_CITYMANIA
def = 5
max = 6
max = 7
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE