script_tunnel.cpp

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