Merge branch 'v14'

This commit is contained in:
dP
2025-09-04 23:08:10 +05:00
24 changed files with 478 additions and 382 deletions

View File

@@ -78,6 +78,8 @@ This is usable for any OpenTTD servers
- Fixed measurement tooltips.
- Fixed n-ice community login by Chucky and iSoSyS.
- Show the number of hidden vehicles in buy and autoreplace windows.
- Renamed cm_*_order_mod settings to cm_*_station_mod.
- Added cm_ctrl_depot_mod, cm_shift_depot_mod, cm_ctrl_shift_depot_mod settings to configure modifier keys for depot orders.
- Added a setting to disable activate-on-release behaviour of toolbar dropdown buttons.
- Added Russian translation.

View File

@@ -186,15 +186,15 @@ static const NWidgetPart _nested_cargos_widgets[] = {
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 1),
NWidget(NWID_HORIZONTAL), SetPadding(WidgetDimensions::scaled.framerect.top, WidgetDimensions::scaled.framerect.right, WidgetDimensions::scaled.framerect.bottom, WidgetDimensions::scaled.framerect.left), SetPIP(0, 9, 0),
NWidget(WWT_PUSHTXTBTN, COLOUR_GREY, WID_CT_HEADER_CARGO), SetFill(1, 0), SetPadding(2,2,2,2), SetStringTip(CM_STR_TOOLBAR_CARGOS_HEADER_CARGO, CM_STR_TOOLBAR_CARGOS_HEADER_CARGO),
NWidget(WWT_TEXT, COLOUR_GREY, WID_CT_HEADER_AMOUNT), SetMinimalSize(108, 16), SetFill(1, 0), SetPadding(2,2,2,2),
NWidget(WWT_TEXT, COLOUR_GREY, WID_CT_HEADER_INCOME), SetMinimalSize(108, 16), SetFill(1, 0), SetPadding(2,2,2,2),
NWidget(WWT_TEXT, INVALID_COLOUR, WID_CT_HEADER_AMOUNT), SetMinimalSize(108, 16), SetFill(1, 0), SetPadding(2,2,2,2),
NWidget(WWT_TEXT, INVALID_COLOUR, WID_CT_HEADER_INCOME), SetMinimalSize(108, 16), SetFill(1, 0), SetPadding(2,2,2,2),
EndContainer(),
EndContainer(),
NWidget(WWT_PANEL, COLOUR_GREY), SetResize(1, 1),
NWidget(NWID_HORIZONTAL), SetPadding(WidgetDimensions::scaled.framerect.top, WidgetDimensions::scaled.framerect.right, WidgetDimensions::scaled.framerect.bottom, WidgetDimensions::scaled.framerect.left), SetPIP(0, 9, 0),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CT_LIST),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CT_AMOUNT),SetMinimalSize(108, 0),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
NWidget(WWT_EMPTY, COLOUR_GREY, WID_CT_INCOME),SetMinimalSize(108, 0),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CT_LIST),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CT_AMOUNT),SetMinimalSize(108, 0),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_CT_INCOME),SetMinimalSize(108, 0),SetFill(1, 0), SetPadding(2,2,2,2), SetResize(1, 1),
EndContainer(),
EndContainer(),
};

View File

@@ -3,11 +3,22 @@
#include <cstdint>
#include "../blitter/32bpp_base.hpp"
#include "../palette_func.h" // PC_WHITE, PC_BLACK
#include <cstdint>
namespace citymania {
extern const uint8_t RGB_TO_M[];
// ', '.join(["true" if grf.srgb_color_distance(c, (255, 255, 255)) > grf.srgb_color_distance(c, (0, 0, 0)) else "false" for c in grf.PALETTE])
constexpr std::array<bool, 256> IS_M_CLOSER_TO_BLACK = { true, true, true, true, true, true, true, true, false, false, false, false, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, false, false, false, false, false, false, false, true, true, true, true, true, false, false, true, true, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, true, true, true, true, true, false, false, false, true, true, true, true, true, true, true, true, true, true, true, true, true, true, false, false, false, false, true, true, true, true, true, false, true, true, true, true, true, false, false, false, true, true, true, true, false, false, false, false, true, true, true, true, true, true, false, false, false, false, true, true, true, true, false, false, false, false, true, true, true, false, false, false, false, false, true, true, true, false, false, false, false, false, true, true, true, true, true, true, true, true, true, false, false, false, false, false, true, false, false, false, false, false, true, true, true, true, true, true, false, false, true, true, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, false, true, true, true, true, false, true, true, true, false, false, false, false, true, true, true, true, true, false, true, true, true, true, true, true, false, false, false, true, false };
constexpr std::array<uint8_t, 256> BLINK_COLOUR = { 141, 7, 9, 10, 11, 12, 13, 14, 2, 2, 3, 4, 5, 6, 6, 8, 22, 22, 135, 210, 2, 3, 16, 18, 29, 30, 59, 31, 69, 24, 25, 26, 37, 38, 38, 39, 104, 32, 33, 35, 77, 47, 166, 166, 49, 49, 41, 41, 42, 125, 55, 85, 86, 37, 120, 65, 69, 104, 24, 25, 78, 120, 121, 197, 60, 54, 55, 27, 85, 28, 126, 78, 79, 79, 167, 167, 167, 178, 71, 72, 94, 94, 95, 95, 95, 209, 80, 81, 101, 102, 31, 103, 69, 80, 81, 82, 101, 102, 103, 103, 69, 96, 97, 98, 36, 111, 37, 120, 121, 121, 39, 105, 79, 120, 167, 167, 167, 178, 122, 122, 61, 108, 79, 79, 167, 167, 168, 71, 133, 134, 134, 177, 177, 128, 16, 18, 142, 142, 143, 143, 143, 136, 136, 171, 150, 150, 151, 151, 152, 152, 144, 200, 154, 156, 213, 213, 212, 153, 128, 154, 155, 157, 166, 166, 180, 180, 180, 124, 35, 7, 174, 143, 176, 176, 170, 130, 131, 132, 77, 166, 166, 166, 165, 165, 180, 180, 180, 180, 62, 63, 27, 65, 53, 61, 62, 62, 55, 55, 204, 151, 151, 152, 152, 152, 198, 154, 80, 81, 83, 84, 19, 157, 156, 154, 154, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 170, 78, 79, 167, 168, 72, 180, 180, 180, 180, 62, 62, 63, 77, 181, 29, 30, 95, 86, 152, 152, 152, 152, 152, 153, 128, 19, 161, 153, 8 };
static inline uint8_t GetBlinkColour(uint8_t m) {
return BLINK_COLOUR[m];
}
static inline uint8_t GetMForRGB(uint8_t r, uint8_t g, uint8_t b) {
return RGB_TO_M[((uint)(r & 0xf0) >> 4) | ((uint)g & 0xf0) | ((uint)(b & 0xf0) << 4)];
}

View File

@@ -28,11 +28,13 @@ namespace citymania {
typedef std::function<bool(bool)> CommandCallback;
extern bool _no_estimate_command;
extern bool _automatic_command;
extern CommandCallback _current_callback;
class Command {
public:
bool no_estimate_flag = false;
bool automatic_flag = false;
CompanyID company = CompanyID::Invalid();
StringID error = (StringID)0;
CommandCallback callback = nullptr;
@@ -50,10 +52,12 @@ public:
if (this->company != CompanyID::Invalid())
_current_company = company;
_no_estimate_command = this->no_estimate_flag;
_automatic_command = this->automatic_flag;
_current_callback = this->callback;
bool res = this->_post(reinterpret_cast<::CommandCallback *>(reinterpret_cast<void(*)()>(callback)));
_current_company = company_backup;
_no_estimate_command = false;
_automatic_command = false;
return res;
}
@@ -84,6 +88,13 @@ public:
return *this;
}
Command &set_auto() {
// Doesn't count for apm
this->automatic_flag = true;
this->no_estimate_flag = true;
return *this;
}
Command &as_company(CompanyID company) {
this->company = company;
return *this;

View File

@@ -20,6 +20,7 @@ std::map<size_t, std::pair<uint32, std::vector<CommandCallback>>> _command_callb
std::queue<std::pair<size_t, uint32>> _command_sent;
CommandCallback _current_callback = nullptr;
bool _no_estimate_command = false;
bool _automatic_command = false;
template <typename T, int MaxLen>
class SumLast {

View File

@@ -184,9 +184,6 @@ struct TileZoning {
static std::unique_ptr<TileZoning[]> _mz = nullptr;
static IndustryType _industry_forbidden_tiles = IT_INVALID;
extern const Station *_station_to_join;
extern const Station *_highlight_station_to_join;
extern TileArea _highlight_join_area;
extern bool _fn_mod;
std::set<std::pair<uint32, const Town*>, std::greater<std::pair<uint32, const Town*>>> _town_cache;
@@ -545,31 +542,6 @@ void ObjectHighlight::AddTile(TileIndex tile, ObjectTileHighlight &&oh) {
this->tiles.insert(std::make_pair(tile, std::move(oh)));
}
void ObjectHighlight::AddStationOverlayData(int w, int h, int rad, StationCoverageType sct) {
if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED;
auto production = citymania::GetProductionAroundTiles(this->tile, w, h, rad);
bool has_header = false;
for (CargoType i = 0; i < NUM_CARGO; i++) {
if (production[i] == 0) continue;
switch (sct) {
case SCT_PASSENGERS_ONLY: if (!IsCargoInClass(i, CargoClass::Passengers)) continue; break;
case SCT_NON_PASSENGERS_ONLY: if (IsCargoInClass(i, CargoClass::Passengers)) continue; break;
case SCT_ALL: break;
default: NOT_REACHED();
}
const CargoSpec *cs = CargoSpec::Get(i);
if (cs == nullptr) continue;
if (!has_header) {
this->overlay_data.emplace_back(0, PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_STATION_SUPPLIES));
has_header = true;
}
this->overlay_data.emplace_back(1, cs->GetCargoIcon(), GetString(CM_STR_BUILD_INFO_OVERLAY_STATION_CARGO, i, production[i] >> 8));
}
}
void ObjectHighlight::UpdateTiles() {
this->tiles.clear();
this->sprites.clear();
@@ -633,7 +605,6 @@ void ObjectHighlight::UpdateTiles() {
tile_track += tile_delta ^ TileDiffXY(1, 1); // perpendicular to tile_delta
} while (--numtracks);
this->AddStationOverlayData(ta.w, ta.h, CA_TRAIN, SCT_ALL);
break;
}
case Type::ROAD_STOP: {
@@ -655,9 +626,6 @@ void ObjectHighlight::UpdateTiles() {
for (TileIndex tile : ta) {
this->AddTile(tile, ObjectTileHighlight::make_road_stop(palette, this->roadtype, this->ddir, this->is_truck, this->road_stop_spec_class, this->road_stop_spec_index));
}
auto sct = (this->is_truck ? SCT_NON_PASSENGERS_ONLY : SCT_PASSENGERS_ONLY);
auto rad = (this->is_truck ? CA_BUS : CA_TRUCK);
this->AddStationOverlayData(ta.w, ta.h, rad, sct);
break;
}
@@ -689,7 +657,6 @@ void ObjectHighlight::UpdateTiles() {
for (AirportTileTableIterator iter(as->layouts[this->airport_layout].tiles.data(), this->tile); iter != INVALID_TILE; ++iter) {
this->AddTile(iter, ObjectTileHighlight::make_airport_tile(palette, iter.GetStationGfx()));
}
this->AddStationOverlayData(as->size_x, as->size_y, as->catchment, SCT_ALL);
break;
}
case Type::BLUEPRINT:
@@ -819,43 +786,6 @@ void ObjectHighlight::UpdateTiles() {
}
}
void ObjectHighlight::UpdateOverlay() {
HideBuildInfoOverlay();
auto w = FindWindowFromPt(_cursor.pos.x, _cursor.pos.y);
if (w == nullptr) return;
auto vp = IsPtInWindowViewport(w, _cursor.pos.x, _cursor.pos.y);
if (vp == nullptr) return;
if (this->tile == INVALID_TILE) {
HideBuildInfoOverlay();
return;
}
auto err = this->cost.GetErrorMessage();
// auto extra_err = this->cost.GetExtraErrorMessage();
bool no_money = (err == STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY);
this->overlay_data.emplace_back(0, PAL_NONE, GetString(no_money ? CM_STR_BUILD_INFO_OVERLAY_COST_NO_MONEY : CM_STR_BUILD_INFO_OVERLAY_COST_OK, this->cost.GetCost()));
// if (this->cost.Failed() && err != STR_ERROR_NOT_ENOUGH_CASH_REQUIRES_CURRENCY) {
// if (err == INVALID_STRING_ID) {
// this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR_UNKNOWN));
// } else {
// SetDParam(0, err);
// this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR));
// }
// if (extra_err != INVALID_STRING_ID) {
// SetDParam(0, extra_err);
// this->overlay_data.emplace_back(PAL_NONE, GetString(CM_STR_BUILD_INFO_OVERLAY_ERROR));
// }
// }
// Point pt = RemapCoords2(TileX(this->tile) * TILE_SIZE + TILE_SIZE / 2, TileY(this->tile) * TILE_SIZE + TILE_SIZE / 2);
Point pt = RemapCoords2(TileX(this->tile) * TILE_SIZE, TileY(this->tile) * TILE_SIZE);
pt.x = UnScaleByZoom(pt.x - vp->virtual_left, vp->zoom) + vp->left;
pt.y = UnScaleByZoom(pt.y - vp->virtual_top, vp->zoom) + vp->top;
// this->overlay_pos = pt;
ShowBuildInfoOverlay(pt.x, pt.y, this->overlay_data);
}
void ObjectHighlight::MarkDirty() {
for (const auto &kv: this->tiles) {
MarkTileDirtyByTile(kv.first);
@@ -1834,8 +1764,6 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th)
bool draw_selection = ((_thd.drawstyle & HT_DRAG_MASK) == HT_RECT && _thd.outersize.x > 0);
const Station *highlight_station = _viewport_highlight_station;
if (_highlight_station_to_join) highlight_station = _highlight_station_to_join;
if (draw_selection) {
// const SpriteID pal[] = {SPR_PALETTE_ZONING_RED, SPR_PALETTE_ZONING_YELLOW, SPR_PALETTE_ZONING_LIGHT_BLUE, SPR_PALETTE_ZONING_GREEN};
// auto color = pal[(int)_station_building_status];
@@ -1878,20 +1806,6 @@ static void SetStationSelectionHighlight(const TileInfo *ti, TileHighlight &th)
const SpriteID pal2[] = {PAL_NONE, CM_PALETTE_TINT_WHITE, CM_PALETTE_TINT_BLUE};
th.ground_pal = th.structure_pal = pal2[b.second];
}
if (_highlight_join_area.tile != INVALID_TILE) {
auto b = CalcTileBorders(ti->tile, [](TileIndex t) {
return _highlight_join_area.Contains(t) ? 1 : 0;
});
th.add_border(b.first, CM_SPR_PALETTE_ZONING_LIGHT_BLUE);
if (b.second) {
switch (th.ground_pal) {
case CM_PALETTE_TINT_WHITE: th.ground_pal = th.structure_pal = CM_PALETTE_TINT_CYAN_WHITE; break;
case CM_PALETTE_TINT_BLUE: break;
default: th.ground_pal = th.structure_pal = CM_PALETTE_TINT_CYAN; break;
}
}
}
}
void CalcCBAcceptanceBorders(TileHighlight &th, TileIndex tile, SpriteID border_pal, SpriteID ground_pal) {
@@ -2247,7 +2161,6 @@ HighLightStyle UpdateTileSelection(HighLightStyle new_drawstyle) {
_thd.cm.MarkDirty();
_thd.cm = _thd.cm_new;
_thd.cm.UpdateTiles();
_thd.cm.UpdateOverlay();
_thd.cm.MarkDirty();
}
return new_drawstyle;
@@ -2423,7 +2336,6 @@ PaletteID GetTreeShadePal(TileIndex tile) {
ActiveTool _at;
static void ResetVanillaHighlight() {
if (_thd.window_class != WC_INVALID) {
/* Undo clicking on button and drag & drop */
@@ -2472,7 +2384,7 @@ void UpdateActiveTool() {
auto tile = pt.x == -1 ? INVALID_TILE : TileVirtXY(pt.x, pt.y);
ToolGUIInfo info;
if (citymania::StationBuildTool::active_highlight.has_value()) {
if (citymania::HasSelectedStationHighlight()) {
info = GetSelectedStationGUIInfo();
} else if (_at.tool != nullptr) {
_at.tool->Update(pt, tile);

View File

@@ -28,9 +28,6 @@
namespace citymania {
typedef std::function<up<Command>(TileIndex start_tile, TileIndex end_tile)> HighlightGenerator;
enum ZoningBorder: uint8 {
NONE = 0,
TOP_LEFT = 1,
@@ -76,19 +73,6 @@ public:
};
class TileIndexWrapper {
public:
TileIndex tile;
TileIndexWrapper() {}
TileIndexWrapper(TileIndex tile)
:tile{tile} {}
inline operator TileIndex () const
{
return this->tile;
}
};
class ObjectTileHighlight {
public:
enum class Type : uint8_t {
@@ -405,25 +389,11 @@ public:
void DrawOverlay(DrawPixelInfo *dpi);
void AddStationOverlayData(int w, int h, int rad, StationCoverageType sct);
void UpdateTiles();
void UpdateOverlay();
void MarkDirty();
};
typedef std::tuple<HighlightMap, BuildInfoOverlayData, CommandCost> ToolGUIInfo;
class Preview {
public:
virtual ~Preview() {}
virtual void Update(Point pt, TileIndex tile) = 0;
virtual void HandleMouseMove() {};
virtual bool HandleMousePress() { return false; };
virtual void HandleMouseRelease() {};
virtual bool HandleMouseClick(Viewport* /* vp */, Point /* pt */, TileIndex /* tile */, bool /* double_click */) { return false; };
virtual std::pair<HighlightMap, BuildInfoOverlayData> GetGUIInfo() = 0;
virtual CursorID GetCursor() = 0;
virtual void OnStationRemoved(const Station* /* station */) {};
};
class Action {
public:
virtual ~Action() = default;

View File

@@ -25,6 +25,7 @@ struct StationPickerSelection {
Axis axis; ///< Selected orientation of the station.
};
extern StationPickerSelection _station_gui; ///< Settings of the station picker.
extern bool _generating_world;
namespace citymania {
@@ -48,6 +49,7 @@ static void PurgeLastActions() {
}
void CountEffectiveAction() {
if (_generating_world) return;
auto now = std::chrono::steady_clock::now();
if (!_first_effective_tick) _first_effective_tick = now;
_effective_actions++;
@@ -66,7 +68,7 @@ std::pair<uint32, uint32> GetEPM() {
if (!_first_effective_tick) return std::make_pair(0, 0);
PurgeLastActions();
auto ms = std::chrono::duration_cast<std::chrono::milliseconds>(now - *_first_effective_tick).count();
if (ms == 0) return std::make_pair(0, 0);
if (ms < 1000) return std::make_pair(0, _last_actions.size());
return std::make_pair(_effective_actions * 60000 / ms,
_last_actions.size());
}

View File

@@ -29,6 +29,7 @@
#include <bitset>
#include "cm_colour.hpp"
#include "cm_hotkeys.hpp"
#include "cm_minimap.hpp"
@@ -249,11 +250,7 @@ bool is_cached_industry(const Industry *ind) {
MinimapIndustryKdtreeEntry get_industry_entry(const Industry *ind) {
auto x = TileX(ind->location.tile) * TILE_SIZE + ind->location.w * TILE_SIZE / 2;
auto y = TileY(ind->location.tile) * TILE_SIZE + ind->location.h * TILE_SIZE / 2;
uint num_outputs = 0;
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++)
if (ind->produced[i].cargo != INVALID_CARGO)
num_outputs++;
_max_industry_outputs = std::max(_max_industry_outputs, num_outputs);
_max_industry_outputs = std::max<uint>(_max_industry_outputs, ind->produced.size());
return {(int16)((y - x) / 8), (int16)((y + x) / 8), ind->index};
}
@@ -854,10 +851,11 @@ inline uint32 SmallMapWindow::GetTileColours(const TileArea &ta) const
* This has the highest priority above any value in _tiletype_importance. */
IndustryType type = Industry::GetByTile(ti)->type;
if (_legend_from_industries[_industry_to_list_pos[type]].show_on_map) {
if (type == _smallmap_industry_highlight) {
if (_smallmap_industry_highlight_state) return MKCOLOUR_XXXX(PC_WHITE);
auto map_colour = GetIndustrySpec(type)->map_colour;
if (type == _smallmap_industry_highlight && _smallmap_industry_highlight_state) {
return MKCOLOUR_XXXX(GetBlinkColour(map_colour));
} else {
return GetIndustrySpec(type)->map_colour * 0x01010101;
return map_colour * 0x01010101;
}
}
/* Otherwise make it disappear */
@@ -1034,18 +1032,16 @@ void SmallMapWindow::DrawIndustryProduction(const DrawPixelInfo *dpi) const
);
IconTextSizeHelper its{SPR_CARGO_COAL, WidgetDimensions::scaled.framerect};
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++) {
if (ind->produced[i].cargo == INVALID_CARGO) continue;
its.add(GetString(STR_JUST_INT, ind->produced[i].history[LAST_MONTH].production), FS_SMALL);
for (auto &pc : ind->produced) {
its.add(GetString(STR_JUST_INT, pc.history[LAST_MONTH].production), FS_SMALL);
}
its.calculate();
this->industry_max_sign = maxdim(this->industry_max_sign, its.size);
auto [r, ir] = its.make_rects(pt.x, pt.y);
GfxFillRect(r, PALETTE_TO_TRANSPARENT, FILLRECT_RECOLOUR);
for (auto i = 0; i < INDUSTRY_NUM_OUTPUTS; i++) {
if (ind->produced[i].cargo == INVALID_CARGO) continue;
DrawSprite(CargoSpec::Get(ind->produced[i].cargo)->GetCargoIcon(), PAL_NONE, ir.left, ir.top + its.icon_ofs_y);
auto str = GetString(STR_JUST_INT, ind->produced[i].history[LAST_MONTH].production);
for (auto &pc : ind->produced) {
DrawSprite(CargoSpec::Get(pc.cargo)->GetCargoIcon(), PAL_NONE, ir.left, ir.top + its.icon_ofs_y);
auto str = GetString(STR_JUST_INT, pc.history[LAST_MONTH].production);
DrawString(ir.left + its.text_ofs_x, ir.right, ir.top + its.text_ofs_y, str, TC_WHITE, SA_LEFT, false, FS_SMALL);
ir.top += its.line_height;
}
@@ -1440,7 +1436,8 @@ std::string SmallMapWindow::GetWidgetString(WidgetID widget, StringID stringid)
params[0] = tbl->legend;
params[1] = Industry::GetIndustryTypeCount(tbl->type);
if (tbl->show_on_map && tbl->type == _smallmap_industry_highlight) {
legend_colour = _smallmap_industry_highlight_state ? PC_WHITE : PC_BLACK;
auto mc = GetIndustrySpec(tbl->type)->map_colour;
legend_colour = _smallmap_industry_highlight_state ? GetBlinkColour(mc) : mc;
}
[[fallthrough]];

View File

@@ -29,6 +29,7 @@
#include "../town.h"
#include "../viewport_func.h"
#include "../viewport_kdtree.h"
#include "../window_func.h" // SetWindowDirty
#include "../window_gui.h"
#include "../zoom_type.h"
#include "../zoom_func.h"
@@ -36,10 +37,12 @@
#include "generated/cm_gen_commands.hpp"
#include <cassert>
#include <complex>
#include <cstdio>
#include <optional>
#include <sstream>
#include <unordered_set>
#include <variant>
bool _remove_button_clicked; // replace vanilla static vars
@@ -77,13 +80,20 @@ extern uint8_t _selected_airport_layout; ///< selected airport layout n
namespace citymania {
const Station *_highlight_station_to_join = nullptr;
TileArea _highlight_join_area;
bool UseImprovedStationJoin() {
return _settings_client.gui.cm_use_improved_station_join && _settings_game.station.distant_join_stations;
}
namespace StationAction {
struct Create {};
struct Join { StationID station; };
struct Picker {};
using Mode = std::variant<Create, Join, Picker>;
};
StationAction::Mode _station_action = StationAction::Create{};
static const int MAX_TILE_EXTENT_LEFT = ZOOM_BASE * TILE_PIXELS; ///< Maximum left extent of tile relative to north corner.
static const int MAX_TILE_EXTENT_RIGHT = ZOOM_BASE * TILE_PIXELS; ///< Maximum right extent of tile relative to north corner.
static const int MAX_TILE_EXTENT_TOP = ZOOM_BASE * MAX_BUILDING_PIXELS; ///< Maximum top extent of tile relative to north corner (not considering bridges).
@@ -105,30 +115,9 @@ void MarkTileAreaDirty(const TileArea &ta) {
p2.y + MAX_TILE_EXTENT_BOTTOM);
}
static void UpdateHiglightJoinArea(const Station *station) {
if (!station) {
MarkTileAreaDirty(_highlight_join_area);
_highlight_join_area.tile = INVALID_TILE;
return;
}
// auto &r = _station_to_join->rect;
// auto d = (int)_settings_game.station.station_spread - 1;
// TileArea ta(
// TileXY(std::max<int>(r.right - d, 0),
// std::max<int>(r.bottom - d, 0)),
// TileXY(std::min<int>(r.left + d, Map::SizeX() - 1),
// std::min<int>(r.top + d, Map::SizeY() - 1))
// );
// if (_highlight_join_area.tile == ta.tile &&
// _highlight_join_area.w == ta.w &&
// _highlight_join_area.h == ta.h) return;
// _highlight_join_area = ta;
MarkTileAreaDirty(_highlight_join_area);
}
static void MarkCoverageAreaDirty(const Station *station) {
MarkTileAreaDirty(station->catchment_tiles);
}
// static void MarkCoverageAreaDirty(const Station *station) {
// MarkTileAreaDirty(station->catchment_tiles);
// }
void MarkCoverageHighlightDirty() {
MarkCatchmentTilesDirty();
@@ -568,36 +557,155 @@ extern DiagDirection AddAutodetectionRotation(DiagDirection ddir); // cm_highli
// if (this->station_to_join == station->index) this->station_to_join = StationID::Invalid();
// }
// Non-tool station highlight management (coverage area and picker selection)
enum class StationHighlightMode {
None,
Picker,
Coverage
};
std::optional<ObjectHighlight> _active_highlight_object = std::nullopt;
StationID _selected_station = StationID::Invalid();
StationHighlightMode _station_highlight_mode = StationHighlightMode::None;
void SetSelectedStationToJoin(StationID station_id) {
StationBuildTool::current_selected_station = station_id;
_selected_station = station_id;
UpdateActiveTool();
}
void ResetJoinStationHighlight() {
StationBuildTool::active_highlight = std::nullopt;
SetSelectedStationToJoin(StationID::Invalid());
void ResetSelectedStationToJoin() {
_station_highlight_mode = StationHighlightMode::None;
UpdateActiveTool();
}
void SetHighlightCoverageStation(Station *station, bool sel) {
if (_station_highlight_mode == StationHighlightMode::Picker) return;
SetWindowDirty(WC_STATION_VIEW, _selected_station);
if (station == nullptr || !sel) {
_station_highlight_mode = StationHighlightMode::None;
} else {
_selected_station = station->index;
_station_highlight_mode = StationHighlightMode::Coverage;
}
SetWindowDirty(WC_STATION_VIEW, _selected_station);
UpdateActiveTool();
}
static void ResetHighlightCoverageStation() {
SetHighlightCoverageStation(nullptr, false);
}
bool IsHighlightCoverageStation(const Station *station) {
if (_station_highlight_mode != StationHighlightMode::Coverage) return false;
if (station == nullptr) return false;
return station->index == _selected_station;
}
void OnStationRemoved(const Station *station) {
// if (_last_built_station == station) _last_built_station = nullptr;
if (StationBuildTool::station_to_join == station->index) {
StationBuildTool::station_to_join = StationID::Invalid();
if (auto mode = std::get_if<StationAction::Join>(&_station_action); mode && mode->station == station->index) {
_station_action = StationAction::Create{};
UpdateActiveTool();
}
if (StationBuildTool::current_selected_station == station->index) {
StationBuildTool::current_selected_station = StationID::Invalid();
if (_selected_station == station->index) {
_selected_station = StationID::Invalid();
if (_station_highlight_mode == StationHighlightMode::Coverage) {
_station_highlight_mode = StationHighlightMode::None;
SetWindowDirty(WC_STATION_VIEW, _selected_station);
}
UpdateActiveTool();
}
// TODO?
// if (GetActiveTool() != nullptr) GetActiveTool()->OnStationRemoved(station);
}
static void SetActiveHighlightObject(std::optional<ObjectHighlight> &ohl) {
_active_highlight_object = ohl;
if (_active_highlight_object.has_value()) _active_highlight_object->UpdateTiles();
if (_station_highlight_mode == StationHighlightMode::Coverage)
SetWindowDirty(WC_STATION_VIEW, _selected_station);
_station_highlight_mode = StationHighlightMode::Picker;
}
void AbortStationPlacement() {
// TODO is it necessary?
// SetHighlightStationToJoin(station=nullptr, with_area=false);
}
bool HasSelectedStationHighlight() {
return _station_highlight_mode != StationHighlightMode::None;
}
static HighlightMap PrepareHighilightMap(Station *st_join, std::optional<ObjectHighlight> ohl, SpriteID pal, bool show_join_area, bool show_coverage, uint rad) {
bool add_current = true; // FIXME
auto hlmap = ohl.has_value() ? ohl->GetHighlightMap(pal) : HighlightMap{};
TileArea join_area;
std::set<TileIndex> coverage_area;
if (show_join_area && st_join != nullptr) {
join_area = GetStationJoinArea(st_join->index);
hlmap.AddTileArea(join_area, CM_PALETTE_TINT_CYAN);
}
if (show_coverage && st_join != nullptr) {
// Add joining station coverage
for (auto t : st_join->catchment_tiles) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
hlmap.Add(t, ObjectTileHighlight::make_tint(pal));
coverage_area.insert(t);
}
}
auto area = ohl.has_value() ? ohl->GetArea() : std::nullopt;
if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED;
std::optional<TileArea> rad_area = std::nullopt;
if (area.has_value()) {
auto xarea = area.value();
xarea.Expand(rad);
xarea.ClampToMap();
rad_area = xarea;
}
if (show_coverage && add_current && rad_area.has_value()) {
// Add current station coverage
for (auto t : rad_area.value()) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
hlmap.Add(t, ObjectTileHighlight::make_tint(pal));
coverage_area.insert(t);
}
}
if (show_coverage) {
hlmap.AddTilesBorder(coverage_area, CM_PALETTE_TINT_WHITE);
}
if (st_join != nullptr) {
// Highlight joining station blue
TileArea ta(TileXY(st_join->rect.left, st_join->rect.top), TileXY(st_join->rect.right, st_join->rect.bottom));
for (TileIndex t : ta) {
if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != st_join->index) continue;
hlmap.Add(t, ObjectTileHighlight::make_struct_tint(CM_PALETTE_TINT_BLUE));
}
}
return hlmap;
}
ToolGUIInfo GetSelectedStationGUIInfo() {
if (_station_highlight_mode == StationHighlightMode::None) return {};
auto st = Station::GetIfValid(_selected_station);
auto hlmap = PrepareHighilightMap(
st,
_station_highlight_mode == StationHighlightMode::Picker ? _active_highlight_object : std::nullopt,
CM_PALETTE_TINT_WHITE,
false,
_station_highlight_mode == StationHighlightMode::Coverage,
0
);
return {hlmap, {}, {}};
}
// --- Action base class ---
void Action::OnStationRemoved(const Station *) {}
@@ -647,90 +755,43 @@ ToolGUIInfo RemoveAction<Handler>::GetGUIInfo() {
template <ImplementsRemoveHandler Handler>
void RemoveAction<Handler>::OnStationRemoved(const Station *) {}
static HighlightMap PrepareHighilighMap(Station *st_join, ObjectHighlight &ohl, SpriteID pal, bool show_join_area, StationCoverageType sct, uint rad) {
bool add_current = true; // FIXME
bool show_coverage = (rad > 0);
auto hlmap = ohl.GetHighlightMap(pal);
TileArea join_area;
std::set<TileIndex> coverage_area;
if (show_join_area && st_join != nullptr) {
join_area = GetStationJoinArea(st_join->index);
hlmap.AddTileArea(join_area, CM_PALETTE_TINT_CYAN);
}
if (show_coverage && st_join != nullptr) {
// Add joining station coverage
for (auto t : st_join->catchment_tiles) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
hlmap.Add(t, ObjectTileHighlight::make_tint(pal));
coverage_area.insert(t);
}
}
auto area = ohl.GetArea();
if (!_settings_game.station.modified_catchment) rad = CA_UNMODIFIED;
std::optional<TileArea> rad_area = std::nullopt;
if (area.has_value()) {
auto xarea = area.value();
xarea.Expand(rad);
xarea.ClampToMap();
rad_area = xarea;
}
if (show_coverage && add_current && rad_area.has_value()) {
// Add current station coverage
for (auto t : rad_area.value()) {
auto pal = join_area.Contains(t) ? CM_PALETTE_TINT_CYAN_WHITE : CM_PALETTE_TINT_WHITE;
hlmap.Add(t, ObjectTileHighlight::make_tint(pal));
coverage_area.insert(t);
}
}
if (show_coverage) {
hlmap.AddTilesBorder(coverage_area, CM_PALETTE_TINT_WHITE);
}
if (st_join != nullptr) {
// Highlight joining station blue
TileArea ta(TileXY(st_join->rect.left, st_join->rect.top), TileXY(st_join->rect.right, st_join->rect.bottom));
for (TileIndex t : ta) {
if (!IsTileType(t, MP_STATION) || GetStationIndex(t) != st_join->index) continue;
hlmap.Add(t, ObjectTileHighlight::make_struct_tint(CM_PALETTE_TINT_BLUE));
}
}
return hlmap;
}
ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional<ObjectHighlight> ohl, up<Command> cmd, StationCoverageType sct, uint rad) {
if (!cmd || !ohl.has_value()) return {};
ohl.value().UpdateTiles();
auto palette = CM_PALETTE_TINT_WHITE;
auto area = ohl.value().GetArea();
auto cost = cmd->test();
if (std::holds_alternative<StationAction::Picker>(_station_action)) {
palette = CM_PALETTE_TINT_YELLOW;
} else {
palette = cost.Succeeded() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP;
}
bool show_coverage = _settings_client.gui.station_show_coverage;
auto hlmap = PrepareHighilighMap(
Station::GetIfValid(StationBuildTool::station_to_join),
Station *to_join = nullptr;
if (auto mode = std::get_if<StationAction::Join>(&_station_action))
to_join = Station::GetIfValid(mode->station);
auto hlmap = PrepareHighilightMap(
to_join,
ohl.value(),
cost.Succeeded() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP,
palette,
true,
sct,
show_coverage ? rad : 0
show_coverage,
rad
);
// Prepare build overlay
BuildInfoOverlayData data;
if (StationBuildTool::station_to_join != StationID::Invalid()) {
data.emplace_back(0, PAL_NONE, GetString(CM_STR_BULID_INFO_OVERLAY_JOIN_STATION, StationBuildTool::station_to_join));
if (auto mode = std::get_if<StationAction::Join>(&_station_action)) {
data.emplace_back(0, PAL_NONE, GetString(CM_STR_BULID_INFO_OVERLAY_JOIN_STATION, mode->station));
} else {
data.emplace_back(0, PAL_NONE, GetString(CM_STR_BULID_INFO_OVERLAY_NEW_STATION));
}
auto area = ohl.value().GetArea();
if (area.has_value()) {
// Add supplied cargo information
// TODO can we use rad_area since we already have it?
@@ -825,26 +886,61 @@ ToolGUIInfo PlacementAction::PrepareGUIInfo(std::optional<ObjectHighlight> ohl,
return {hlmap, data, cost};
}
ToolGUIInfo GetSelectedStationGUIInfo() {
if (!StationBuildTool::active_highlight.has_value()) return {};
auto &ohl = StationBuildTool::active_highlight.value();
// TODO maybe update or none at all?
ohl.UpdateTiles();
auto hlmap = PrepareHighilighMap(
Station::GetIfValid(StationBuildTool::current_selected_station),
ohl,
CM_PALETTE_TINT_WHITE,
false,
SCT_ALL,
0
);
return {hlmap, {}, {}};
}
// --- SizedPlacementAction ---
template <ImplementsSizedPlacementHandler Handler>
void SizedPlacementAction<Handler>::Update(Point, TileIndex tile) {
this->cur_tile = tile;
if (UseImprovedStationJoin()) return;
_station_action = StationAction::Create{};
auto area = this->GetArea();
if (!area.has_value()) return;
auto cmdptr = this->handler.GetCommand(tile, StationID::Invalid());
auto cmd = dynamic_cast<cmd::BuildRailStation *>(cmdptr.get());
if (cmd == nullptr) return;
if (!_settings_game.station.distant_join_stations && _fn_mod) return;
area->Expand(1);
area->ClampToMap();
StationID to_join = StationID::Invalid();
bool ambigous_join = false;
for (auto tile : area.value()) {
if (IsTileType(tile, MP_STATION) && GetTileOwner(tile) == _local_company) {
Station *st = Station::GetByTile(tile);
if (st == nullptr || st->index == to_join) continue;
if (to_join != StationID::Invalid()) {
to_join = StationID::Invalid();
if (_settings_game.station.distant_join_stations)
ambigous_join = true;
break;
}
to_join = st->index;
// TODO check for command to return multiple? but also check each to
// see if they can be built
// if (this->GetCommand(true, st->index)->test().Succeeded()) {
// if (this->station_to_join != INVALID_STATION) {
// this->station_to_join = INVALID_STATION;
// this->palette = CM_PALETTE_TINT_YELLOW;
// break;
// } else this->station_to_join = st->index;
// }
}
}
if (!_settings_game.station.distant_join_stations) return;
if (ambigous_join) _station_action = StationAction::Picker{};
else if (to_join != StationID::Invalid()) _station_action = StationAction::Join{to_join};
else _station_action = StationAction::Create{};
// cmd->station_to_join = NEW_STATION;
// cmd->adjacent = true;
// if (StationBuildTool::station_to_join == INVALID_STATION && !cmd->test().Succeeded()) {
// StationBuildTool::ambigous_join = false;
// }
}
template <ImplementsSizedPlacementHandler Handler>
@@ -931,12 +1027,11 @@ template <ImplementsStationSelectHandler Handler>
void StationSelectAction<Handler>::HandleMouseRelease() {
// TODO station sign click
if (!IsValidTile(this->cur_tile)) return;
this->selected_station = StationID::Invalid();
_station_action = StationAction::Create{};
if (IsTileType(this->cur_tile, MP_STATION)) {
auto st = Station::GetByTile(this->cur_tile);
if (st) this->selected_station = st->index;
if (st) _station_action = StationAction::Join{st->index};
}
this->handler.SelectStationToJoin(this->selected_station);
}
template <ImplementsStationSelectHandler Handler>
@@ -956,15 +1051,11 @@ ToolGUIInfo StationSelectAction<Handler>::GetGUIInfo() {
template <ImplementsStationSelectHandler Handler>
void StationSelectAction<Handler>::OnStationRemoved(const Station *station) {
if (this->selected_station == station->index) this->selected_station = StationID::Invalid();
// if (this->selected_station == station->index) this->selected_station = INVALID_STATION;
}
// --- StationBuildTool ---
StationID StationBuildTool::station_to_join = StationID::Invalid();
StationID StationBuildTool::current_selected_station = StationID::Invalid();
std::optional<ObjectHighlight> StationBuildTool::active_highlight = std::nullopt;
TileArea GetCommandArea(const up<Command> &cmd) {
if (auto rail_cmd = dynamic_cast<cmd::BuildRailStation *>(cmd.get())) {
auto w = rail_cmd->numtracks;
@@ -979,23 +1070,27 @@ TileArea GetCommandArea(const up<Command> &cmd) {
return {dock_cmd->tile, tile_to};
} else if (auto airport_cmd = dynamic_cast<cmd::BuildAirport *>(cmd.get())) {
const AirportSpec *as = AirportSpec::Get(airport_cmd->airport_type);
if (as == nullptr) return {};
return {airport_cmd->tile, as->size_x, as->size_y};
}
NOT_REACHED();
}
StationBuildTool::StationBuildTool() {
ResetHighlightCoverageStation();
}
template<typename Thandler, typename Tcallback, typename Targ>
bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback, Targ arg) {
if (UseImprovedStationJoin()) {
auto cmd = handler->GetCommand(arg, StationBuildTool::station_to_join);
StationBuildTool::active_highlight = std::nullopt;
if (auto mode = std::get_if<StationAction::Join>(&_station_action)) {
auto cmd = handler->GetCommand(arg, mode->station);
return cmd ? cmd->post(callback) : false;
}
// Vanilla joining behaviour
auto cmd = handler->GetCommand(arg, StationID::Invalid());
auto proc = [cmd=sp<Command>{std::move(cmd)}, callback](bool test, StationID to_join) -> bool {
StationBuildTool::station_to_join = to_join;
if (!cmd) return false;
auto station_cmd = dynamic_cast<StationBuildCommand *>(cmd.get());
if (station_cmd == nullptr) return false;
@@ -1003,16 +1098,16 @@ bool StationBuildTool::ExecuteBuildCommand(Thandler *handler, Tcallback callback
if (test) {
return cmd->test().Succeeded();
} else {
StationBuildTool::active_highlight = std::nullopt;
ResetSelectedStationToJoin();
return cmd->post(callback);
}
};
auto ohl = handler->GetObjectHighlight(arg);
if (!ohl.has_value()) return false;
StationBuildTool::active_highlight = ohl;
auto area = ohl->GetArea();
if (!area.has_value()) return false;
SetActiveHighlightObject(ohl);
ShowSelectStationIfNeeded(area.value(), proc);
return true;
}
@@ -1035,6 +1130,14 @@ bool RailStationBuildTool::RemoveHandler::Execute(TileArea area) {
return cmd->post(&CcPlaySound_CONSTRUCTION_RAIL);
}
std::optional<TileArea> RailStationBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const {
if (!IsValidTile(tile)) return std::nullopt;
auto w = _settings_client.gui.station_numtracks;
auto h = _settings_client.gui.station_platlength;
if (_station_gui.axis == AXIS_X) std::swap(w, h);
return TileArea{tile, w, h};
}
up<Command> RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
// TODO mostly same as DragNDropPlacement
auto cmd = make_up<cmd::BuildRailStation>(
@@ -1046,7 +1149,7 @@ up<Command> RailStationBuildTool::SizedPlacementHandler::GetCommand(TileIndex ti
_station_gui.sel_class,
_station_gui.sel_type,
to_join,
true
_fn_mod
);
cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
return cmd;
@@ -1071,7 +1174,7 @@ up<Command> RailStationBuildTool::DragNDropPlacementHandler::GetCommand(TileArea
_station_gui.sel_class,
_station_gui.sel_type,
to_join,
true
_fn_mod
);
cmd->with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
return cmd;
@@ -1179,7 +1282,7 @@ up<Command> RoadStopBuildTool::DragNDropPlacementHandler::GetCommand(TileArea ar
_roadstop_gui.sel_class,
_roadstop_gui.sel_type,
to_join,
true
_fn_mod
);
return res;
@@ -1275,14 +1378,23 @@ bool DockBuildTool::RemoveHandler::Execute(TileArea area) {
}
// SizedPlacementHandler
std::optional<TileArea> DockBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const {
if (!IsValidTile(tile)) return std::nullopt;
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile);
return TileArea{tile, tile_to};
}
up<Command> DockBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
return make_up<cmd::BuildDock>(
tile,
to_join,
true
_fn_mod
);
}
bool DockBuildTool::SizedPlacementHandler::Execute(TileIndex tile) {
return this->tool.ExecuteBuildCommand(this, &CcBuildDocks, tile);
}
@@ -1349,17 +1461,28 @@ bool AirportBuildTool::RemoveHandler::Execute(TileArea area) {
}
// SizedPlacementHandler
std::optional<TileArea> AirportBuildTool::SizedPlacementHandler::GetArea(TileIndex tile) const {
if (!IsValidTile(tile)) return std::nullopt;
auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
if (as == nullptr) return std::nullopt;
return TileArea{tile, as->size_x, as->size_y};
}
up<Command> AirportBuildTool::SizedPlacementHandler::GetCommand(TileIndex tile, StationID to_join) {
// STR_ERROR_CAN_T_BUILD_AIRPORT_HERE,
auto airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
auto as = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index);
if (as == nullptr) return nullptr;
auto airport_type = as->GetIndex();
auto layout = _selected_airport_layout;
return make_up<cmd::BuildAirport>(
auto cmd = make_up<cmd::BuildAirport>(
tile,
airport_type,
layout,
StationBuildTool::station_to_join,
true
to_join,
_fn_mod
);
cmd->with_error(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE);
return cmd;
}
bool AirportBuildTool::SizedPlacementHandler::Execute(TileIndex tile) {
@@ -1429,5 +1552,4 @@ template class DragNDropPlacementAction<RoadStopBuildTool::DragNDropPlacementHan
template class RemoveAction<DockBuildTool::RemoveHandler>;
template class SizedPlacementAction<DockBuildTool::SizedPlacementHandler>;
} // namespace citymania

View File

@@ -48,7 +48,13 @@ DiagDirection AutodetectRoadObjectDirection(TileIndex tile, Point pt, RoadType r
DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area, Point pt, RoadType roadtype);
DiagDirection AutodetectRailObjectDirection(TileIndex tile, Point pt);
void SetSelectedStationToJoin(StationID station_id);
void ResetJoinStationHighlight();
void ResetSelectedStationToJoin();
void SetHighlightCoverageStation(Station *station, bool sel);
bool IsHighlightCoverageStation(const Station *station);
bool HasSelectedStationHighlight();
ToolGUIInfo GetSelectedStationGUIInfo();
struct OverlayParams {
@@ -89,7 +95,6 @@ public:
class StationSelectHandler {
public:
virtual ~StationSelectHandler() = default;
virtual void SelectStationToJoin(StationID station_id) = 0;
};
template<typename Handler>
concept ImplementsStationSelectHandler = std::derived_from<Handler, StationSelectHandler>;
@@ -99,7 +104,6 @@ class StationSelectAction : public Action {
private:
Handler handler;
TileIndex cur_tile = INVALID_TILE;
StationID selected_station = StationID::Invalid();
public:
StationSelectAction(const Handler &handler) : handler{handler} {}
~StationSelectAction() override = default;
@@ -125,6 +129,7 @@ public:
virtual bool Execute(TileIndex tile) = 0;
virtual std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) = 0;
virtual std::pair<StationCoverageType, uint> GetCatchmentParams() = 0;
virtual std::optional<TileArea> GetArea(TileIndex tile) const = 0;
};
template<typename Handler>
concept ImplementsSizedPlacementHandler = std::derived_from<Handler, SizedPlacementHandler>;
@@ -138,7 +143,7 @@ public:
SizedPlacementAction(const Handler &handler) : handler{handler} {}
~SizedPlacementAction() override = default;
void Update(Point pt, TileIndex tile) override;
std::optional<TileArea> GetArea() const override { return std::nullopt; };
std::optional<TileArea> GetArea() const override { return this->handler.GetArea(this->cur_tile); }
bool HandleMousePress() override;
void HandleMouseRelease() override;
ToolGUIInfo GetGUIInfo() override;
@@ -176,20 +181,18 @@ public:
class StationBuildTool : public Tool {
public:
static StationID station_to_join;
static StationID current_selected_station;
static std::optional<ObjectHighlight> active_highlight;
// static StationID station_to_join;
// static bool ambigous_join;
class StationSelectHandler : public citymania::StationSelectHandler {
public:
StationBuildTool &tool;
StationSelectHandler(StationBuildTool &tool) : tool(tool) {}
~StationSelectHandler() {}
void SelectStationToJoin(StationID station_id) override { this->tool.SelectStationToJoin(station_id); };
};
StationBuildTool();
~StationBuildTool() override = default;
void SelectStationToJoin(StationID station_id) { StationBuildTool::station_to_join = station_id; };
ToolGUIInfo GetGUIInfo() override {
if (!this->action) return {};
return this->action->GetGUIInfo();
@@ -223,6 +226,7 @@ private:
bool Execute(TileIndex tile) override;
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {this->tool.GetCatchmentParams()}; };
std::optional<TileArea> GetArea(TileIndex tile) const override;
};
class DragNDropPlacementHandler: public citymania::DragNDropPlacementHandler {
@@ -309,6 +313,7 @@ private:
bool Execute(TileIndex tile) override;
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
std::pair<StationCoverageType, uint> GetCatchmentParams() override { return {SCT_ALL, CA_DOCK}; };
std::optional<TileArea> GetArea(TileIndex tile) const override;
};
public:
@@ -343,6 +348,7 @@ private:
bool Execute(TileIndex tile) override;
std::optional<ObjectHighlight> GetObjectHighlight(TileIndex tile) override;
std::pair<StationCoverageType, uint> GetCatchmentParams() override;
std::optional<TileArea> GetArea(TileIndex tile) const override;
};
public:
@@ -355,8 +361,6 @@ private:
Mode mode;
};
ToolGUIInfo GetSelectedStationGUIInfo();
} // namespace citymania
#endif

View File

@@ -246,8 +246,6 @@ void CommandHelperBase::InternalPostResult(CommandCost &res, TileIndex tile, boo
int x = TileX(tile) * TILE_SIZE;
int y = TileY(tile) * TILE_SIZE;
// FIXME if (!(cmd & CMD_NO_ESTIMATE) && my_cmd) citymania::CountEffectiveAction();
if (res.Failed()) {
/* Only show the error when it's for us. */
if (estimate_only || (IsLocalCompany() && err_message != 0 && my_cmd)) {

View File

@@ -24,7 +24,9 @@ extern uint32 _frame_counter;
struct CommandPacket;
namespace citymania {
extern CommandCost _command_execute_cost;
extern bool _automatic_command;
void ExecuteCurrentCallback(const CommandCost &cost);
void CountEffectiveAction();
}
/**
@@ -304,6 +306,7 @@ protected:
Tret res = Execute(err_message, reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)), my_cmd, estimate_only, network_command, tile, args);
InternalPostResult(ExtractCommandCost(res), tile, estimate_only, only_sending, err_message, my_cmd);
citymania::_command_execute_cost = ExtractCommandCost(res);
if (!estimate_only && !only_sending && !citymania::_automatic_command && my_cmd) citymania::CountEffectiveAction();
if (!estimate_only && !only_sending && callback != nullptr) {
if constexpr (std::is_same_v<Tcallback, CommandCallback>) {

View File

@@ -63,7 +63,6 @@ namespace citymania {
void ChangeGraphBackgroundColour(NWidgetPart *nwid_begin, NWidgetPart *nwid_end) {
for (auto w = nwid_begin; w != nwid_end; w++) {
switch (w->type) {
case WWT_TEXT:
case WWT_RESIZEBOX:
case WWT_MATRIX:
case NWID_VSCROLLBAR:

View File

@@ -3201,7 +3201,7 @@ struct IndustryCargoesWindow : public Window {
Dimension d = GetLargestCargoIconSize();
for (const CargoSpec *cs : _sorted_standard_cargo_specs) {
std::string cargo_str;
if (_settings_client.gui.developer >= 1)
if (!_settings_client.gui.newgrf_developer_tools)
cargo_str = GetString(CM_STR_CARGO_WITH_ID, cs->name, cs->Index());
else
cargo_str = GetString(cs->name);
@@ -3222,7 +3222,7 @@ struct IndustryCargoesWindow : public Window {
if (!indsp->enabled) continue;
std::string indsp_str;
if (_settings_client.gui.developer >= 1)
if (!_settings_client.gui.newgrf_developer_tools)
indsp_str = GetString(CM_STR_INDUSTRY_TYPE_WITH_ID, indsp->name, ind);
else
indsp_str = GetString(indsp->name);

View File

@@ -6285,19 +6285,27 @@ CM_STR_NETWORK_COMPANY_LIST_SPECTATE :Spectate
CM_STR_RAIL_TOOLBAR_TOOLTIP_BLUEPRINT :{BLACK}Rail blueprint tool (copy-paste)
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL :Ctrl+click: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_SHIFT :Shift+click: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL_SHIFT :Ctrl+Shift+lick: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT :Alt+Click: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_SHIFT :Alt+Shift+click: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_CTRL :Ctrl+Alt+click: {STRING2}
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE :do nothing
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FULL_LOAD_ANY :Full load any cargo
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_TRANSFER_CARGO :Transfer cargo
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_UNLOAD_ALL :Force unload of all cargo
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_LOAD :Feeder Load (replace first order)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_UNLOAD :Feeder Unload (replace last order)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NO_LOAD :Do not load any cargo
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL :Ctrl+click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT :Shift+click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT :Ctrl+Shift+click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT :Alt+Click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT :Alt+Shift+click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL :Ctrl+Alt+click station: {STRING2}
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE :Do nothing
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FULL_LOAD_ANY :Full load any cargo
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_TRANSFER_CARGO :Transfer cargo
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_UNLOAD_ALL :Force unload of all cargo
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_DEPOT_MOD_CTRL :Ctrl+click depot: {STRING2}
CM_STR_CONFIG_SETTING_DEPOT_MOD_SHIFT :Shift+click depot: {STRING2}
CM_STR_CONFIG_SETTING_DEPOT_MOD_CTRL_SHIFT :Ctrl+Shift+click depot: {STRING2}
CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_NONE :Do nothing
CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_SERVICE :Service if needed
CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_STOP :Stop
CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_UNBUNCH :Unbunch
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS :Keep depot building tools active after usage: {STRING2}
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS_HELPTEXT :Keep the building tools for road, train and ship depots (reversible by placing with Ctrl).

View File

@@ -6228,19 +6228,19 @@ CM_STR_NETWORK_COMPANY_LIST_SPECTATE :Zuschauen
CM_STR_RAIL_TOOLBAR_TOOLTIP_BLUEPRINT :{BLACK}Schienen-Blaupausen-Tool (kopieren-einfügen)
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL :Strg+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_SHIFT :Umschalt+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL_SHIFT :Strg+Umschalt+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT :Alt+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_SHIFT :Alt+Umschalt+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_CTRL :Strg+Alt+Linksklick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE :Nichts machen
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FULL_LOAD_ANY :Mit beliebiger Fracht voll beladen
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_TRANSFER_CARGO :Fracht umladen
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_UNLOAD_ALL :Entladen jeder Fracht erzwingen
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_LOAD :Zulieferer-Beladung (ersten Auftrag ersetzen)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_UNLOAD :Zulieferer-Entladung (letzten Auftrag ersetzen)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NO_LOAD :Mit keiner Fracht beladen
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL :Strg+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT :Umschalt+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT :Strg+Umschalt+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT :Alt+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT :Alt+Umschalt+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL :Strg+Alt+Linksklick station: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE :Nichts machen
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FULL_LOAD_ANY :Mit beliebiger Fracht voll beladen
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_TRANSFER_CARGO :Fracht umladen
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_UNLOAD_ALL :Entladen jeder Fracht erzwingen
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_LOAD :Zulieferer-Beladung (ersten Auftrag ersetzen)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_UNLOAD :Zulieferer-Entladung (letzten Auftrag ersetzen)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_LOAD :Mit keiner Fracht beladen
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS :Die Depot-Bauwerkzeuge nach Benutzung weiter aktiviert lassen: {STRING}
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS_HELPTEXT :Die Bauwerkzeuge für Fahrzeug- und Zugdepot sowie Werft behalten (umkehrbar durch platzieren mit Strg).

View File

@@ -6545,19 +6545,19 @@ CM_STR_NETWORK_COMPANY_LIST_SPECTATE :Стать зр
CM_STR_RAIL_TOOLBAR_TOOLTIP_BLUEPRINT :{BLACK}Чертежи рельсов (копировать-вставить)
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL :Ctrl+click: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_SHIFT :Shift+click: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL_SHIFT :Ctrl+Shift+lick: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT :Alt+Click: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_SHIFT :Alt+Shift+click: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_CTRL :Ctrl+Alt+click: {STRING}
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE :ничего не делать
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FULL_LOAD_ANY :Полная загрузка любым грузом
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_TRANSFER_CARGO :Передать груз
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_UNLOAD_ALL :Выгрузит весь груз
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_LOAD :Загрузка фидера (заменяет первое задание)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_FEEDER_UNLOAD :Разгрузка фидера (заменяет последнее задание)
CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NO_LOAD :Ничего не загружать
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL :Ctrl+click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT :Shift+click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT :Ctrl+Shift+click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT :Alt+Click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT :Alt+Shift+click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL :Ctrl+Alt+click по станции: {STRING}
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE :ничего не делать
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FULL_LOAD_ANY :Полная загрузка любым грузом
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_TRANSFER_CARGO :Передать груз
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_UNLOAD_ALL :Выгрузит весь груз
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_LOAD :Загрузка фидера (заменяет первое задание)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_FEEDER_UNLOAD :Разгрузка фидера (заменяет последнее задание)
CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NO_LOAD :Ничего не загружать
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS :Оставлять инструмент строительства депо открытым после использования: {STRING}
CM_STR_CONFIG_SETTING_PERSISTENT_DEPOTTOOLS_HELPTEXT :Оставлять инструмент строительства депо открытым после использования (поведение инвертируется нажанием Fn).

View File

@@ -7,6 +7,7 @@
/** @file order_gui.cpp GUI related to orders. */
#include "gfx_func.h"
#include "stdafx.h"
#include "command_func.h"
#include "viewport_func.h"
@@ -473,7 +474,22 @@ 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);
if (citymania::_fn_mod) {
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;
default: break;
}
if (order.GetDepotActionType() & ODATFB_UNBUNCH) {
/* Check to see if we are allowed to make this an unbunching order. */
bool failed = false;
if (v->HasFullLoadOrder()) {
@@ -497,7 +513,7 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
}
/* Now we are allowed to set the action type. */
order.SetDepotActionType(ODATFB_UNBUNCH);
// order.SetDepotActionType(ODATFB_UNBUNCH);
}
return {order, FeederOrderMod::NONE};
@@ -552,20 +568,20 @@ static std::pair<Order, FeederOrderMod> GetOrderCmdFromTile(const Vehicle *v, Ti
uint8 os = 0xff;
if (_ctrl_pressed) {
if (_shift_pressed)
os = _settings_client.gui.cm_ctrl_shift_order_mod;
os = _settings_client.gui.cm_ctrl_shift_station_mod;
else if (_alt_pressed)
os = _settings_client.gui.cm_alt_ctrl_order_mod;
os = _settings_client.gui.cm_alt_ctrl_station_mod;
else
os = _settings_client.gui.cm_ctrl_order_mod;
os = _settings_client.gui.cm_ctrl_station_mod;
}
else if (_shift_pressed) {
if (_alt_pressed)
os = _settings_client.gui.cm_alt_shift_order_mod;
os = _settings_client.gui.cm_alt_shift_station_mod;
else
os = _settings_client.gui.cm_shift_order_mod;
os = _settings_client.gui.cm_shift_station_mod;
}
else if (_alt_pressed)
os = _settings_client.gui.cm_alt_order_mod;
os = _settings_client.gui.cm_alt_station_mod;
auto feeder_mod = FeederOrderMod::NONE;
if (os != 0xff) {
@@ -1628,7 +1644,7 @@ public:
if (feeder_mod == FeederOrderMod::LOAD) {
if (citymania::cmd::InsertOrder(this->vehicle->tile, this->vehicle->index, 1, cmd)
.with_error(STR_ERROR_CAN_T_INSERT_NEW_ORDER)
.no_estimate()
.set_auto()
.post()) {
citymania::cmd::DeleteOrder(this->vehicle->tile, this->vehicle->index, 0)
.with_error(STR_ERROR_CAN_T_DELETE_THIS_ORDER)
@@ -1639,7 +1655,7 @@ public:
} else if (feeder_mod == 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)
.no_estimate()
.set_auto()
.post()) {
citymania::cmd::DeleteOrder(this->vehicle->tile, this->vehicle->index, this->vehicle->GetNumOrders() + (int)_networking - 2)
.with_error(STR_ERROR_CAN_T_DELETE_THIS_ORDER)

View File

@@ -246,12 +246,17 @@ struct GUISettings {
uint32 cm_powerfund_money; ///< minimum amount of money for powerfund to work
uint16 cm_powerfund_houses; ///< powerfunding maximum houses limit
uint8 cm_ctrl_order_mod; ///< goto action shortcut CTRL+LEFT-CLICK
uint8 cm_shift_order_mod; ///< goto action shortcut SHIFT+LEFT-CLICK
uint8 cm_ctrl_shift_order_mod; ///< goto action shortcut CTRL+SHIFT+LEFT-CLICK
uint8 cm_alt_order_mod; ///< goto action shortcut ALT+LEFT-CLICK
uint8 cm_alt_shift_order_mod; ///< goto action shortcut ALT+SHIFT+LEFT-CLICK
uint8 cm_alt_ctrl_order_mod; ///< goto action shortcut ALT+CTRL+LEFT-CLICK
uint8 cm_ctrl_station_mod; ///< station action shortcut on CTRL+LEFT-CLICK
uint8 cm_shift_station_mod; ///< station action shortcut on SHIFT+LEFT-CLICK
uint8 cm_ctrl_shift_station_mod; ///< station action shortcut on CTRL+SHIFT+LEFT-CLICK
uint8 cm_alt_station_mod; ///< station action shortcut on ALT+LEFT-CLICK
uint8 cm_alt_shift_station_mod; ///< station action shortcut on ALT+SHIFT+LEFT-CLICK
uint8 cm_alt_ctrl_station_mod; ///< station action shortcut on ALT+CTRL+LEFT-CLICK
uint8 cm_ctrl_depot_mod; ///< depot action shortcut on CTRL+LEFT-CLICK
uint8 cm_shift_depot_mod; ///< depot action shortcut on SHIFT+LEFT-CLICK
uint8 cm_ctrl_shift_depot_mod; ///< depot action shortcut on CTRL+SHIFT+LEFT-CLICK
bool cm_no_loading_on_transfer_order; ///< automatically set no-loading when ordering to transfer all cargo
bool cm_no_loading_on_unload_order; ///< automatically set no-loading when ordering to unload all cargo

View File

@@ -1491,7 +1491,7 @@ struct StationViewWindow : public Window {
extern const Station *_viewport_highlight_station;
this->SetWidgetDisabledState(WID_SV_CATCHMENT, st->facilities == StationFacilities{});
this->SetWidgetLoweredState(WID_SV_CATCHMENT, _viewport_highlight_station == st);
this->SetWidgetLoweredState(WID_SV_CATCHMENT, citymania::IsHighlightCoverageStation(st));
this->DrawWidgets();
@@ -1991,7 +1991,8 @@ struct StationViewWindow : public Window {
break;
case WID_SV_CATCHMENT:
SetViewportCatchmentStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT));
citymania::SetHighlightCoverageStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT));
// SetViewportCatchmentStation(Station::Get(this->window_number), !this->IsWidgetLowered(WID_SV_CATCHMENT));
break;
case WID_SV_LOCATION:
@@ -2365,7 +2366,7 @@ struct SelectStationWindow : Window {
void Close([[maybe_unused]] int data = 0) override
{
if constexpr (std::is_same_v<T, Waypoint *>) SetViewportCatchmentSpecializedStation<typename T::StationType>(nullptr, true);
else citymania::ResetJoinStationHighlight();
else citymania::ResetSelectedStationToJoin();
_thd.freeze = false;
this->Window::Close();

View File

@@ -233,7 +233,7 @@ struct StatusBarWindow : Window {
this->SetWidgetDirty(WID_S_LEFT);
}};
TimeoutTimer<TimerWindow> cm_epm_interval = {std::chrono::seconds(1), [this]() {
IntervalTimer<TimerWindow> cm_epm_interval = {std::chrono::seconds(1), [this](uint) {
this->SetWidgetDirty(CM_WID_S_APM);
}};
};

View File

@@ -2,7 +2,8 @@
static void cm_v_RedrawStatusBar(int32 new_value);
static void cm_v_RedrawGraphs(int32 new_value);
static std::initializer_list<const char*> _order_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"};
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"};
static std::initializer_list<const char*> _graph_background_options{"black", "grey"};
@@ -64,69 +65,102 @@ def = true
str = CM_STR_CONFIG_SETTING_AUTOSET_NOLOAD_ON_UNLOAD
[SDTC_OMANY]
var = gui.cm_ctrl_order_mod
var = gui.cm_ctrl_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 1
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_shift_order_mod
var = gui.cm_shift_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 0
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_SHIFT
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_ctrl_shift_order_mod
var = gui.cm_ctrl_shift_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 2
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_CTRL_SHIFT
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_CTRL_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_alt_order_mod
var = gui.cm_alt_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 4
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_ALT
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_alt_shift_order_mod
var = gui.cm_alt_shift_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 3
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_SHIFT
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_SHIFT
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_alt_ctrl_order_mod
var = gui.cm_alt_ctrl_station_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 5
max = 6
full = _order_mod_actions
str = CM_STR_CONFIG_SETTING_ORDER_MOD_ALT_CTRL
strval = CM_STR_CONFIG_SETTING_ORDER_MOD_ACTION_NONE
full = _station_mod_actions
str = CM_STR_CONFIG_SETTING_STATION_MOD_ALT_CTRL
strval = CM_STR_CONFIG_SETTING_STATION_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_ctrl_depot_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 3
max = 3
full = _depot_mod_actions
str = CM_STR_CONFIG_SETTING_DEPOT_MOD_CTRL
strval = CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_shift_depot_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 1
max = 3
full = _depot_mod_actions
str = CM_STR_CONFIG_SETTING_DEPOT_MOD_SHIFT
strval = CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_OMANY]
var = gui.cm_ctrl_shift_depot_mod
type = SLE_UINT8
flags = SettingFlag::NotInSave, SettingFlag::NoNetworkSync, SettingFlag::GuiDropdown, SettingFlag::CityMania
def = 2
max = 3
full = _depot_mod_actions
str = CM_STR_CONFIG_SETTING_DEPOT_MOD_CTRL_SHIFT
strval = CM_STR_CONFIG_SETTING_DEPOT_MOD_ACTION_NONE
cat = SC_BASIC
[SDTC_BOOL]

View File

@@ -1017,7 +1017,7 @@ static void DoRegularFunding(Town *t)
} else if (TimerGameTick::counter - t->cm.last_funding < Ticks::TOWN_GROWTH_TICKS) return;
citymania::cmd::DoTownAction(t->xy, t->index, TownAction::FundBuildings)
.no_estimate()
.set_auto()
.as_company(_local_company)
.post();
t->cm.last_funding = TimerGameTick::counter;
@@ -1062,7 +1062,7 @@ static void DoRegularAdvertising(Town *t) {
t->cm.last_advertisement = TimerGameTick::counter;
citymania::cmd::DoTownAction(t->xy, t->index, TownAction::AdvertiseLarge)
.no_estimate()
.set_auto()
.as_company(_local_company)
.with_callback([=] (bool res) -> bool {
if (!res) return true;