Feature: House placer mode to replace existing houses (#14469)
This commit is contained in:
@@ -5,7 +5,7 @@ from pathlib import Path
|
|||||||
from pprint import pprint
|
from pprint import pprint
|
||||||
|
|
||||||
RX_COMMAND = re.compile(r'(?P<returns>CommandCost|std::tuple<CommandCost, [^>]*>) (?P<name>Cmd\w*)\((?P<args>[^)]*)\);')
|
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+(?P<flags>[^,()]+(?:\([^)]+\))?),\s+(?P<category>\w+)\)')
|
RX_DEF_TRAIT = re.compile(r'DEF_CMD_TRAIT\((?P<constant>\w+),\s+(?P<function>\w+),\s+(?P<flags>[^,()]+(?:\([^)]+\))?),\s+(?P<category>[\w:]+)\)')
|
||||||
RX_ARG = re.compile(r'(?P<type>(:?const |)[\w:]* &?)(?P<name>\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 = re.compile(r'void\s+(?P<name>Cc\w+)\(Commands')
|
||||||
RX_CALLBACK_REF = re.compile(r'CommandCallback(?:Data|)\s+(?P<name>Cc\w+);')
|
RX_CALLBACK_REF = re.compile(r'CommandCallback(?:Data|)\s+(?P<name>Cc\w+);')
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ static constexpr auto _callback_tuple = std::make_tuple(
|
|||||||
(::CommandCallback *)nullptr, // Make sure this is actually a pointer-to-function.
|
(::CommandCallback *)nullptr, // Make sure this is actually a pointer-to-function.
|
||||||
&CcBuildDocks,
|
&CcBuildDocks,
|
||||||
&CcPlaySound_CONSTRUCTION_WATER,
|
&CcPlaySound_CONSTRUCTION_WATER,
|
||||||
|
&CcMoveWaypointName,
|
||||||
|
&CcMoveStationName,
|
||||||
&CcRoadDepot,
|
&CcRoadDepot,
|
||||||
&CcRoadStop,
|
&CcRoadStop,
|
||||||
&CcPlaySound_CONSTRUCTION_OTHER,
|
&CcPlaySound_CONSTRUCTION_OTHER,
|
||||||
@@ -242,6 +244,15 @@ CommandCost RenameWaypoint::_do(DoCommandFlags flags) {
|
|||||||
return (::Command<CMD_RENAME_WAYPOINT>::Do(flags, waypoint_id, text));
|
return (::Command<CMD_RENAME_WAYPOINT>::Do(flags, waypoint_id, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Commands MoveWaypointName::get_command() { return CMD_MOVE_WAYPOINT_NAME; }
|
||||||
|
static constexpr auto _MoveWaypointName_dispatch = MakeDispatchTable<CMD_MOVE_WAYPOINT_NAME, StationID, TileIndex>();
|
||||||
|
bool MoveWaypointName::_post(::CommandCallback *callback) {
|
||||||
|
return _MoveWaypointName_dispatch[FindCallbackIndex(callback)](this->error, this->waypoint_id, this->tile);
|
||||||
|
}
|
||||||
|
CommandCost MoveWaypointName::_do(DoCommandFlags flags) {
|
||||||
|
return std::get<0>(::Command<CMD_MOVE_WAYPOINT_NAME>::Do(flags, waypoint_id, tile));
|
||||||
|
}
|
||||||
|
|
||||||
Commands BuildAirport::get_command() { return CMD_BUILD_AIRPORT; }
|
Commands BuildAirport::get_command() { return CMD_BUILD_AIRPORT; }
|
||||||
static constexpr auto _BuildAirport_dispatch = MakeDispatchTable<CMD_BUILD_AIRPORT, TileIndex, uint8_t, uint8_t, StationID, bool>();
|
static constexpr auto _BuildAirport_dispatch = MakeDispatchTable<CMD_BUILD_AIRPORT, TileIndex, uint8_t, uint8_t, StationID, bool>();
|
||||||
bool BuildAirport::_post(::CommandCallback *callback) {
|
bool BuildAirport::_post(::CommandCallback *callback) {
|
||||||
@@ -305,6 +316,15 @@ CommandCost RenameStation::_do(DoCommandFlags flags) {
|
|||||||
return (::Command<CMD_RENAME_STATION>::Do(flags, station_id, text));
|
return (::Command<CMD_RENAME_STATION>::Do(flags, station_id, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Commands MoveStationName::get_command() { return CMD_MOVE_STATION_NAME; }
|
||||||
|
static constexpr auto _MoveStationName_dispatch = MakeDispatchTable<CMD_MOVE_STATION_NAME, StationID, TileIndex>();
|
||||||
|
bool MoveStationName::_post(::CommandCallback *callback) {
|
||||||
|
return _MoveStationName_dispatch[FindCallbackIndex(callback)](this->error, this->station_id, this->tile);
|
||||||
|
}
|
||||||
|
CommandCost MoveStationName::_do(DoCommandFlags flags) {
|
||||||
|
return std::get<0>(::Command<CMD_MOVE_STATION_NAME>::Do(flags, station_id, tile));
|
||||||
|
}
|
||||||
|
|
||||||
Commands OpenCloseAirport::get_command() { return CMD_OPEN_CLOSE_AIRPORT; }
|
Commands OpenCloseAirport::get_command() { return CMD_OPEN_CLOSE_AIRPORT; }
|
||||||
static constexpr auto _OpenCloseAirport_dispatch = MakeDispatchTable<CMD_OPEN_CLOSE_AIRPORT, StationID>();
|
static constexpr auto _OpenCloseAirport_dispatch = MakeDispatchTable<CMD_OPEN_CLOSE_AIRPORT, StationID>();
|
||||||
bool OpenCloseAirport::_post(::CommandCallback *callback) {
|
bool OpenCloseAirport::_post(::CommandCallback *callback) {
|
||||||
@@ -692,6 +712,15 @@ CommandCost RenameSign::_do(DoCommandFlags flags) {
|
|||||||
return (::Command<CMD_RENAME_SIGN>::Do(flags, sign_id, text));
|
return (::Command<CMD_RENAME_SIGN>::Do(flags, sign_id, text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Commands MoveSign::get_command() { return CMD_MOVE_SIGN; }
|
||||||
|
static constexpr auto _MoveSign_dispatch = MakeDispatchTable<CMD_MOVE_SIGN, SignID, TileIndex>();
|
||||||
|
bool MoveSign::_post(::CommandCallback *callback) {
|
||||||
|
return _MoveSign_dispatch[FindCallbackIndex(callback)](this->error, this->sign_id, this->tile);
|
||||||
|
}
|
||||||
|
CommandCost MoveSign::_do(DoCommandFlags flags) {
|
||||||
|
return (::Command<CMD_MOVE_SIGN>::Do(flags, sign_id, tile));
|
||||||
|
}
|
||||||
|
|
||||||
Commands BuildVehicle::get_command() { return CMD_BUILD_VEHICLE; }
|
Commands BuildVehicle::get_command() { return CMD_BUILD_VEHICLE; }
|
||||||
static constexpr auto _BuildVehicle_dispatch = MakeDispatchTable<CMD_BUILD_VEHICLE, TileIndex, EngineID, bool, CargoType, ClientID>();
|
static constexpr auto _BuildVehicle_dispatch = MakeDispatchTable<CMD_BUILD_VEHICLE, TileIndex, EngineID, bool, CargoType, ClientID>();
|
||||||
bool BuildVehicle::_post(::CommandCallback *callback) {
|
bool BuildVehicle::_post(::CommandCallback *callback) {
|
||||||
@@ -1071,12 +1100,12 @@ CommandCost DeleteTown::_do(DoCommandFlags flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Commands PlaceHouse::get_command() { return CMD_PLACE_HOUSE; }
|
Commands PlaceHouse::get_command() { return CMD_PLACE_HOUSE; }
|
||||||
static constexpr auto _PlaceHouse_dispatch = MakeDispatchTable<CMD_PLACE_HOUSE, TileIndex, HouseID, bool>();
|
static constexpr auto _PlaceHouse_dispatch = MakeDispatchTable<CMD_PLACE_HOUSE, TileIndex, HouseID, bool, bool>();
|
||||||
bool PlaceHouse::_post(::CommandCallback *callback) {
|
bool PlaceHouse::_post(::CommandCallback *callback) {
|
||||||
return _PlaceHouse_dispatch[FindCallbackIndex(callback)](this->error, this->tile, this->house, this->house_protected);
|
return _PlaceHouse_dispatch[FindCallbackIndex(callback)](this->error, this->tile, this->house, this->house_protected, this->replace);
|
||||||
}
|
}
|
||||||
CommandCost PlaceHouse::_do(DoCommandFlags flags) {
|
CommandCost PlaceHouse::_do(DoCommandFlags flags) {
|
||||||
return (::Command<CMD_PLACE_HOUSE>::Do(flags, tile, house, house_protected));
|
return (::Command<CMD_PLACE_HOUSE>::Do(flags, tile, house, house_protected, replace));
|
||||||
}
|
}
|
||||||
|
|
||||||
Commands TurnRoadVeh::get_command() { return CMD_TURN_ROADVEH; }
|
Commands TurnRoadVeh::get_command() { return CMD_TURN_ROADVEH; }
|
||||||
|
|||||||
@@ -271,6 +271,20 @@ public:
|
|||||||
Commands get_command() override;
|
Commands get_command() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MoveWaypointName: public Command {
|
||||||
|
public:
|
||||||
|
StationID waypoint_id;
|
||||||
|
TileIndex tile;
|
||||||
|
|
||||||
|
MoveWaypointName(StationID waypoint_id, TileIndex tile)
|
||||||
|
:waypoint_id{waypoint_id}, tile{tile} {}
|
||||||
|
~MoveWaypointName() override {}
|
||||||
|
|
||||||
|
bool _post(::CommandCallback * callback) override;
|
||||||
|
CommandCost _do(DoCommandFlags flags) override;
|
||||||
|
Commands get_command() override;
|
||||||
|
};
|
||||||
|
|
||||||
class BuildAirport: public StationBuildCommand {
|
class BuildAirport: public StationBuildCommand {
|
||||||
public:
|
public:
|
||||||
TileIndex tile;
|
TileIndex tile;
|
||||||
@@ -385,6 +399,20 @@ public:
|
|||||||
Commands get_command() override;
|
Commands get_command() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MoveStationName: public Command {
|
||||||
|
public:
|
||||||
|
StationID station_id;
|
||||||
|
TileIndex tile;
|
||||||
|
|
||||||
|
MoveStationName(StationID station_id, TileIndex tile)
|
||||||
|
:station_id{station_id}, tile{tile} {}
|
||||||
|
~MoveStationName() override {}
|
||||||
|
|
||||||
|
bool _post(::CommandCallback * callback) override;
|
||||||
|
CommandCost _do(DoCommandFlags flags) override;
|
||||||
|
Commands get_command() override;
|
||||||
|
};
|
||||||
|
|
||||||
class OpenCloseAirport: public Command {
|
class OpenCloseAirport: public Command {
|
||||||
public:
|
public:
|
||||||
StationID station_id;
|
StationID station_id;
|
||||||
@@ -1036,6 +1064,20 @@ public:
|
|||||||
Commands get_command() override;
|
Commands get_command() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class MoveSign: public Command {
|
||||||
|
public:
|
||||||
|
SignID sign_id;
|
||||||
|
TileIndex tile;
|
||||||
|
|
||||||
|
MoveSign(SignID sign_id, TileIndex tile)
|
||||||
|
:sign_id{sign_id}, tile{tile} {}
|
||||||
|
~MoveSign() override {}
|
||||||
|
|
||||||
|
bool _post(::CommandCallback * callback) override;
|
||||||
|
CommandCost _do(DoCommandFlags flags) override;
|
||||||
|
Commands get_command() override;
|
||||||
|
};
|
||||||
|
|
||||||
class BuildVehicle: public Command {
|
class BuildVehicle: public Command {
|
||||||
public:
|
public:
|
||||||
TileIndex tile;
|
TileIndex tile;
|
||||||
@@ -1688,9 +1730,10 @@ public:
|
|||||||
TileIndex tile;
|
TileIndex tile;
|
||||||
HouseID house;
|
HouseID house;
|
||||||
bool house_protected;
|
bool house_protected;
|
||||||
|
bool replace;
|
||||||
|
|
||||||
PlaceHouse(TileIndex tile, HouseID house, bool house_protected)
|
PlaceHouse(TileIndex tile, HouseID house, bool house_protected, bool replace)
|
||||||
:tile{tile}, house{house}, house_protected{house_protected} {}
|
:tile{tile}, house{house}, house_protected{house_protected}, replace{replace} {}
|
||||||
~PlaceHouse() override {}
|
~PlaceHouse() override {}
|
||||||
|
|
||||||
bool _post(::CommandCallback * callback) override;
|
bool _post(::CommandCallback * callback) override;
|
||||||
|
|||||||
@@ -2883,10 +2883,11 @@ STR_HOUSE_PICKER_CLASS_ZONE3 :Outer Suburbs
|
|||||||
STR_HOUSE_PICKER_CLASS_ZONE4 :Inner Suburbs
|
STR_HOUSE_PICKER_CLASS_ZONE4 :Inner Suburbs
|
||||||
STR_HOUSE_PICKER_CLASS_ZONE5 :Town centre
|
STR_HOUSE_PICKER_CLASS_ZONE5 :Town centre
|
||||||
|
|
||||||
STR_HOUSE_PICKER_PROTECT_TITLE :Prevent upgrades
|
STR_HOUSE_PICKER_PROTECT :Prevent upgrades
|
||||||
STR_HOUSE_PICKER_PROTECT_TOOLTIP :Choose whether this house will be protected from replacement as the town grows
|
STR_HOUSE_PICKER_PROTECT_TOOLTIP :Choose whether this house will be protected from replacement as the town grows
|
||||||
STR_HOUSE_PICKER_PROTECT_OFF :Off
|
|
||||||
STR_HOUSE_PICKER_PROTECT_ON :On
|
STR_HOUSE_PICKER_REPLACE :Replace existing
|
||||||
|
STR_HOUSE_PICKER_REPLACE_TOOLTIP :Choose whether to automatically remove an existing house on the tile where this house is placed
|
||||||
|
|
||||||
STR_STATION_CLASS_DFLT :Default
|
STR_STATION_CLASS_DFLT :Default
|
||||||
STR_STATION_CLASS_DFLT_STATION :Default station
|
STR_STATION_CLASS_DFLT_STATION :Default station
|
||||||
|
|||||||
@@ -3254,9 +3254,10 @@ static bool TryBuildTownHouse(Town *t, TileIndex tile, TownExpandModes modes, bo
|
|||||||
* @param tile Tile on which to place the house.
|
* @param tile Tile on which to place the house.
|
||||||
* @param HouseID The HouseID of the house spec.
|
* @param HouseID The HouseID of the house spec.
|
||||||
* @param is_protected Whether the house is protected from the town upgrading it.
|
* @param is_protected Whether the house is protected from the town upgrading it.
|
||||||
|
* @param replace Whether to automatically demolish an existing house on this tile, if present.
|
||||||
* @return Empty cost or an error.
|
* @return Empty cost or an error.
|
||||||
*/
|
*/
|
||||||
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool is_protected)
|
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool is_protected, bool replace)
|
||||||
{
|
{
|
||||||
if (_game_mode != GM_EDITOR && _settings_game.economy.place_houses == PH_FORBIDDEN) return CMD_ERROR;
|
if (_game_mode != GM_EDITOR && _settings_game.economy.place_houses == PH_FORBIDDEN) return CMD_ERROR;
|
||||||
|
|
||||||
@@ -3266,39 +3267,45 @@ CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, b
|
|||||||
const HouseSpec *hs = HouseSpec::Get(house);
|
const HouseSpec *hs = HouseSpec::Get(house);
|
||||||
if (!hs->enabled) return CMD_ERROR;
|
if (!hs->enabled) return CMD_ERROR;
|
||||||
|
|
||||||
Town *t = ClosestTownFromTile(tile, UINT_MAX);
|
int maxz = GetTileMaxZ(tile);
|
||||||
|
|
||||||
/* cannot build on these slopes... */
|
/* Check each tile of a multi-tile house. */
|
||||||
Slope slope = GetTileSlope(tile);
|
TileArea ta(tile, 1, 1);
|
||||||
|
if (hs->building_flags.Test(BuildingFlag::Size2x2)) ta.Add(TileAddXY(tile, 1, 1));
|
||||||
|
if (hs->building_flags.Test(BuildingFlag::Size2x1)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
|
||||||
|
if (hs->building_flags.Test(BuildingFlag::Size1x2)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
|
||||||
|
|
||||||
|
for (const TileIndex subtile : ta) {
|
||||||
|
/* Houses cannot be built on steep slopes. */
|
||||||
|
Slope slope = GetTileSlope(subtile);
|
||||||
if (IsSteepSlope(slope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
if (IsSteepSlope(slope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||||
|
|
||||||
/* building under a bridge? */
|
/* Houses cannot be built under bridges. */
|
||||||
if (IsBridgeAbove(tile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
if (IsBridgeAbove(subtile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
|
||||||
|
|
||||||
/* can we clear the land? */
|
|
||||||
CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, tile);
|
|
||||||
if (!cost.Succeeded()) return cost;
|
|
||||||
|
|
||||||
int maxz = GetTileMaxZ(tile);
|
|
||||||
|
|
||||||
/* Make sure there is no slope? */
|
/* Make sure there is no slope? */
|
||||||
bool noslope = hs->building_flags.Test(BuildingFlag::NotSloped);
|
bool noslope = hs->building_flags.Test(BuildingFlag::NotSloped);
|
||||||
if (noslope && slope != SLOPE_FLAT) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
|
if (noslope && slope != SLOPE_FLAT) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
|
||||||
|
|
||||||
TileArea ta = tile;
|
/* All tiles of a multi-tile house must have the same z-level. */
|
||||||
if (hs->building_flags.Test(BuildingFlag::Size2x2)) ta.Add(TileAddXY(tile, 1, 1));
|
if (GetTileMaxZ(subtile) != maxz) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
||||||
if (hs->building_flags.Test(BuildingFlag::Size2x1)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
|
|
||||||
if (hs->building_flags.Test(BuildingFlag::Size1x2)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
|
|
||||||
|
|
||||||
/* Check additional tiles covered by this house. */
|
/* We might be replacing an existing house, otherwise check if we can clear land. */
|
||||||
for (const TileIndex &subtile : ta) {
|
if (!(replace && GetTileType(subtile) == MP_HOUSE)) {
|
||||||
cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, subtile);
|
CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, subtile);
|
||||||
if (!cost.Succeeded()) return cost;
|
if (!cost.Succeeded()) return cost;
|
||||||
|
}
|
||||||
if (!CheckBuildHouseSameZ(subtile, maxz, noslope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (flags.Test(DoCommandFlag::Execute)) {
|
if (flags.Test(DoCommandFlag::Execute)) {
|
||||||
|
/* If replacing, clear any existing houses first. */
|
||||||
|
if (replace) {
|
||||||
|
for (const TileIndex &subtile : ta) {
|
||||||
|
if (GetTileType(subtile) == MP_HOUSE) ClearTownHouse(Town::GetByTile(subtile), subtile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Town *t = ClosestTownFromTile(tile, UINT_MAX);
|
||||||
bool house_completed = _settings_game.economy.place_houses == PH_ALLOWED_CONSTRUCTED;
|
bool house_completed = _settings_game.economy.place_houses == PH_ALLOWED_CONSTRUCTED;
|
||||||
BuildTownHouse(t, tile, hs, house, Random(), house_completed, is_protected, false);
|
BuildTownHouse(t, tile, hs, house, Random(), house_completed, is_protected, false);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ CommandCost CmdTownCargoGoal(DoCommandFlags flags, TownID town_id, TownAcceptanc
|
|||||||
CommandCost CmdTownSetText(DoCommandFlags flags, TownID town_id, const EncodedString &text);
|
CommandCost CmdTownSetText(DoCommandFlags flags, TownID town_id, const EncodedString &text);
|
||||||
CommandCost CmdExpandTown(DoCommandFlags flags, TownID town_id, uint32_t grow_amount, TownExpandModes modes);
|
CommandCost CmdExpandTown(DoCommandFlags flags, TownID town_id, uint32_t grow_amount, TownExpandModes modes);
|
||||||
CommandCost CmdDeleteTown(DoCommandFlags flags, TownID town_id);
|
CommandCost CmdDeleteTown(DoCommandFlags flags, TownID town_id);
|
||||||
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool house_protected);
|
CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool house_protected, bool replace);
|
||||||
|
|
||||||
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CommandFlags({CommandFlag::Deity, CommandFlag::NoTest}), CommandType::LandscapeConstruction) // founding random town can fail only in exec run
|
DEF_CMD_TRAIT(CMD_FOUND_TOWN, CmdFoundTown, CommandFlags({CommandFlag::Deity, CommandFlag::NoTest}), CommandType::LandscapeConstruction) // founding random town can fail only in exec run
|
||||||
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CommandFlags({CommandFlag::Deity, CommandFlag::Server}), CommandType::OtherManagement)
|
DEF_CMD_TRAIT(CMD_RENAME_TOWN, CmdRenameTown, CommandFlags({CommandFlag::Deity, CommandFlag::Server}), CommandType::OtherManagement)
|
||||||
|
|||||||
@@ -1744,6 +1744,7 @@ static CargoTypes GetProducedCargoOfHouse(const HouseSpec *hs)
|
|||||||
struct BuildHouseWindow : public PickerWindow {
|
struct BuildHouseWindow : public PickerWindow {
|
||||||
std::string house_info{};
|
std::string house_info{};
|
||||||
static inline bool house_protected;
|
static inline bool house_protected;
|
||||||
|
static inline bool replace;
|
||||||
|
|
||||||
BuildHouseWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, 0, HousePickerCallbacks::instance)
|
BuildHouseWindow(WindowDesc &desc, Window *parent) : PickerWindow(desc, parent, 0, HousePickerCallbacks::instance)
|
||||||
{
|
{
|
||||||
@@ -1850,11 +1851,17 @@ struct BuildHouseWindow : public PickerWindow {
|
|||||||
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
void OnClick([[maybe_unused]] Point pt, WidgetID widget, [[maybe_unused]] int click_count) override
|
||||||
{
|
{
|
||||||
switch (widget) {
|
switch (widget) {
|
||||||
case WID_BH_PROTECT_OFF:
|
case WID_BH_PROTECT_TOGGLE:
|
||||||
case WID_BH_PROTECT_ON:
|
BuildHouseWindow::house_protected = !BuildHouseWindow::house_protected;
|
||||||
BuildHouseWindow::house_protected = (widget == WID_BH_PROTECT_ON);
|
this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
|
||||||
this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !BuildHouseWindow::house_protected);
|
|
||||||
this->SetWidgetLoweredState(WID_BH_PROTECT_ON, BuildHouseWindow::house_protected);
|
SndClickBeep();
|
||||||
|
this->SetDirty();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WID_BH_REPLACE_TOGGLE:
|
||||||
|
BuildHouseWindow::replace = !BuildHouseWindow::replace;
|
||||||
|
this->SetWidgetLoweredState(WID_BH_REPLACE_TOGGLE, BuildHouseWindow::replace);
|
||||||
|
|
||||||
SndClickBeep();
|
SndClickBeep();
|
||||||
this->SetDirty();
|
this->SetDirty();
|
||||||
@@ -1883,17 +1890,16 @@ struct BuildHouseWindow : public PickerWindow {
|
|||||||
bool hasflag = spec->extra_flags.Test(HouseExtraFlag::BuildingIsProtected);
|
bool hasflag = spec->extra_flags.Test(HouseExtraFlag::BuildingIsProtected);
|
||||||
if (hasflag) BuildHouseWindow::house_protected = true;
|
if (hasflag) BuildHouseWindow::house_protected = true;
|
||||||
|
|
||||||
this->SetWidgetLoweredState(WID_BH_PROTECT_OFF, !BuildHouseWindow::house_protected);
|
this->SetWidgetLoweredState(WID_BH_PROTECT_TOGGLE, BuildHouseWindow::house_protected);
|
||||||
this->SetWidgetLoweredState(WID_BH_PROTECT_ON, BuildHouseWindow::house_protected);
|
this->SetWidgetLoweredState(WID_BH_REPLACE_TOGGLE, BuildHouseWindow::replace);
|
||||||
|
|
||||||
this->SetWidgetDisabledState(WID_BH_PROTECT_OFF, hasflag);
|
this->SetWidgetDisabledState(WID_BH_PROTECT_TOGGLE, hasflag);
|
||||||
this->SetWidgetDisabledState(WID_BH_PROTECT_ON, hasflag);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
|
void OnPlaceObject([[maybe_unused]] Point pt, TileIndex tile) override
|
||||||
{
|
{
|
||||||
const HouseSpec *spec = HouseSpec::Get(HousePickerCallbacks::sel_type);
|
const HouseSpec *spec = HouseSpec::Get(HousePickerCallbacks::sel_type);
|
||||||
Command<CMD_PLACE_HOUSE>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), BuildHouseWindow::house_protected);
|
Command<CMD_PLACE_HOUSE>::Post(STR_ERROR_CAN_T_BUILD_HOUSE, CcPlaySound_CONSTRUCTION_OTHER, tile, spec->Index(), BuildHouseWindow::house_protected, BuildHouseWindow::replace);
|
||||||
}
|
}
|
||||||
|
|
||||||
const IntervalTimer<TimerWindow> view_refresh_interval = {std::chrono::milliseconds(2500), [this](auto) {
|
const IntervalTimer<TimerWindow> view_refresh_interval = {std::chrono::milliseconds(2500), [this](auto) {
|
||||||
@@ -1923,15 +1929,11 @@ static constexpr std::initializer_list<NWidgetPart> _nested_build_house_widgets
|
|||||||
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
|
NWidget(WWT_PANEL, COLOUR_DARK_GREEN),
|
||||||
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_picker, 0), SetPadding(WidgetDimensions::unscaled.picker),
|
NWidget(NWID_VERTICAL), SetPIP(0, WidgetDimensions::unscaled.vsep_picker, 0), SetPadding(WidgetDimensions::unscaled.picker),
|
||||||
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BH_INFO), SetFill(1, 1), SetMinimalTextLines(10, 0),
|
NWidget(WWT_EMPTY, INVALID_COLOUR, WID_BH_INFO), SetFill(1, 1), SetMinimalTextLines(10, 0),
|
||||||
NWidget(WWT_LABEL, INVALID_COLOUR), SetStringTip(STR_HOUSE_PICKER_PROTECT_TITLE, STR_NULL), SetFill(1, 0),
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
|
||||||
NWidget(NWID_HORIZONTAL), SetPIPRatio(1, 0, 1),
|
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_REPLACE_TOGGLE), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_REPLACE, STR_HOUSE_PICKER_REPLACE_TOOLTIP),
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_OFF), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_OFF, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
|
|
||||||
NWidget(WWT_TEXTBTN, COLOUR_GREY, WID_BH_PROTECT_ON), SetMinimalSize(60, 12), SetStringTip(STR_HOUSE_PICKER_PROTECT_ON, STR_HOUSE_PICKER_PROTECT_TOOLTIP),
|
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
|
|
||||||
EndContainer(),
|
|
||||||
NWidgetFunction(MakePickerTypeWidgets),
|
NWidgetFunction(MakePickerTypeWidgets),
|
||||||
EndContainer(),
|
EndContainer(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -80,8 +80,8 @@ enum TownFoundingWidgets : WidgetID {
|
|||||||
/** Widgets of the #BuildHouseWindow class. */
|
/** Widgets of the #BuildHouseWindow class. */
|
||||||
enum BuildHouseWidgets : WidgetID {
|
enum BuildHouseWidgets : WidgetID {
|
||||||
WID_BH_INFO, ///< Information panel of selected house.
|
WID_BH_INFO, ///< Information panel of selected house.
|
||||||
WID_BH_PROTECT_OFF, ///< Button to protect the next house built.
|
WID_BH_PROTECT_TOGGLE, ///< Button to toggle protecting the next house built.
|
||||||
WID_BH_PROTECT_ON, ///< Button to not protect the next house built.
|
WID_BH_REPLACE_TOGGLE, ///< Button to toggle replacing existing houses.
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CBTownWidgets {
|
enum CBTownWidgets {
|
||||||
|
|||||||
Reference in New Issue
Block a user