Update: Translations from eints
[openttd-github.git] / src / script / api / script_road.cpp
blob25b7fc2631c9878cf9456d86b8c10d55616bfc58
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_road.cpp Implementation of ScriptRoad. */
10 #include "../../stdafx.h"
11 #include "script_map.hpp"
12 #include "script_station.hpp"
13 #include "script_cargo.hpp"
14 #include "../../station_base.h"
15 #include "../../landscape_cmd.h"
16 #include "../../road_cmd.h"
17 #include "../../station_cmd.h"
18 #include "../../newgrf_roadstop.h"
19 #include "../../script/squirrel_helper_type.hpp"
21 #include "../../safeguards.h"
23 /* static */ ScriptRoad::RoadVehicleType ScriptRoad::GetRoadVehicleTypeForCargo(CargoID cargo_type)
25 return ScriptCargo::HasCargoClass(cargo_type, ScriptCargo::CC_PASSENGERS) ? ROADVEHTYPE_BUS : ROADVEHTYPE_TRUCK;
28 /* static */ std::optional<std::string> ScriptRoad::GetName(RoadType road_type)
30 if (!IsRoadTypeAvailable(road_type)) return std::nullopt;
32 return GetString(GetRoadTypeInfo((::RoadType)road_type)->strings.name);
35 /* static */ bool ScriptRoad::IsRoadTile(TileIndex tile)
37 if (!::IsValidTile(tile)) return false;
39 return (::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) != ROAD_TILE_DEPOT) ||
40 IsDriveThroughRoadStationTile(tile);
43 /* static */ bool ScriptRoad::IsRoadDepotTile(TileIndex tile)
45 if (!::IsValidTile(tile)) return false;
46 if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
48 return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT &&
49 HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
52 /* static */ bool ScriptRoad::IsRoadStationTile(TileIndex tile)
54 if (!::IsValidTile(tile)) return false;
55 if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
57 return ::IsStationRoadStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
60 /* static */ bool ScriptRoad::IsDriveThroughRoadStationTile(TileIndex tile)
62 if (!::IsValidTile(tile)) return false;
63 if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
65 return ::IsDriveThroughStopTile(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)GetCurrentRoadType());
68 /* static */ bool ScriptRoad::IsRoadTypeAvailable(RoadType road_type)
70 EnforceDeityOrCompanyModeValid(false);
71 return (::RoadType)road_type < ROADTYPE_END && ::HasRoadTypeAvail(ScriptObject::GetCompany(), (::RoadType)road_type);
74 /* static */ ScriptRoad::RoadType ScriptRoad::GetCurrentRoadType()
76 return (RoadType)ScriptObject::GetRoadType();
79 /* static */ void ScriptRoad::SetCurrentRoadType(RoadType road_type)
81 if (!IsRoadTypeAvailable(road_type)) return;
83 ScriptObject::SetRoadType((::RoadType)road_type);
86 /* static */ bool ScriptRoad::RoadVehCanRunOnRoad(RoadType engine_road_type, RoadType road_road_type)
88 return RoadVehHasPowerOnRoad(engine_road_type, road_road_type);
91 /* static */ bool ScriptRoad::RoadVehHasPowerOnRoad(RoadType engine_road_type, RoadType road_road_type)
93 if (!IsRoadTypeAvailable(engine_road_type)) return false;
94 if (!IsRoadTypeAvailable(road_road_type)) return false;
96 return ::HasPowerOnRoad((::RoadType)engine_road_type, (::RoadType)road_road_type);
99 /* static */ bool ScriptRoad::HasRoadType(TileIndex tile, RoadType road_type)
101 if (!ScriptMap::IsValidTile(tile)) return false;
102 if (!IsRoadTypeAvailable(road_type)) return false;
103 return ::MayHaveRoad(tile) && HasBit(::GetPresentRoadTypes(tile), (::RoadType)road_type);
106 /* static */ bool ScriptRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
108 if (!::IsValidTile(t1)) return false;
109 if (!::IsValidTile(t2)) return false;
110 if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
112 /* Tiles not neighbouring */
113 if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
115 RoadTramType rtt = ::GetRoadTramType(ScriptObject::GetRoadType());
116 RoadBits r1 = ::GetAnyRoadBits(t1, rtt); // TODO
117 RoadBits r2 = ::GetAnyRoadBits(t2, rtt); // TODO
119 uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
120 uint dir_2 = 2 ^ dir_1;
122 DisallowedRoadDirections drd2 = IsNormalRoadTile(t2) ? GetDisallowedRoadDirections(t2) : DRD_NONE;
124 return HasBit(r1, dir_1) && HasBit(r2, dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND);
127 /* static */ bool ScriptRoad::ConvertRoadType(TileIndex start_tile, TileIndex end_tile, RoadType road_type)
129 EnforceCompanyModeValid(false);
130 EnforcePrecondition(false, ::IsValidTile(start_tile));
131 EnforcePrecondition(false, ::IsValidTile(end_tile));
132 EnforcePrecondition(false, IsRoadTypeAvailable(road_type));
134 return ScriptObject::Command<CMD_CONVERT_ROAD>::Do(start_tile, end_tile, (::RoadType)road_type);
137 /* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */
140 * Check whether the given existing bits the start and end part can be build.
141 * As the function assumes the bits being build on a slope that does not
142 * allow level foundations all of the existing parts will always be in
143 * a straight line. This also needs to hold for the start and end parts,
144 * otherwise it is for sure not valid. Finally a check will be done to
145 * determine whether the existing road parts match the to-be-build parts.
146 * As they can only be placed in one direction, just checking the start
147 * part with the first existing part is enough.
148 * @param existing The existing road parts.
149 * @param start The part that should be build first.
150 * @param end The part that will be build second.
151 * @return True if and only if the road bits can be build.
153 static bool CheckAutoExpandedRoadBits(const Array<> &existing, int32_t start, int32_t end)
155 return (start + end == 0) && (existing.empty() || existing[0] == start || existing[0] == end);
159 * Lookup function for building road parts when building on slopes is disabled.
160 * @param slope The slope of the tile to examine.
161 * @param existing The existing road parts.
162 * @param start The part that should be build first.
163 * @param end The part that will be build second.
164 * @return 0 when the build parts do not connect, 1 when they do connect once
165 * they are build or 2 when building the first part automatically
166 * builds the second part.
168 static int32_t LookupWithoutBuildOnSlopes(::Slope slope, const Array<> &existing, int32_t start, int32_t end)
170 switch (slope) {
171 /* Flat slopes can always be build. */
172 case SLOPE_FLAT:
173 return 1;
175 /* Only 4 of the slopes can be build upon. Testing the existing bits is
176 * necessary because these bits can be something else when the settings
177 * in the game have been changed.
179 case SLOPE_NE: case SLOPE_SW:
180 return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing.empty() ? 2 : 1) : 0;
181 case SLOPE_SE: case SLOPE_NW:
182 return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing.empty() ? 2 : 1) : 0;
184 /* Any other tile cannot be built on. */
185 default:
186 return 0;
191 * Rotate a neighbour bit a single time clockwise.
192 * @param neighbour The neighbour.
193 * @return The rotate neighbour data.
195 static int32_t RotateNeighbour(int32_t neighbour)
197 switch (neighbour) {
198 case -2: return -1;
199 case -1: return 2;
200 case 1: return -2;
201 case 2: return 1;
202 default: NOT_REACHED();
207 * Convert a neighbour to a road bit representation for easy internal use.
208 * @param neighbour The neighbour.
209 * @return The bits representing the direction.
211 static RoadBits NeighbourToRoadBits(int32_t neighbour)
213 switch (neighbour) {
214 case -2: return ROAD_NW;
215 case -1: return ROAD_NE;
216 case 2: return ROAD_SE;
217 case 1: return ROAD_SW;
218 default: NOT_REACHED();
223 * Lookup function for building road parts when building on slopes is enabled.
224 * @param slope The slope of the tile to examine.
225 * @param existing The existing neighbours.
226 * @param start The part that should be build first.
227 * @param end The part that will be build second.
228 * @return 0 when the build parts do not connect, 1 when they do connect once
229 * they are build or 2 when building the first part automatically
230 * builds the second part.
232 static int32_t LookupWithBuildOnSlopes(::Slope slope, const Array<> &existing, int32_t start, int32_t end)
234 /* Steep slopes behave the same as slopes with one corner raised. */
235 if (IsSteepSlope(slope)) {
236 slope = SlopeWithOneCornerRaised(GetHighestSlopeCorner(slope));
239 /* The slope is not steep. Furthermore lots of slopes are generally the
240 * same but are only rotated. So to reduce the amount of lookup work that
241 * needs to be done the data is made uniform. This means rotating the
242 * existing parts and updating the slope. */
243 static const ::Slope base_slopes[] = {
244 SLOPE_FLAT, SLOPE_W, SLOPE_W, SLOPE_SW,
245 SLOPE_W, SLOPE_EW, SLOPE_SW, SLOPE_WSE,
246 SLOPE_W, SLOPE_SW, SLOPE_EW, SLOPE_WSE,
247 SLOPE_SW, SLOPE_WSE, SLOPE_WSE};
248 static const uint8_t base_rotates[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 2, 3, 2, 2, 1};
250 if (slope >= (::Slope)lengthof(base_slopes)) {
251 /* This slope is an invalid slope, so ignore it. */
252 return -1;
254 uint8_t base_rotate = base_rotates[slope];
255 slope = base_slopes[slope];
257 /* Some slopes don't need rotating, so return early when we know we do
258 * not need to rotate. */
259 switch (slope) {
260 case SLOPE_FLAT:
261 /* Flat slopes can always be build. */
262 return 1;
264 case SLOPE_EW:
265 case SLOPE_WSE:
266 /* A slope similar to a SLOPE_EW or SLOPE_WSE will always cause
267 * foundations which makes them accessible from all sides. */
268 return 1;
270 case SLOPE_W:
271 case SLOPE_SW:
272 /* A slope for which we need perform some calculations. */
273 break;
275 default:
276 /* An invalid slope. */
277 return -1;
280 /* Now perform the actual rotation. */
281 for (int j = 0; j < base_rotate; j++) {
282 start = RotateNeighbour(start);
283 end = RotateNeighbour(end);
286 /* Create roadbits out of the data for easier handling. */
287 RoadBits start_roadbits = NeighbourToRoadBits(start);
288 RoadBits new_roadbits = start_roadbits | NeighbourToRoadBits(end);
289 RoadBits existing_roadbits = ROAD_NONE;
290 for (int32_t neighbour : existing) {
291 for (int j = 0; j < base_rotate; j++) {
292 neighbour = RotateNeighbour(neighbour);
294 existing_roadbits |= NeighbourToRoadBits(neighbour);
297 switch (slope) {
298 case SLOPE_W:
299 /* A slope similar to a SLOPE_W. */
300 switch (new_roadbits) {
301 case ROAD_N:
302 case ROAD_E:
303 case ROAD_S:
304 /* Cannot build anything with a turn from the low side. */
305 return 0;
307 case ROAD_X:
308 case ROAD_Y:
309 /* A 'sloped' tile is going to be build. */
310 if ((existing_roadbits | new_roadbits) != new_roadbits) {
311 /* There is already a foundation on the tile, or at least
312 * another slope that is not compatible with the new one. */
313 return 0;
315 /* If the start is in the low part, it is automatically
316 * building the second part too. */
317 return ((start_roadbits & ROAD_E) && !(existing_roadbits & ROAD_W)) ? 2 : 1;
319 default:
320 /* Roadbits causing a foundation are going to be build.
321 * When the existing roadbits are slopes (the lower bits
322 * are used), this cannot be done. */
323 if ((existing_roadbits | new_roadbits) == new_roadbits) return 1;
324 return (existing_roadbits & ROAD_E) ? 0 : 1;
327 case SLOPE_SW:
328 /* A slope similar to a SLOPE_SW. */
329 switch (new_roadbits) {
330 case ROAD_N:
331 case ROAD_E:
332 /* Cannot build anything with a turn from the low side. */
333 return 0;
335 case ROAD_X:
336 /* A 'sloped' tile is going to be build. */
337 if ((existing_roadbits | new_roadbits) != new_roadbits) {
338 /* There is already a foundation on the tile, or at least
339 * another slope that is not compatible with the new one. */
340 return 0;
342 /* If the start is in the low part, it is automatically
343 * building the second part too. */
344 return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1;
346 default:
347 /* Roadbits causing a foundation are going to be build.
348 * When the existing roadbits are slopes (the lower bits
349 * are used), this cannot be done. */
350 return (existing_roadbits & ROAD_NE) ? 0 : 1;
353 default:
354 NOT_REACHED();
359 * Normalise all input data so we can easily handle it without needing
360 * to call the API lots of times or create large if-elseif-elseif-else
361 * constructs.
362 * In this case it means that a TileXY(0, -1) becomes -2 and TileXY(0, 1)
363 * becomes 2. TileXY(-1, 0) and TileXY(1, 0) stay respectively -1 and 1.
364 * Any other value means that it is an invalid tile offset.
365 * @param tile The tile to normalise.
366 * @return True if and only if the tile offset is valid.
368 static bool NormaliseTileOffset(int32_t *tile)
370 if (*tile == 1 || *tile == -1) return true;
371 if (*tile == ::TileDiffXY(0, -1)) {
372 *tile = -2;
373 return true;
375 if (*tile == ::TileDiffXY(0, 1)) {
376 *tile = 2;
377 return true;
379 return false;
382 /* static */ SQInteger ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array<> &&existing, TileIndex start_, TileIndex end_)
384 ::Slope slope = (::Slope)slope_;
385 int32_t start = start_.base();
386 int32_t end = end_.base();
388 /* The start tile and end tile cannot be the same tile either. */
389 if (start == end) return -1;
391 for (size_t i = 0; i < existing.size(); i++) {
392 if (!NormaliseTileOffset(&existing[i])) return -1;
395 if (!NormaliseTileOffset(&start)) return -1;
396 if (!NormaliseTileOffset(&end)) return -1;
398 /* Without build on slopes the characteristics are vastly different, so use
399 * a different helper function (one that is much simpler). */
400 return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end);
403 /* static */ SQInteger ScriptRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end)
405 if (!::IsValidTile(tile) || !::IsValidTile(start) || !::IsValidTile(end)) return -1;
406 if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1;
408 /* ROAD_NW ROAD_SW ROAD_SE ROAD_NE */
409 const TileIndexDiff neighbours[] = {::TileDiffXY(0, -1), ::TileDiffXY(1, 0), ::TileDiffXY(0, 1), ::TileDiffXY(-1, 0)};
411 ::RoadBits rb = ::ROAD_NONE;
412 if (::IsNormalRoadTile(tile)) {
413 rb = ::GetAllRoadBits(tile);
414 } else {
415 rb = ::GetAnyRoadBits(tile, RTT_ROAD) | ::GetAnyRoadBits(tile, RTT_TRAM);
418 Array<> existing;
419 for (uint i = 0; i < lengthof(neighbours); i++) {
420 if (HasBit(rb, i)) existing.emplace_back(neighbours[i]);
423 return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), std::move(existing), start - tile, end - tile);
427 * Check whether one can reach (possibly by building) a road piece the center
428 * of the neighbouring tile. This includes roads and (drive through) stations.
429 * @param rt The road type we want to know reachability for
430 * @param start_tile The tile to "enter" the neighbouring tile.
431 * @param neighbour The direction to the neighbouring tile to "enter".
432 * @return true if and only if the tile is reachable.
434 static bool NeighbourHasReachableRoad(::RoadType rt, TileIndex start_tile, DiagDirection neighbour)
436 TileIndex neighbour_tile = ::TileAddByDiagDir(start_tile, neighbour);
437 if (!HasBit(::GetPresentRoadTypes(neighbour_tile), rt)) return false;
439 switch (::GetTileType(neighbour_tile)) {
440 case MP_ROAD:
441 return (::GetRoadTileType(neighbour_tile) != ROAD_TILE_DEPOT);
443 case MP_STATION:
444 if (::IsDriveThroughStopTile(neighbour_tile)) {
445 return (::DiagDirToAxis(neighbour) == ::DiagDirToAxis(::GetRoadStopDir(neighbour_tile)));
447 return false;
449 default:
450 return false;
454 /* static */ SQInteger ScriptRoad::GetNeighbourRoadCount(TileIndex tile)
456 if (!::IsValidTile(tile)) return -1;
457 if (!IsRoadTypeAvailable(GetCurrentRoadType())) return -1;
459 ::RoadType rt = (::RoadType)GetCurrentRoadType();
460 int32_t neighbour = 0;
462 if (TileX(tile) > 0 && NeighbourHasReachableRoad(rt, tile, DIAGDIR_NE)) neighbour++;
463 if (NeighbourHasReachableRoad(rt, tile, DIAGDIR_SE)) neighbour++;
464 if (NeighbourHasReachableRoad(rt, tile, DIAGDIR_SW)) neighbour++;
465 if (TileY(tile) > 0 && NeighbourHasReachableRoad(rt, tile, DIAGDIR_NW)) neighbour++;
467 return neighbour;
470 /* static */ TileIndex ScriptRoad::GetRoadDepotFrontTile(TileIndex depot)
472 if (!IsRoadDepotTile(depot)) return INVALID_TILE;
474 return depot + ::TileOffsByDiagDir(::GetRoadDepotDirection(depot));
477 /* static */ TileIndex ScriptRoad::GetRoadStationFrontTile(TileIndex station)
479 if (!IsRoadStationTile(station)) return INVALID_TILE;
481 return station + ::TileOffsByDiagDir(::GetRoadStopDir(station));
484 /* static */ TileIndex ScriptRoad::GetDriveThroughBackTile(TileIndex station)
486 if (!IsDriveThroughRoadStationTile(station)) return INVALID_TILE;
488 return station + ::TileOffsByDiagDir(::ReverseDiagDir(::GetRoadStopDir(station)));
491 /* static */ bool ScriptRoad::_BuildRoadInternal(TileIndex start, TileIndex end, bool one_way, bool full)
493 EnforceDeityOrCompanyModeValid(false);
494 EnforcePrecondition(false, start != end);
495 EnforcePrecondition(false, ::IsValidTile(start));
496 EnforcePrecondition(false, ::IsValidTile(end));
497 EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
498 EnforcePrecondition(false, !one_way || RoadTypeIsRoad(ScriptObject::GetRoadType()));
499 EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
501 Axis axis = ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X;
502 return ScriptObject::Command<CMD_BUILD_LONG_ROAD>::Do(end, start, ScriptObject::GetRoadType(), axis, one_way ? DRD_NORTHBOUND : DRD_NONE, (start < end) == !full, (start < end) != !full, true);
505 /* static */ bool ScriptRoad::BuildRoad(TileIndex start, TileIndex end)
507 return _BuildRoadInternal(start, end, false, false);
510 /* static */ bool ScriptRoad::BuildOneWayRoad(TileIndex start, TileIndex end)
512 EnforceCompanyModeValid(false);
513 return _BuildRoadInternal(start, end, true, false);
516 /* static */ bool ScriptRoad::BuildRoadFull(TileIndex start, TileIndex end)
518 return _BuildRoadInternal(start, end, false, true);
521 /* static */ bool ScriptRoad::BuildOneWayRoadFull(TileIndex start, TileIndex end)
523 EnforceCompanyModeValid(false);
524 return _BuildRoadInternal(start, end, true, true);
527 /* static */ bool ScriptRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
529 EnforceCompanyModeValid(false);
530 EnforcePrecondition(false, tile != front);
531 EnforcePrecondition(false, ::IsValidTile(tile));
532 EnforcePrecondition(false, ::IsValidTile(front));
533 EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
534 EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
536 DiagDirection entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? DIAGDIR_SE : DIAGDIR_NW) : (::TileX(tile) < ::TileX(front) ? DIAGDIR_SW : DIAGDIR_NE);
538 return ScriptObject::Command<CMD_BUILD_ROAD_DEPOT>::Do(tile, ScriptObject::GetRoadType(), entrance_dir);
541 /* static */ bool ScriptRoad::_BuildRoadStationInternal(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, bool drive_through, StationID station_id)
543 EnforceCompanyModeValid(false);
544 EnforcePrecondition(false, tile != front);
545 EnforcePrecondition(false, ::IsValidTile(tile));
546 EnforcePrecondition(false, ::IsValidTile(front));
547 EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
548 EnforcePrecondition(false, station_id == ScriptStation::STATION_NEW || station_id == ScriptStation::STATION_JOIN_ADJACENT || ScriptStation::IsValidStation(station_id));
549 EnforcePrecondition(false, road_veh_type == ROADVEHTYPE_BUS || road_veh_type == ROADVEHTYPE_TRUCK);
550 EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
552 DiagDirection entrance_dir = DiagdirBetweenTiles(tile, front);
553 RoadStopType stop_type = road_veh_type == ROADVEHTYPE_TRUCK ? ROADSTOP_TRUCK : ROADSTOP_BUS;
554 StationID to_join = ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION;
555 return ScriptObject::Command<CMD_BUILD_ROAD_STOP>::Do(tile, 1, 1, stop_type, drive_through, entrance_dir, ScriptObject::GetRoadType(), ROADSTOP_CLASS_DFLT, 0, to_join, station_id != ScriptStation::STATION_JOIN_ADJACENT);
558 /* static */ bool ScriptRoad::BuildRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
560 return _BuildRoadStationInternal(tile, front, road_veh_type, false, station_id);
563 /* static */ bool ScriptRoad::BuildDriveThroughRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
565 return _BuildRoadStationInternal(tile, front, road_veh_type, true, station_id);
568 /* static */ bool ScriptRoad::RemoveRoad(TileIndex start, TileIndex end)
570 EnforceCompanyModeValid(false);
571 EnforcePrecondition(false, start != end);
572 EnforcePrecondition(false, ::IsValidTile(start));
573 EnforcePrecondition(false, ::IsValidTile(end));
574 EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
575 EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
577 return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(end, start, ScriptObject::GetRoadType(), ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X, start < end, start >= end);
580 /* static */ bool ScriptRoad::RemoveRoadFull(TileIndex start, TileIndex end)
582 EnforceCompanyModeValid(false);
583 EnforcePrecondition(false, start != end);
584 EnforcePrecondition(false, ::IsValidTile(start));
585 EnforcePrecondition(false, ::IsValidTile(end));
586 EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
587 EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
589 return ScriptObject::Command<CMD_REMOVE_LONG_ROAD>::Do(end, start, ScriptObject::GetRoadType(), ::TileY(start) != ::TileY(end) ? AXIS_Y : AXIS_X, start >= end, start < end);
592 /* static */ bool ScriptRoad::RemoveRoadDepot(TileIndex tile)
594 EnforceCompanyModeValid(false);
595 EnforcePrecondition(false, ::IsValidTile(tile));
596 EnforcePrecondition(false, IsTileType(tile, MP_ROAD))
597 EnforcePrecondition(false, GetRoadTileType(tile) == ROAD_TILE_DEPOT);
599 return ScriptObject::Command<CMD_LANDSCAPE_CLEAR>::Do(tile);
602 /* static */ bool ScriptRoad::RemoveRoadStation(TileIndex tile)
604 EnforceCompanyModeValid(false);
605 EnforcePrecondition(false, ::IsValidTile(tile));
606 EnforcePrecondition(false, IsTileType(tile, MP_STATION));
607 EnforcePrecondition(false, IsStationRoadStop(tile));
609 return ScriptObject::Command<CMD_REMOVE_ROAD_STOP>::Do(tile, 1, 1, GetRoadStopType(tile), false);
612 /* static */ Money ScriptRoad::GetBuildCost(RoadType roadtype, BuildType build_type)
614 if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return -1;
616 switch (build_type) {
617 case BT_ROAD: return ::RoadBuildCost((::RoadType)roadtype);
618 case BT_DEPOT: return ::GetPrice(PR_BUILD_DEPOT_ROAD, 1, nullptr);
619 case BT_BUS_STOP: return ::GetPrice(PR_BUILD_STATION_BUS, 1, nullptr);
620 case BT_TRUCK_STOP: return ::GetPrice(PR_BUILD_STATION_TRUCK, 1, nullptr);
621 default: return -1;
625 /* static */ ScriptRoad::RoadTramTypes ScriptRoad::GetRoadTramType(RoadType roadtype)
627 return (RoadTramTypes)(1 << ::GetRoadTramType((::RoadType)roadtype));
630 /* static */ SQInteger ScriptRoad::GetMaxSpeed(RoadType road_type)
632 if (!ScriptRoad::IsRoadTypeAvailable(road_type)) return -1;
634 return GetRoadTypeInfo((::RoadType)road_type)->max_speed;
637 /* static */ SQInteger ScriptRoad::GetMaintenanceCostFactor(RoadType roadtype)
639 if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return 0;
641 return GetRoadTypeInfo((::RoadType)roadtype)->maintenance_multiplier;