Codechange: Un-bitstuff landscape commands.
[openttd-github.git] / src / script / api / script_tile.cpp
blob8be74c0304266ac2c474a7c52ac137c262b5625c
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 if (!::IsValidTile(tile)) return false;
30 switch (::GetTileType(tile)) {
31 default: return false;
32 case MP_CLEAR: return true;
33 case MP_TREES: return true;
34 case MP_WATER: return IsCoast(tile);
35 case MP_ROAD:
36 /* Tram bits aren't considered buildable */
37 if (::GetRoadTypeTram(tile) != INVALID_ROADTYPE) return false;
38 /* Depots and crossings aren't considered buildable */
39 if (::GetRoadTileType(tile) != ROAD_TILE_NORMAL) return false;
40 if (!HasExactlyOneBit(::GetRoadBits(tile, RTT_ROAD))) return false;
41 if (::IsRoadOwner(tile, RTT_ROAD, OWNER_TOWN)) return true;
42 if (::IsRoadOwner(tile, RTT_ROAD, ScriptObject::GetCompany())) return true;
43 return false;
47 /* static */ bool ScriptTile::IsBuildableRectangle(TileIndex tile, uint width, uint height)
49 /* Check whether we can extract valid X and Y */
50 if (!::IsValidTile(tile)) return false;
52 uint tx = ScriptMap::GetTileX(tile);
53 uint ty = ScriptMap::GetTileY(tile);
55 for (uint x = tx; x < width + tx; x++) {
56 for (uint y = ty; y < height + ty; y++) {
57 if (!IsBuildable(ScriptMap::GetTileIndex(x, y))) return false;
61 return true;
64 /* static */ bool ScriptTile::IsSeaTile(TileIndex tile)
66 if (!::IsValidTile(tile)) return false;
68 return ::IsTileType(tile, MP_WATER) && ::IsSea(tile);
71 /* static */ bool ScriptTile::IsRiverTile(TileIndex tile)
73 if (!::IsValidTile(tile)) return false;
75 return ::IsTileType(tile, MP_WATER) && ::IsRiver(tile);
78 /* static */ bool ScriptTile::IsWaterTile(TileIndex tile)
80 if (!::IsValidTile(tile)) return false;
82 return ::IsTileType(tile, MP_WATER) && !::IsCoast(tile);
85 /* static */ bool ScriptTile::IsCoastTile(TileIndex tile)
87 if (!::IsValidTile(tile)) return false;
89 return (::IsTileType(tile, MP_WATER) && ::IsCoast(tile)) ||
90 (::IsTileType(tile, MP_TREES) && ::GetTreeGround(tile) == TREE_GROUND_SHORE);
93 /* static */ bool ScriptTile::IsStationTile(TileIndex tile)
95 if (!::IsValidTile(tile)) return false;
97 return ::IsTileType(tile, MP_STATION);
100 /* static */ bool ScriptTile::IsSteepSlope(Slope slope)
102 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
104 return ::IsSteepSlope((::Slope)slope);
107 /* static */ bool ScriptTile::IsHalftileSlope(Slope slope)
109 if ((slope & ~(SLOPE_ELEVATED | SLOPE_STEEP | SLOPE_HALFTILE_MASK)) != 0) return false;
111 return ::IsHalftileSlope((::Slope)slope);
114 /* static */ bool ScriptTile::HasTreeOnTile(TileIndex tile)
116 if (!::IsValidTile(tile)) return false;
118 return ::IsTileType(tile, MP_TREES);
121 /* static */ bool ScriptTile::IsFarmTile(TileIndex tile)
123 if (!::IsValidTile(tile)) return false;
125 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_FIELDS));
128 /* static */ bool ScriptTile::IsRockTile(TileIndex tile)
130 if (!::IsValidTile(tile)) return false;
132 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROCKS);
135 /* static */ bool ScriptTile::IsRoughTile(TileIndex tile)
137 if (!::IsValidTile(tile)) return false;
139 return (::IsTileType(tile, MP_CLEAR) && ::GetRawClearGround(tile) == ::CLEAR_ROUGH);
142 /* static */ bool ScriptTile::IsSnowTile(TileIndex tile)
144 if (!::IsValidTile(tile)) return false;
146 return (::IsTileType(tile, MP_CLEAR) && ::IsSnowTile(tile));
149 /* static */ bool ScriptTile::IsDesertTile(TileIndex tile)
151 if (!::IsValidTile(tile)) return false;
153 return (::IsTileType(tile, MP_CLEAR) && ::IsClearGround(tile, CLEAR_DESERT));
156 /* static */ ScriptTile::TerrainType ScriptTile::GetTerrainType(TileIndex tile)
158 if (!::IsValidTile(tile)) return TERRAIN_NORMAL;
160 switch (::GetTerrainType(tile)) {
161 default:
162 case 0: return TERRAIN_NORMAL;
163 case 1: return TERRAIN_DESERT;
164 case 2: return TERRAIN_RAINFOREST;
165 case 4: return TERRAIN_SNOW;
169 /* static */ ScriptTile::Slope ScriptTile::GetSlope(TileIndex tile)
171 if (!::IsValidTile(tile)) return SLOPE_INVALID;
173 return (Slope)::GetTileSlope(tile);
176 /* static */ ScriptTile::Slope ScriptTile::GetComplementSlope(Slope slope)
178 if ((slope & ~SLOPE_ELEVATED) != 0) return SLOPE_INVALID;
180 return (Slope)::ComplementSlope((::Slope)slope);
183 /* static */ int32 ScriptTile::GetMinHeight(TileIndex tile)
185 if (!::IsValidTile(tile)) return -1;
187 return ::GetTileZ(tile);
190 /* static */ int32 ScriptTile::GetMaxHeight(TileIndex tile)
192 if (!::IsValidTile(tile)) return -1;
194 return ::GetTileMaxZ(tile);
197 /* static */ int32 ScriptTile::GetCornerHeight(TileIndex tile, Corner corner)
199 if (!::IsValidTile(tile) || !::IsValidCorner((::Corner)corner)) return -1;
201 int z;
202 ::Slope slope = ::GetTileSlope(tile, &z);
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)(byte)::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 */ int32 ScriptTile::GetCargoAcceptance(TileIndex tile, CargoID cargo_type, int width, int height, int 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 */ int32 ScriptTile::GetCargoProduction(TileIndex tile, CargoID cargo_type, int width, int height, int 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 */ int32 ScriptTile::GetDistanceManhattanToTile(TileIndex tile_from, TileIndex tile_to)
245 return ScriptMap::DistanceManhattan(tile_from, tile_to);
248 /* static */ int32 ScriptTile::GetDistanceSquareToTile(TileIndex tile_from, TileIndex tile_to)
250 return ScriptMap::DistanceSquare(tile_from, tile_to);
253 /* static */ bool ScriptTile::RaiseTile(TileIndex tile, int32 slope)
255 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
256 EnforcePrecondition(false, tile < ::MapSize());
258 return ScriptObject::Command<CMD_TERRAFORM_LAND>::Do(tile, (::Slope)slope, true);
261 /* static */ bool ScriptTile::LowerTile(TileIndex tile, int32 slope)
263 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
264 EnforcePrecondition(false, tile < ::MapSize());
266 return ScriptObject::Command<CMD_TERRAFORM_LAND>::Do(tile, (::Slope)slope, false);
269 /* static */ bool ScriptTile::LevelTiles(TileIndex start_tile, TileIndex end_tile)
271 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
272 EnforcePrecondition(false, start_tile < ::MapSize());
273 EnforcePrecondition(false, end_tile < ::MapSize());
275 return ScriptObject::Command<CMD_LEVEL_LAND>::Do(end_tile, start_tile, false, LM_LEVEL);
278 /* static */ bool ScriptTile::DemolishTile(TileIndex tile)
280 EnforcePrecondition(false, ::IsValidTile(tile));
282 return ScriptObject::Command<CMD_LANDSCAPE_CLEAR>::Do(tile);
285 /* static */ bool ScriptTile::PlantTree(TileIndex tile)
287 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
288 EnforcePrecondition(false, ::IsValidTile(tile));
290 return ScriptObject::Command<CMD_PLANT_TREE>::Do(tile, TREE_INVALID, tile, {});
293 /* static */ bool ScriptTile::PlantTreeRectangle(TileIndex tile, uint width, uint height)
295 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
296 EnforcePrecondition(false, ::IsValidTile(tile));
297 EnforcePrecondition(false, width >= 1 && width <= 20);
298 EnforcePrecondition(false, height >= 1 && height <= 20);
299 TileIndex end_tile = tile + ::TileDiffXY(width - 1, height - 1);
301 return ScriptObject::Command<CMD_PLANT_TREE>::Do(tile, TREE_INVALID, end_tile, {});
304 /* static */ bool ScriptTile::IsWithinTownInfluence(TileIndex tile, TownID town_id)
306 return ScriptTown::IsWithinTownInfluence(town_id, tile);
309 /* static */ TownID ScriptTile::GetTownAuthority(TileIndex tile)
311 if (!::IsValidTile(tile)) return INVALID_TOWN;
313 Town *town = ::ClosestTownFromTile(tile, _settings_game.economy.dist_local_authority);
314 if (town == nullptr) return INVALID_TOWN;
316 return town->index;
319 /* static */ TownID ScriptTile::GetClosestTown(TileIndex tile)
321 if (!::IsValidTile(tile)) return INVALID_TOWN;
323 Town *town = ::ClosestTownFromTile(tile, UINT_MAX);
324 if (town == nullptr) return INVALID_TOWN;
326 return town->index;
329 /* static */ Money ScriptTile::GetBuildCost(BuildType build_type)
331 switch (build_type) {
332 case BT_FOUNDATION: return ::GetPrice(PR_BUILD_FOUNDATION, 1, nullptr);
333 case BT_TERRAFORM: return ::GetPrice(PR_TERRAFORM, 1, nullptr);
334 case BT_BUILD_TREES: return ::GetPrice(PR_BUILD_TREES, 1, nullptr);
335 case BT_CLEAR_GRASS: return ::GetPrice(PR_CLEAR_GRASS, 1, nullptr);
336 case BT_CLEAR_ROUGH: return ::GetPrice(PR_CLEAR_ROUGH, 1, nullptr);
337 case BT_CLEAR_ROCKY: return ::GetPrice(PR_CLEAR_ROCKS, 1, nullptr);
338 case BT_CLEAR_FIELDS: return ::GetPrice(PR_CLEAR_FIELDS, 1, nullptr);
339 case BT_CLEAR_HOUSE: return ::GetPrice(PR_CLEAR_HOUSE, 1, nullptr);
340 case BT_CLEAR_WATER: return ::GetPrice(PR_CLEAR_WATER, 1, nullptr);
341 default: return -1;