MCPcopy Create free account
hub / github.com/OpenTTD/OpenTTD / CmdPlaceHouse

Function CmdPlaceHouse

src/town_cmd.cpp:2947–3001  ·  view source on GitHub ↗

* Place an individual house. * @param flags Type of operation. * @param tile Tile on which to place the house. * @param HouseID The HouseID of the house spec. * @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. */

Source from the content-addressed store, hash-verified

2945 * @return Empty cost or an error.
2946 */
2947CommandCost CmdPlaceHouse(DoCommandFlags flags, TileIndex tile, HouseID house, bool is_protected, bool replace)
2948{
2949 if (_game_mode != GM_EDITOR && _settings_game.economy.place_houses == PH_FORBIDDEN) return CMD_ERROR;
2950
2951 if (Town::GetNumItems() == 0) return CommandCost(STR_ERROR_MUST_FOUND_TOWN_FIRST);
2952
2953 if (static_cast<size_t>(house) >= HouseSpec::Specs().size()) return CMD_ERROR;
2954 const HouseSpec *hs = HouseSpec::Get(house);
2955 if (!hs->enabled) return CMD_ERROR;
2956
2957 int maxz = GetTileMaxZ(tile);
2958
2959 /* Check each tile of a multi-tile house. */
2960 TileArea ta(tile, 1, 1);
2961 if (hs->building_flags.Test(BuildingFlag::Size2x2)) ta.Add(TileAddXY(tile, 1, 1));
2962 if (hs->building_flags.Test(BuildingFlag::Size2x1)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SW));
2963 if (hs->building_flags.Test(BuildingFlag::Size1x2)) ta.Add(TileAddByDiagDir(tile, DIAGDIR_SE));
2964
2965 for (const TileIndex subtile : ta) {
2966 /* Houses cannot be built on steep slopes. */
2967 Slope slope = GetTileSlope(subtile);
2968 if (IsSteepSlope(slope)) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
2969
2970 /* Houses cannot be built under bridges. */
2971 if (IsBridgeAbove(subtile)) return CommandCost(STR_ERROR_MUST_DEMOLISH_BRIDGE_FIRST);
2972
2973 /* Make sure there is no slope? */
2974 bool noslope = hs->building_flags.Test(BuildingFlag::NotSloped);
2975 if (noslope && slope != SLOPE_FLAT) return CommandCost(STR_ERROR_FLAT_LAND_REQUIRED);
2976
2977 /* All tiles of a multi-tile house must have the same z-level. */
2978 if (GetTileMaxZ(subtile) != maxz) return CommandCost(STR_ERROR_LAND_SLOPED_IN_WRONG_DIRECTION);
2979
2980 /* We might be replacing an existing house, otherwise check if we can clear land. */
2981 if (!(replace && GetTileType(subtile) == MP_HOUSE)) {
2982 CommandCost cost = Command<CMD_LANDSCAPE_CLEAR>::Do({DoCommandFlag::Auto, DoCommandFlag::NoWater}, subtile);
2983 if (!cost.Succeeded()) return cost;
2984 }
2985 }
2986
2987 if (flags.Test(DoCommandFlag::Execute)) {
2988 /* If replacing, clear any existing houses first. */
2989 if (replace) {
2990 for (const TileIndex &subtile : ta) {
2991 if (GetTileType(subtile) == MP_HOUSE) ClearTownHouse(Town::GetByTile(subtile), subtile);
2992 }
2993 }
2994
2995 Town *t = ClosestTownFromTile(tile, UINT_MAX);
2996 bool house_completed = _settings_game.economy.place_houses == PH_ALLOWED_CONSTRUCTED;
2997 BuildTownHouse(t, tile, hs, house, Random(), house_completed, is_protected);
2998 }
2999
3000 return CommandCost();
3001}
3002
3003/**
3004 * Update data structures when a house is removed

Callers

nothing calls this directly

Calls 15

CommandCostClass · 0.85
GetTileMaxZFunction · 0.85
TileAddXYFunction · 0.85
TileAddByDiagDirFunction · 0.85
GetTileSlopeFunction · 0.85
IsSteepSlopeFunction · 0.85
IsBridgeAboveFunction · 0.85
GetTileTypeFunction · 0.85
ClearTownHouseFunction · 0.85
ClosestTownFromTileFunction · 0.85
BuildTownHouseFunction · 0.85
TestMethod · 0.80

Tested by

no test coverage detected