Update: Translations from eints
[openttd-github.git] / src / script / api / script_engine.cpp
blob088b692925acf05f0a6693d5696c26b1f35fe009
1 /*
2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
6 */
8 /** @file script_engine.cpp Implementation of ScriptEngine. */
10 #include "../../stdafx.h"
11 #include "script_engine.hpp"
12 #include "script_cargo.hpp"
13 #include "../../company_base.h"
14 #include "../../strings_func.h"
15 #include "../../rail.h"
16 #include "../../road.h"
17 #include "../../engine_base.h"
18 #include "../../engine_func.h"
19 #include "../../articulated_vehicles.h"
20 #include "../../engine_cmd.h"
21 #include "../../timer/timer_game_calendar.h"
22 #include "table/strings.h"
24 #include "../../safeguards.h"
26 /* static */ bool ScriptEngine::IsValidEngine(EngineID engine_id)
28 EnforceDeityOrCompanyModeValid(false);
29 const Engine *e = ::Engine::GetIfValid(engine_id);
30 if (e == nullptr || !e->IsEnabled()) return false;
32 /* AIs have only access to engines they can purchase or still have in use.
33 * Deity has access to all engined that will be or were available ever. */
34 CompanyID company = ScriptObject::GetCompany();
35 return ScriptCompanyMode::IsDeity() || ::IsEngineBuildable(engine_id, e->type, company) || ::Company::Get(company)->group_all[e->type].GetNumEngines(engine_id) > 0;
38 /* static */ bool ScriptEngine::IsBuildable(EngineID engine_id)
40 EnforceDeityOrCompanyModeValid(false);
41 const Engine *e = ::Engine::GetIfValid(engine_id);
42 return e != nullptr && ::IsEngineBuildable(engine_id, e->type, ScriptObject::GetCompany());
45 /* static */ std::optional<std::string> ScriptEngine::GetName(EngineID engine_id)
47 if (!IsValidEngine(engine_id)) return std::nullopt;
49 ::SetDParam(0, engine_id);
50 return GetString(STR_ENGINE_NAME);
53 /* static */ CargoID ScriptEngine::GetCargoType(EngineID engine_id)
55 if (!IsValidEngine(engine_id)) return INVALID_CARGO;
57 CargoArray cap = ::GetCapacityOfArticulatedParts(engine_id);
59 auto it = std::max_element(std::cbegin(cap), std::cend(cap));
60 if (*it == 0) return INVALID_CARGO;
62 return CargoID(std::distance(std::cbegin(cap), it));
65 /* static */ bool ScriptEngine::CanRefitCargo(EngineID engine_id, CargoID cargo_id)
67 if (!IsValidEngine(engine_id)) return false;
68 if (!ScriptCargo::IsValidCargo(cargo_id)) return false;
70 return HasBit(::GetUnionOfArticulatedRefitMasks(engine_id, true), cargo_id);
73 /* static */ bool ScriptEngine::CanPullCargo(EngineID engine_id, CargoID cargo_id)
75 if (!IsValidEngine(engine_id)) return false;
76 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
77 if (!ScriptCargo::IsValidCargo(cargo_id)) return false;
79 return (::RailVehInfo(engine_id)->ai_passenger_only != 1) || ScriptCargo::HasCargoClass(cargo_id, ScriptCargo::CC_PASSENGERS);
83 /* static */ SQInteger ScriptEngine::GetCapacity(EngineID engine_id)
85 if (!IsValidEngine(engine_id)) return -1;
87 const Engine *e = ::Engine::Get(engine_id);
88 switch (e->type) {
89 case VEH_ROAD:
90 case VEH_TRAIN: {
91 CargoArray capacities = GetCapacityOfArticulatedParts(engine_id);
92 for (uint &cap : capacities) {
93 if (cap != 0) return cap;
95 return -1;
98 case VEH_SHIP:
99 case VEH_AIRCRAFT:
100 return e->GetDisplayDefaultCapacity();
102 default: NOT_REACHED();
106 /* static */ SQInteger ScriptEngine::GetReliability(EngineID engine_id)
108 if (!IsValidEngine(engine_id)) return -1;
109 if (GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL && IsWagon(engine_id)) return -1;
111 return ::ToPercent16(::Engine::Get(engine_id)->reliability);
114 /* static */ SQInteger ScriptEngine::GetMaxSpeed(EngineID engine_id)
116 if (!IsValidEngine(engine_id)) return -1;
118 const Engine *e = ::Engine::Get(engine_id);
119 uint max_speed = e->GetDisplayMaxSpeed(); // km-ish/h
120 if (e->type == VEH_AIRCRAFT) max_speed /= _settings_game.vehicle.plane_speed;
121 return max_speed;
124 /* static */ Money ScriptEngine::GetPrice(EngineID engine_id)
126 if (!IsValidEngine(engine_id)) return -1;
128 return ::Engine::Get(engine_id)->GetCost();
131 /* static */ SQInteger ScriptEngine::GetMaxAge(EngineID engine_id)
133 if (!IsValidEngine(engine_id)) return -1;
134 if (GetVehicleType(engine_id) == ScriptVehicle::VT_RAIL && IsWagon(engine_id)) return -1;
136 return ::Engine::Get(engine_id)->GetLifeLengthInDays().base();
139 /* static */ Money ScriptEngine::GetRunningCost(EngineID engine_id)
141 if (!IsValidEngine(engine_id)) return -1;
143 return ::Engine::Get(engine_id)->GetRunningCost();
146 /* static */ SQInteger ScriptEngine::GetPower(EngineID engine_id)
148 if (!IsValidEngine(engine_id)) return -1;
149 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL && GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return -1;
150 if (IsWagon(engine_id)) return -1;
152 return ::Engine::Get(engine_id)->GetPower();
155 /* static */ SQInteger ScriptEngine::GetWeight(EngineID engine_id)
157 if (!IsValidEngine(engine_id)) return -1;
158 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL && GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return -1;
160 return ::Engine::Get(engine_id)->GetDisplayWeight();
163 /* static */ SQInteger ScriptEngine::GetMaxTractiveEffort(EngineID engine_id)
165 if (!IsValidEngine(engine_id)) return -1;
166 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL && GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return -1;
167 if (IsWagon(engine_id)) return -1;
169 return ::Engine::Get(engine_id)->GetDisplayMaxTractiveEffort() / 1000;
172 /* static */ ScriptDate::Date ScriptEngine::GetDesignDate(EngineID engine_id)
174 if (!IsValidEngine(engine_id)) return ScriptDate::DATE_INVALID;
176 return (ScriptDate::Date)::Engine::Get(engine_id)->intro_date.base();
179 /* static */ ScriptVehicle::VehicleType ScriptEngine::GetVehicleType(EngineID engine_id)
181 if (!IsValidEngine(engine_id)) return ScriptVehicle::VT_INVALID;
183 switch (::Engine::Get(engine_id)->type) {
184 case VEH_ROAD: return ScriptVehicle::VT_ROAD;
185 case VEH_TRAIN: return ScriptVehicle::VT_RAIL;
186 case VEH_SHIP: return ScriptVehicle::VT_WATER;
187 case VEH_AIRCRAFT: return ScriptVehicle::VT_AIR;
188 default: NOT_REACHED();
192 /* static */ bool ScriptEngine::IsWagon(EngineID engine_id)
194 if (!IsValidEngine(engine_id)) return false;
195 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
197 return ::RailVehInfo(engine_id)->power == 0;
200 /* static */ bool ScriptEngine::CanRunOnRail(EngineID engine_id, ScriptRail::RailType track_rail_type)
202 if (!IsValidEngine(engine_id)) return false;
203 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
204 if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
206 return ::IsCompatibleRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
209 /* static */ bool ScriptEngine::HasPowerOnRail(EngineID engine_id, ScriptRail::RailType track_rail_type)
211 if (!IsValidEngine(engine_id)) return false;
212 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
213 if (!ScriptRail::IsRailTypeAvailable(track_rail_type)) return false;
215 return ::HasPowerOnRail((::RailType)::RailVehInfo(engine_id)->railtype, (::RailType)track_rail_type);
218 /* static */ bool ScriptEngine::CanRunOnRoad(EngineID engine_id, ScriptRoad::RoadType road_type)
220 return HasPowerOnRoad(engine_id, road_type);
223 /* static */ bool ScriptEngine::HasPowerOnRoad(EngineID engine_id, ScriptRoad::RoadType road_type)
225 if (!IsValidEngine(engine_id)) return false;
226 if (GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return false;
227 if (!ScriptRoad::IsRoadTypeAvailable(road_type)) return false;
229 return ::HasPowerOnRoad((::RoadType)::RoadVehInfo(engine_id)->roadtype, (::RoadType)road_type);
232 /* static */ ScriptRoad::RoadType ScriptEngine::GetRoadType(EngineID engine_id)
234 if (!IsValidEngine(engine_id)) return ScriptRoad::ROADTYPE_INVALID;
235 if (GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD) return ScriptRoad::ROADTYPE_INVALID;
237 return (ScriptRoad::RoadType)(uint)::RoadVehInfo(engine_id)->roadtype;
240 /* static */ ScriptRail::RailType ScriptEngine::GetRailType(EngineID engine_id)
242 if (!IsValidEngine(engine_id)) return ScriptRail::RAILTYPE_INVALID;
243 if (GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return ScriptRail::RAILTYPE_INVALID;
245 return (ScriptRail::RailType)(uint)::RailVehInfo(engine_id)->railtype;
248 /* static */ bool ScriptEngine::IsArticulated(EngineID engine_id)
250 if (!IsValidEngine(engine_id)) return false;
251 if (GetVehicleType(engine_id) != ScriptVehicle::VT_ROAD && GetVehicleType(engine_id) != ScriptVehicle::VT_RAIL) return false;
253 return IsArticulatedEngine(engine_id);
256 /* static */ ScriptAirport::PlaneType ScriptEngine::GetPlaneType(EngineID engine_id)
258 if (!IsValidEngine(engine_id)) return ScriptAirport::PT_INVALID;
259 if (GetVehicleType(engine_id) != ScriptVehicle::VT_AIR) return ScriptAirport::PT_INVALID;
261 return (ScriptAirport::PlaneType)::AircraftVehInfo(engine_id)->subtype;
264 /* static */ SQInteger ScriptEngine::GetMaximumOrderDistance(EngineID engine_id)
266 if (!IsValidEngine(engine_id)) return 0;
267 if (GetVehicleType(engine_id) != ScriptVehicle::VT_AIR) return 0;
269 return (SQInteger)::Engine::Get(engine_id)->GetRange() * ::Engine::Get(engine_id)->GetRange();
272 /* static */ bool ScriptEngine::EnableForCompany(EngineID engine_id, ScriptCompany::CompanyID company)
274 company = ScriptCompany::ResolveCompanyID(company);
276 EnforceDeityMode(false);
277 EnforcePrecondition(false, IsValidEngine(engine_id));
278 EnforcePrecondition(false, company != ScriptCompany::COMPANY_INVALID);
280 return ScriptObject::Command<CMD_ENGINE_CTRL>::Do(engine_id, (::CompanyID)company, true);
283 /* static */ bool ScriptEngine::DisableForCompany(EngineID engine_id, ScriptCompany::CompanyID company)
285 company = ScriptCompany::ResolveCompanyID(company);
287 EnforceDeityMode(false);
288 EnforcePrecondition(false, IsValidEngine(engine_id));
289 EnforcePrecondition(false, company != ScriptCompany::COMPANY_INVALID);
291 return ScriptObject::Command<CMD_ENGINE_CTRL>::Do(engine_id, (::CompanyID)company, false);