script_road.cpp

Go to the documentation of this file.
00001 /* $Id: script_road.cpp 23633 2011-12-19 21:05:36Z truebrain $ */
00002 
00003 /*
00004  * This file is part of OpenTTD.
00005  * 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.
00006  * 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.
00007  * 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/>.
00008  */
00009 
00012 #include "../../stdafx.h"
00013 #include "script_map.hpp"
00014 #include "script_station.hpp"
00015 #include "script_cargo.hpp"
00016 #include "../../station_base.h"
00017 #include "../../script/squirrel_helper_type.hpp"
00018 
00019 /* static */ ScriptRoad::RoadVehicleType ScriptRoad::GetRoadVehicleTypeForCargo(CargoID cargo_type)
00020 {
00021   return ScriptCargo::HasCargoClass(cargo_type, ScriptCargo::CC_PASSENGERS) ? ROADVEHTYPE_BUS : ROADVEHTYPE_TRUCK;
00022 }
00023 
00024 /* static */ bool ScriptRoad::IsRoadTile(TileIndex tile)
00025 {
00026   if (!::IsValidTile(tile)) return false;
00027 
00028   return (::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) != ROAD_TILE_DEPOT) ||
00029       IsDriveThroughRoadStationTile(tile);
00030 }
00031 
00032 /* static */ bool ScriptRoad::IsRoadDepotTile(TileIndex tile)
00033 {
00034   if (!::IsValidTile(tile)) return false;
00035 
00036   return ::IsTileType(tile, MP_ROAD) && ::GetRoadTileType(tile) == ROAD_TILE_DEPOT &&
00037       (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
00038 }
00039 
00040 /* static */ bool ScriptRoad::IsRoadStationTile(TileIndex tile)
00041 {
00042   if (!::IsValidTile(tile)) return false;
00043 
00044   return ::IsRoadStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
00045 }
00046 
00047 /* static */ bool ScriptRoad::IsDriveThroughRoadStationTile(TileIndex tile)
00048 {
00049   if (!::IsValidTile(tile)) return false;
00050 
00051   return ::IsDriveThroughStopTile(tile) && (::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType()) & ::GetRoadTypes(tile)) != 0;
00052 }
00053 
00054 /* static */ bool ScriptRoad::IsRoadTypeAvailable(RoadType road_type)
00055 {
00056   return ::HasRoadTypesAvail(ScriptObject::GetCompany(), ::RoadTypeToRoadTypes((::RoadType)road_type));
00057 }
00058 
00059 /* static */ ScriptRoad::RoadType ScriptRoad::GetCurrentRoadType()
00060 {
00061   return (RoadType)ScriptObject::GetRoadType();
00062 }
00063 
00064 /* static */ void ScriptRoad::SetCurrentRoadType(RoadType road_type)
00065 {
00066   if (!IsRoadTypeAvailable(road_type)) return;
00067 
00068   ScriptObject::SetRoadType((::RoadType)road_type);
00069 }
00070 
00071 /* static */ bool ScriptRoad::HasRoadType(TileIndex tile, RoadType road_type)
00072 {
00073   if (!ScriptMap::IsValidTile(tile)) return false;
00074   if (!IsRoadTypeAvailable(road_type)) return false;
00075   return ::GetAnyRoadBits(tile, (::RoadType)road_type, false) != ROAD_NONE;
00076 }
00077 
00078 /* static */ bool ScriptRoad::AreRoadTilesConnected(TileIndex t1, TileIndex t2)
00079 {
00080   if (!::IsValidTile(t1)) return false;
00081   if (!::IsValidTile(t2)) return false;
00082   if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
00083 
00084   /* Tiles not neighbouring */
00085   if ((abs((int)::TileX(t1) - (int)::TileX(t2)) + abs((int)::TileY(t1) - (int)::TileY(t2))) != 1) return false;
00086 
00087   RoadBits r1 = ::GetAnyRoadBits(t1, ScriptObject::GetRoadType());
00088   RoadBits r2 = ::GetAnyRoadBits(t2, ScriptObject::GetRoadType());
00089 
00090   uint dir_1 = (::TileX(t1) == ::TileX(t2)) ? (::TileY(t1) < ::TileY(t2) ? 2 : 0) : (::TileX(t1) < ::TileX(t2) ? 1 : 3);
00091   uint dir_2 = 2 ^ dir_1;
00092 
00093   DisallowedRoadDirections drd2 = IsNormalRoadTile(t2) ? GetDisallowedRoadDirections(t2) : DRD_NONE;
00094 
00095   return HasBit(r1, dir_1) && HasBit(r2, dir_2) && drd2 != DRD_BOTH && drd2 != (dir_1 > dir_2 ? DRD_SOUTHBOUND : DRD_NORTHBOUND);
00096 }
00097 
00098 /* Helper functions for ScriptRoad::CanBuildConnectedRoadParts(). */
00099 
00114 static bool CheckAutoExpandedRoadBits(const Array *existing, int32 start, int32 end)
00115 {
00116   return (start + end == 0) && (existing->size == 0 || existing->array[0] == start || existing->array[0] == end);
00117 }
00118 
00129 static int32 LookupWithoutBuildOnSlopes(::Slope slope, const Array *existing, int32 start, int32 end)
00130 {
00131   switch (slope) {
00132     /* Flat slopes can always be build. */
00133     case SLOPE_FLAT:
00134       return 1;
00135 
00136     /* Only 4 of the slopes can be build upon. Testing the existing bits is
00137      * necessary because these bits can be something else when the settings
00138      * in the game have been changed.
00139      */
00140     case SLOPE_NE: case SLOPE_SW:
00141       return (CheckAutoExpandedRoadBits(existing, start, end) && (start == 1 || end == 1)) ? (existing->size == 0 ? 2 : 1) : 0;
00142     case SLOPE_SE: case SLOPE_NW:
00143       return (CheckAutoExpandedRoadBits(existing, start, end) && (start != 1 && end != 1)) ? (existing->size == 0 ? 2 : 1) : 0;
00144 
00145     /* Any other tile cannot be built on. */
00146     default:
00147       return 0;
00148   }
00149 }
00150 
00156 static int32 RotateNeighbour(int32 neighbour)
00157 {
00158   switch (neighbour) {
00159     case -2: return -1;
00160     case -1: return  2;
00161     case  1: return -2;
00162     case  2: return  1;
00163     default: NOT_REACHED();
00164   }
00165 }
00166 
00172 static RoadBits NeighbourToRoadBits(int32 neighbour)
00173 {
00174   switch (neighbour) {
00175     case -2: return ROAD_NW;
00176     case -1: return ROAD_NE;
00177     case  2: return ROAD_SE;
00178     case  1: return ROAD_SW;
00179     default: NOT_REACHED();
00180   }
00181 }
00182 
00193 static int32 LookupWithBuildOnSlopes(::Slope slope, Array *existing, int32 start, int32 end)
00194 {
00195   /* Steep slopes behave the same as slopes with one corner raised. */
00196   if (IsSteepSlope(slope)) {
00197     slope = SlopeWithOneCornerRaised(GetHighestSlopeCorner(slope));
00198   }
00199 
00200   /* The slope is not steep. Furthermore lots of slopes are generally the
00201    * same but are only rotated. So to reduce the amount of lookup work that
00202    * needs to be done the data is made uniform. This means rotating the
00203    * existing parts and updating the slope. */
00204   static const ::Slope base_slopes[] = {
00205     SLOPE_FLAT, SLOPE_W,   SLOPE_W,   SLOPE_SW,
00206     SLOPE_W,    SLOPE_EW,  SLOPE_SW,  SLOPE_WSE,
00207     SLOPE_W,    SLOPE_SW,  SLOPE_EW,  SLOPE_WSE,
00208     SLOPE_SW,   SLOPE_WSE, SLOPE_WSE};
00209   static const byte base_rotates[] = {0, 0, 1, 0, 2, 0, 1, 0, 3, 3, 2, 3, 2, 2, 1};
00210 
00211   if (slope >= (::Slope)lengthof(base_slopes)) {
00212     /* This slope is an invalid slope, so ignore it. */
00213     return -1;
00214   }
00215   byte base_rotate = base_rotates[slope];
00216   slope = base_slopes[slope];
00217 
00218   /* Some slopes don't need rotating, so return early when we know we do
00219    * not need to rotate. */
00220   switch (slope) {
00221     case SLOPE_FLAT:
00222       /* Flat slopes can always be build. */
00223       return 1;
00224 
00225     case SLOPE_EW:
00226     case SLOPE_WSE:
00227       /* A slope similar to a SLOPE_EW or SLOPE_WSE will always cause
00228        * foundations which makes them accessible from all sides. */
00229       return 1;
00230 
00231     case SLOPE_W:
00232     case SLOPE_SW:
00233       /* A slope for which we need perform some calculations. */
00234       break;
00235 
00236     default:
00237       /* An invalid slope. */
00238       return -1;
00239   }
00240 
00241   /* Now perform the actual rotation. */
00242   for (int j = 0; j < base_rotate; j++) {
00243     for (int i = 0; i < existing->size; i++) {
00244       existing->array[i] = RotateNeighbour(existing->array[i]);
00245     }
00246     start = RotateNeighbour(start);
00247     end   = RotateNeighbour(end);
00248   }
00249 
00250   /* Create roadbits out of the data for easier handling. */
00251   RoadBits start_roadbits    = NeighbourToRoadBits(start);
00252   RoadBits new_roadbits      = start_roadbits | NeighbourToRoadBits(end);
00253   RoadBits existing_roadbits = ROAD_NONE;
00254   for (int i = 0; i < existing->size; i++) {
00255     existing_roadbits |= NeighbourToRoadBits(existing->array[i]);
00256   }
00257 
00258   switch (slope) {
00259     case SLOPE_W:
00260       /* A slope similar to a SLOPE_W. */
00261       switch (new_roadbits) {
00262         case ROAD_N:
00263         case ROAD_E:
00264         case ROAD_S:
00265           /* Cannot build anything with a turn from the low side. */
00266           return 0;
00267 
00268         case ROAD_X:
00269         case ROAD_Y:
00270           /* A 'sloped' tile is going to be build. */
00271           if ((existing_roadbits | new_roadbits) != new_roadbits) {
00272             /* There is already a foundation on the tile, or at least
00273              * another slope that is not compatible with the new one. */
00274             return 0;
00275           }
00276           /* If the start is in the low part, it is automatically
00277            * building the second part too. */
00278           return ((start_roadbits & ROAD_E) && !(existing_roadbits & ROAD_W)) ? 2 : 1;
00279 
00280         default:
00281           /* Roadbits causing a foundation are going to be build.
00282            * When the existing roadbits are slopes (the lower bits
00283            * are used), this cannot be done. */
00284           if ((existing_roadbits | new_roadbits) == new_roadbits) return 1;
00285           return (existing_roadbits & ROAD_E) ? 0 : 1;
00286       }
00287 
00288     case SLOPE_SW:
00289       /* A slope similar to a SLOPE_SW. */
00290       switch (new_roadbits) {
00291         case ROAD_N:
00292         case ROAD_E:
00293           /* Cannot build anything with a turn from the low side. */
00294           return 0;
00295 
00296         case ROAD_X:
00297           /* A 'sloped' tile is going to be build. */
00298           if ((existing_roadbits | new_roadbits) != new_roadbits) {
00299             /* There is already a foundation on the tile, or at least
00300              * another slope that is not compatible with the new one. */
00301             return 0;
00302           }
00303           /* If the start is in the low part, it is automatically
00304            * building the second part too. */
00305           return ((start_roadbits & ROAD_NE) && !(existing_roadbits & ROAD_SW)) ? 2 : 1;
00306 
00307         default:
00308           /* Roadbits causing a foundation are going to be build.
00309            * When the existing roadbits are slopes (the lower bits
00310            * are used), this cannot be done. */
00311           return (existing_roadbits & ROAD_NE) ? 0 : 1;
00312       }
00313 
00314     default:
00315       NOT_REACHED();
00316   }
00317 }
00318 
00329 static bool NormaliseTileOffset(int32 *tile)
00330 {
00331     if (*tile == 1 || *tile == -1) return true;
00332     if (*tile == ::TileDiffXY(0, -1)) {
00333       *tile = -2;
00334       return true;
00335     }
00336     if (*tile == ::TileDiffXY(0, 1)) {
00337       *tile = 2;
00338       return true;
00339     }
00340     return false;
00341 }
00342 
00343 /* static */ int32 ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::Slope slope_, Array *existing, TileIndex start_, TileIndex end_)
00344 {
00345 	::Slope slope = (::Slope)slope_;
00346   int32 start = start_;
00347   int32 end = end_;
00348 
00349   /* The start tile and end tile cannot be the same tile either. */
00350   if (start == end) return -1;
00351 
00352   for (int i = 0; i < existing->size; i++) {
00353     if (!NormaliseTileOffset(&existing->array[i])) return -1;
00354   }
00355 
00356   if (!NormaliseTileOffset(&start)) return -1;
00357   if (!NormaliseTileOffset(&end)) return -1;
00358 
00359   /* Without build on slopes the characteristics are vastly different, so use
00360    * a different helper function (one that is much simpler). */
00361   return _settings_game.construction.build_on_slopes ? LookupWithBuildOnSlopes(slope, existing, start, end) : LookupWithoutBuildOnSlopes(slope, existing, start, end);
00362 }
00363 
00364 /* static */ int32 ScriptRoad::CanBuildConnectedRoadPartsHere(TileIndex tile, TileIndex start, TileIndex end)
00365 {
00366   if (!::IsValidTile(tile) || !::IsValidTile(start) || !::IsValidTile(end)) return -1;
00367   if (::DistanceManhattan(tile, start) != 1 || ::DistanceManhattan(tile, end) != 1) return -1;
00368 
00369   /*                                       ROAD_NW              ROAD_SW             ROAD_SE             ROAD_NE */
00370   static const TileIndex neighbours[] = {::TileDiffXY(0, -1), ::TileDiffXY(1, 0), ::TileDiffXY(0, 1), ::TileDiffXY(-1, 0)};
00371   Array *existing = (Array*)alloca(sizeof(Array) + lengthof(neighbours) * sizeof(int32));
00372   existing->size = 0;
00373 
00374 	::RoadBits rb = ::ROAD_NONE;
00375   if (::IsNormalRoadTile(tile)) {
00376     rb = ::GetAllRoadBits(tile);
00377   } else {
00378     for (::RoadType rt = ::ROADTYPE_BEGIN; rt < ::ROADTYPE_END; rt++) rb |= ::GetAnyRoadBits(tile, rt);
00379   }
00380   for (uint i = 0; i < lengthof(neighbours); i++) {
00381     if (HasBit(rb, i)) existing->array[existing->size++] = neighbours[i];
00382   }
00383 
00384   return ScriptRoad::CanBuildConnectedRoadParts(ScriptTile::GetSlope(tile), existing, start - tile, end - tile);
00385 }
00386 
00395 static bool NeighbourHasReachableRoad(::RoadTypes rts, TileIndex start_tile, DiagDirection neighbour)
00396 {
00397   TileIndex neighbour_tile = ::TileAddByDiagDir(start_tile, neighbour);
00398   if ((rts & ::GetRoadTypes(neighbour_tile)) == 0) return false;
00399 
00400   switch (::GetTileType(neighbour_tile)) {
00401     case MP_ROAD:
00402       return (::GetRoadTileType(neighbour_tile) != ROAD_TILE_DEPOT);
00403 
00404     case MP_STATION:
00405       if (::IsDriveThroughStopTile(neighbour_tile)) {
00406         return (::DiagDirToAxis(neighbour) == ::DiagDirToAxis(::GetRoadStopDir(neighbour_tile)));
00407       }
00408       return false;
00409 
00410     default:
00411       return false;
00412   }
00413 }
00414 
00415 /* static */ int32 ScriptRoad::GetNeighbourRoadCount(TileIndex tile)
00416 {
00417   if (!::IsValidTile(tile)) return false;
00418   if (!IsRoadTypeAvailable(GetCurrentRoadType())) return false;
00419 
00420 	::RoadTypes rts = ::RoadTypeToRoadTypes((::RoadType)GetCurrentRoadType());
00421   int32 neighbour = 0;
00422 
00423   if (TileX(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NE)) neighbour++;
00424   if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SE)) neighbour++;
00425   if (NeighbourHasReachableRoad(rts, tile, DIAGDIR_SW)) neighbour++;
00426   if (TileY(tile) > 0 && NeighbourHasReachableRoad(rts, tile, DIAGDIR_NW)) neighbour++;
00427 
00428   return neighbour;
00429 }
00430 
00431 /* static */ TileIndex ScriptRoad::GetRoadDepotFrontTile(TileIndex depot)
00432 {
00433   if (!IsRoadDepotTile(depot)) return INVALID_TILE;
00434 
00435   return depot + ::TileOffsByDiagDir(::GetRoadDepotDirection(depot));
00436 }
00437 
00438 /* static */ TileIndex ScriptRoad::GetRoadStationFrontTile(TileIndex station)
00439 {
00440   if (!IsRoadStationTile(station)) return INVALID_TILE;
00441 
00442   return station + ::TileOffsByDiagDir(::GetRoadStopDir(station));
00443 }
00444 
00445 /* static */ TileIndex ScriptRoad::GetDriveThroughBackTile(TileIndex station)
00446 {
00447   if (!IsDriveThroughRoadStationTile(station)) return INVALID_TILE;
00448 
00449   return station + ::TileOffsByDiagDir(::ReverseDiagDir(::GetRoadStopDir(station)));
00450 }
00451 
00452 /* static */ bool ScriptRoad::_BuildRoadInternal(TileIndex start, TileIndex end, bool one_way, bool full)
00453 {
00454   EnforcePrecondition(false, start != end);
00455   EnforcePrecondition(false, ::IsValidTile(start));
00456   EnforcePrecondition(false, ::IsValidTile(end));
00457   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
00458   EnforcePrecondition(false, !one_way || ScriptObject::GetRoadType() == ::ROADTYPE_ROAD);
00459   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
00460 
00461   return ScriptObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (((start < end) == !full) ? 1 : 2) | (ScriptObject::GetRoadType() << 3) | ((one_way ? 1 : 0) << 5) | 1 << 6, CMD_BUILD_LONG_ROAD);
00462 }
00463 
00464 /* static */ bool ScriptRoad::BuildRoad(TileIndex start, TileIndex end)
00465 {
00466   return _BuildRoadInternal(start, end, false, false);
00467 }
00468 
00469 /* static */ bool ScriptRoad::BuildOneWayRoad(TileIndex start, TileIndex end)
00470 {
00471   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00472   return _BuildRoadInternal(start, end, true, false);
00473 }
00474 
00475 /* static */ bool ScriptRoad::BuildRoadFull(TileIndex start, TileIndex end)
00476 {
00477   return _BuildRoadInternal(start, end, false, true);
00478 }
00479 
00480 /* static */ bool ScriptRoad::BuildOneWayRoadFull(TileIndex start, TileIndex end)
00481 {
00482   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00483   return _BuildRoadInternal(start, end, true, true);
00484 }
00485 
00486 /* static */ bool ScriptRoad::BuildRoadDepot(TileIndex tile, TileIndex front)
00487 {
00488   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00489   EnforcePrecondition(false, tile != front);
00490   EnforcePrecondition(false, ::IsValidTile(tile));
00491   EnforcePrecondition(false, ::IsValidTile(front));
00492   EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
00493   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
00494 
00495   uint entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
00496 
00497   return ScriptObject::DoCommand(tile, entrance_dir | (ScriptObject::GetRoadType() << 2), 0, CMD_BUILD_ROAD_DEPOT);
00498 }
00499 
00500 /* static */ bool ScriptRoad::_BuildRoadStationInternal(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, bool drive_through, StationID station_id)
00501 {
00502   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00503   EnforcePrecondition(false, tile != front);
00504   EnforcePrecondition(false, ::IsValidTile(tile));
00505   EnforcePrecondition(false, ::IsValidTile(front));
00506   EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
00507   EnforcePrecondition(false, station_id == ScriptStation::STATION_NEW || station_id == ScriptStation::STATION_JOIN_ADJACENT || ScriptStation::IsValidStation(station_id));
00508   EnforcePrecondition(false, road_veh_type == ROADVEHTYPE_BUS || road_veh_type == ROADVEHTYPE_TRUCK);
00509   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
00510 
00511   uint entrance_dir;
00512   if (drive_through) {
00513     entrance_dir = ::TileY(tile) != ::TileY(front);
00514   } else {
00515     entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
00516   }
00517 
00518   uint p2 = station_id == ScriptStation::STATION_JOIN_ADJACENT ? 0 : 32;
00519   p2 |= drive_through ? 2 : 0;
00520   p2 |= road_veh_type == ROADVEHTYPE_TRUCK ? 1 : 0;
00521   p2 |= ::RoadTypeToRoadTypes(ScriptObject::GetRoadType()) << 2;
00522   p2 |= entrance_dir << 6;
00523   p2 |= (ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16;
00524   return ScriptObject::DoCommand(tile, 1 | 1 << 8, p2, CMD_BUILD_ROAD_STOP);
00525 }
00526 
00527 /* static */ bool ScriptRoad::BuildRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
00528 {
00529   return _BuildRoadStationInternal(tile, front, road_veh_type, false, station_id);
00530 }
00531 
00532 /* static */ bool ScriptRoad::BuildDriveThroughRoadStation(TileIndex tile, TileIndex front, RoadVehicleType road_veh_type, StationID station_id)
00533 {
00534   return _BuildRoadStationInternal(tile, front, road_veh_type, true, station_id);
00535 }
00536 
00537 /* static */ bool ScriptRoad::RemoveRoad(TileIndex start, TileIndex end)
00538 {
00539   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00540   EnforcePrecondition(false, ::IsValidTile(start));
00541   EnforcePrecondition(false, ::IsValidTile(end));
00542   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
00543   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
00544 
00545   return ScriptObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 1 : 2) | (ScriptObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
00546 }
00547 
00548 /* static */ bool ScriptRoad::RemoveRoadFull(TileIndex start, TileIndex end)
00549 {
00550   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00551   EnforcePrecondition(false, ::IsValidTile(start));
00552   EnforcePrecondition(false, ::IsValidTile(end));
00553   EnforcePrecondition(false, ::TileX(start) == ::TileX(end) || ::TileY(start) == ::TileY(end));
00554   EnforcePrecondition(false, IsRoadTypeAvailable(GetCurrentRoadType()));
00555 
00556   return ScriptObject::DoCommand(start, end, (::TileY(start) != ::TileY(end) ? 4 : 0) | (start < end ? 2 : 1) | (ScriptObject::GetRoadType() << 3), CMD_REMOVE_LONG_ROAD);
00557 }
00558 
00559 /* static */ bool ScriptRoad::RemoveRoadDepot(TileIndex tile)
00560 {
00561   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00562   EnforcePrecondition(false, ::IsValidTile(tile));
00563   EnforcePrecondition(false, IsTileType(tile, MP_ROAD))
00564   EnforcePrecondition(false, GetRoadTileType(tile) == ROAD_TILE_DEPOT);
00565 
00566   return ScriptObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
00567 }
00568 
00569 /* static */ bool ScriptRoad::RemoveRoadStation(TileIndex tile)
00570 {
00571   EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
00572   EnforcePrecondition(false, ::IsValidTile(tile));
00573   EnforcePrecondition(false, IsTileType(tile, MP_STATION));
00574   EnforcePrecondition(false, IsRoadStop(tile));
00575 
00576   return ScriptObject::DoCommand(tile, 1 | 1 << 8, GetRoadStopType(tile), CMD_REMOVE_ROAD_STOP);
00577 }
00578 
00579 /* static */ Money ScriptRoad::GetBuildCost(RoadType roadtype, BuildType build_type)
00580 {
00581   if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return -1;
00582 
00583   switch (build_type) {
00584     case BT_ROAD:       return ::GetPrice(PR_BUILD_ROAD, 1, NULL);
00585     case BT_DEPOT:      return ::GetPrice(PR_BUILD_DEPOT_ROAD, 1, NULL);
00586     case BT_BUS_STOP:   return ::GetPrice(PR_BUILD_STATION_BUS, 1, NULL);
00587     case BT_TRUCK_STOP: return ::GetPrice(PR_BUILD_STATION_TRUCK, 1, NULL);
00588     default: return -1;
00589   }
00590 }
00591 
00592 /* static */ uint16 ScriptRoad::GetMaintenanceCostFactor(RoadType roadtype)
00593 {
00594   if (!ScriptRoad::IsRoadTypeAvailable(roadtype)) return 0;
00595 
00596   return roadtype == ROADTYPE_TRAM ? 3 : 2;
00597 }