4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file script_tile.cpp Implementation of ScriptTile. */
12 #include "../../stdafx.h"
13 #include "script_tile.hpp"
14 #include "script_map.hpp"
15 #include "script_town.hpp"
16 #include "../../station_func.h"
17 #include "../../water_map.h"
18 #include "../../clear_map.h"
19 #include "../../tree_map.h"
20 #include "../../town.h"
21 #include "../../landscape.h"
23 #include "../../safeguards.h"
25 /* static */ bool ScriptTile::IsBuildable(TileIndex tile
)
27 if (!::IsValidTile(tile
)) return false;
29 switch (::GetTileType(tile
)) {
30 default: return false;
31 case MP_CLEAR
: return true;
32 case MP_TREES
: return true;
33 case MP_WATER
: return IsCoast(tile
);
35 /* Tram bits aren't considered buildable */
36 if (::GetRoadTypes(tile
) != ROADTYPES_ROAD
) return false;
37 /* Depots and crossings aren't considered buildable */
38 if (::GetRoadTileType(tile
) != ROAD_TILE_NORMAL
) return false;
39 if (!HasExactlyOneBit(::GetRoadBits(tile
, ROADTYPE_ROAD
))) return false;
40 if (::IsRoadOwner(tile
, ROADTYPE_ROAD
, OWNER_TOWN
)) return true;
41 if (::IsRoadOwner(tile
, ROADTYPE_ROAD
, ScriptObject::GetCompany())) return true;
46 /* static */ bool ScriptTile::IsBuildableRectangle(TileIndex tile
, uint width
, uint height
)
48 /* Check whether we can extract valid X and Y */
49 if (!::IsValidTile(tile
)) return false;
51 uint tx
= ScriptMap::GetTileX(tile
);
52 uint ty
= ScriptMap::GetTileY(tile
);
54 for (uint x
= tx
; x
< width
+ tx
; x
++) {
55 for (uint y
= ty
; y
< height
+ ty
; y
++) {
56 if (!IsBuildable(ScriptMap::GetTileIndex(x
, y
))) return false;
63 /* static */ bool ScriptTile::IsWaterTile(TileIndex tile
)
65 if (!::IsValidTile(tile
)) return false;
67 return ::IsTileType(tile
, MP_WATER
) && !::IsCoast(tile
);
70 /* static */ bool ScriptTile::IsCoastTile(TileIndex tile
)
72 if (!::IsValidTile(tile
)) return false;
74 return (::IsTileType(tile
, MP_WATER
) && ::IsCoast(tile
)) ||
75 (::IsTileType(tile
, MP_TREES
) && ::GetTreeGround(tile
) == TREE_GROUND_SHORE
);
78 /* static */ bool ScriptTile::IsStationTile(TileIndex tile
)
80 if (!::IsValidTile(tile
)) return false;
82 return ::IsTileType(tile
, MP_STATION
);
85 /* static */ bool ScriptTile::IsSteepSlope(Slope slope
)
87 if ((slope
& ~(SLOPE_ELEVATED
| SLOPE_STEEP
| SLOPE_HALFTILE_MASK
)) != 0) return false;
89 return ::IsSteepSlope((::Slope
)slope
);
92 /* static */ bool ScriptTile::IsHalftileSlope(Slope slope
)
94 if ((slope
& ~(SLOPE_ELEVATED
| SLOPE_STEEP
| SLOPE_HALFTILE_MASK
)) != 0) return false;
96 return ::IsHalftileSlope((::Slope
)slope
);
99 /* static */ bool ScriptTile::HasTreeOnTile(TileIndex tile
)
101 if (!::IsValidTile(tile
)) return false;
103 return ::IsTileType(tile
, MP_TREES
);
106 /* static */ bool ScriptTile::IsFarmTile(TileIndex tile
)
108 if (!::IsValidTile(tile
)) return false;
110 return (::IsTileType(tile
, MP_CLEAR
) && ::IsClearGround(tile
, CLEAR_FIELDS
));
113 /* static */ bool ScriptTile::IsRockTile(TileIndex tile
)
115 if (!::IsValidTile(tile
)) return false;
117 return (::IsTileType(tile
, MP_CLEAR
) && ::GetRawClearGround(tile
) == ::CLEAR_ROCKS
);
120 /* static */ bool ScriptTile::IsRoughTile(TileIndex tile
)
122 if (!::IsValidTile(tile
)) return false;
124 return (::IsTileType(tile
, MP_CLEAR
) && ::GetRawClearGround(tile
) == ::CLEAR_ROUGH
);
127 /* static */ bool ScriptTile::IsSnowTile(TileIndex tile
)
129 if (!::IsValidTile(tile
)) return false;
131 return (::IsTileType(tile
, MP_CLEAR
) && ::IsSnowTile(tile
));
134 /* static */ bool ScriptTile::IsDesertTile(TileIndex tile
)
136 if (!::IsValidTile(tile
)) return false;
138 return (::IsTileType(tile
, MP_CLEAR
) && ::IsClearGround(tile
, CLEAR_DESERT
));
141 /* static */ ScriptTile::TerrainType
ScriptTile::GetTerrainType(TileIndex tile
)
143 if (!::IsValidTile(tile
)) return TERRAIN_NORMAL
;
145 switch (::GetTerrainType(tile
)) {
147 case 0: return TERRAIN_NORMAL
;
148 case 1: return TERRAIN_DESERT
;
149 case 2: return TERRAIN_RAINFOREST
;
150 case 4: return TERRAIN_SNOW
;
154 /* static */ ScriptTile::Slope
ScriptTile::GetSlope(TileIndex tile
)
156 if (!::IsValidTile(tile
)) return SLOPE_INVALID
;
158 return (Slope
)::GetTileSlope(tile
);
161 /* static */ ScriptTile::Slope
ScriptTile::GetComplementSlope(Slope slope
)
163 if ((slope
& ~SLOPE_ELEVATED
) != 0) return SLOPE_INVALID
;
165 return (Slope
)::ComplementSlope((::Slope
)slope
);
168 /* static */ int32
ScriptTile::GetMinHeight(TileIndex tile
)
170 if (!::IsValidTile(tile
)) return -1;
172 return ::GetTileZ(tile
);
175 /* static */ int32
ScriptTile::GetMaxHeight(TileIndex tile
)
177 if (!::IsValidTile(tile
)) return -1;
179 return ::GetTileMaxZ(tile
);
182 /* static */ int32
ScriptTile::GetCornerHeight(TileIndex tile
, Corner corner
)
184 if (!::IsValidTile(tile
) || !::IsValidCorner((::Corner
)corner
)) return -1;
187 ::Slope slope
= ::GetTileSlope(tile
, &z
);
188 return (z
+ ::GetSlopeZInCorner(slope
, (::Corner
)corner
));
191 /* static */ ScriptCompany::CompanyID
ScriptTile::GetOwner(TileIndex tile
)
193 if (!::IsValidTile(tile
)) return ScriptCompany::COMPANY_INVALID
;
194 if (::IsTileType(tile
, MP_HOUSE
)) return ScriptCompany::COMPANY_INVALID
;
195 if (::IsTileType(tile
, MP_INDUSTRY
)) return ScriptCompany::COMPANY_INVALID
;
197 return ScriptCompany::ResolveCompanyID((ScriptCompany::CompanyID
)(byte
)::GetTileOwner(tile
));
200 /* static */ bool ScriptTile::HasTransportType(TileIndex tile
, TransportType transport_type
)
202 if (!::IsValidTile(tile
)) return false;
204 return ::TrackStatusToTrackdirBits(::GetTileTrackStatus(tile
, (::TransportType
)transport_type
, UINT32_MAX
)) != TRACKDIR_BIT_NONE
;
207 /* static */ int32
ScriptTile::GetCargoAcceptance(TileIndex tile
, CargoID cargo_type
, int width
, int height
, int radius
)
209 if (!::IsValidTile(tile
) || width
<= 0 || height
<= 0 || radius
< 0 || !ScriptCargo::IsValidCargo(cargo_type
)) return -1;
211 CargoArray acceptance
= ::GetAcceptanceAroundTiles(tile
, width
, height
, _settings_game
.station
.modified_catchment
? radius
: (int)CA_UNMODIFIED
);
212 return acceptance
[cargo_type
];
215 /* static */ int32
ScriptTile::GetCargoProduction(TileIndex tile
, CargoID cargo_type
, int width
, int height
, int radius
)
217 if (!::IsValidTile(tile
) || width
<= 0 || height
<= 0 || radius
< 0 || !ScriptCargo::IsValidCargo(cargo_type
)) return -1;
219 CargoArray produced
= ::GetProductionAroundTiles(tile
, width
, height
, _settings_game
.station
.modified_catchment
? radius
: (int)CA_UNMODIFIED
);
220 return produced
[cargo_type
];
223 /* static */ int32
ScriptTile::GetDistanceManhattanToTile(TileIndex tile_from
, TileIndex tile_to
)
225 return ScriptMap::DistanceManhattan(tile_from
, tile_to
);
228 /* static */ int32
ScriptTile::GetDistanceSquareToTile(TileIndex tile_from
, TileIndex tile_to
)
230 return ScriptMap::DistanceSquare(tile_from
, tile_to
);
233 /* static */ bool ScriptTile::RaiseTile(TileIndex tile
, int32 slope
)
235 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
236 EnforcePrecondition(false, tile
< ::MapSize());
238 return ScriptObject::DoCommand(tile
, slope
, 1, CMD_TERRAFORM_LAND
);
241 /* static */ bool ScriptTile::LowerTile(TileIndex tile
, int32 slope
)
243 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
244 EnforcePrecondition(false, tile
< ::MapSize());
246 return ScriptObject::DoCommand(tile
, slope
, 0, CMD_TERRAFORM_LAND
);
249 /* static */ bool ScriptTile::LevelTiles(TileIndex start_tile
, TileIndex end_tile
)
251 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
252 EnforcePrecondition(false, start_tile
< ::MapSize());
253 EnforcePrecondition(false, end_tile
< ::MapSize());
255 return ScriptObject::DoCommand(end_tile
, start_tile
, LM_LEVEL
<< 1, CMD_LEVEL_LAND
);
258 /* static */ bool ScriptTile::DemolishTile(TileIndex tile
)
260 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
261 EnforcePrecondition(false, ::IsValidTile(tile
));
263 return ScriptObject::DoCommand(tile
, 0, 0, CMD_LANDSCAPE_CLEAR
);
266 /* static */ bool ScriptTile::PlantTree(TileIndex tile
)
268 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
269 EnforcePrecondition(false, ::IsValidTile(tile
));
271 return ScriptObject::DoCommand(tile
, TREE_INVALID
, tile
, CMD_PLANT_TREE
);
274 /* static */ bool ScriptTile::PlantTreeRectangle(TileIndex tile
, uint width
, uint height
)
276 EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY
);
277 EnforcePrecondition(false, ::IsValidTile(tile
));
278 EnforcePrecondition(false, width
>= 1 && width
<= 20);
279 EnforcePrecondition(false, height
>= 1 && height
<= 20);
280 TileIndex end_tile
= tile
+ ::TileDiffXY(width
- 1, height
- 1);
282 return ScriptObject::DoCommand(tile
, TREE_INVALID
, end_tile
, CMD_PLANT_TREE
);
285 /* static */ bool ScriptTile::IsWithinTownInfluence(TileIndex tile
, TownID town_id
)
287 return ScriptTown::IsWithinTownInfluence(town_id
, tile
);
290 /* static */ TownID
ScriptTile::GetTownAuthority(TileIndex tile
)
292 if (!::IsValidTile(tile
)) return INVALID_TOWN
;
294 Town
*town
= ::ClosestTownFromTile(tile
, _settings_game
.economy
.dist_local_authority
);
295 if (town
== NULL
) return INVALID_TOWN
;
300 /* static */ TownID
ScriptTile::GetClosestTown(TileIndex tile
)
302 if (!::IsValidTile(tile
)) return INVALID_TOWN
;
304 Town
*town
= ::ClosestTownFromTile(tile
, UINT_MAX
);
305 if (town
== NULL
) return INVALID_TOWN
;
310 /* static */ Money
ScriptTile::GetBuildCost(BuildType build_type
)
312 switch (build_type
) {
313 case BT_FOUNDATION
: return ::GetPrice(PR_BUILD_FOUNDATION
, 1, NULL
);
314 case BT_TERRAFORM
: return ::GetPrice(PR_TERRAFORM
, 1, NULL
);
315 case BT_BUILD_TREES
: return ::GetPrice(PR_BUILD_TREES
, 1, NULL
);
316 case BT_CLEAR_GRASS
: return ::GetPrice(PR_CLEAR_GRASS
, 1, NULL
);
317 case BT_CLEAR_ROUGH
: return ::GetPrice(PR_CLEAR_ROUGH
, 1, NULL
);
318 case BT_CLEAR_ROCKY
: return ::GetPrice(PR_CLEAR_ROCKS
, 1, NULL
);
319 case BT_CLEAR_FIELDS
: return ::GetPrice(PR_CLEAR_FIELDS
, 1, NULL
);
320 case BT_CLEAR_HOUSE
: return ::GetPrice(PR_CLEAR_HOUSE
, 1, NULL
);