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

Function TownActionBuildStatue

src/town_cmd.cpp:3493–3544  ·  view source on GitHub ↗

* Perform a 9x9 tiles circular search from the center of the town * in order to find a free tile to place a statue * @param t town to search in * @param flags Used to check if the statue must be built or not. * @return Empty cost or an error. */

Source from the content-addressed store, hash-verified

3491 * @return Empty cost or an error.
3492 */
3493static CommandCost TownActionBuildStatue(Town *t, DoCommandFlags flags)
3494{
3495 if (!Object::CanAllocateItem()) return CommandCost(STR_ERROR_TOO_MANY_OBJECTS);
3496
3497 static const int STATUE_NUMBER_INNER_TILES = 25; // Number of tiles int the center of the city, where we try to protect houses.
3498
3499 TileIndex best_position = INVALID_TILE; ///< Best position found so far.
3500 uint tile_count = 0; ///< Number of tiles tried.
3501 for (auto tile : SpiralTileSequence(t->xy, 9)) {
3502 tile_count++;
3503
3504 /* Statues can be build on slopes, just like houses. Only the steep slopes is a no go. */
3505 if (IsSteepSlope(GetTileSlope(tile))) continue;
3506 /* Don't build statues under bridges. */
3507 if (IsBridgeAbove(tile)) continue;
3508
3509 /* A clear-able open space is always preferred. */
3510 if ((IsTileType(tile, MP_CLEAR) || IsTileType(tile, MP_TREES)) && CheckClearTile(tile)) {
3511 best_position = tile;
3512 break;
3513 }
3514
3515 bool house = IsTileType(tile, MP_HOUSE);
3516
3517 /* Searching inside the inner circle. */
3518 if (tile_count <= STATUE_NUMBER_INNER_TILES) {
3519 /* Save first house in inner circle. */
3520 if (house && best_position == INVALID_TILE && CheckClearTile(tile)) {
3521 best_position = tile;
3522 }
3523
3524 /* If we have reached the end of the inner circle, and have a saved house, terminate the search. */
3525 if (tile_count == STATUE_NUMBER_INNER_TILES && best_position != INVALID_TILE) break;
3526 }
3527
3528 /* Searching outside the circle, just pick the first possible spot. */
3529 if (!house || !CheckClearTile(tile)) continue;
3530 best_position = tile;
3531 break;
3532 }
3533 if (best_position == INVALID_TILE) return CommandCost(STR_ERROR_STATUE_NO_SUITABLE_PLACE);
3534
3535 if (flags.Test(DoCommandFlag::Execute)) {
3536 Backup<CompanyID> cur_company(_current_company, OWNER_NONE);
3537 Command<CMD_LANDSCAPE_CLEAR>::Do(DoCommandFlag::Execute, best_position);
3538 cur_company.Restore();
3539 BuildObject(OBJECT_STATUE, best_position, _current_company, t);
3540 t->statues.Set(_current_company); // Once found and built, "inform" the Town.
3541 MarkTileDirtyByTile(best_position);
3542 }
3543 return CommandCost();
3544}
3545
3546/**
3547 * Perform the "fund new buildings" town action.

Callers

nothing calls this directly

Calls 12

CommandCostClass · 0.85
SpiralTileSequenceClass · 0.85
IsSteepSlopeFunction · 0.85
GetTileSlopeFunction · 0.85
IsBridgeAboveFunction · 0.85
IsTileTypeFunction · 0.85
CheckClearTileFunction · 0.85
BuildObjectFunction · 0.85
TestMethod · 0.80
MarkTileDirtyByTileFunction · 0.70
RestoreMethod · 0.45
SetMethod · 0.45

Tested by

no test coverage detected