Update: Translations from eints
[openttd-github.git] / src / script / api / script_tile.cpp
blobe4286dd9f1f865b08ae7a0ddcb7c4925b0f906b0
1 /*
2 * This file is part of OpenTTD.
3 * OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
4 * OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
5 * See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
6 */
8 /** @file script_tile.cpp Implementation of ScriptTile. */
10 #include "../../stdafx.h"
11 #include "script_tile.hpp"
12 #include "script_map.hpp"
13 #include "script_town.hpp"
14 #include "../../station_func.h"
15 #include "../../water_map.h"
16 #include "../../clear_map.h"
17 #include "../../tree_map.h"
18 #include "../../town.h"
19 #include "../../landscape.h"
20 #include "../../landscape_cmd.h"
21 #include "../../terraform_cmd.h"
22 #include "../../tree_cmd.h"
24 #include "../../safeguards.h"
26 /* static */ bool ScriptTile::IsBuildable(TileIndex tile)
28 EnforceDeityOrCompanyModeValid(false);
29 if (!::IsValidTile(tile)) return false;
31 switch (::GetTileType(tile)) {
32 default: return false;
33 case MP_CLEAR: return true;
34 case MP_TREES: return true;
35 case MP_WATER: return IsCoast(tile);
36 case MP_ROAD:
37 /* Tram bits aren't considered buildable */
38 if (::GetRoadTypeTram(tile) != INVALID_ROADTYPE) return false;
39 /* Depots and crossings aren't considered buildable */
40 if (::GetRoadTileType(tile) != ROAD_TILE_NORMAL) return false;
41 if (!HasExactlyOneBit(::GetRoadBits(tile, RTT_ROAD))) return false;
42 if (::IsRoadOwner(tile, RTT_ROAD, OWNER_TOWN)) return true;
43 if (::IsRoadOwner(tile, RTT_ROAD, ScriptObject::GetCompany())) return true;
44 return false;
48 /* static */ bool ScriptTile::IsBuildableRectangle(TileIndex tile, SQInteger width, SQInteger height)
50 /* Check whether we can extract valid X and Y */
51 if (!::IsValidTile(tile) || width < 0 || height < 0) return false;
53 uint tx = ScriptMap::GetTileX(tile);
54 uint ty = ScriptMap::GetTileY(tile);
56 for (uint x = tx; x < width + tx; x++) {
57 for (uint y = ty; y < height + ty; y++) {
58 if (!IsBuildable(ScriptMap::GetTileIndex(x, y))) return false;
62 return true;
65 /* static */ bool ScriptTile::IsSeaTile(TileIndex tile)
67 if (!::IsValidTile(tile)) return false;
69 return ::IsTileType(tile, MP_WATER) && ::IsSea(tile);
72 /* static */ bool ScriptTile::IsRiverTile(TileIndex tile)
74 if (!::IsValidTile(tile)) return false;
76 return ::IsTileType(tile, MP_WATER) && ::IsRiver(tile);
79 /* static */ bool ScriptTile::IsWaterTile(TileIndex tile)
81 if (!::IsValidTile(tile)) return false;
83 return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
86 /* static */ bool ScriptTile::IsCoastTile(TileIndex tile)
88 if (!::IsValidTile(tile)) return false;
90 return (::IsTileType(tile, MP_WATER) && ::IsCoast(tile)) ||
91 (::IsTileType(tile, MP_TREES) && ::GetTreeGround(tile) == TREE_GROUND_SHORE);
94 /* static */ bool ScriptTile::IsStationTile(TileIndex tile)
96 if (!::IsValidTile(tile)) return false;
98 return ::IsTileType(tile, MP_STATION);
101 /* static */ bool ScriptTile::IsSteepSlope(Slope slope)
103 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
105 return ::IsSteepSlope((::Slope)slope);
108 /* static */ bool ScriptTile::IsHalftileSlope(Slope slope)
110 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
112 return ::IsHalftileSlope((::Slope)slope);
115 /* static */ bool ScriptTile::HasTreeOnTile(TileIndex tile)
117 if (!::IsValidTile(tile)) return false;
119 return ::IsTileType(tile, MP_TREES);
122 /* static */ bool ScriptTile::IsFarmTile(TileIndex tile)
124 if (!::IsValidTile(tile)) return false;
126 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_FIELDS));
129 /* static */ bool ScriptTile::IsRockTile(TileIndex tile)
131 if (!::IsValidTile(tile)) return false;
133 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROCKS);
136 /* static */ bool ScriptTile::IsRoughTile(TileIndex tile)
138 if (!::IsValidTile(tile)) return false;
140 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROUGH);
143 /* static */ bool ScriptTile::IsSnowTile(TileIndex tile)
145 if (!::IsValidTile(tile)) return false;
147 return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
150 /* static */ bool ScriptTile::IsDesertTile(TileIndex tile)
152 if (!::IsValidTile(tile)) return false;
154 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_DESERT));
157 /* static */ ScriptTile::TerrainType ScriptTile::GetTerrainType(TileIndex tile)
159 if (!::IsValidTile(tile)) return TERRAIN_NORMAL;
161 switch (::GetTerrainType(tile)) {
162 default:
163 case 0: return TERRAIN_NORMAL;
164 case 1: return TERRAIN_DESERT;
165 case 2: return TERRAIN_RAINFOREST;
166 case 4: return TERRAIN_SNOW;
170 /* static */ ScriptTile::Slope ScriptTile::GetSlope(TileIndex tile)
172 if (!::IsValidTile(tile)) return SLOPE_INVALID;
174 return (Slope)::GetTileSlope(tile);
177 /* static */ ScriptTile::Slope ScriptTile::GetComplementSlope(Slope slope)
179 if ((slope & ~SLOPE_ELEVATED) != 0) return SLOPE_INVALID;
181 return (Slope)::ComplementSlope((::Slope)slope);
184 /* static */ SQInteger ScriptTile::GetMinHeight(TileIndex tile)
186 if (!::IsValidTile(tile)) return -1;
188 return ::GetTileZ(tile);
191 /* static */ SQInteger ScriptTile::GetMaxHeight(TileIndex tile)
193 if (!::IsValidTile(tile)) return -1;
195 return ::GetTileMaxZ(tile);
198 /* static */ SQInteger ScriptTile::GetCornerHeight(TileIndex tile, Corner corner)
200 if (!::IsValidTile(tile) || !::IsValidCorner((::Corner)corner)) return -1;
202 auto [slope, z] = ::GetTileSlopeZ(tile);
203 return (z + ::GetSlopeZInCorner(slope, (::Corner)corner));
206 /* static */ ScriptCompany::CompanyID ScriptTile::GetOwner(TileIndex tile)
208 if (!::IsValidTile(tile)) return ScriptCompany::COMPANY_INVALID;
209 if (::IsTileType(tile, MP_HOUSE)) return ScriptCompany::COMPANY_INVALID;
210 if (::IsTileType(tile, MP_INDUSTRY)) return ScriptCompany::COMPANY_INVALID;
212 return ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID)(uint8_t)::GetTileOwner(tile));
215 /* static */ bool ScriptTile::HasTransportType(TileIndex tile, TransportType transport_type)
217 if (!::IsValidTile(tile)) return false;
219 if (transport_type == TRANSPORT_ROAD) {
220 return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 0)) != TRACKDIR_BIT_NONE ||
221 ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 1)) != TRACKDIR_BIT_NONE;
222 } else {
223 return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile, (::TransportType)transport_type, 0)) != TRACKDIR_BIT_NONE;
227 /* static */ SQInteger ScriptTile::GetCargoAcceptance(TileIndex tile, CargoID cargo_type, SQInteger width, SQInteger height, SQInteger radius)
229 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0 || !ScriptCargo::IsValidCargo(cargo_type)) return -1;
231 CargoArray acceptance = ::GetAcceptanceAroundTiles(tile, width, height, _settings_game.station.modified_catchment ? radius : (int)CA_UNMODIFIED);
232 return acceptance[cargo_type];
235 /* static */ SQInteger ScriptTile::GetCargoProduction(TileIndex tile, CargoID cargo_type, SQInteger width, SQInteger height, SQInteger radius)
237 if (!::IsValidTile(tile) || width <= 0 || height <= 0 || radius < 0 || !ScriptCargo::IsValidCargo(cargo_type)) return -1;
239 CargoArray produced = ::GetProductionAroundTiles(tile, width, height, _settings_game.station.modified_catchment ? radius : (int)CA_UNMODIFIED);
240 return produced[cargo_type];
243 /* static */ SQInteger ScriptTile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
245 return ScriptMap::DistanceManhattan(tile_from, tile_to);
248 /* static */ SQInteger ScriptTile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
250 return ScriptMap::DistanceSquare(tile_from, tile_to);
253 /* static */ bool ScriptTile::RaiseTile(TileIndex tile, Slope slope)
255 EnforceCompanyModeValid(false);
256 EnforcePrecondition(false, tile < ScriptMap::GetMapSize());
258 return ScriptObject::Command<CMD_TERRAFORM_LAND>::Do(tile, (::Slope)slope, true);
261 /* static */ bool ScriptTile::LowerTile(TileIndex tile, Slope slope)
263 EnforceCompanyModeValid(false);
264 EnforcePrecondition(false, tile < ScriptMap::GetMapSize());
266 return ScriptObject::Command<CMD_TERRAFORM_LAND>::Do(tile, (::Slope)slope, false);
269 /* static */ bool ScriptTile::LevelTiles(TileIndex start_tile, TileIndex end_tile)
271 EnforceCompanyModeValid(false);
272 EnforcePrecondition(false, start_tile < ScriptMap::GetMapSize());
273 EnforcePrecondition(false, end_tile < ScriptMap::GetMapSize());
275 return ScriptObject::Command<CMD_LEVEL_LAND>::Do(end_tile, start_tile, false, LM_LEVEL);
278 /* static */ bool ScriptTile::DemolishTile(TileIndex tile)
280 EnforceDeityOrCompanyModeValid(false);
281 EnforcePrecondition(false, ::IsValidTile(tile));
283 return ScriptObject::Command<CMD_LANDSCAPE_CLEAR>::Do(tile);
286 /* static */ bool ScriptTile::PlantTree(TileIndex tile)
288 EnforceCompanyModeValid(false);
289 EnforcePrecondition(false, ::IsValidTile(tile));
291 return ScriptObject::Command<CMD_PLANT_TREE>::Do(tile, tile, TREE_INVALID, false);
294 /* static */ bool ScriptTile::PlantTreeRectangle(TileIndex tile, SQInteger width, SQInteger height)
296 EnforceCompanyModeValid(false);
297 EnforcePrecondition(false, ::IsValidTile(tile));
298 EnforcePrecondition(false, width >= 1 && width <= 20);
299 EnforcePrecondition(false, height >= 1 && height <= 20);
300 TileIndex end_tile = tile + ::TileDiffXY(width - 1, height - 1);
302 return ScriptObject::Command<CMD_PLANT_TREE>::Do(tile, end_tile, TREE_INVALID, false);
305 /* static */ bool ScriptTile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
307 return ScriptTown::IsWithinTownInfluence(town_id, tile);
310 /* static */ TownID ScriptTile::GetTownAuthority(TileIndex tile)
312 if (!::IsValidTile(tile)) return INVALID_TOWN;
314 Town *town = ::ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
315 if (town == nullptr) return INVALID_TOWN;
317 return town->index;
320 /* static */ TownID ScriptTile::GetClosestTown(TileIndex tile)
322 if (!::IsValidTile(tile)) return INVALID_TOWN;
324 Town *town = ::ClosestTownFromTile(tile, UINT_MAX);
325 if (town == nullptr) return INVALID_TOWN;
327 return town->index;
330 /* static */ Money ScriptTile::GetBuildCost(BuildType build_type)
332 switch (build_type) {
333 case BT_FOUNDATION: return ::GetPrice(PR_BUILD_FOUNDATION, 1, nullptr);
334 case BT_TERRAFORM: return ::GetPrice(PR_TERRAFORM, 1, nullptr);
335 case BT_BUILD_TREES: return ::GetPrice(PR_BUILD_TREES, 1, nullptr);
336 case BT_CLEAR_GRASS: return ::GetPrice(PR_CLEAR_GRASS, 1, nullptr);
337 case BT_CLEAR_ROUGH: return ::GetPrice(PR_CLEAR_ROUGH, 1, nullptr);
338 case BT_CLEAR_ROCKY: return ::GetPrice(PR_CLEAR_ROCKS, 1, nullptr);
339 case BT_CLEAR_FIELDS: return ::GetPrice(PR_CLEAR_FIELDS, 1, nullptr);
340 case BT_CLEAR_HOUSE: return ::GetPrice(PR_CLEAR_HOUSE, 1, nullptr);
341 case BT_CLEAR_WATER: return ::GetPrice(PR_CLEAR_WATER, 1, nullptr);
342 default: return -1;