script_tunnel.cpp

Go to the documentation of this file.
00001 /* $Id$ */
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_tunnel.hpp"
00014 #include "script_rail.hpp"
00015 #include "../script_instance.hpp"
00016 #include "../../tunnel_map.h"
00017 #include "../../command_func.h"
00018 
00019 /* static */ bool ScriptTunnel::IsTunnelTile(TileIndex tile)
00020 {
00021   if (!::IsValidTile(tile)) return false;
00022   return ::IsTunnelTile(tile);
00023 }
00024 
00025 /* static */ TileIndex ScriptTunnel::GetOtherTunnelEnd(TileIndex tile)
00026 {
00027   if (!::IsValidTile(tile)) return INVALID_TILE;
00028 
00029   /* If it's a tunnel already, take the easy way out! */
00030   if (IsTunnelTile(tile)) return ::GetOtherTunnelEnd(tile);
00031 
00032   int start_z;
00033   Slope start_tileh = ::GetTileSlope(tile, &start_z);
00034   DiagDirection direction = ::GetInclinedSlopeDirection(start_tileh);
00035   if (direction == INVALID_DIAGDIR) return INVALID_TILE;
00036 
00037   TileIndexDiff delta = ::TileOffsByDiagDir(direction);
00038   int end_z;
00039   do {
00040     tile += delta;
00041     if (!::IsValidTile(tile)) return INVALID_TILE;
00042 
00043 		::GetTileSlope(tile, &end_z);
00044   } while (start_z != end_z);
00045 
00046   return tile;
00047 }
00048 
00053 static void _DoCommandReturnBuildTunnel2(class ScriptInstance *instance)
00054 {
00055   if (!ScriptTunnel::_BuildTunnelRoad2()) {
00056     ScriptInstance::DoCommandReturn(instance);
00057     return;
00058   }
00059 
00060   /* This can never happen, as in test-mode this callback is never executed,
00061    *  and in execute-mode, the other callback is called. */
00062   NOT_REACHED();
00063 }
00064 
00069 static void _DoCommandReturnBuildTunnel1(class ScriptInstance *instance)
00070 {
00071   if (!ScriptTunnel::_BuildTunnelRoad1()) {
00072     ScriptInstance::DoCommandReturn(instance);
00073     return;
00074   }
00075 
00076   /* This can never happen, as in test-mode this callback is never executed,
00077    *  and in execute-mode, the other callback is called. */
00078   NOT_REACHED();
00079 }
00080 
00081 /* static */ bool ScriptTunnel::BuildTunnel(ScriptVehicle::VehicleType vehicle_type, TileIndex start)
00082 {
00083   EnforcePrecondition(false, ::IsValidTile(start));
00084   EnforcePrecondition(false, vehicle_type == ScriptVehicle::VT_RAIL || vehicle_type == ScriptVehicle::VT_ROAD);
00085   EnforcePrecondition(false, vehicle_type != ScriptVehicle::VT_RAIL || ScriptRail::IsRailTypeAvailable(ScriptRail::GetCurrentRailType()));
00086 
00087   uint type = 0;
00088   if (vehicle_type == ScriptVehicle::VT_ROAD) {
00089     type |= (TRANSPORT_ROAD << 8);
00090     type |= ::RoadTypeToRoadTypes((::RoadType)ScriptObject::GetRoadType());
00091   } else {
00092     type |= (TRANSPORT_RAIL << 8);
00093     type |= ScriptRail::GetCurrentRailType();
00094   }
00095 
00096   /* For rail we do nothing special */
00097   if (vehicle_type == ScriptVehicle::VT_RAIL) {
00098     return ScriptObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL);
00099   }
00100 
00101   ScriptObject::SetCallbackVariable(0, start);
00102   return ScriptObject::DoCommand(start, type, 0, CMD_BUILD_TUNNEL, NULL, &::_DoCommandReturnBuildTunnel1);
00103 }
00104 
00105 /* static */ bool ScriptTunnel::_BuildTunnelRoad1()
00106 {
00107   /* Build the piece of road on the 'start' side of the tunnel */
00108   TileIndex end = ScriptObject::GetCallbackVariable(0);
00109   TileIndex start = ScriptTunnel::GetOtherTunnelEnd(end);
00110 
00111   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
00112   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
00113 
00114   return ScriptObject::DoCommand(start + ::TileOffsByDiagDir(dir_1), ::DiagDirToRoadBits(dir_2) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD, NULL, &::_DoCommandReturnBuildTunnel2);
00115 }
00116 
00117 /* static */ bool ScriptTunnel::_BuildTunnelRoad2()
00118 {
00119   /* Build the piece of road on the 'end' side of the tunnel */
00120   TileIndex end = ScriptObject::GetCallbackVariable(0);
00121   TileIndex start = ScriptTunnel::GetOtherTunnelEnd(end);
00122 
00123   DiagDirection dir_1 = ::DiagdirBetweenTiles(end, start);
00124   DiagDirection dir_2 = ::ReverseDiagDir(dir_1);
00125 
00126   return ScriptObject::DoCommand(end + ::TileOffsByDiagDir(dir_2), ::DiagDirToRoadBits(dir_1) | (ScriptObject::GetRoadType() << 4), 0, CMD_BUILD_ROAD);
00127 }
00128 
00129 /* static */ bool ScriptTunnel::RemoveTunnel(TileIndex tile)
00130 {
00131   EnforcePrecondition(false, IsTunnelTile(tile));
00132 
00133   return ScriptObject::DoCommand(tile, 0, 0, CMD_LANDSCAPE_CLEAR);
00134 }