2009-01-12 17:11:45 +00:00
|
|
|
/* $Id$ */
|
|
|
|
|
2009-08-21 20:21:05 +00:00
|
|
|
/*
|
|
|
|
* This file is part of OpenTTD.
|
|
|
|
* 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.
|
|
|
|
* 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.
|
|
|
|
* 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/>.
|
|
|
|
*/
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/** @file script_rail.cpp Implementation of ScriptRail. */
|
2009-01-12 17:11:45 +00:00
|
|
|
|
2011-01-22 10:33:16 +00:00
|
|
|
#include "../../stdafx.h"
|
2011-11-29 23:07:38 +00:00
|
|
|
#include "script_rail.hpp"
|
|
|
|
#include "script_map.hpp"
|
|
|
|
#include "script_station.hpp"
|
|
|
|
#include "script_industrytype.hpp"
|
|
|
|
#include "script_cargo.hpp"
|
2009-01-12 17:11:45 +00:00
|
|
|
#include "../../debug.h"
|
2009-06-24 17:39:54 +00:00
|
|
|
#include "../../station_base.h"
|
2009-01-12 17:11:45 +00:00
|
|
|
#include "../../newgrf_generic.h"
|
|
|
|
#include "../../newgrf_station.h"
|
2010-12-29 23:20:12 +00:00
|
|
|
#include "../../strings_func.h"
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ char *ScriptRail::GetName(RailType rail_type)
|
2010-12-29 23:20:12 +00:00
|
|
|
{
|
|
|
|
if (!IsRailTypeAvailable(rail_type)) return NULL;
|
|
|
|
|
2012-01-08 21:48:05 +00:00
|
|
|
return GetString(GetRailTypeInfo((::RailType)rail_type)->strings.menu_text);
|
2010-12-29 23:20:12 +00:00
|
|
|
}
|
2009-01-12 17:11:45 +00:00
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsRailTile(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!::IsValidTile(tile)) return false;
|
|
|
|
|
|
|
|
return (::IsTileType(tile, MP_RAILWAY) && !::IsRailDepot(tile)) ||
|
2009-07-24 11:15:11 +00:00
|
|
|
(::HasStationTileRail(tile) && !::IsStationTileBlocked(tile)) || ::IsLevelCrossingTile(tile);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsLevelCrossingTile(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!::IsValidTile(tile)) return false;
|
|
|
|
|
|
|
|
return ::IsLevelCrossingTile(tile);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsRailDepotTile(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!::IsValidTile(tile)) return false;
|
|
|
|
|
|
|
|
return ::IsRailDepotTile(tile);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsRailStationTile(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!::IsValidTile(tile)) return false;
|
|
|
|
|
2009-07-24 11:47:12 +00:00
|
|
|
return ::IsRailStationTile(tile);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsRailWaypointTile(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!::IsValidTile(tile)) return false;
|
|
|
|
|
2009-07-22 08:59:57 +00:00
|
|
|
return ::IsRailWaypointTile(tile);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::IsRailTypeAvailable(RailType rail_type)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if ((::RailType)rail_type < RAILTYPE_BEGIN || (::RailType)rail_type >= RAILTYPE_END) return false;
|
|
|
|
|
2011-12-19 21:05:25 +00:00
|
|
|
return ScriptObject::GetCompany() == OWNER_DEITY || ::HasRailtypeAvail(ScriptObject::GetCompany(), (::RailType)rail_type);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ ScriptRail::RailType ScriptRail::GetCurrentRailType()
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
return (RailType)ScriptObject::GetRailType();
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ void ScriptRail::SetCurrentRailType(RailType rail_type)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!IsRailTypeAvailable(rail_type)) return;
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
ScriptObject::SetRailType((::RailType)rail_type);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::TrainCanRunOnRail(ScriptRail::RailType engine_rail_type, ScriptRail::RailType track_rail_type)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (!ScriptRail::IsRailTypeAvailable(engine_rail_type)) return false;
|
|
|
|
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
return ::IsCompatibleRail((::RailType)engine_rail_type, (::RailType)track_rail_type);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::TrainHasPowerOnRail(ScriptRail::RailType engine_rail_type, ScriptRail::RailType track_rail_type)
|
2009-01-12 17:11:45 +00:00
|
|
|
{\
|
2011-11-29 23:15:35 +00:00
|
|
|
if (!ScriptRail::IsRailTypeAvailable(engine_rail_type)) return false;
|
|
|
|
if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
return ::HasPowerOnRail((::RailType)engine_rail_type, (::RailType)track_rail_type);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ ScriptRail::RailType ScriptRail::GetRailType(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (!ScriptTile::HasTransportType(tile, ScriptTile::TRANSPORT_RAIL)) return RAILTYPE_INVALID;
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
return (RailType)::GetRailType(tile);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::ConvertRailType(TileIndex start_tile, TileIndex end_tile, ScriptRail::RailType convert_to)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(start_tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(end_tile));
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(convert_to));
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(start_tile, end_tile, convert_to, CMD_CONVERT_RAIL);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ TileIndex ScriptRail::GetRailDepotFrontTile(TileIndex depot)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!IsRailDepotTile(depot)) return INVALID_TILE;
|
|
|
|
|
|
|
|
return depot + ::TileOffsByDiagDir(::GetRailDepotDirection(depot));
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ ScriptRail::RailTrack ScriptRail::GetRailStationDirection(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!IsRailStationTile(tile)) return RAILTRACK_INVALID;
|
|
|
|
|
2009-05-26 22:03:16 +00:00
|
|
|
return (RailTrack)::GetRailStationTrackBits(tile);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildRailDepot(TileIndex tile, TileIndex front)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, tile != front);
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(front));
|
|
|
|
EnforcePrecondition(false, ::TileX(tile) == ::TileX(front) || ::TileY(tile) == ::TileY(front));
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
|
|
|
|
|
|
|
uint entrance_dir = (::TileX(tile) == ::TileX(front)) ? (::TileY(tile) < ::TileY(front) ? 1 : 3) : (::TileX(tile) < ::TileX(front) ? 2 : 0);
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, ScriptObject::GetRailType(), entrance_dir, CMD_BUILD_TRAIN_DEPOT);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildRailStation(TileIndex tile, RailTrack direction, uint num_platforms, uint platform_length, StationID station_id)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, direction == RAILTRACK_NW_SE || direction == RAILTRACK_NE_SW);
|
|
|
|
EnforcePrecondition(false, num_platforms > 0 && num_platforms <= 0xFF);
|
|
|
|
EnforcePrecondition(false, platform_length > 0 && platform_length <= 0xFF);
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
2011-11-29 23:15:35 +00:00
|
|
|
EnforcePrecondition(false, station_id == ScriptStation::STATION_NEW || station_id == ScriptStation::STATION_JOIN_ADJACENT || ScriptStation::IsValidStation(station_id));
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8);
|
|
|
|
if (direction == RAILTRACK_NW_SE) p1 |= (1 << 4);
|
2011-11-29 23:15:35 +00:00
|
|
|
if (station_id != ScriptStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24);
|
|
|
|
return ScriptObject::DoCommand(tile, p1, (ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16, CMD_BUILD_RAIL_STATION);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildNewGRFRailStation(TileIndex tile, RailTrack direction, uint num_platforms, uint platform_length, StationID station_id, CargoID cargo_id, IndustryType source_industry, IndustryType goal_industry, int distance, bool source_station)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, direction == RAILTRACK_NW_SE || direction == RAILTRACK_NE_SW);
|
|
|
|
EnforcePrecondition(false, num_platforms > 0 && num_platforms <= 0xFF);
|
|
|
|
EnforcePrecondition(false, platform_length > 0 && platform_length <= 0xFF);
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
2011-11-29 23:15:35 +00:00
|
|
|
EnforcePrecondition(false, station_id == ScriptStation::STATION_NEW || station_id == ScriptStation::STATION_JOIN_ADJACENT || ScriptStation::IsValidStation(station_id));
|
|
|
|
EnforcePrecondition(false, ScriptCargo::IsValidCargo(cargo_id));
|
|
|
|
EnforcePrecondition(false, source_industry == ScriptIndustryType::INDUSTRYTYPE_UNKNOWN || source_industry == ScriptIndustryType::INDUSTRYTYPE_TOWN || ScriptIndustryType::IsValidIndustryType(source_industry));
|
|
|
|
EnforcePrecondition(false, goal_industry == ScriptIndustryType::INDUSTRYTYPE_UNKNOWN || goal_industry == ScriptIndustryType::INDUSTRYTYPE_TOWN || ScriptIndustryType::IsValidIndustryType(goal_industry));
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
uint32 p1 = GetCurrentRailType() | (platform_length << 16) | (num_platforms << 8);
|
|
|
|
if (direction == RAILTRACK_NW_SE) p1 |= 1 << 4;
|
2011-11-29 23:15:35 +00:00
|
|
|
if (station_id != ScriptStation::STATION_JOIN_ADJACENT) p1 |= (1 << 24);
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
const GRFFile *file;
|
2010-04-24 11:52:58 +00:00
|
|
|
uint16 res = GetAiPurchaseCallbackResult(GSF_STATIONS, cargo_id, 0, source_industry, goal_industry, min(255, distance / 2), AICE_STATION_GET_STATION_ID, source_station ? 0 : 1, min(15, num_platforms) << 4 | min(15, platform_length), &file);
|
2011-11-29 23:15:35 +00:00
|
|
|
uint32 p2 = (ScriptStation::IsValidStation(station_id) ? station_id : INVALID_STATION) << 16;
|
2009-01-12 17:11:45 +00:00
|
|
|
if (res != CALLBACK_FAILED) {
|
2009-02-09 22:49:28 +00:00
|
|
|
int index = 0;
|
2010-08-07 22:07:07 +00:00
|
|
|
const StationSpec *spec = StationClass::GetByGrf(file->grfid, res, &index);
|
2009-02-09 22:49:28 +00:00
|
|
|
if (spec == NULL) {
|
2009-01-12 17:11:45 +00:00
|
|
|
DEBUG(grf, 1, "%s returned an invalid station ID for 'AI construction/purchase selection (18)' callback", file->filename);
|
|
|
|
} else {
|
2010-08-07 21:10:57 +00:00
|
|
|
p2 |= spec->cls_id | index << 8;
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, p1, p2, CMD_BUILD_RAIL_STATION);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildRailWaypoint(TileIndex tile)
|
2009-02-19 07:40:08 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-02-19 07:40:08 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, IsRailTile(tile));
|
|
|
|
EnforcePrecondition(false, GetRailTracks(tile) == RAILTRACK_NE_SW || GetRailTracks(tile) == RAILTRACK_NW_SE);
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, GetCurrentRailType() | (GetRailTracks(tile) == RAILTRACK_NE_SW ? AXIS_X : AXIS_Y) << 4 | 1 << 8 | 1 << 16, STAT_CLASS_WAYP | INVALID_STATION << 16, CMD_BUILD_RAIL_WAYPOINT);
|
2009-02-19 07:40:08 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::RemoveRailWaypointTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
|
2009-07-30 15:17:03 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-07-30 15:17:03 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile2));
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, tile2, keep_rail ? 1 : 0, CMD_REMOVE_FROM_RAIL_WAYPOINT);
|
2009-07-30 15:17:03 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::RemoveRailStationTileRectangle(TileIndex tile, TileIndex tile2, bool keep_rail)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile2));
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, tile2, keep_rail ? 1 : 0, CMD_REMOVE_FROM_RAIL_STATION);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ uint ScriptRail::GetRailTracks(TileIndex tile)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!IsRailTile(tile)) return RAILTRACK_INVALID;
|
|
|
|
|
2009-07-22 08:59:57 +00:00
|
|
|
if (IsRailStationTile(tile) || IsRailWaypointTile(tile)) return ::TrackToTrackBits(::GetRailStationTrack(tile));
|
2009-01-12 17:11:45 +00:00
|
|
|
if (IsLevelCrossingTile(tile)) return ::GetCrossingRailBits(tile);
|
2009-05-15 16:07:36 +00:00
|
|
|
if (IsRailDepotTile(tile)) return ::TRACK_BIT_NONE;
|
2009-01-12 17:11:45 +00:00
|
|
|
return ::GetTrackBits(tile);
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildRailTrack(TileIndex tile, RailTrack rail_track)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, rail_track != 0);
|
|
|
|
EnforcePrecondition(false, (rail_track & ~::TRACK_BIT_ALL) == 0);
|
|
|
|
EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0);
|
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 4), CMD_BUILD_RAILROAD_TRACK);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::RemoveRailTrack(TileIndex tile, RailTrack rail_track)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
2009-08-29 17:01:39 +00:00
|
|
|
EnforcePrecondition(false, ::IsPlainRailTile(tile) || ::IsLevelCrossingTile(tile));
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, GetRailTracks(tile) & rail_track);
|
|
|
|
EnforcePrecondition(false, KillFirstBit((uint)rail_track) == 0);
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, tile, GetCurrentRailType() | (FindFirstTrack((::TrackBits)rail_track) << 4), CMD_REMOVE_RAILROAD_TRACK);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::AreTilesConnected(TileIndex from, TileIndex tile, TileIndex to)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
|
|
|
if (!IsRailTile(tile)) return false;
|
2011-11-29 23:15:35 +00:00
|
|
|
if (from == to || ScriptMap::DistanceManhattan(from, tile) != 1 || ScriptMap::DistanceManhattan(tile, to) != 1) return false;
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
if (to < from) ::Swap(from, to);
|
|
|
|
|
|
|
|
if (tile - from == 1) {
|
|
|
|
if (to - tile == 1) return (GetRailTracks(tile) & RAILTRACK_NE_SW) != 0;
|
|
|
|
if (to - tile == ::MapSizeX()) return (GetRailTracks(tile) & RAILTRACK_NE_SE) != 0;
|
|
|
|
} else if (tile - from == ::MapSizeX()) {
|
|
|
|
if (tile - to == 1) return (GetRailTracks(tile) & RAILTRACK_NW_NE) != 0;
|
|
|
|
if (to - tile == 1) return (GetRailTracks(tile) & RAILTRACK_NW_SW) != 0;
|
|
|
|
if (to - tile == ::MapSizeX()) return (GetRailTracks(tile) & RAILTRACK_NW_SE) != 0;
|
|
|
|
} else {
|
|
|
|
return (GetRailTracks(tile) & RAILTRACK_SW_SE) != 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
NOT_REACHED();
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Prepare the second parameter for CmdBuildRailroadTrack and CmdRemoveRailroadTrack. The direction
|
|
|
|
* depends on all three tiles. Sometimes the third tile needs to be adjusted.
|
|
|
|
*/
|
|
|
|
static uint32 SimulateDrag(TileIndex from, TileIndex tile, TileIndex *to)
|
|
|
|
{
|
|
|
|
int diag_offset = abs(abs((int)::TileX(*to) - (int)::TileX(tile)) - abs((int)::TileY(*to) - (int)::TileY(tile)));
|
2011-11-29 23:15:35 +00:00
|
|
|
uint32 p2 = ScriptRail::GetCurrentRailType();
|
2009-01-12 17:11:45 +00:00
|
|
|
if (::TileY(from) == ::TileY(*to)) {
|
|
|
|
p2 |= (TRACK_X << 4);
|
|
|
|
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
|
|
|
|
} else if (::TileX(from) == ::TileX(*to)) {
|
|
|
|
p2 |= (TRACK_Y << 4);
|
|
|
|
*to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
|
|
|
|
} else if (::TileY(from) < ::TileY(tile)) {
|
|
|
|
if (::TileX(*to) < ::TileX(tile)) {
|
|
|
|
p2 |= (TRACK_UPPER << 4);
|
|
|
|
} else {
|
|
|
|
p2 |= (TRACK_LEFT << 4);
|
|
|
|
}
|
2011-02-25 22:04:38 +00:00
|
|
|
if (diag_offset != 0) {
|
2009-01-12 17:11:45 +00:00
|
|
|
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
|
|
|
|
} else {
|
|
|
|
*to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
|
|
|
|
}
|
|
|
|
} else if (::TileY(from) > ::TileY(tile)) {
|
|
|
|
if (::TileX(*to) < ::TileX(tile)) {
|
|
|
|
p2 |= (TRACK_RIGHT << 4);
|
|
|
|
} else {
|
|
|
|
p2 |= (TRACK_LOWER << 4);
|
|
|
|
}
|
2011-02-25 22:04:38 +00:00
|
|
|
if (diag_offset != 0) {
|
2009-01-12 17:11:45 +00:00
|
|
|
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
|
|
|
|
} else {
|
|
|
|
*to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
|
|
|
|
}
|
|
|
|
} else if (::TileX(from) < ::TileX(tile)) {
|
|
|
|
if (::TileY(*to) < ::TileY(tile)) {
|
|
|
|
p2 |= (TRACK_UPPER << 4);
|
|
|
|
} else {
|
|
|
|
p2 |= (TRACK_RIGHT << 4);
|
|
|
|
}
|
2011-02-25 22:04:38 +00:00
|
|
|
if (diag_offset == 0) {
|
2009-01-12 17:11:45 +00:00
|
|
|
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
|
|
|
|
} else {
|
|
|
|
*to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
|
|
|
|
}
|
|
|
|
} else if (::TileX(from) > ::TileX(tile)) {
|
|
|
|
if (::TileY(*to) < ::TileY(tile)) {
|
|
|
|
p2 |= (TRACK_LEFT << 4);
|
|
|
|
} else {
|
|
|
|
p2 |= (TRACK_LOWER << 4);
|
|
|
|
}
|
2011-02-25 22:04:38 +00:00
|
|
|
if (diag_offset == 0) {
|
2009-01-12 17:11:45 +00:00
|
|
|
*to -= Clamp((int)::TileX(*to) - (int)::TileX(tile), -1, 1);
|
|
|
|
} else {
|
|
|
|
*to -= ::MapSizeX() * Clamp((int)::TileY(*to) - (int)::TileY(tile), -1, 1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return p2;
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildRail(TileIndex from, TileIndex tile, TileIndex to)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(from));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(to));
|
|
|
|
EnforcePrecondition(false, ::DistanceManhattan(from, tile) == 1);
|
2009-03-14 18:16:29 +00:00
|
|
|
EnforcePrecondition(false, ::DistanceManhattan(tile, to) >= 1);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, IsRailTypeAvailable(GetCurrentRailType()));
|
|
|
|
int diag_offset = abs(abs((int)::TileX(to) - (int)::TileX(tile)) - abs((int)::TileY(to) - (int)::TileY(tile)));
|
|
|
|
EnforcePrecondition(false, diag_offset <= 1 ||
|
|
|
|
(::TileX(from) == ::TileX(tile) && ::TileX(tile) == ::TileX(to)) ||
|
|
|
|
(::TileY(from) == ::TileY(tile) && ::TileY(tile) == ::TileY(to)));
|
|
|
|
|
2010-02-02 22:27:03 +00:00
|
|
|
uint32 p2 = SimulateDrag(from, tile, &to) | 1 << 8;
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, to, p2, CMD_BUILD_RAILROAD_TRACK);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::RemoveRail(TileIndex from, TileIndex tile, TileIndex to)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidTile(from));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(tile));
|
|
|
|
EnforcePrecondition(false, ::IsValidTile(to));
|
|
|
|
EnforcePrecondition(false, ::DistanceManhattan(from, tile) == 1);
|
2009-03-14 18:16:29 +00:00
|
|
|
EnforcePrecondition(false, ::DistanceManhattan(tile, to) >= 1);
|
2009-01-12 17:11:45 +00:00
|
|
|
int diag_offset = abs(abs((int)::TileX(to) - (int)::TileX(tile)) - abs((int)::TileY(to) - (int)::TileY(tile)));
|
|
|
|
EnforcePrecondition(false, diag_offset <= 1 ||
|
|
|
|
(::TileX(from) == ::TileX(tile) && ::TileX(tile) == ::TileX(to)) ||
|
|
|
|
(::TileY(from) == ::TileY(tile) && ::TileY(tile) == ::TileY(to)));
|
|
|
|
|
|
|
|
if (!IsRailTypeAvailable(GetCurrentRailType())) SetCurrentRailType(GetRailType(tile));
|
|
|
|
uint32 p2 = SimulateDrag(from, tile, &to);
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, to, p2, CMD_REMOVE_RAILROAD_TRACK);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Contains information about the trackdir that belongs to a track when entering
|
|
|
|
* from a specific direction.
|
|
|
|
*/
|
2011-11-29 23:15:35 +00:00
|
|
|
struct ScriptRailSignalData {
|
2010-08-01 19:36:36 +00:00
|
|
|
Track track; ///< The track that will be taken to travel.
|
|
|
|
Trackdir trackdir; ///< The Trackdir belonging to that track.
|
|
|
|
uint signal_cycles; ///< How many times the signal should be cycled in order to build it in the correct direction.
|
2009-01-12 17:11:45 +00:00
|
|
|
};
|
|
|
|
|
2010-08-01 19:36:36 +00:00
|
|
|
static const int NUM_TRACK_DIRECTIONS = 3; ///< The number of directions you can go when entering a tile.
|
2009-01-12 17:11:45 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* List information about the trackdir and number of needed cycles for building signals when
|
|
|
|
* entering a track from a specific direction. The first index is the difference between the
|
|
|
|
* TileIndex of the previous and current tile, where (-)MapSizeX is replaced with -2 / 2 and
|
|
|
|
* 2 it added.
|
|
|
|
*/
|
2011-11-29 23:15:35 +00:00
|
|
|
static const ScriptRailSignalData _possible_trackdirs[5][NUM_TRACK_DIRECTIONS] = {
|
2009-01-12 17:11:45 +00:00
|
|
|
{{TRACK_UPPER, TRACKDIR_UPPER_E, 0}, {TRACK_Y, TRACKDIR_Y_SE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_S, 1}},
|
|
|
|
{{TRACK_RIGHT, TRACKDIR_RIGHT_S, 1}, {TRACK_X, TRACKDIR_X_SW, 1}, {TRACK_UPPER, TRACKDIR_UPPER_W, 1}},
|
|
|
|
{{INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}, {INVALID_TRACK, INVALID_TRACKDIR, 0}},
|
|
|
|
{{TRACK_LOWER, TRACKDIR_LOWER_E, 0}, {TRACK_X, TRACKDIR_X_NE, 0}, {TRACK_LEFT, TRACKDIR_LEFT_N, 0}},
|
|
|
|
{{TRACK_RIGHT, TRACKDIR_RIGHT_N, 0}, {TRACK_Y, TRACKDIR_Y_NW, 1}, {TRACK_LOWER, TRACKDIR_LOWER_W, 1}}
|
|
|
|
};
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ ScriptRail::SignalType ScriptRail::GetSignalType(TileIndex tile, TileIndex front)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (ScriptMap::DistanceManhattan(tile, front) != 1) return SIGNALTYPE_NONE;
|
2009-01-12 17:11:45 +00:00
|
|
|
if (!::IsTileType(tile, MP_RAILWAY) || !::HasSignals(tile)) return SIGNALTYPE_NONE;
|
|
|
|
|
|
|
|
int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
|
|
|
|
|
|
|
|
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
|
|
|
|
const Track &track = _possible_trackdirs[data_index][i].track;
|
|
|
|
if (!(::TrackToTrackBits(track) & GetRailTracks(tile))) continue;
|
|
|
|
if (!HasSignalOnTrack(tile, track)) continue;
|
|
|
|
if (!HasSignalOnTrackdir(tile, _possible_trackdirs[data_index][i].trackdir)) continue;
|
|
|
|
SignalType st = (SignalType)::GetSignalType(tile, track);
|
|
|
|
if (HasSignalOnTrackdir(tile, ::ReverseTrackdir(_possible_trackdirs[data_index][i].trackdir))) st = (SignalType)(st | SIGNALTYPE_TWOWAY);
|
|
|
|
return st;
|
|
|
|
}
|
|
|
|
|
|
|
|
return SIGNALTYPE_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Check if signal_type is a valid SignalType.
|
|
|
|
*/
|
|
|
|
static bool IsValidSignalType(int signal_type)
|
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (signal_type < ScriptRail::SIGNALTYPE_NORMAL || signal_type > ScriptRail::SIGNALTYPE_COMBO_TWOWAY) return false;
|
|
|
|
if (signal_type > ScriptRail::SIGNALTYPE_PBS_ONEWAY && signal_type < ScriptRail::SIGNALTYPE_NORMAL_TWOWAY) return false;
|
2009-01-12 17:11:45 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::BuildSignal(TileIndex tile, TileIndex front, SignalType signal)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2011-11-29 23:15:35 +00:00
|
|
|
EnforcePrecondition(false, ScriptMap::DistanceManhattan(tile, front) == 1)
|
2009-05-18 01:26:23 +00:00
|
|
|
EnforcePrecondition(false, ::IsPlainRailTile(tile));
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, ::IsValidSignalType(signal));
|
|
|
|
|
|
|
|
Track track = INVALID_TRACK;
|
|
|
|
uint signal_cycles;
|
|
|
|
|
|
|
|
int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
|
|
|
|
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
|
|
|
|
const Track &t = _possible_trackdirs[data_index][i].track;
|
|
|
|
if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
|
|
|
|
track = t;
|
|
|
|
signal_cycles = _possible_trackdirs[data_index][i].signal_cycles;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EnforcePrecondition(false, track != INVALID_TRACK);
|
|
|
|
|
|
|
|
uint p1 = track;
|
|
|
|
if (signal < SIGNALTYPE_TWOWAY) {
|
|
|
|
if (signal != SIGNALTYPE_PBS && signal != SIGNALTYPE_PBS_ONEWAY) signal_cycles++;
|
|
|
|
p1 |= (signal_cycles << 15);
|
|
|
|
}
|
|
|
|
p1 |= ((signal >= SIGNALTYPE_TWOWAY ? signal ^ SIGNALTYPE_TWOWAY : signal) << 5);
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, p1, 0, CMD_BUILD_SIGNALS);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ bool ScriptRail::RemoveSignal(TileIndex tile, TileIndex front)
|
2009-01-12 17:11:45 +00:00
|
|
|
{
|
2011-12-19 21:05:36 +00:00
|
|
|
EnforcePrecondition(false, ScriptObject::GetCompany() != OWNER_DEITY);
|
2011-11-29 23:15:35 +00:00
|
|
|
EnforcePrecondition(false, ScriptMap::DistanceManhattan(tile, front) == 1)
|
2009-01-12 17:11:45 +00:00
|
|
|
EnforcePrecondition(false, GetSignalType(tile, front) != SIGNALTYPE_NONE);
|
|
|
|
|
|
|
|
Track track = INVALID_TRACK;
|
|
|
|
int data_index = 2 + (::TileX(front) - ::TileX(tile)) + 2 * (::TileY(front) - ::TileY(tile));
|
|
|
|
for (int i = 0; i < NUM_TRACK_DIRECTIONS; i++) {
|
|
|
|
const Track &t = _possible_trackdirs[data_index][i].track;
|
|
|
|
if (!(::TrackToTrackBits(t) & GetRailTracks(tile))) continue;
|
|
|
|
track = t;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
EnforcePrecondition(false, track != INVALID_TRACK);
|
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
return ScriptObject::DoCommand(tile, track, 0, CMD_REMOVE_SIGNALS);
|
2009-01-12 17:11:45 +00:00
|
|
|
}
|
2010-01-29 23:56:42 +00:00
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ Money ScriptRail::GetBuildCost(RailType railtype, BuildType build_type)
|
2010-01-29 23:56:42 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (!ScriptRail::IsRailTypeAvailable(railtype)) return -1;
|
2010-01-29 23:56:42 +00:00
|
|
|
|
|
|
|
switch (build_type) {
|
|
|
|
case BT_TRACK: return ::RailBuildCost((::RailType)railtype);
|
|
|
|
case BT_SIGNAL: return ::GetPrice(PR_BUILD_SIGNALS, 1, NULL);
|
|
|
|
case BT_DEPOT: return ::GetPrice(PR_BUILD_DEPOT_TRAIN, 1, NULL);
|
|
|
|
case BT_STATION: return ::GetPrice(PR_BUILD_STATION_RAIL, 1, NULL) + ::GetPrice(PR_BUILD_STATION_RAIL_LENGTH, 1, NULL);
|
|
|
|
case BT_WAYPOINT: return ::GetPrice(PR_BUILD_WAYPOINT_RAIL, 1, NULL);
|
|
|
|
default: return -1;
|
|
|
|
}
|
|
|
|
}
|
2010-04-09 12:02:50 +00:00
|
|
|
|
2011-11-29 23:15:35 +00:00
|
|
|
/* static */ int32 ScriptRail::GetMaxSpeed(RailType railtype)
|
2010-04-09 12:02:50 +00:00
|
|
|
{
|
2011-11-29 23:15:35 +00:00
|
|
|
if (!ScriptRail::IsRailTypeAvailable(railtype)) return -1;
|
2010-04-09 12:02:50 +00:00
|
|
|
|
|
|
|
return ::GetRailTypeInfo((::RailType)railtype)->max_speed;
|
|
|
|
}
|
2011-12-03 23:40:57 +00:00
|
|
|
|
|
|
|
/* static */ uint16 ScriptRail::GetMaintenanceCostFactor(RailType railtype)
|
|
|
|
{
|
|
|
|
if (!ScriptRail::IsRailTypeAvailable(railtype)) return 0;
|
|
|
|
|
|
|
|
return ::GetRailTypeInfo((::RailType)railtype)->maintenance_multiplier;
|
|
|
|
}
|