Some fixes after merging

This commit is contained in:
Pavel Stupnikov
2022-11-26 22:25:47 +04:00
parent f3ecdf6f7f
commit 4dea7601c0
23 changed files with 520 additions and 265 deletions

View File

@@ -1,4 +1,5 @@
import re
from pathlib import Path
from pprint import pprint
RX_COMMAND = re.compile(r'(?P<returns>CommandCost|std::tuple<CommandCost, [^>]*>) (?P<name>Cmd\w*)\((?P<args>[^)]*)\);')
@@ -6,31 +7,40 @@ RX_ARG = re.compile(r'(?P<type>(:?const |)[\w:]* &?)(?P<name>\w*)')
RX_CAMEL_TO_SNAKE = re.compile(r'(?<!^)(?=[A-Z])')
FILES = [
'src/misc_cmd.h',
'src/object_cmd.h',
'src/order_cmd.h',
'src/story_cmd.h',
'src/town_cmd.h',
]
OUTPUT = 'src/citymania/generated/cm_gen_commands'
BASE_DIR = Path(__file__).parent
OUTPUT = BASE_DIR / 'src/citymania/generated/cm_gen_commands'
def parse_commands():
res = []
for f in FILES:
for returns, name, args_str in RX_COMMAND.findall(open(f).read()):
for returns, name, args_str in RX_COMMAND.findall(open(BASE_DIR / f).read()):
if returns.startswith('std::tuple'):
ret_type = returns[24: -1]
else:
ret_type = None
args = [RX_ARG.fullmatch(x).group('type', 'name') for x in args_str.split(', ')]
args = args[1:]
if args[0][0].strip() == 'TileIndex':
args = args[1:]
print(name, args)
res.append((ret_type, name[3:], args))
return res
def run():
commands = parse_commands()
with open(OUTPUT + '.hpp', 'w') as f:
with open(OUTPUT.with_suffix('.hpp'), 'w') as f:
f.write(
'// This file is generated by gen_commands.py, do not edit\n\n'
'#ifndef CM_GEN_COMMANDS_HPP\n'
'#define CM_GEN_COMMANDS_HPP\n'
'#include "../cm_command_type.hpp"\n'
'namespace citymania {\n'
'namespace cmd {\n\n'
@@ -43,24 +53,31 @@ def run():
f'public:\n'
)
for at, an in args:
f.write(f' {at} {an};\n')
f.write(f' {at}{an};\n')
f.write(
f'\n'
f' {name}({args_list})\n'
f' :{args_init} {{}}\n'
f' ~{name}() override {{}}\n'
f'\n'
f' bool Post(bool automatic=False);\n'
f' bool DoPost() override;\n'
f'}};\n\n'
)
f.write(
'} // namaespace cmd\n'
'} // namaespace citymania\n'
'} // namespace cmd\n'
'} // namespace citymania\n'
'#endif\n'
)
with open(OUTPUT + '.cpp', 'w') as f:
with open(OUTPUT.with_suffix('.cpp'), 'w') as f:
f.write(
'// This file is generated by gen_commands.py, do not edit\n\n'
'#include "cm_gen_commands.cpp"\n'
'#include "../../stdafx.h"\n'
'#include "cm_gen_commands.hpp"\n'
)
for fn in FILES:
f.write(f'#include "../../{fn}"\n')
f.write(
'namespace citymania {\n'
'namespace cmd {\n\n'
)
@@ -68,13 +85,14 @@ def run():
constant = 'CMD_' + RX_CAMEL_TO_SNAKE.sub('_', name).upper()
args_list = ', '.join(f'this->{an}' for _, an in args)
f.write(
f'bool {name}::Post(bool automatic) {{\n'
f' return ::Command<{constant}>({args_list});\n'
'}\n\n'
f'bool {name}::DoPost() {{\n'
f' return ::Command<{constant}>::Post(this->error, this->tile, {args_list});\n'
'}\n'
)
f.write('\n')
f.write(
'} // namaespace cmd\n'
'} // namaespace citymania\n'
'} // namespace cmd\n'
'} // namespace citymania\n'
)
if __name__ == "__main__":

View File

@@ -460,7 +460,7 @@ public:
/* strings such as 'Size' and 'Coverage Area' */
top = DrawStationCoverageAreaText(r.left, r.right, top, SCT_ALL, rad, false) + ScaleGUITrad(WD_PAR_VSEP_NORMAL);
top = DrawStationCoverageAreaText(r.left, r.right, top, SCT_ALL, rad, true) + ScaleGUITrad(WD_PAR_VSEP_NORMAL);
top = DrawStationAuthorityText(panel_nwi->pos_x + WD_FRAMERECT_LEFT, right - WD_FRAMERECT_RIGHT, top) + WD_PAR_VSEP_NORMAL;
top = DrawStationAuthorityText(r.left, r.right, top) + ScaleGUITrad(WD_PAR_VSEP_NORMAL);
}
/* Resize background if the window is too small.

View File

@@ -40,7 +40,7 @@ public:
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
Sprite *Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) override {
return Blitter_32bppSSE_Base::Encode(sprite, allocator, this);
return Blitter_32bppSSE2::Encode(sprite, allocator);
}
const char *GetName() override { return "32bpp-sse4-anim"; }
using Blitter_32bppSSE2_Anim::LookupColourInPalette;

View File

@@ -1,4 +1,5 @@
add_subdirectory(extensions)
add_subdirectory(generated)
add_files(
cm_bitstream.hpp

View File

@@ -0,0 +1,53 @@
#ifndef CM_COMMAND_TYPE_HPP
#define CM_COMMAND_TYPE_HPP
#include "../command_func.h"
#include "../misc_cmd.h"
#include "../object_type.h"
#include "../order_type.h"
namespace citymania {
class Command {
public:
TileIndex tile = 0;
bool automatic = false;
CompanyID as_company = INVALID_COMPANY;
StringID error = (StringID)0;
virtual ~Command() {}
virtual bool DoPost()=0;
bool Post() {
CompanyID old = _current_company;
if (this->as_company != INVALID_COMPANY)
_current_company = as_company;
bool res = this->DoPost();
_current_company = old;
return res;
}
Command &WithTile(TileIndex tile) {
this->tile = tile;
return *this;
}
Command &WithError(StringID error) {
this->error = error;
return *this;
}
Command &SetAuto() {
this->automatic = true;
return *this;
}
Command &AsCompany(CompanyID company) {
this->as_company = company;
return *this;
}
};
} // namaespace citymania
#endif

View File

@@ -29,7 +29,7 @@ size_t GetCommandHash(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const st
hash_combine(res, tile, p1, p2, cmd, text);
return res;
}
/*
void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text, CommandCallback callback) {
if (!_networking) {
callback(true);
@@ -56,7 +56,7 @@ bool DoCommandWithCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, ::C
bool DoCommandWithCallback(const CommandContainer &cc, CommandCallback callback) {
return DoCommandWithCallback(cc.tile, cc.p1, cc.p2, cc.cmd, cc.callback, cc.text, callback);
}
*/
void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text) {
auto hash = GetCommandHash(tile, p1, p2, cmd & CMD_ID_MASK, text);
auto p = _command_callbacks.find(hash);
@@ -109,14 +109,33 @@ void HandleNextClientFrame() {
ClearOldCallbacks();
}
void SendClientCommand(const CommandPacket *cp) {
/*void SendClientCommand(const CommandPacket *cp) {
if (_outgoing_queue.empty() && CanSendCommand()) {
MyClient::SendCommand(cp);
_commands_this_frame++;
return;
}
_outgoing_queue.push(*cp);
}*/
namespace cmd {
bool Pause::Post(bool automati) {
return ::Command<CMD_PAUSE>::Post(this->mode, this->pause);
}
bool DoTownAction::Post(bool automatic) {
return ::Command<CMD_DO_TOWN_ACTION>::Post(this->town_id, this->town_action);
}
bool SkipToOrder::Post(bool automatic) {
return ::Command<CMD_SKIP_TO_ORDER>::Post(
this->veh_id, this->sel_ord
_ctrl_pressed ? STR_ERROR_CAN_T_SKIP_TO_ORDER : STR_ERROR_CAN_T_SKIP_ORDER,
this->vehicle->tile, this->vehicle->index, citymania::_fn_mod ? this->OrderGetSel() : ((this->vehicle->cur_implicit_order_index + 1) % this->vehicle->GetNumOrders()));
}
} // namespace cmd
} // namespace citymania

View File

@@ -5,17 +5,19 @@
#include "../tile_type.h"
#include "../network/network_internal.h"
#include "generated/cm_gen_commands.hpp"
namespace citymania {
typedef std::function<bool(bool)> CommandCallback;
void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text, CommandCallback callback);
bool DoCommandWithCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, ::CommandCallback *callback, const std::string &text, CommandCallback cm_callback);
bool DoCommandWithCallback(const CommandContainer &cc, CommandCallback callback);
// void AddCommandCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text, CommandCallback callback);
// bool DoCommandWithCallback(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, ::CommandCallback *callback, const std::string &text, CommandCallback cm_callback);
// bool DoCommandWithCallback(const CommandContainer &cc, CommandCallback callback);
void HandleCommandExecution(bool res, TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, const std::string &text);
void InitCommandQueue();
void HandleNextClientFrame();
void SendClientCommand(const CommandPacket *cp);
// void SendClientCommand(const CommandPacket *cp);
} // namespace citymania

View File

@@ -2,6 +2,7 @@
#include "cm_console_cmds.hpp"
#include "cm_commands.hpp"
#include "cm_export.hpp"
#include "../command_func.h"
@@ -53,7 +54,8 @@ bool ConStep(byte argc, char *argv[]) {
}
auto n = (argc > 1 ? atoi(argv[1]) : 1);
DoCommandP(0, PM_PAUSED_NORMAL, 0 | (n << 1), CMD_PAUSE);
// FIXME (n << 1)
cmd::Pause(PM_PAUSED_NORMAL, 0).Post();
return true;
}
@@ -123,7 +125,8 @@ bool ConTreeMap(byte argc, char *argv[]) {
auto tree_count = std::min(t / 51, 4);
// auto tree_growth = (uint)(t % 51) * 7 / 50;
for (auto i = 0; i < tree_count; i++) {
DoCommand(tile, TREE_INVALID, tile, DC_EXEC, CMD_PLANT_TREE);
// FIXME
// DoCommand(tile, TREE_INVALID, tile, DC_EXEC, CMD_PLANT_TREE);
}
}
@@ -200,7 +203,8 @@ void ExecuteFakeCommands(Date date, DateFract date_fract) {
while (!_fake_commands.empty() && !DatePredate(date, date_fract, _fake_commands.front().date, _fake_commands.front().date_fract)) {
auto &x = _fake_commands.front();
fprintf(stderr, "Executing command: company=%u cmd=%u(%s) tile=%u p1=%u p2=%u text=%s ... ", x.company_id, x.cmd, GetCommandName(x.cmd), x.tile, x.p1, x.p2, x.text.c_str());
// FIXME
// fprintf(stderr, "Executing command: company=%u cmd=%u(%s) tile=%u p1=%u p2=%u text=%s ... ", x.company_id, x.cmd, GetCommandName(x.cmd), x.tile, x.p1, x.p2, x.text.c_str());
if (x.res == 0) {
fprintf(stderr, "REJECTED\n");
_fake_commands.pop();
@@ -208,6 +212,7 @@ void ExecuteFakeCommands(Date date, DateFract date_fract) {
}
if (_networking) {
/* FIXME
CommandPacket cp;
cp.tile = x.tile;
cp.p1 = x.p1;
@@ -223,9 +228,10 @@ void ExecuteFakeCommands(Date date, DateFract date_fract) {
if (cs->status >= NetworkClientSocket::STATUS_MAP) {
cs->outgoing_queue.Append(&cp);
}
}
}*/
}
_current_company = (CompanyID)x.company_id;
/* FIXME
auto res = DoCommandPInternal(x.tile, x.p1, x.p2, x.cmd | CMD_NETWORK_COMMAND, nullptr, x.text.c_str(), false, false);
if (res.Failed() != (x.res != 1)) {
if (!res.Failed()) {
@@ -242,7 +248,7 @@ void ExecuteFakeCommands(Date date, DateFract date_fract) {
}
if (x.seed != (_random.state[0] & 255)) {
fprintf(stderr, "*** DESYNC expected seed %u vs current %u ***\n", x.seed, _random.state[0] & 255);
}
}*/
_fake_commands.pop();
}
_current_company = backup_company;
@@ -273,7 +279,7 @@ void LoadCommands(const std::string &filename) {
while(std::getline(file, str)) {
std::istringstream ss(str);
FakeCommand cmd;
ss >> cmd.date >> cmd.date_fract >> cmd.res >> cmd.seed >> cmd.company_id >> cmd.cmd >> cmd.tile >> cmd.p1 >> cmd.p2;
// FIXME ss >> cmd.date >> cmd.date_fract >> cmd.res >> cmd.seed >> cmd.company_id >> cmd.cmd >> cmd.tile >> cmd.p1 >> cmd.p2;
std::string s;
ss.get();
std::getline(ss, cmd.text);

View File

@@ -15,7 +15,7 @@
#include "../strings_type.h"
#include "../table/palettes.h"
#include "../table/sprites.h"
#include "../table/train_cmd.h"
#include "../table/train_sprites.h"
#include "../viewport_sprite_sorter.h"
#include "../viewport_type.h"
#include "../window_func.h"

View File

@@ -19,6 +19,19 @@
namespace citymania {
class TileIndexWrapper {
public:
TileIndex tile;
TileIndexWrapper() {}
TileIndexWrapper(TileIndex tile)
:tile{tile} {}
inline operator TileIndex () const
{
return this->tile;
}
};
class ObjectTileHighlight {
public:
enum class Type {
@@ -31,6 +44,7 @@ public:
RAIL_TUNNEL_HEAD,
ROAD_STOP,
ROAD_DEPOT,
AIRPORT_TILE,
POINT,
NUMBERED_RECT,
@@ -57,7 +71,7 @@ public:
} signal;
struct {
DiagDirection ddir;
TileIndex other_end;
TileIndexWrapper other_end;
BridgeType type;
} bridge_head;
struct {

View File

@@ -202,25 +202,18 @@ bool CheckStationJoin(TileIndex start_tile, TileIndex end_tile) {
return false;
}
void JoinAndBuild(CommandContainer cmdcont) {
auto join_to = _highlight_station_to_join;
uint32 adj_bit = ((citymania::_fn_mod || join_to) ? 1 : 0);
auto cmd = (cmdcont.cmd & CMD_ID_MASK);
if (cmd == CMD_BUILD_RAIL_STATION) {
SB(cmdcont.p1, 24, 1, adj_bit);
} else if (cmd == CMD_BUILD_ROAD_STOP) {
SB(cmdcont.p2, 2, 1, adj_bit);
} else if (cmd == CMD_BUILD_DOCK) {
SB(cmdcont.p1, 0, 1, adj_bit);
} else if (cmd == CMD_BUILD_AIRPORT) {
SB(cmdcont.p2, 0, 1, adj_bit);
}
if (citymania::_fn_mod) SB(cmdcont.p2, 16, 16, NEW_STATION);
else if (join_to) SB(cmdcont.p2, 16, 16, join_to->index);
else SB(cmdcont.p2, 16, 16, INVALID_STATION);
using JoinAndBuildCmdProc = std::function<bool(bool test, StationID to_join, bool adjacent)>;
_last_station_bulid_cmd = cmdcont;
DoCommandP(&cmdcont);
void JoinAndBuild(JoinAndBuildCmdProc proc) {
auto join_to = _highlight_station_to_join;
bool adjacent = (citymania::_fn_mod || join_to);
StationID to_join = INVALID_STATION;
if (citymania::_fn_mod) to_join = NEW_STATION;
else if (join_to) to_join = join_to->index;
FIXME _last_station_bulid_cmd = cmdcont;
proc(false, to_join, adjacent);
}
static DiagDirection TileFractCoordsToDiagDir(Point pt) {
@@ -412,16 +405,22 @@ void PlaceDock(TileIndex tile) {
}
void PlaceAirport(TileIndex tile) {
FIXME
if (CheckStationJoin(tile, tile)) return;
if (_selected_airport_index == -1) return;
uint32 p2 = (citymania::_fn_mod ? 1 : 0);
SB(p2, 16, 16, INVALID_STATION); // no station to join
byte airport_type = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
byte layout = _selected_airport_layout;
auto proc = [=](bool test, StationID to_join, bool adjacent) -> bool {
if (test) {
return Command<CMD_BUILD_AIRPORT>::Do(CommandFlagsToDCFlags(GetCommandFlags<CMD_BUILD_AIRPORT>()), tile, airport_type, layout, INVALID_STATION, adjacent).Succeeded();
} else {
return Command<CMD_BUILD_AIRPORT>::Post(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE, CcBuildAirport, tile, airport_type, layout, to_join, adjacent);
}
};
uint32 p1 = AirportClass::Get(_selected_airport_class)->GetSpec(_selected_airport_index)->GetIndex();
p1 |= _selected_airport_layout << 8;
CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_AIRPORT | CMD_MSG(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE), CcBuildAirport, "" };
JoinAndBuild(cmdcont);
}

View File

@@ -701,4 +701,22 @@ void ShowWatchWindow(CompanyID company_to_watch = INVALID_COMPANY, int type = EW
}
}
void UpdateWatching(CompanyID company, TileIndex tile) {
/* Send Tile Number to Watching Company Windows */
WatchCompany *wc;
for(int watching_window = 0; ; watching_window++){
wc = dynamic_cast<citymania::WatchCompany*>(FindWindowById(WC_WATCH_COMPANY, watching_window));
if(wc != NULL) wc->OnDoCommand(_current_company, tile);
else break;
}
for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
if (ci->client_playas == _current_company) {
wc = dynamic_cast<citymania::WatchCompany*>(FindWindowById(WC_WATCH_COMPANYA, ci->client_id));
if (wc != NULL) wc->OnDoCommand(_current_company, tile);
break;
}
}
}
} // namespace citymania

View File

@@ -91,6 +91,7 @@ public:
};
void ShowWatchWindow(CompanyID company_to_watch, int type);
void UpdateWatching(CompanyID company, TileIndex tile);
} // namespace citymania

View File

@@ -1,76 +1,109 @@
// This file is generated by gen_commands.py, do not edit
#include "cm_gen_commands.cpp"
#include "../../stdafx.h"
#include "cm_gen_commands.hpp"
#include "../../src/misc_cmd.h"
#include "../../src/object_cmd.h"
#include "../../src/order_cmd.h"
#include "../../src/town_cmd.h"
namespace citymania {
namespace cmd {
bool ModifyOrder::Post(bool automatic) {
return ::Command<CMD_MODIFY_ORDER>(this->flags, this->veh, this->sel_ord, this->mof, this->data);
bool MoneyCheat::DoPost() {
return ::Command<CMD_MONEY_CHEAT>::Post(this->error, this->tile, this->amount);
}
bool SkipToOrder::Post(bool automatic) {
return ::Command<CMD_SKIP_TO_ORDER>(this->flags, this->veh_id, this->sel_ord);
bool ChangeBankBalance::DoPost() {
return ::Command<CMD_CHANGE_BANK_BALANCE>::Post(this->error, this->tile, this->delta, this->company, this->expenses_type);
}
bool DeleteOrder::Post(bool automatic) {
return ::Command<CMD_DELETE_ORDER>(this->flags, this->veh_id, this->sel_ord);
bool IncreaseLoan::DoPost() {
return ::Command<CMD_INCREASE_LOAN>::Post(this->error, this->tile, this->cmd, this->amount);
}
bool InsertOrder::Post(bool automatic) {
return ::Command<CMD_INSERT_ORDER>(this->flags, this->veh, this->sel_ord, this->new_order);
bool DecreaseLoan::DoPost() {
return ::Command<CMD_DECREASE_LOAN>::Post(this->error, this->tile, this->cmd, this->amount);
}
bool OrderRefit::Post(bool automatic) {
return ::Command<CMD_ORDER_REFIT>(this->flags, this->veh, this->order_number, this->cargo);
bool Pause::DoPost() {
return ::Command<CMD_PAUSE>::Post(this->error, this->tile, this->mode, this->pause);
}
bool CloneOrder::Post(bool automatic) {
return ::Command<CMD_CLONE_ORDER>(this->flags, this->action, this->veh_dst, this->veh_src);
bool BuildObject::DoPost() {
return ::Command<CMD_BUILD_OBJECT>::Post(this->error, this->tile, this->type, this->view);
}
bool MoveOrder::Post(bool automatic) {
return ::Command<CMD_MOVE_ORDER>(this->flags, this->veh, this->moving_order, this->target_order);
bool BuildObjectArea::DoPost() {
return ::Command<CMD_BUILD_OBJECT_AREA>::Post(this->error, this->tile, this->start_tile, this->type, this->view, this->diagonal);
}
bool ClearOrderBackup::Post(bool automatic) {
return ::Command<CMD_CLEAR_ORDER_BACKUP>(this->flags, this->tile, this->user_id);
bool ModifyOrder::DoPost() {
return ::Command<CMD_MODIFY_ORDER>::Post(this->error, this->tile, this->veh, this->sel_ord, this->mof, this->data);
}
bool CreateStoryPage::Post(bool automatic) {
return ::Command<CMD_CREATE_STORY_PAGE>(this->flags, this->company, this->text);
bool SkipToOrder::DoPost() {
return ::Command<CMD_SKIP_TO_ORDER>::Post(this->error, this->tile, this->veh_id, this->sel_ord);
}
bool CreateStoryPageElement::Post(bool automatic) {
return ::Command<CMD_CREATE_STORY_PAGE_ELEMENT>(this->flags, this->tile, this->page_id, this->type, this->reference, this->text);
bool DeleteOrder::DoPost() {
return ::Command<CMD_DELETE_ORDER>::Post(this->error, this->tile, this->veh_id, this->sel_ord);
}
bool UpdateStoryPageElement::Post(bool automatic) {
return ::Command<CMD_UPDATE_STORY_PAGE_ELEMENT>(this->flags, this->tile, this->page_element_id, this->reference, this->text);
bool InsertOrder::DoPost() {
return ::Command<CMD_INSERT_ORDER>::Post(this->error, this->tile, this->veh, this->sel_ord, this->new_order);
}
bool SetStoryPageTitle::Post(bool automatic) {
return ::Command<CMD_SET_STORY_PAGE_TITLE>(this->flags, this->page_id, this->text);
bool OrderRefit::DoPost() {
return ::Command<CMD_ORDER_REFIT>::Post(this->error, this->tile, this->veh, this->order_number, this->cargo);
}
bool SetStoryPageDate::Post(bool automatic) {
return ::Command<CMD_SET_STORY_PAGE_DATE>(this->flags, this->page_id, this->date);
bool CloneOrder::DoPost() {
return ::Command<CMD_CLONE_ORDER>::Post(this->error, this->tile, this->action, this->veh_dst, this->veh_src);
}
bool ShowStoryPage::Post(bool automatic) {
return ::Command<CMD_SHOW_STORY_PAGE>(this->flags, this->page_id);
bool MoveOrder::DoPost() {
return ::Command<CMD_MOVE_ORDER>::Post(this->error, this->tile, this->veh, this->moving_order, this->target_order);
}
bool RemoveStoryPage::Post(bool automatic) {
return ::Command<CMD_REMOVE_STORY_PAGE>(this->flags, this->page_id);
bool ClearOrderBackup::DoPost() {
return ::Command<CMD_CLEAR_ORDER_BACKUP>::Post(this->error, this->tile, this->user_id);
}
bool RemoveStoryPageElement::Post(bool automatic) {
return ::Command<CMD_REMOVE_STORY_PAGE_ELEMENT>(this->flags, this->page_element_id);
bool FoundTown::DoPost() {
return ::Command<CMD_FOUND_TOWN>::Post(this->error, this->tile, this->size, this->city, this->layout, this->random_location, this->townnameparts, this->text);
}
bool StoryPageButton::Post(bool automatic) {
return ::Command<CMD_STORY_PAGE_BUTTON>(this->flags, this->tile, this->page_element_id, this->reference);
bool RenameTown::DoPost() {
return ::Command<CMD_RENAME_TOWN>::Post(this->error, this->tile, this->town_id, this->text);
}
} // namaespace cmd
} // namaespace citymania
bool DoTownAction::DoPost() {
return ::Command<CMD_DO_TOWN_ACTION>::Post(this->error, this->tile, this->town_id, this->action);
}
bool TownGrowthRate::DoPost() {
return ::Command<CMD_TOWN_GROWTH_RATE>::Post(this->error, this->tile, this->town_id, this->growth_rate);
}
bool TownRating::DoPost() {
return ::Command<CMD_TOWN_RATING>::Post(this->error, this->tile, this->town_id, this->company_id, this->rating);
}
bool TownCargoGoal::DoPost() {
return ::Command<CMD_TOWN_CARGO_GOAL>::Post(this->error, this->tile, this->town_id, this->te, this->goal);
}
bool TownSetText::DoPost() {
return ::Command<CMD_TOWN_SET_TEXT>::Post(this->error, this->tile, this->town_id, this->text);
}
bool ExpandTown::DoPost() {
return ::Command<CMD_EXPAND_TOWN>::Post(this->error, this->tile, this->town_id, this->grow_amount);
}
bool DeleteTown::DoPost() {
return ::Command<CMD_DELETE_TOWN>::Post(this->error, this->tile, this->town_id);
}
} // namespace cmd
} // namespace citymania

View File

@@ -1,221 +1,311 @@
// This file is generated by gen_commands.py, do not edit
#ifndef CM_GEN_COMMANDS_HPP
#define CM_GEN_COMMANDS_HPP
#include "../cm_command_type.hpp"
namespace citymania {
namespace cmd {
class MoneyCheat: public Command {
public:
Money amount;
MoneyCheat(Money amount)
:amount{amount} {}
~MoneyCheat() override {}
bool DoPost() override;
};
class ChangeBankBalance: public Command {
public:
Money delta;
CompanyID company;
ExpensesType expenses_type;
ChangeBankBalance(Money delta, CompanyID company, ExpensesType expenses_type)
:delta{delta}, company{company}, expenses_type{expenses_type} {}
~ChangeBankBalance() override {}
bool DoPost() override;
};
class IncreaseLoan: public Command {
public:
LoanCommand cmd;
Money amount;
IncreaseLoan(LoanCommand cmd, Money amount)
:cmd{cmd}, amount{amount} {}
~IncreaseLoan() override {}
bool DoPost() override;
};
class DecreaseLoan: public Command {
public:
LoanCommand cmd;
Money amount;
DecreaseLoan(LoanCommand cmd, Money amount)
:cmd{cmd}, amount{amount} {}
~DecreaseLoan() override {}
bool DoPost() override;
};
class Pause: public Command {
public:
PauseMode mode;
bool pause;
Pause(PauseMode mode, bool pause)
:mode{mode}, pause{pause} {}
~Pause() override {}
bool DoPost() override;
};
class BuildObject: public Command {
public:
ObjectType type;
uint8 view;
BuildObject(ObjectType type, uint8 view)
:type{type}, view{view} {}
~BuildObject() override {}
bool DoPost() override;
};
class BuildObjectArea: public Command {
public:
TileIndex start_tile;
ObjectType type;
uint8 view;
bool diagonal;
BuildObjectArea(TileIndex start_tile, ObjectType type, uint8 view, bool diagonal)
:start_tile{start_tile}, type{type}, view{view}, diagonal{diagonal} {}
~BuildObjectArea() override {}
bool DoPost() override;
};
class ModifyOrder: public Command {
public:
DoCommandFlag flags;
VehicleID veh;
VehicleOrderID sel_ord;
ModifyOrderFlags mof;
uint16 data;
VehicleID veh;
VehicleOrderID sel_ord;
ModifyOrderFlags mof;
uint16 data;
ModifyOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID sel_ord, ModifyOrderFlags mof, uint16 data)
:flags{flags}, veh{veh}, sel_ord{sel_ord}, mof{mof}, data{data} {}
ModifyOrder(VehicleID veh, VehicleOrderID sel_ord, ModifyOrderFlags mof, uint16 data)
:veh{veh}, sel_ord{sel_ord}, mof{mof}, data{data} {}
~ModifyOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class SkipToOrder: public Command {
public:
DoCommandFlag flags;
VehicleID veh_id;
VehicleOrderID sel_ord;
VehicleID veh_id;
VehicleOrderID sel_ord;
SkipToOrder(DoCommandFlag flags, VehicleID veh_id, VehicleOrderID sel_ord)
:flags{flags}, veh_id{veh_id}, sel_ord{sel_ord} {}
SkipToOrder(VehicleID veh_id, VehicleOrderID sel_ord)
:veh_id{veh_id}, sel_ord{sel_ord} {}
~SkipToOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class DeleteOrder: public Command {
public:
DoCommandFlag flags;
VehicleID veh_id;
VehicleOrderID sel_ord;
VehicleID veh_id;
VehicleOrderID sel_ord;
DeleteOrder(DoCommandFlag flags, VehicleID veh_id, VehicleOrderID sel_ord)
:flags{flags}, veh_id{veh_id}, sel_ord{sel_ord} {}
DeleteOrder(VehicleID veh_id, VehicleOrderID sel_ord)
:veh_id{veh_id}, sel_ord{sel_ord} {}
~DeleteOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class InsertOrder: public Command {
public:
DoCommandFlag flags;
VehicleID veh;
VehicleOrderID sel_ord;
const Order & new_order;
VehicleID veh;
VehicleOrderID sel_ord;
const Order &new_order;
InsertOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID sel_ord, const Order & new_order)
:flags{flags}, veh{veh}, sel_ord{sel_ord}, new_order{new_order} {}
InsertOrder(VehicleID veh, VehicleOrderID sel_ord, const Order & new_order)
:veh{veh}, sel_ord{sel_ord}, new_order{new_order} {}
~InsertOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class OrderRefit: public Command {
public:
DoCommandFlag flags;
VehicleID veh;
VehicleOrderID order_number;
CargoID cargo;
VehicleID veh;
VehicleOrderID order_number;
CargoID cargo;
OrderRefit(DoCommandFlag flags, VehicleID veh, VehicleOrderID order_number, CargoID cargo)
:flags{flags}, veh{veh}, order_number{order_number}, cargo{cargo} {}
OrderRefit(VehicleID veh, VehicleOrderID order_number, CargoID cargo)
:veh{veh}, order_number{order_number}, cargo{cargo} {}
~OrderRefit() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class CloneOrder: public Command {
public:
DoCommandFlag flags;
CloneOptions action;
VehicleID veh_dst;
VehicleID veh_src;
CloneOptions action;
VehicleID veh_dst;
VehicleID veh_src;
CloneOrder(DoCommandFlag flags, CloneOptions action, VehicleID veh_dst, VehicleID veh_src)
:flags{flags}, action{action}, veh_dst{veh_dst}, veh_src{veh_src} {}
CloneOrder(CloneOptions action, VehicleID veh_dst, VehicleID veh_src)
:action{action}, veh_dst{veh_dst}, veh_src{veh_src} {}
~CloneOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class MoveOrder: public Command {
public:
DoCommandFlag flags;
VehicleID veh;
VehicleOrderID moving_order;
VehicleOrderID target_order;
VehicleID veh;
VehicleOrderID moving_order;
VehicleOrderID target_order;
MoveOrder(DoCommandFlag flags, VehicleID veh, VehicleOrderID moving_order, VehicleOrderID target_order)
:flags{flags}, veh{veh}, moving_order{moving_order}, target_order{target_order} {}
MoveOrder(VehicleID veh, VehicleOrderID moving_order, VehicleOrderID target_order)
:veh{veh}, moving_order{moving_order}, target_order{target_order} {}
~MoveOrder() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class ClearOrderBackup: public Command {
public:
DoCommandFlag flags;
TileIndex tile;
ClientID user_id;
ClientID user_id;
ClearOrderBackup(DoCommandFlag flags, TileIndex tile, ClientID user_id)
:flags{flags}, tile{tile}, user_id{user_id} {}
ClearOrderBackup(ClientID user_id)
:user_id{user_id} {}
~ClearOrderBackup() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class CreateStoryPage: public Command {
class FoundTown: public Command {
public:
DoCommandFlag flags;
CompanyID company;
const std::string & text;
TownSize size;
bool city;
TownLayout layout;
bool random_location;
uint32 townnameparts;
const std::string &text;
CreateStoryPage(DoCommandFlag flags, CompanyID company, const std::string & text)
:flags{flags}, company{company}, text{text} {}
FoundTown(TownSize size, bool city, TownLayout layout, bool random_location, uint32 townnameparts, const std::string & text)
:size{size}, city{city}, layout{layout}, random_location{random_location}, townnameparts{townnameparts}, text{text} {}
~FoundTown() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class CreateStoryPageElement: public Command {
class RenameTown: public Command {
public:
DoCommandFlag flags;
TileIndex tile;
StoryPageID page_id;
StoryPageElementType type;
uint32 reference;
const std::string & text;
TownID town_id;
const std::string &text;
CreateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageID page_id, StoryPageElementType type, uint32 reference, const std::string & text)
:flags{flags}, tile{tile}, page_id{page_id}, type{type}, reference{reference}, text{text} {}
RenameTown(TownID town_id, const std::string & text)
:town_id{town_id}, text{text} {}
~RenameTown() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class UpdateStoryPageElement: public Command {
class DoTownAction: public Command {
public:
DoCommandFlag flags;
TileIndex tile;
StoryPageElementID page_element_id;
uint32 reference;
const std::string & text;
TownID town_id;
uint8 action;
UpdateStoryPageElement(DoCommandFlag flags, TileIndex tile, StoryPageElementID page_element_id, uint32 reference, const std::string & text)
:flags{flags}, tile{tile}, page_element_id{page_element_id}, reference{reference}, text{text} {}
DoTownAction(TownID town_id, uint8 action)
:town_id{town_id}, action{action} {}
~DoTownAction() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class SetStoryPageTitle: public Command {
class TownGrowthRate: public Command {
public:
DoCommandFlag flags;
StoryPageID page_id;
const std::string & text;
TownID town_id;
uint16 growth_rate;
SetStoryPageTitle(DoCommandFlag flags, StoryPageID page_id, const std::string & text)
:flags{flags}, page_id{page_id}, text{text} {}
TownGrowthRate(TownID town_id, uint16 growth_rate)
:town_id{town_id}, growth_rate{growth_rate} {}
~TownGrowthRate() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class SetStoryPageDate: public Command {
class TownRating: public Command {
public:
DoCommandFlag flags;
StoryPageID page_id;
Date date;
TownID town_id;
CompanyID company_id;
int16 rating;
SetStoryPageDate(DoCommandFlag flags, StoryPageID page_id, Date date)
:flags{flags}, page_id{page_id}, date{date} {}
TownRating(TownID town_id, CompanyID company_id, int16 rating)
:town_id{town_id}, company_id{company_id}, rating{rating} {}
~TownRating() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class ShowStoryPage: public Command {
class TownCargoGoal: public Command {
public:
DoCommandFlag flags;
StoryPageID page_id;
TownID town_id;
TownEffect te;
uint32 goal;
ShowStoryPage(DoCommandFlag flags, StoryPageID page_id)
:flags{flags}, page_id{page_id} {}
TownCargoGoal(TownID town_id, TownEffect te, uint32 goal)
:town_id{town_id}, te{te}, goal{goal} {}
~TownCargoGoal() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class RemoveStoryPage: public Command {
class TownSetText: public Command {
public:
DoCommandFlag flags;
StoryPageID page_id;
TownID town_id;
const std::string &text;
RemoveStoryPage(DoCommandFlag flags, StoryPageID page_id)
:flags{flags}, page_id{page_id} {}
TownSetText(TownID town_id, const std::string & text)
:town_id{town_id}, text{text} {}
~TownSetText() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class RemoveStoryPageElement: public Command {
class ExpandTown: public Command {
public:
DoCommandFlag flags;
StoryPageElementID page_element_id;
TownID town_id;
uint32 grow_amount;
RemoveStoryPageElement(DoCommandFlag flags, StoryPageElementID page_element_id)
:flags{flags}, page_element_id{page_element_id} {}
ExpandTown(TownID town_id, uint32 grow_amount)
:town_id{town_id}, grow_amount{grow_amount} {}
~ExpandTown() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
class StoryPageButton: public Command {
class DeleteTown: public Command {
public:
DoCommandFlag flags;
TileIndex tile;
StoryPageElementID page_element_id;
VehicleID reference;
TownID town_id;
StoryPageButton(DoCommandFlag flags, TileIndex tile, StoryPageElementID page_element_id, VehicleID reference)
:flags{flags}, tile{tile}, page_element_id{page_element_id}, reference{reference} {}
DeleteTown(TownID town_id)
:town_id{town_id} {}
~DeleteTown() override {}
bool Post(bool automatic=False);
bool DoPost() override;
};
} // namaespace cmd
} // namaespace citymania
} // namespace cmd
} // namespace citymania
#endif

View File

@@ -261,7 +261,7 @@ void CommandHelperBase::InternalPostResult(const CommandCost &res, TileIndex til
int x = TileX(tile) * TILE_SIZE;
int y = TileY(tile) * TILE_SIZE;
FIXME if (!(cmd & CMD_NO_ESTIMATE) && my_cmd) citymania::CountEffectiveAction();
// FIXME if (!(cmd & CMD_NO_ESTIMATE) && my_cmd) citymania::CountEffectiveAction();
if (res.Failed()) {
/* Only show the error when it's for us. */
@@ -412,22 +412,7 @@ CommandCost CommandHelperBase::InternalExecuteProcessResult(Commands cmd, Comman
if (c != nullptr) c->last_build_coordinate = tile;
}
FIXME
/* Send Tile Number to Watching Company Windows */
citymania::WatchCompany *wc;
for(int watching_window = 0; ; watching_window++){
wc = dynamic_cast<citymania::WatchCompany*>(FindWindowById(WC_WATCH_COMPANY, watching_window));
if(wc != NULL) wc->OnDoCommand(_current_company, tile);
else break;
}
for (const NetworkClientInfo *ci : NetworkClientInfo::Iterate()) {
if (ci->client_playas == _current_company) {
wc = dynamic_cast<citymania::WatchCompany*>(FindWindowById(WC_WATCH_COMPANYA, ci->client_id));
if (wc != NULL) wc->OnDoCommand(_current_company, tile);
break;
}
}
citymania::UpdateWatching(_current_company, tile);
SubtractMoneyFromCompany(res_exec);

View File

@@ -881,11 +881,13 @@ struct DepotWindow : Window {
*/
bool OnVehicleSelect(const Vehicle *v) override
{
if (_settings_client.gui.cm_open_vehicle_for_shared_clone) { // CM
if (DoCommandP(this->window_number, v->index, citymania::_fn_mod ? 1 : 0, CMD_CLONE_VEHICLE | CMD_MSG(STR_ERROR_CAN_T_BUY_TRAIN + v->type), CcCloneVehicle))
/* CityMania code start */
if (_settings_client.gui.cm_open_vehicle_for_shared_clone) {
if (Command<CMD_CLONE_VEHICLE>::Post(STR_ERROR_CAN_T_BUY_TRAIN + v->type, CcCloneVehicle, this->window_number, v->index, citymania::_fn_mod))
ResetObjectToPlace();
return true;
}
/* CityMania code end */
if (citymania::_fn_mod) {
/* Share-clone, do not open new viewport, and keep tool active */

View File

@@ -372,7 +372,9 @@ struct MainWindow : Window
break;
case GHK_BORROW_ALL:
DoCommandP(0, 0, 1, CMD_INCREASE_LOAN | CMD_MSG(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY));
citymania::cmd::IncreaseLoan(LoanCommand::Max, 0)
.WithError(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY)
.Post();
break;
case GHK_CHAT: // smart chat; send to team if any, otherwise to all

View File

@@ -647,19 +647,19 @@ struct BuildRoadToolbarWindow : Window {
VpSelectTilesWithMethod(pt.x, pt.y, select_method);
}
void TryToRemoveExtraRoadBits(TileIndex tile, RoadBits &rb) {
for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
RoadBits dir_rb = DiagDirToRoadBits(dir);
if (!(rb & dir_rb)) continue;
if (CanConnectToRoad(tile, _cur_roadtype, dir)) continue;
DoCommandP(tile, tile,
(dir_rb == ROAD_NW || dir_rb == ROAD_NE ? 0 : 3) |
(dir_rb & ROAD_X ? 0 : 4) |
(_cur_roadtype << 3),
CMD_REMOVE_LONG_ROAD);
rb &= ~dir_rb;
}
}
// void TryToRemoveExtraRoadBits(TileIndex tile, RoadBits &rb) {
// for (DiagDirection dir = DIAGDIR_BEGIN; dir != DIAGDIR_END; dir++) {
// RoadBits dir_rb = DiagDirToRoadBits(dir);
// if (!(rb & dir_rb)) continue;
// if (CanConnectToRoad(tile, _cur_roadtype, dir)) continue;
// DoCommandP(tile, tile,
// (dir_rb == ROAD_NW || dir_rb == ROAD_NE ? 0 : 3) |
// (dir_rb & ROAD_X ? 0 : 4) |
// (_cur_roadtype << 3),
// CMD_REMOVE_LONG_ROAD);
// rb &= ~dir_rb;
// }
// }
void OnPlaceMouseUp(ViewportPlaceMethod select_method, ViewportDragDropSelectionProcess select_proc, Point pt, TileIndex start_tile, TileIndex end_tile) override
{

View File

@@ -59,6 +59,7 @@
#include "object_type.h"
#include "citymania/cm_cargo_table_gui.hpp"
#include "citymania/cm_commands.hpp"
#include "citymania/cm_commands_gui.hpp"
#include "citymania/cm_locations.hpp"
#include "citymania/cm_main.hpp"
@@ -88,7 +89,7 @@ enum CallBackFunction {
CBF_NONE,
CBF_PLACE_SIGN,
CBF_PLACE_LANDINFO,
CBF_BUILD_HQ,
CM_CBF_BUILD_HQ,
};
static CallBackFunction _last_started_action = CBF_NONE; ///< Last started user action.
@@ -275,13 +276,13 @@ static CallBackFunction SelectSignTool()
/* hq hotkey */
static CallBackFunction BuildCompanyHQ(){
if (_last_started_action == CBF_BUILD_HQ) {
if (_last_started_action == CM_CBF_BUILD_HQ) {
ResetObjectToPlace();
return CBF_NONE;
} else {
SetObjectToPlace(SPR_CURSOR_HQ, PAL_NONE, HT_RECT, WC_MAIN_TOOLBAR, 0, CM_DDSP_BUILD_HQ);
SetTileSelectSize(2, 2);
return CBF_BUILD_HQ;
return CM_CBF_BUILD_HQ;
}
}
@@ -670,13 +671,12 @@ static CallBackFunction MenuClickCompany(int index)
case CTMN_NEW_COMPANY:
if (_network_server) {
DoCommandP(0, CCA_NEW, _network_own_client_id, CMD_COMPANY_CTRL);
Command<CMD_COMPANY_CTRL>::Post(CCA_NEW, INVALID_COMPANY, CRR_NONE, _network_own_client_id);
} else {
NetworkSendCommand(0, CCA_NEW, 0, CMD_COMPANY_CTRL, nullptr, {}, _local_company);
Command<CMD_COMPANY_CTRL>::SendNet(STR_NULL, _local_company, CCA_NEW, INVALID_COMPANY, CRR_NONE, INVALID_CLIENT_ID);
}
return CBF_NONE;
case CTMN_SPECTATE:
if (_network_server) {
NetworkServerDoMove(CLIENT_ID_SERVER, COMPANY_SPECTATOR);
@@ -2167,8 +2167,11 @@ struct MainToolbarWindow : Window {
VpStartPlaceSizing(tile, VPM_X_AND_Y, DDSP_MEASURE);
break;
case CBF_BUILD_HQ:
if(DoCommandP(tile, OBJECT_HQ, 0, CMD_BUILD_OBJECT | CMD_MSG(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS))){
case CM_CBF_BUILD_HQ:
if(citymania::cmd::BuildObject(OBJECT_HQ, 0)
.WithTile(tile)
.WithError(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)
.Post()) {
ResetObjectToPlace();
this->RaiseButtons();
}

View File

@@ -56,6 +56,7 @@
#include "table/strings.h"
#include "table/town_land.h"
#include "citymania/cm_commands.hpp"
#include "citymania/cm_highlight.hpp"
#include "citymania/cm_main.hpp"
@@ -918,11 +919,12 @@ static void DoRegularFunding(Town *t)
if (UINT32_MAX - t->last_funding + _tick_counter < TOWN_GROWTH_TICKS) return;
} else if (_tick_counter - t->last_funding < TOWN_GROWTH_TICKS) return;
CompanyID old = _current_company;
_current_company = _local_company;
DoCommandP(t->xy, t->index, HK_FUND, CMD_DO_TOWN_ACTION | CMD_NO_ESTIMATE);
citymania::cmd::DoTownAction(t->index, HK_FUND)
.WithTile(t->xy)
.SetAuto()
.AsCompany(_local_company)
.Post();
t->last_funding = _tick_counter;
_current_company = old;
}
static void DoRegularAdvertising(Town *t) {
@@ -954,10 +956,11 @@ static void DoRegularAdvertising(Town *t) {
} else if (_tick_counter - t->last_advertisement < 30) return;
t->last_advertisement = _tick_counter;
CompanyID old = _current_company;
_current_company = _local_company;
DoCommandP(t->xy, t->index, HK_LADVERT, CMD_DO_TOWN_ACTION | CMD_NO_ESTIMATE);
_current_company = old;
citymania::cmd::DoTownAction(t->index, HK_LADVERT)
.WithTile(t->xy)
.SetAuto()
.AsCompany(_local_company)
.Post();
}
static void TownTickHandler(Town *t)

View File

@@ -60,7 +60,10 @@ static void DrawExtraTownInfo (const Rect &r, uint &y, Town *town, uint line, bo
bool TownExecuteAction(const Town *town, uint action){
if(!(action == HK_STATUE && HasBit(town->statues, _current_company))){ //don't built statue when there is one
return DoCommandP(town->xy, town->index, action, CMD_DO_TOWN_ACTION | CMD_MSG(STR_ERROR_CAN_T_DO_THIS));
return citymania::cmd::DoTownAction(town->index, action)
.WithTile(town->xy)
.WithError(STR_ERROR_CAN_T_DO_THIS)
.Post();
}
return false;
}

View File

@@ -43,6 +43,7 @@
#include "train_cmd.h"
#include "hotkeys.h"
#include "citymania/cm_commands.hpp"
#include "citymania/cm_hotkeys.hpp"
#include "safeguards.h"
@@ -2647,7 +2648,9 @@ void CcCloneVehicleWithOrderIndex(const CommandCost &result, TileIndex tile, uin
if (!cloned || !cloned->IsPrimaryVehicle()) return;
const Vehicle *v = Vehicle::Get(_new_vehicle_id);
if (cloned->cur_implicit_order_index == v->cur_implicit_order_index) return;
DoCommandP(v->tile, v->index, cloned->cur_implicit_order_index, CMD_SKIP_TO_ORDER);
citymania::cmd::SkipToOrder(v->index, cloned->cur_implicit_order_index)
.WithTile(v->tile)
.Post();
}
/** Window manager class for viewing a vehicle. */