4 * This file is part of OpenTTD.
5 * 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.
6 * 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.
7 * 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/>.
10 /** @file script_engine.cpp Implementation of ScriptEngine. */
12 #include "../../stdafx.h"
13 #include "script_engine.hpp"
14 #include "script_cargo.hpp"
15 #include "../../company_base.h"
16 #include "../../strings_func.h"
17 #include "../../rail.h"
18 #include "../../engine_base.h"
19 #include "../../engine_func.h"
20 #include "../../articulated_vehicles.h"
21 #include "table/strings.h"
23 #include "../../safeguards.h"
25 /* static */ bool ScriptEngine::IsValidEngine(EngineID engine_id
)
27 const Engine
*e
= ::Engine::GetIfValid(engine_id
);
28 if (e
== NULL
|| !e
->IsEnabled()) return false;
30 /* AIs have only access to engines they can purchase or still have in use.
31 * Deity has access to all engined that will be or were available ever. */
32 CompanyID company
= ScriptObject::GetCompany();
33 return company
== OWNER_DEITY
|| ::IsEngineBuildable(engine_id
, e
->type
, company
) || ::Company::Get(company
)->group_all
[e
->type
].num_engines
[engine_id
] > 0;
36 /* static */ bool ScriptEngine::IsBuildable(EngineID engine_id
)
38 const Engine
*e
= ::Engine::GetIfValid(engine_id
);
39 return e
!= NULL
&& ::IsEngineBuildable(engine_id
, e
->type
, ScriptObject::GetCompany());
42 /* static */ char *ScriptEngine::GetName(EngineID engine_id
)
44 if (!IsValidEngine(engine_id
)) return NULL
;
46 ::SetDParam(0, engine_id
);
47 return GetString(STR_ENGINE_NAME
);
50 /* static */ CargoID
ScriptEngine::GetCargoType(EngineID engine_id
)
52 if (!IsValidEngine(engine_id
)) return CT_INVALID
;
54 CargoArray cap
= ::GetCapacityOfArticulatedParts(engine_id
);
56 CargoID most_cargo
= CT_INVALID
;
58 for (CargoID cid
= 0; cid
< NUM_CARGO
; cid
++) {
59 if (cap
[cid
] > amount
) {
68 /* static */ bool ScriptEngine::CanRefitCargo(EngineID engine_id
, CargoID cargo_id
)
70 if (!IsValidEngine(engine_id
)) return false;
71 if (!ScriptCargo::IsValidCargo(cargo_id
)) return false;
73 return HasBit(::GetUnionOfArticulatedRefitMasks(engine_id
, true), cargo_id
);
76 /* static */ bool ScriptEngine::CanPullCargo(EngineID engine_id
, CargoID cargo_id
)
78 if (!IsValidEngine(engine_id
)) return false;
79 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return false;
80 if (!ScriptCargo::IsValidCargo(cargo_id
)) return false;
82 return (::RailVehInfo(engine_id
)->ai_passenger_only
!= 1) || ScriptCargo::HasCargoClass(cargo_id
, ScriptCargo::CC_PASSENGERS
);
86 /* static */ int32
ScriptEngine::GetCapacity(EngineID engine_id
)
88 if (!IsValidEngine(engine_id
)) return -1;
90 const Engine
*e
= ::Engine::Get(engine_id
);
94 CargoArray capacities
= GetCapacityOfArticulatedParts(engine_id
);
95 for (CargoID c
= 0; c
< NUM_CARGO
; c
++) {
96 if (capacities
[c
] == 0) continue;
104 return e
->GetDisplayDefaultCapacity();
106 default: NOT_REACHED();
110 /* static */ int32
ScriptEngine::GetReliability(EngineID engine_id
)
112 if (!IsValidEngine(engine_id
)) return -1;
113 if (GetVehicleType(engine_id
) == ScriptVehicle::VT_RAIL
&& IsWagon(engine_id
)) return -1;
115 return ::ToPercent16(::Engine::Get(engine_id
)->reliability
);
118 /* static */ int32
ScriptEngine::GetMaxSpeed(EngineID engine_id
)
120 if (!IsValidEngine(engine_id
)) return -1;
122 const Engine
*e
= ::Engine::Get(engine_id
);
123 int32 max_speed
= e
->GetDisplayMaxSpeed(); // km-ish/h
124 if (e
->type
== VEH_AIRCRAFT
) max_speed
/= _settings_game
.vehicle
.plane_speed
;
128 /* static */ Money
ScriptEngine::GetPrice(EngineID engine_id
)
130 if (!IsValidEngine(engine_id
)) return -1;
132 return ::Engine::Get(engine_id
)->GetCost();
135 /* static */ int32
ScriptEngine::GetMaxAge(EngineID engine_id
)
137 if (!IsValidEngine(engine_id
)) return -1;
138 if (GetVehicleType(engine_id
) == ScriptVehicle::VT_RAIL
&& IsWagon(engine_id
)) return -1;
140 return ::Engine::Get(engine_id
)->GetLifeLengthInDays();
143 /* static */ Money
ScriptEngine::GetRunningCost(EngineID engine_id
)
145 if (!IsValidEngine(engine_id
)) return -1;
147 return ::Engine::Get(engine_id
)->GetRunningCost();
150 /* static */ int32
ScriptEngine::GetPower(EngineID engine_id
)
152 if (!IsValidEngine(engine_id
)) return -1;
153 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
&& GetVehicleType(engine_id
) != ScriptVehicle::VT_ROAD
) return -1;
154 if (IsWagon(engine_id
)) return -1;
156 return ::Engine::Get(engine_id
)->GetPower();
159 /* static */ int32
ScriptEngine::GetWeight(EngineID engine_id
)
161 if (!IsValidEngine(engine_id
)) return -1;
162 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
&& GetVehicleType(engine_id
) != ScriptVehicle::VT_ROAD
) return -1;
164 return ::Engine::Get(engine_id
)->GetDisplayWeight();
167 /* static */ int32
ScriptEngine::GetMaxTractiveEffort(EngineID engine_id
)
169 if (!IsValidEngine(engine_id
)) return -1;
170 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
&& GetVehicleType(engine_id
) != ScriptVehicle::VT_ROAD
) return -1;
171 if (IsWagon(engine_id
)) return -1;
173 return ::Engine::Get(engine_id
)->GetDisplayMaxTractiveEffort();
176 /* static */ ScriptDate::Date
ScriptEngine::GetDesignDate(EngineID engine_id
)
178 if (!IsValidEngine(engine_id
)) return ScriptDate::DATE_INVALID
;
180 return (ScriptDate::Date
)::Engine::Get(engine_id
)->intro_date
;
183 /* static */ ScriptVehicle::VehicleType
ScriptEngine::GetVehicleType(EngineID engine_id
)
185 if (!IsValidEngine(engine_id
)) return ScriptVehicle::VT_INVALID
;
187 switch (::Engine::Get(engine_id
)->type
) {
188 case VEH_ROAD
: return ScriptVehicle::VT_ROAD
;
189 case VEH_TRAIN
: return ScriptVehicle::VT_RAIL
;
190 case VEH_SHIP
: return ScriptVehicle::VT_WATER
;
191 case VEH_AIRCRAFT
: return ScriptVehicle::VT_AIR
;
192 default: NOT_REACHED();
196 /* static */ bool ScriptEngine::IsWagon(EngineID engine_id
)
198 if (!IsValidEngine(engine_id
)) return false;
199 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return false;
201 return ::RailVehInfo(engine_id
)->power
== 0;
204 /* static */ bool ScriptEngine::CanRunOnRail(EngineID engine_id
, ScriptRail::RailType track_rail_type
)
206 if (!IsValidEngine(engine_id
)) return false;
207 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return false;
208 if (!ScriptRail::IsRailTypeAvailable(track_rail_type
)) return false;
210 return ::IsCompatibleRail((::RailType
)::RailVehInfo(engine_id
)->railtype
, (::RailType
)track_rail_type
);
213 /* static */ bool ScriptEngine::HasPowerOnRail(EngineID engine_id
, ScriptRail::RailType track_rail_type
)
215 if (!IsValidEngine(engine_id
)) return false;
216 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return false;
217 if (!ScriptRail::IsRailTypeAvailable(track_rail_type
)) return false;
219 return ::HasPowerOnRail((::RailType
)::RailVehInfo(engine_id
)->railtype
, (::RailType
)track_rail_type
);
222 /* static */ ScriptRoad::RoadType
ScriptEngine::GetRoadType(EngineID engine_id
)
224 if (!IsValidEngine(engine_id
)) return ScriptRoad::ROADTYPE_INVALID
;
225 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_ROAD
) return ScriptRoad::ROADTYPE_INVALID
;
227 return HasBit(::EngInfo(engine_id
)->misc_flags
, EF_ROAD_TRAM
) ? ScriptRoad::ROADTYPE_TRAM
: ScriptRoad::ROADTYPE_ROAD
;
230 /* static */ ScriptRail::RailType
ScriptEngine::GetRailType(EngineID engine_id
)
232 if (!IsValidEngine(engine_id
)) return ScriptRail::RAILTYPE_INVALID
;
233 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return ScriptRail::RAILTYPE_INVALID
;
235 return (ScriptRail::RailType
)(uint
)::RailVehInfo(engine_id
)->railtype
;
238 /* static */ bool ScriptEngine::IsArticulated(EngineID engine_id
)
240 if (!IsValidEngine(engine_id
)) return false;
241 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_ROAD
&& GetVehicleType(engine_id
) != ScriptVehicle::VT_RAIL
) return false;
243 return IsArticulatedEngine(engine_id
);
246 /* static */ ScriptAirport::PlaneType
ScriptEngine::GetPlaneType(EngineID engine_id
)
248 if (!IsValidEngine(engine_id
)) return ScriptAirport::PT_INVALID
;
249 if (GetVehicleType(engine_id
) != ScriptVehicle::VT_AIR
) return ScriptAirport::PT_INVALID
;
251 return (ScriptAirport::PlaneType
)::AircraftVehInfo(engine_id
)->subtype
;
254 /* static */ uint
ScriptEngine::GetMaximumOrderDistance(EngineID engine_id
)
256 if (!IsValidEngine(engine_id
)) return 0;
258 switch (GetVehicleType(engine_id
)) {
259 case ScriptVehicle::VT_WATER
:
260 return _settings_game
.pf
.pathfinder_for_ships
!= VPF_NPF
? 129 : 0;
262 case ScriptVehicle::VT_AIR
:
263 return ::Engine::Get(engine_id
)->GetRange() * ::Engine::Get(engine_id
)->GetRange();