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
+4 -4
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;
};
+30 -16
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;
}
};
+1 -1
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;
}
+5 -5
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;
+70 -59
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)
+2 -2
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
+5
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) {
+2 -2
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
+1 -2
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;
}
+3 -3
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 */
+1 -1
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);
+3 -3
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();
}
+8 -8
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)
+3 -3
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;
}