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/>.
8 /** @file script_industry.cpp Implementation of ScriptIndustry. */
10 #include "../../stdafx.h"
11 #include "script_industry.hpp"
12 #include "script_cargo.hpp"
13 #include "script_company.hpp"
14 #include "script_error.hpp"
15 #include "script_map.hpp"
16 #include "../../company_base.h"
17 #include "../../industry.h"
18 #include "../../string_func.h"
19 #include "../../strings_func.h"
20 #include "../../station_base.h"
21 #include "../../newgrf_industries.h"
22 #include "../../industry_cmd.h"
23 #include "../../timer/timer_game_calendar.h"
24 #include "table/strings.h"
26 #include "../../safeguards.h"
28 /* static */ SQInteger
ScriptIndustry::GetIndustryCount()
30 return ::Industry::GetNumItems();
33 /* static */ bool ScriptIndustry::IsValidIndustry(IndustryID industry_id
)
35 return ::Industry::IsValidID(industry_id
);
38 /* static */ IndustryID
ScriptIndustry::GetIndustryID(TileIndex tile
)
40 if (!::IsValidTile(tile
) || !::IsTileType(tile
, MP_INDUSTRY
)) return INVALID_INDUSTRY
;
41 return ::GetIndustryIndex(tile
);
44 /* static */ std::optional
<std::string
> ScriptIndustry::GetName(IndustryID industry_id
)
46 if (!IsValidIndustry(industry_id
)) return std::nullopt
;
48 ::SetDParam(0, industry_id
);
49 return GetString(STR_INDUSTRY_NAME
);
52 /* static */ ScriptDate::Date
ScriptIndustry::GetConstructionDate(IndustryID industry_id
)
54 const Industry
*i
= Industry::GetIfValid(industry_id
);
55 if (i
== nullptr) return ScriptDate::DATE_INVALID
;
56 return (ScriptDate::Date
)i
->construction_date
.base();
59 /* static */ bool ScriptIndustry::SetText(IndustryID industry_id
, Text
*text
)
61 CCountedPtr
<Text
> counter(text
);
63 EnforceDeityMode(false);
64 EnforcePrecondition(false, IsValidIndustry(industry_id
));
66 return ScriptObject::Command
<CMD_INDUSTRY_SET_TEXT
>::Do(industry_id
, text
!= nullptr ? text
->GetEncodedText() : std::string
{});
69 /* static */ ScriptIndustry::CargoAcceptState
ScriptIndustry::IsCargoAccepted(IndustryID industry_id
, CargoID cargo_id
)
71 if (!IsValidIndustry(industry_id
)) return CAS_NOT_ACCEPTED
;
72 if (!ScriptCargo::IsValidCargo(cargo_id
)) return CAS_NOT_ACCEPTED
;
74 /* Not const because IndustryTemporarilyRefusesCargo tests a callback which needs a non-const object. */
75 Industry
*i
= ::Industry::Get(industry_id
);
77 if (!i
->IsCargoAccepted(cargo_id
)) return CAS_NOT_ACCEPTED
;
78 if (IndustryTemporarilyRefusesCargo(i
, cargo_id
)) return CAS_TEMP_REFUSED
;
83 /* static */ SQInteger
ScriptIndustry::GetStockpiledCargo(IndustryID industry_id
, CargoID cargo_id
)
85 if (!IsValidIndustry(industry_id
)) return -1;
86 if (!ScriptCargo::IsValidCargo(cargo_id
)) return -1;
88 const Industry
*i
= ::Industry::Get(industry_id
);
90 auto it
= i
->GetCargoAccepted(cargo_id
);
91 if (it
== std::end(i
->accepted
)) return -1;
96 /* static */ SQInteger
ScriptIndustry::GetLastMonthProduction(IndustryID industry_id
, CargoID cargo_id
)
98 if (!IsValidIndustry(industry_id
)) return -1;
99 if (!ScriptCargo::IsValidCargo(cargo_id
)) return -1;
101 const Industry
*i
= ::Industry::Get(industry_id
);
103 auto it
= i
->GetCargoProduced(cargo_id
);
104 if (it
== std::end(i
->produced
)) return -1;
106 return it
->history
[LAST_MONTH
].production
;
109 /* static */ SQInteger
ScriptIndustry::GetLastMonthTransported(IndustryID industry_id
, CargoID cargo_id
)
111 if (!IsValidIndustry(industry_id
)) return -1;
112 if (!ScriptCargo::IsValidCargo(cargo_id
)) return -1;
114 const Industry
*i
= ::Industry::Get(industry_id
);
116 auto it
= i
->GetCargoProduced(cargo_id
);
117 if (it
== std::end(i
->produced
)) return -1;
119 return it
->history
[LAST_MONTH
].transported
;
122 /* static */ SQInteger
ScriptIndustry::GetLastMonthTransportedPercentage(IndustryID industry_id
, CargoID cargo_id
)
124 if (!IsValidIndustry(industry_id
)) return -1;
125 if (!ScriptCargo::IsValidCargo(cargo_id
)) return -1;
127 const Industry
*i
= ::Industry::Get(industry_id
);
129 auto it
= i
->GetCargoProduced(cargo_id
);
130 if (it
== std::end(i
->produced
)) return -1;
132 return ::ToPercent8(it
->history
[LAST_MONTH
].PctTransported());
135 /* static */ TileIndex
ScriptIndustry::GetLocation(IndustryID industry_id
)
137 if (!IsValidIndustry(industry_id
)) return INVALID_TILE
;
139 return ::Industry::Get(industry_id
)->location
.tile
;
142 /* static */ SQInteger
ScriptIndustry::GetAmountOfStationsAround(IndustryID industry_id
)
144 if (!IsValidIndustry(industry_id
)) return -1;
146 const Industry
*ind
= ::Industry::Get(industry_id
);
147 return ind
->stations_near
.size();
150 /* static */ SQInteger
ScriptIndustry::GetDistanceManhattanToTile(IndustryID industry_id
, TileIndex tile
)
152 if (!IsValidIndustry(industry_id
)) return -1;
154 return ScriptMap::DistanceManhattan(tile
, GetLocation(industry_id
));
157 /* static */ SQInteger
ScriptIndustry::GetDistanceSquareToTile(IndustryID industry_id
, TileIndex tile
)
159 if (!IsValidIndustry(industry_id
)) return -1;
161 return ScriptMap::DistanceSquare(tile
, GetLocation(industry_id
));
164 /* static */ bool ScriptIndustry::IsBuiltOnWater(IndustryID industry_id
)
166 if (!IsValidIndustry(industry_id
)) return false;
168 return (::GetIndustrySpec(::Industry::Get(industry_id
)->type
)->behaviour
& INDUSTRYBEH_BUILT_ONWATER
) != 0;
171 /* static */ bool ScriptIndustry::HasHeliport(IndustryID industry_id
)
173 if (!IsValidIndustry(industry_id
)) return false;
175 return (::GetIndustrySpec(::Industry::Get(industry_id
)->type
)->behaviour
& INDUSTRYBEH_AI_AIRSHIP_ROUTES
) != 0;
178 /* static */ TileIndex
ScriptIndustry::GetHeliportLocation(IndustryID industry_id
)
180 if (!IsValidIndustry(industry_id
)) return INVALID_TILE
;
181 if (!HasHeliport(industry_id
)) return INVALID_TILE
;
183 const Industry
*ind
= ::Industry::Get(industry_id
);
184 for (TileIndex tile_cur
: ind
->location
) {
185 if (IsTileType(tile_cur
, MP_STATION
) && IsOilRig(tile_cur
)) {
193 /* static */ bool ScriptIndustry::HasDock(IndustryID industry_id
)
195 if (!IsValidIndustry(industry_id
)) return false;
197 return (::GetIndustrySpec(::Industry::Get(industry_id
)->type
)->behaviour
& INDUSTRYBEH_AI_AIRSHIP_ROUTES
) != 0;
200 /* static */ TileIndex
ScriptIndustry::GetDockLocation(IndustryID industry_id
)
202 if (!IsValidIndustry(industry_id
)) return INVALID_TILE
;
203 if (!HasDock(industry_id
)) return INVALID_TILE
;
205 const Industry
*ind
= ::Industry::Get(industry_id
);
206 for (TileIndex tile_cur
: ind
->location
) {
207 if (IsTileType(tile_cur
, MP_STATION
) && IsOilRig(tile_cur
)) {
215 /* static */ IndustryType
ScriptIndustry::GetIndustryType(IndustryID industry_id
)
217 if (!IsValidIndustry(industry_id
)) return INVALID_INDUSTRYTYPE
;
219 return ::Industry::Get(industry_id
)->type
;
222 /* static */ SQInteger
ScriptIndustry::GetLastProductionYear(IndustryID industry_id
)
224 const Industry
*i
= Industry::GetIfValid(industry_id
);
225 if (i
== nullptr) return 0;
226 return i
->last_prod_year
.base();
229 /* static */ ScriptDate::Date
ScriptIndustry::GetCargoLastAcceptedDate(IndustryID industry_id
, CargoID cargo_type
)
231 const Industry
*i
= Industry::GetIfValid(industry_id
);
232 if (i
== nullptr) return ScriptDate::DATE_INVALID
;
234 if (!::IsValidCargoID(cargo_type
)) {
235 auto it
= std::max_element(std::begin(i
->accepted
), std::end(i
->accepted
), [](const auto &a
, const auto &b
) { return a
.last_accepted
< b
.last_accepted
; });
236 return (ScriptDate::Date
)it
->last_accepted
.base();
238 auto it
= i
->GetCargoAccepted(cargo_type
);
239 if (it
== std::end(i
->accepted
)) return ScriptDate::DATE_INVALID
;
240 return (ScriptDate::Date
)it
->last_accepted
.base();
244 /* static */ SQInteger
ScriptIndustry::GetControlFlags(IndustryID industry_id
)
246 const Industry
*i
= Industry::GetIfValid(industry_id
);
247 if (i
== nullptr) return 0;
251 /* static */ bool ScriptIndustry::SetControlFlags(IndustryID industry_id
, SQInteger control_flags
)
253 EnforceDeityMode(false);
254 if (!IsValidIndustry(industry_id
)) return false;
256 return ScriptObject::Command
<CMD_INDUSTRY_SET_FLAGS
>::Do(industry_id
, (::IndustryControlFlags
)control_flags
& ::INDCTL_MASK
);
259 /* static */ ScriptCompany::CompanyID
ScriptIndustry::GetExclusiveSupplier(IndustryID industry_id
)
261 if (!IsValidIndustry(industry_id
)) return ScriptCompany::COMPANY_INVALID
;
263 auto company_id
= ::Industry::Get(industry_id
)->exclusive_supplier
;
264 if (!::Company::IsValidID(company_id
)) return ScriptCompany::COMPANY_INVALID
;
266 return (ScriptCompany::CompanyID
)((uint8_t)company_id
);
269 /* static */ bool ScriptIndustry::SetExclusiveSupplier(IndustryID industry_id
, ScriptCompany::CompanyID company_id
)
271 EnforceDeityMode(false);
272 EnforcePrecondition(false, IsValidIndustry(industry_id
));
274 auto company
= ScriptCompany::ResolveCompanyID(company_id
);
275 ::Owner owner
= (company
== ScriptCompany::COMPANY_INVALID
? ::INVALID_OWNER
: (::Owner
)company
);
276 return ScriptObject::Command
<CMD_INDUSTRY_SET_EXCLUSIVITY
>::Do(industry_id
, owner
, false);
279 /* static */ ScriptCompany::CompanyID
ScriptIndustry::GetExclusiveConsumer(IndustryID industry_id
)
281 if (!IsValidIndustry(industry_id
)) return ScriptCompany::COMPANY_INVALID
;
283 auto company_id
= ::Industry::Get(industry_id
)->exclusive_consumer
;
284 if (!::Company::IsValidID(company_id
)) return ScriptCompany::COMPANY_INVALID
;
286 return (ScriptCompany::CompanyID
)((uint8_t)company_id
);
289 /* static */ bool ScriptIndustry::SetExclusiveConsumer(IndustryID industry_id
, ScriptCompany::CompanyID company_id
)
291 EnforceDeityMode(false);
292 EnforcePrecondition(false, IsValidIndustry(industry_id
));
294 auto company
= ScriptCompany::ResolveCompanyID(company_id
);
295 ::Owner owner
= (company
== ScriptCompany::COMPANY_INVALID
? ::INVALID_OWNER
: (::Owner
)company
);
296 return ScriptObject::Command
<CMD_INDUSTRY_SET_EXCLUSIVITY
>::Do(industry_id
, owner
, true);
299 /* static */ SQInteger
ScriptIndustry::GetProductionLevel(IndustryID industry_id
)
301 const Industry
*i
= Industry::GetIfValid(industry_id
);
302 if (i
== nullptr) return 0;
303 return i
->prod_level
;
306 /* static */ bool ScriptIndustry::SetProductionLevel(IndustryID industry_id
, SQInteger prod_level
, bool show_news
, Text
*custom_news
)
308 CCountedPtr
<Text
> counter(custom_news
);
310 EnforceDeityMode(false);
311 EnforcePrecondition(false, IsValidIndustry(industry_id
));
312 EnforcePrecondition(false, prod_level
>= PRODLEVEL_MINIMUM
&& prod_level
<= PRODLEVEL_MAXIMUM
);
314 return ScriptObject::Command
<CMD_INDUSTRY_SET_PRODUCTION
>::Do(industry_id
, prod_level
, show_news
, custom_news
!= nullptr ? custom_news
->GetEncodedText() : std::string
{});