Fix new station joining

This commit is contained in:
Pavel Stupnikov
2022-12-20 19:46:24 +04:00
parent 4e047eec9b
commit f5f85a47ec
20 changed files with 3408 additions and 700 deletions

View File

@@ -1,3 +1,4 @@
import glob
import re
from pathlib import Path
from pprint import pprint
@@ -5,6 +6,8 @@ from pprint import pprint
RX_COMMAND = re.compile(r'(?P<returns>CommandCost|std::tuple<CommandCost, [^>]*>) (?P<name>Cmd\w*)\((?P<args>[^)]*)\);')
RX_DEF_TRAIT = re.compile(r'DEF_CMD_TRAIT\((?P<constant>\w+),\s+(?P<function>\w+),\s+[^,]*,\s+(?P<category>\w+)\)')
RX_ARG = re.compile(r'(?P<type>(:?const |)[\w:]* &?)(?P<name>\w*)')
RX_CALLBACK = re.compile(r'void\s+(?P<name>Cc\w+)\(Commands')
RX_CALLBACK_REF = re.compile(r'CommandCallback\s+(?P<name>Cc\w+);')
RX_CAMEL_TO_SNAKE = re.compile(r'(?<!^)(?=[A-Z])')
FILES = [
@@ -24,12 +27,23 @@ OUTPUT = BASE_DIR / 'src/citymania/generated/cm_gen_commands'
def parse_commands():
res = []
for f in FILES:
data = open(BASE_DIR / f).read()
includes = []
callbacks = []
for f in glob.glob(str(BASE_DIR / 'src' / '*_cmd.h')):
includes.append(Path(f).name)
data = open(f).read()
traits = {}
for constant, name, category in RX_DEF_TRAIT.findall(data):
traits[name] = constant
traits[name] = constant, category
callbacks.extend(RX_CALLBACK.findall(data))
callbacks.extend(RX_CALLBACK_REF.findall(data))
for returns, name, args_str in RX_COMMAND.findall(data):
trait = traits.get(name)
if not trait:
print(f'Not a command: {name}')
continue
print(f, name, end=' ', flush=True)
constant, category = trait
if returns.startswith('std::tuple'):
ret_type = returns[24: -1]
else:
@@ -39,25 +53,80 @@ def parse_commands():
first_tile_arg = (args[0][0].strip() == 'TileIndex')
if first_tile_arg:
args = args[1:]
print(name, traits[name], args)
print(constant, category, args)
res.append({
'name': name[3:],
'constant': traits[name],
'constant': constant,
'category': category,
'args': args,
'first_tile_arg': first_tile_arg,
'returns': ret_type,
})
return res
return res, includes, callbacks
CPP_TEMPLATES = '''\
inline constexpr size_t _callback_tuple_size = std::tuple_size_v<decltype(_callback_tuple)>;
#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wcast-function-type"
#endif
template <size_t... i>
inline auto MakeCallbackTable(std::index_sequence<i...>) noexcept {
return std::array<CommandCallback *, sizeof...(i)>{{ reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(std::get<i>(_callback_tuple)))... }}; // MingW64 fails linking when casting a pointer to its own type. To work around, cast it to some other type first.
}
/** Type-erased table of callbacks. */
static auto _callback_table = MakeCallbackTable(std::make_index_sequence<_callback_tuple_size>{});\n
template <typename T> struct CallbackArgsHelper;
template <typename... Targs>
struct CallbackArgsHelper<void(*const)(Commands, const CommandCost &, Targs...)> {
using Args = std::tuple<std::decay_t<Targs>...>;
};
#ifdef SILENCE_GCC_FUNCTION_POINTER_CAST
# pragma GCC diagnostic pop
#endif
static size_t FindCallbackIndex(CommandCallback *callback) {
if (auto it = std::find(std::cbegin(_callback_table), std::cend(_callback_table), callback); it != std::cend(_callback_table)) {
return static_cast<size_t>(std::distance(std::cbegin(_callback_table), it));
}
return std::numeric_limits<size_t>::max();
}
template <Commands Tcmd, size_t Tcb, typename... Targs>
bool _DoPost(StringID err_msg, TileIndex tile, Targs... args) {
return ::Command<Tcmd>::Post(err_msg, std::get<Tcb>(_callback_tuple), tile, std::forward<Targs>(args)...);
}
template <Commands Tcmd, size_t Tcb, typename... Targs>
constexpr auto MakeCallback() noexcept {
/* Check if the callback matches with the command arguments. If not, don''t generate an Unpack proc. */
using Tcallback = std::tuple_element_t<Tcb, decltype(_callback_tuple)>;
if constexpr (std::is_same_v<Tcallback, CommandCallback * const> ||
std::is_same_v<Tcallback, CommandCallbackData * const> ||
std::is_same_v<typename CommandTraits<Tcmd>::CbArgs, typename CallbackArgsHelper<Tcallback>::Args> ||
(!std::is_void_v<typename CommandTraits<Tcmd>::RetTypes> && std::is_same_v<typename CallbackArgsHelper<typename CommandTraits<Tcmd>::RetCallbackProc const>::Args, typename CallbackArgsHelper<Tcallback>::Args>)) {
return &_DoPost<Tcmd, Tcb, Targs...>;
} else {
return nullptr;
}
}
'''
def run():
commands = parse_commands()
commands, includes, callbacks = parse_commands()
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'
)
for i in includes:
f.write(f'#include "../../{i}"\n')
f.write('\n')
f.write(
'namespace citymania {\n'
'namespace cmd {\n\n'
)
@@ -71,21 +140,26 @@ def run():
)
for at, an in cmd['args']:
f.write(f' {at}{an};\n')
f.write(
f'\n'
f' {name}({args_list})\n'
f' :{args_init} {{}}\n'
)
if cmd.get('first_tile_arg'):
f.write(f'\n')
if args_init:
f.write(
f' {name}(TileIndex tile, {args_list})\n'
f' :Command{{tile}}, {args_init} {{}}\n'
f' {name}({args_list})\n'
f' :{args_init} {{}}\n'
)
else:
f.write(f' {name}({args_list}) {{}}\n')
if cmd.get('first_tile_arg'):
separator = ', ' if args_list else ''
f.write(
f' {name}(TileIndex tile{separator}{args_list})\n'
f' :Command{{tile}}{separator}{args_init} {{}}\n'
)
f.write(
f' ~{name}() override {{}}\n'
f'\n'
f' bool DoPost() override;\n'
f' bool DoTest() override;\n'
f' bool do_post(CommandCallback * callback) override;\n'
f' bool do_test() override;\n'
f'}};\n\n'
)
f.write(
@@ -106,24 +180,51 @@ def run():
'namespace citymania {\n'
'namespace cmd {\n\n'
)
f.write(
'/*\n'
' * The code is mostly copied from network_command.cpp\n'
' * but the table is not the same.\n'
' */\n'
'static constexpr auto _callback_tuple = std::make_tuple(\n'
' (CommandCallback *)nullptr, // Make sure this is actually a pointer-to-function.\n'
)
for i, cb in enumerate(callbacks):
comma = ',' if i != len(callbacks) - 1 else ''
f.write(f' &{cb}{comma}\n')
f.write(');\n\n')
f.write(CPP_TEMPLATES)
for cmd in commands:
name = cmd['name']
constant = cmd['constant']
# constant = 'CMD_' + RX_CAMEL_TO_SNAKE.sub('_', name).upper()
args_list = ', '.join(f'this->{an}' for _, an in cmd['args'])
this_args_list = ', '.join(f'this->{an}' for _, an in cmd['args'])
args_list = ', '.join(f'{an}' for _, an in cmd['args'])
args_type_list = ', '.join(f'{at}' for at, an in cmd['args'])
test_args_list = args_list
if cmd.get('first_tile_arg'):
test_args_list = f'this->tile, ' + args_list
if args_list:
test_args_list = f'this->tile, ' + args_list
else:
test_args_list = f'this->tile'
cost_getter = '' if cmd['returns'] is None else 'std::get<0>'
sep_args_list = sep_args_type_list = sep_this_args_list = ''
if args_list:
sep_args_list = ', ' + args_list
sep_args_type_list = ', ' + args_type_list
sep_this_args_list = ', ' + this_args_list
f.write(
f'bool {name}::DoPost() {{\n'
f' return ::Command<{constant}>::Post(this->error, this->tile, {args_list});\n'
f''
'template <typename T, T... i, size_t... j>\n'
f'inline constexpr auto MakeDispatchTable{name}(std::index_sequence<i...>) noexcept\n'
'{\n'
f' return std::array<bool (*)(StringID err_msg, TileIndex tile{sep_args_type_list}), sizeof...(i)>{{MakeCallback<{constant}, i{sep_args_type_list}>()... }};\n'
'}\n'
)
f.write(
f'bool {name}::DoTest() {{\n'
f'static constexpr auto _{name}_dispatch = MakeDispatchTable{name}(std::make_index_sequence<_callback_tuple_size>{{}});\n'
f'bool {name}::do_post(CommandCallback *callback) {{\n'
f' return _{name}_dispatch[FindCallbackIndex(callback)](this->error, this->tile{sep_this_args_list});\n'
'}\n'
f'bool {name}::do_test() {{\n'
f' return {cost_getter}(::Command<{constant}>::Do(DC_NONE, {test_args_list})).Succeeded();\n'
'}\n'
)

View File

@@ -7,6 +7,8 @@ gen = grf.NewGRF(
grfid=b'CMAL',
name='CityMania Alpine Landscape',
description='Modified OpenGFX sprites for alpine climate.',
version=2,
min_compatible_version=0,
)
@@ -352,8 +354,9 @@ for i in range(81):
gen.add(layout := grf.AdvancedSpriteLayout(
feature=grf.OBJECT,
ground={
'sprite': grf.SpriteRef(4550, is_global=True),
'sprite': grf.SpriteRef(0, is_global=True),
'flags': 2,
'add': grf.Temp(1),
},
buildings=[{
'sprite': grf.SpriteRef(i, is_global=False),
@@ -363,7 +366,6 @@ for i in range(81):
))
gen.add(layout_switch := grf.Switch(
feature=grf.OBJECT,
ranges={0: layout},
default=layout,
code=f'''

View File

@@ -3,6 +3,7 @@ import numpy as np
import math
import os
import random
import spectra
import grf
@@ -305,6 +306,10 @@ for i in range (81):
# if not inp:
# continue
for ii in inp:
for oo in outp:
xy = ((edges[ii][0] + xx, edges[ii][1] + yy), (edges[oo][0] + xx, edges[oo][1] + yy))
draw_bezier(imd2, 0x38, 5, xy[0], center, xy[1])
for ii in inp:
for oo in outp:
xy = ((edges[ii][0] + xx, edges[ii][1] + yy), (edges[oo][0] + xx, edges[oo][1] + yy))
@@ -340,4 +345,14 @@ for i in range (81):
# dout[oy + y + 64 * i, ox + x] = find_best_color(c)
# im2 = Image.fromarray(dout)
# im2.putpalette(im.getpalette())
#
px = im2.load()
for y in range(im2.height):
for x in range(im2.width):
if px[x, y] == 0xF5:
px[x, y] = random.randint(0xF5, 0xF9)
elif px[x, y] == 0x42:
px[x, y] = random.randint(0x10, 0x14)
elif px[x, y] == 0x38:
px[x, y] = random.randint(0x19, 0x1e)
im2.save(os.path.join(DEST_DIR, "rivers.png"))

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 515 KiB

View File

@@ -215,14 +215,14 @@ std::multimap<TileIndex, ObjectTileHighlight> Blueprint::GetTiles(TileIndex tile
std::set<StationID> can_build_station_sign;
for (auto &item: this->items) {
if (item.type != Item::Type::RAIL_STATION) continue;
if (GetBlueprintCommand(tile, item)->Test())
if (GetBlueprintCommand(tile, item)->test())
can_build_station_sign.insert(item.u.rail.station.id);
}
for (auto &o: this->items) {
auto otile = AddTileIndexDiffCWrap(tile, o.tdiff);
auto palette = CM_PALETTE_TINT_WHITE;
if (o.type != Item::Type::RAIL_SIGNAL && !GetBlueprintCommand(tile, o)->Test())
if (o.type != Item::Type::RAIL_SIGNAL && !GetBlueprintCommand(tile, o)->test())
palette = CM_PALETTE_TINT_RED_DEEP;
switch(o.type) {
@@ -600,7 +600,7 @@ void BuildBlueprint(sp<Blueprint> &blueprint, TileIndex start) {
case Blueprint::Item::Type::RAIL_TUNNEL:
case Blueprint::Item::Type::RAIL_BRIDGE: {
auto cc = GetBlueprintCommand(start, item);
cc->Post();
cc->post();
if (item.type == Blueprint::Item::Type::RAIL_TRACK) last_rail = std::move(cc);
break;
}
@@ -634,7 +634,7 @@ void BuildBlueprint(sp<Blueprint> &blueprint, TileIndex start) {
for (auto &item : blueprint->items) {
if (item.type != Blueprint::Item::Type::RAIL_SIGNAL) continue;
auto cc = GetBlueprintCommand(start, item);
cc->Post();
cc->post();
}
return true;
};

View File

@@ -3,13 +3,21 @@
#include "../bridge.h"
#include "../command_func.h"
#include "../depot_type.h"
#include "../goal_type.h"
#include "../group_cmd.h"
#include "../engine_type.h"
#include "../livery.h"
#include "../misc_cmd.h"
#include "../news_type.h"
#include "../object_type.h"
#include "../order_type.h"
#include "../road_type.h"
#include "../road_type.h"
#include "../station_type.h"
#include "../story_type.h"
#include "../track_type.h"
#include "../vehiclelist.h"
enum StationClassID : byte;
@@ -19,50 +27,56 @@ class Command {
public:
TileIndex tile = 0;
bool automatic = false;
CompanyID as_company = INVALID_COMPANY;
CompanyID company = INVALID_COMPANY;
StringID error = (StringID)0;
Command() {}
Command(TileIndex tile) :tile{tile} {}
virtual ~Command() {}
virtual bool DoPost()=0;
virtual bool DoTest()=0;
bool Post() {
virtual bool do_post(CommandCallback *callback)=0;
virtual bool do_test()=0;
template <typename Tcallback>
bool post(Tcallback callback) {
CompanyID old = _current_company;
if (this->as_company != INVALID_COMPANY)
_current_company = as_company;
bool res = this->DoPost();
if (this->company != INVALID_COMPANY)
_current_company = company;
bool res = this->do_post(reinterpret_cast<CommandCallback *>(reinterpret_cast<void(*)()>(callback)));
_current_company = old;
return res;
}
bool Test() {
bool post() {
return this->post<CommandCallback *>(nullptr);
}
bool test() {
CompanyID old = _current_company;
if (this->as_company != INVALID_COMPANY)
_current_company = as_company;
bool res = this->DoTest();
if (this->company != INVALID_COMPANY)
_current_company = company;
bool res = this->do_test();
_current_company = old;
return res;
}
Command &WithTile(TileIndex tile) {
Command &with_tile(TileIndex tile) {
this->tile = tile;
return *this;
}
Command &WithError(StringID error) {
Command &with_error(StringID error) {
this->error = error;
return *this;
}
Command &SetAuto() {
Command &set_auto() {
this->automatic = true;
return *this;
}
Command &AsCompany(CompanyID company) {
this->as_company = company;
Command &as_company(CompanyID company) {
this->company = company;
return *this;
}
};

View File

@@ -55,7 +55,7 @@ bool ConStep(byte argc, char *argv[]) {
auto n = (argc > 1 ? atoi(argv[1]) : 1);
// FIXME (n << 1)
cmd::Pause(PM_PAUSED_NORMAL, 0).Post();
cmd::Pause(PM_PAUSED_NORMAL, 0).post();
return true;
}

View File

@@ -329,7 +329,7 @@ void ObjectHighlight::UpdateTiles() {
this->tile,
_cur_railtype,
dir
).Test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
).test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
this->tiles.insert(std::make_pair(this->tile, ObjectTileHighlight::make_rail_depot(palette, dir)));
auto tile = this->tile + TileOffsByDiagDir(dir);
@@ -356,7 +356,7 @@ void ObjectHighlight::UpdateTiles() {
_railstation.station_type,
NEW_STATION,
true
).Test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
).test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
auto layout_ptr = AllocaM(byte, (int)numtracks * plat_len);
GetStationLayout(layout_ptr, numtracks, plat_len, nullptr); // TODO statspec
@@ -388,7 +388,7 @@ void ObjectHighlight::UpdateTiles() {
this->roadtype,
NEW_STATION,
true
).Test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
).test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
for (TileIndex tile : ta) {
this->AddTile(tile, ObjectTileHighlight::make_road_stop(palette, this->roadtype, this->ddir, this->is_truck));
}
@@ -400,7 +400,7 @@ void ObjectHighlight::UpdateTiles() {
this->tile,
this->roadtype,
this->ddir
).Test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
).test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
this->AddTile(this->tile, ObjectTileHighlight::make_road_depot(palette, this->roadtype, this->ddir));
break;
}
@@ -412,7 +412,7 @@ void ObjectHighlight::UpdateTiles() {
this->airport_layout,
NEW_STATION,
true
).Test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
).test() ? CM_PALETTE_TINT_WHITE : CM_PALETTE_TINT_RED_DEEP);
const AirportSpec *as = AirportSpec::Get(this->airport_type);
if (!as->IsAvailable() || this->airport_layout >= as->num_table) break;

View File

@@ -3,6 +3,7 @@
#include "cm_station_gui.hpp"
#include "cm_hotkeys.hpp"
#include "cm_commands.hpp"
#include "../core/math_func.hpp"
#include "../command_type.h"
@@ -189,7 +190,6 @@ const Station *CheckClickOnDeadStationSign() {
}
bool CheckStationJoin(TileIndex start_tile, TileIndex end_tile) {
// if (_ctrl_pressed && start_tile == end_tile) {
if (citymania::_fn_mod) {
if (IsTileType (start_tile, MP_STATION)) {
citymania::SelectStationToJoin(Station::GetByTile(start_tile));
@@ -204,18 +204,19 @@ bool CheckStationJoin(TileIndex start_tile, TileIndex end_tile) {
return false;
}
using JoinAndBuildCmdProc = std::function<bool(bool test, StationID to_join, bool adjacent)>;
// using JoinAndBuildCmdProc = std::function<bool(bool test, StationID to_join, bool adjacent)>;
void JoinAndBuild(JoinAndBuildCmdProc proc) {
template <typename Tcommand, typename Tcallback>
void JoinAndBuild(Tcommand command, Tcallback *callback) {
auto join_to = _highlight_station_to_join;
bool adjacent = (citymania::_fn_mod || join_to);
StationID to_join = INVALID_STATION;
command.adjacent = (citymania::_fn_mod || join_to);
command.station_to_join = INVALID_STATION;
if (citymania::_fn_mod) to_join = NEW_STATION;
else if (join_to) to_join = join_to->index;
if (citymania::_fn_mod) command.station_to_join = NEW_STATION;
else if (join_to) command.station_to_join = join_to->index;
//FIXME _last_station_bulid_cmd = cmdcont;
proc(false, to_join, adjacent);
command.post(callback);
}
static DiagDirection TileFractCoordsToDiagDir(Point pt) {
@@ -341,24 +342,30 @@ DiagDirection AutodetectDriveThroughRoadStopDirection(TileArea area, Point pt, R
return DiagDirToAxis(AutodetectRoadObjectDirection(area.tile, pt, roadtype)) == AXIS_X ? STATIONDIR_X : STATIONDIR_Y;
}
void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, uint32 cmd) {
void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, RoadStopType stop_type, bool adjacent, RoadType rt, StringID err_msg) {
assert(_thd.cm.type == citymania::ObjectHighlight::Type::ROAD_STOP);
uint8 ddir = _thd.cm.ddir;
DiagDirection ddir = _thd.cm.ddir;
SB(p2, 16, 16, INVALID_STATION); // no station to join
TileArea ta(start_tile, end_tile);
if (CheckStationJoin(start_tile, end_tile)) return;
if (ddir >= DIAGDIR_END) { // drive-through stops
SetBit(p2, 1);
ddir -= DIAGDIR_END;
}
p2 |= ddir << 3; // Set the DiagDirecion into p2 bits 3 and 4.
bool drive_through = (ddir >= DIAGDIR_END);
if (drive_through) ddir = static_cast<DiagDirection>(ddir - DIAGDIR_END); // Adjust picker result to actual direction.
// FIXME
// CommandContainer cmdcont = { ta.tile, (uint32)(ta.w | ta.h << 8), p2, cmd, CcRoadStop, "" };
// JoinAndBuild(cmdcont);
auto c = cmd::BuildRoadStop(
ta.tile,
ta.w,
ta.h,
stop_type,
drive_through,
static_cast<DiagDirection>(ddir),
rt,
INVALID_STATION,
adjacent
);
c.with_error(err_msg);
JoinAndBuild(c, CcRoadStop);
}
void HandleStationPlacement(TileIndex start, TileIndex end)
@@ -371,47 +378,51 @@ void HandleStationPlacement(TileIndex start, TileIndex end)
if (_railstation.orientation == AXIS_X) Swap(numtracks, platlength);
uint32 p1 = _cur_railtype | _railstation.orientation << 6 | numtracks << 8 | platlength << 16 | (citymania::_fn_mod ? 1 << 24 : 0);
uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16;
// FIXME
// CommandContainer cmdcont = { ta.tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" };
// JoinAndBuild(cmdcont);
auto c = cmd::BuildRailStation(
ta.tile,
_cur_railtype,
_railstation.orientation,
numtracks,
platlength,
_railstation.station_class,
_railstation.station_type,
INVALID_STATION,
false
);
c.with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
JoinAndBuild(c, CcStation);
}
void PlaceRail_Station(TileIndex tile) {
if (CheckStationJoin(tile, tile)) return;
uint32 p1 = _cur_railtype | _railstation.orientation << 6 | _settings_client.gui.station_numtracks << 8 | _settings_client.gui.station_platlength << 16 | (citymania::_fn_mod ? 1 << 24 : 0);
uint32 p2 = _railstation.station_class | _railstation.station_type << 8 | INVALID_STATION << 16;
int w = _settings_client.gui.station_numtracks;
int h = _settings_client.gui.station_platlength;
if (!_railstation.orientation) Swap(w, h);
// FIXME
// CommandContainer cmdcont = { tile, p1, p2, CMD_BUILD_RAIL_STATION | CMD_MSG(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION), CcStation, "" };
// JoinAndBuild(cmdcont);
auto c = cmd::BuildRailStation(
tile,
_cur_railtype,
_railstation.orientation,
_settings_client.gui.station_numtracks,
_settings_client.gui.station_platlength,
_railstation.station_class,
_railstation.station_type,
INVALID_STATION,
false
);
c.with_error(STR_ERROR_CAN_T_BUILD_RAILROAD_STATION);
JoinAndBuild(c, CcStation);
}
void PlaceDock(TileIndex tile) {
if (CheckStationJoin(tile, tile)) return;
void PlaceDock(TileIndex tile, TileIndex tile_to) {
if (CheckStationJoin(tile, tile_to)) return;
uint32 p2 = (uint32)INVALID_STATION << 16; // no station to join
/* tile is always the land tile, so need to evaluate _thd.pos */
// CommandContainer cmdcont = { tile, citymania::_fn_mod, p2, CMD_BUILD_DOCK | CMD_MSG(STR_ERROR_CAN_T_BUILD_DOCK_HERE), CcBuildDocks, "" };
/* Determine the watery part of the dock. */
// DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
// TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile);
// FIXME
// JoinAndBuild(cmdcont);
auto c = cmd::BuildDock(
tile,
INVALID_STATION,
false
);
c.with_error(STR_ERROR_CAN_T_BUILD_DOCK_HERE);
JoinAndBuild(c, CcBuildDocks);
}
void PlaceAirport(TileIndex tile) {
// FIXME
if (CheckStationJoin(tile, tile)) return;
if (_selected_airport_index == -1) return;
@@ -419,15 +430,15 @@ void PlaceAirport(TileIndex tile) {
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);
}
};
// FIXME JoinAndBuild(cmdcont);
auto c = cmd::BuildAirport(
tile,
airport_type,
layout,
INVALID_STATION,
false
);
c.with_error(STR_ERROR_CAN_T_BUILD_AIRPORT_HERE);
JoinAndBuild(c, CcBuildAirport);
}
static void FindStationsAroundSelection(const TileArea &location)

View File

@@ -27,10 +27,10 @@ enum class StationBuildingStatus {
bool UseImprovedStationJoin();
void OnStationTileSetChange(const Station *station, bool adding, StationType type);
void OnStationPartBuilt(const Station *station, TileIndex tile, uint32 p1, uint32 p2);
void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, uint32 p2, uint32 cmd);
void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, RoadStopType stop_type, bool adjacent, RoadType rt, StringID err_msg);
void HandleStationPlacement(TileIndex start, TileIndex end);
void PlaceRail_Station(TileIndex tile);
void PlaceDock(TileIndex tile);
void PlaceDock(TileIndex tile, TileIndex tile_to);
void PlaceAirport(TileIndex tile);
void SelectStationToJoin(const Station *station);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -217,6 +217,11 @@ struct BuildDocksToolbarWindow : Window {
DiagDirection dir = GetInclinedSlopeDirection(GetTileSlope(tile));
TileIndex tile_to = (dir != INVALID_DIAGDIR ? TileAddByDiagDir(tile, ReverseDiagDir(dir)) : tile);
if (citymania::UseImprovedStationJoin()) {
citymania::PlaceDock(tile, tile_to);
break;
}
bool adjacent = _ctrl_pressed;
auto proc = [=](bool test, StationID to_join) -> bool {
if (test) {

View File

@@ -375,8 +375,8 @@ struct MainWindow : Window
case GHK_BORROW_ALL:
citymania::cmd::IncreaseLoan(LoanCommand::Max, 0)
.WithError(STR_ERROR_CAN_T_BORROW_ANY_MORE_MONEY)
.Post();
.with_error(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

@@ -170,8 +170,7 @@ void CcRoadStop(Commands cmd, const CommandCost &result, TileIndex tile, uint8 w
static void PlaceRoadStop(TileIndex start_tile, TileIndex end_tile, RoadStopType stop_type, bool adjacent, RoadType rt, StringID err_msg)
{
if (citymania::UseImprovedStationJoin()) {
// FIXME
// citymania::PlaceRoadStop(start_tile, end_tile, stop_type, adjacent, rt, err_msg);
citymania::PlaceRoadStop(start_tile, end_tile, stop_type, adjacent, rt, err_msg);
return;
}

View File

@@ -2213,10 +2213,10 @@ void UpdateAirportsNoise()
* @param airport_type airport type, @see airport.h
* @param layout airport layout
* @param station_to_join station ID to join (NEW_STATION if build new one)
* @param allow_adjacent allow airports directly adjacent to other airports.
* @param adjacent allow airports directly adjacent to other airports.
* @return the cost of this operation or an error
*/
CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool allow_adjacent)
CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool adjacent)
{
bool reuse = (station_to_join != NEW_STATION);
if (!reuse) station_to_join = INVALID_STATION;
@@ -2281,7 +2281,7 @@ CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_ty
}
Station *st = nullptr;
ret = FindJoiningStation(INVALID_STATION, station_to_join, allow_adjacent, airport_area, &st);
ret = FindJoiningStation(INVALID_STATION, station_to_join, adjacent, airport_area, &st);
if (ret.Failed()) return ret;
/* Distant join */

View File

@@ -15,7 +15,7 @@
enum StationClassID : byte;
CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool allow_adjacent);
CommandCost CmdBuildAirport(DoCommandFlag flags, TileIndex tile, byte airport_type, byte layout, StationID station_to_join, bool adjacent);
CommandCost CmdBuildDock(DoCommandFlag flags, TileIndex tile, StationID station_to_join, bool adjacent);
CommandCost CmdBuildRailStation(DoCommandFlag flags, TileIndex tile_org, RailType rt, Axis axis, byte numtracks, byte plat_len, StationClassID spec_class, byte spec_index, StationID station_to_join, bool adjacent);
CommandCost CmdRemoveFromRailStation(DoCommandFlag flags, TileIndex start, TileIndex end, bool keep_rail);

View File

@@ -2170,9 +2170,9 @@ struct MainToolbarWindow : Window {
case CM_CBF_BUILD_HQ:
if(citymania::cmd::BuildObject(OBJECT_HQ, 0)
.WithTile(tile)
.WithError(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)
.Post()) {
.with_tile(tile)
.with_error(STR_ERROR_CAN_T_BUILD_COMPANY_HEADQUARTERS)
.post()) {
ResetObjectToPlace();
this->RaiseButtons();
}

View File

@@ -920,10 +920,10 @@ static void DoRegularFunding(Town *t)
} else if (_tick_counter - t->last_funding < TOWN_GROWTH_TICKS) return;
citymania::cmd::DoTownAction(t->index, HK_FUND)
.WithTile(t->xy)
.SetAuto()
.AsCompany(_local_company)
.Post();
.with_tile(t->xy)
.set_auto()
.as_company(_local_company)
.post();
t->last_funding = _tick_counter;
}
@@ -957,10 +957,10 @@ static void DoRegularAdvertising(Town *t) {
t->last_advertisement = _tick_counter;
citymania::cmd::DoTownAction(t->index, HK_LADVERT)
.WithTile(t->xy)
.SetAuto()
.AsCompany(_local_company)
.Post();
.with_tile(t->xy)
.set_auto()
.as_company(_local_company)
.post();
}
static void TownTickHandler(Town *t)

View File

@@ -62,9 +62,9 @@ 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 citymania::cmd::DoTownAction(town->index, action)
.WithTile(town->xy)
.WithError(STR_ERROR_CAN_T_DO_THIS)
.Post();
.with_tile(town->xy)
.with_error(STR_ERROR_CAN_T_DO_THIS)
.post();
}
return false;
}