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_group.cpp Implementation of ScriptGroup. */
10 #include "../../stdafx.h"
11 #include "script_group.hpp"
12 #include "script_engine.hpp"
13 #include "../script_instance.hpp"
14 #include "../../string_func.h"
15 #include "../../strings_func.h"
16 #include "../../autoreplace_func.h"
17 #include "../../settings_func.h"
18 #include "../../vehicle_base.h"
19 #include "../../autoreplace_cmd.h"
20 #include "../../group_cmd.h"
21 #include "../../settings_cmd.h"
22 #include "table/strings.h"
24 #include "../../safeguards.h"
26 /* static */ bool ScriptGroup::IsValidGroup(GroupID group_id
)
28 EnforceDeityOrCompanyModeValid(false);
29 const Group
*g
= ::Group::GetIfValid(group_id
);
30 return g
!= nullptr && g
->owner
== ScriptObject::GetCompany();
33 /* static */ ScriptGroup::GroupID
ScriptGroup::CreateGroup(ScriptVehicle::VehicleType vehicle_type
, GroupID parent_group_id
)
35 EnforceCompanyModeValid(GROUP_INVALID
);
36 if (!ScriptObject::Command
<CMD_CREATE_GROUP
>::Do(&ScriptInstance::DoCommandReturnGroupID
, (::VehicleType
)vehicle_type
, parent_group_id
)) return GROUP_INVALID
;
38 /* In case of test-mode, we return GroupID 0 */
39 return (ScriptGroup::GroupID
)0;
42 /* static */ bool ScriptGroup::DeleteGroup(GroupID group_id
)
44 EnforceCompanyModeValid(false);
45 EnforcePrecondition(false, IsValidGroup(group_id
));
47 return ScriptObject::Command
<CMD_DELETE_GROUP
>::Do(group_id
);
50 /* static */ ScriptVehicle::VehicleType
ScriptGroup::GetVehicleType(GroupID group_id
)
52 if (!IsValidGroup(group_id
)) return ScriptVehicle::VT_INVALID
;
54 return (ScriptVehicle::VehicleType
)((::VehicleType
)::Group::Get(group_id
)->vehicle_type
);
57 /* static */ bool ScriptGroup::SetName(GroupID group_id
, Text
*name
)
59 CCountedPtr
<Text
> counter(name
);
61 EnforceCompanyModeValid(false);
62 EnforcePrecondition(false, IsValidGroup(group_id
));
63 EnforcePrecondition(false, name
!= nullptr);
64 const std::string
&text
= name
->GetDecodedText();
65 EnforcePreconditionEncodedText(false, text
);
66 EnforcePreconditionCustomError(false, ::Utf8StringLength(text
) < MAX_LENGTH_GROUP_NAME_CHARS
, ScriptError::ERR_PRECONDITION_STRING_TOO_LONG
);
68 return ScriptObject::Command
<CMD_ALTER_GROUP
>::Do(AlterGroupMode::Rename
, group_id
, 0, text
);
71 /* static */ std::optional
<std::string
> ScriptGroup::GetName(GroupID group_id
)
73 if (!IsValidGroup(group_id
)) return std::nullopt
;
75 ::SetDParam(0, group_id
);
76 return GetString(STR_GROUP_NAME
);
79 /* static */ bool ScriptGroup::SetParent(GroupID group_id
, GroupID parent_group_id
)
81 EnforceCompanyModeValid(false);
82 EnforcePrecondition(false, IsValidGroup(group_id
));
83 EnforcePrecondition(false, IsValidGroup(parent_group_id
));
85 return ScriptObject::Command
<CMD_ALTER_GROUP
>::Do(AlterGroupMode::SetParent
, group_id
, parent_group_id
, {});
88 /* static */ ScriptGroup::GroupID
ScriptGroup::GetParent(GroupID group_id
)
90 EnforcePrecondition((ScriptGroup::GroupID
)INVALID_GROUP
, IsValidGroup(group_id
));
92 const Group
*g
= ::Group::GetIfValid(group_id
);
93 return (ScriptGroup::GroupID
)g
->parent
;
96 /* static */ bool ScriptGroup::EnableAutoReplaceProtection(GroupID group_id
, bool enable
)
98 EnforceCompanyModeValid(false);
99 EnforcePrecondition(false, IsValidGroup(group_id
));
101 return ScriptObject::Command
<CMD_SET_GROUP_FLAG
>::Do(group_id
, GroupFlags::GF_REPLACE_PROTECTION
, enable
, false);
104 /* static */ bool ScriptGroup::GetAutoReplaceProtection(GroupID group_id
)
106 if (!IsValidGroup(group_id
)) return false;
108 return HasBit(::Group::Get(group_id
)->flags
, GroupFlags::GF_REPLACE_PROTECTION
);
111 /* static */ SQInteger
ScriptGroup::GetNumEngines(GroupID group_id
, EngineID engine_id
)
113 EnforceCompanyModeValid(-1);
114 if (!ScriptEngine::IsValidEngine(engine_id
)) return -1;
115 bool valid_group
= IsValidGroup(group_id
);
116 if (!valid_group
&& group_id
!= GROUP_DEFAULT
&& group_id
!= GROUP_ALL
) return -1;
117 if (valid_group
&& ScriptEngine::GetVehicleType(engine_id
) != GetVehicleType(group_id
)) return -1;
119 return GetGroupNumEngines(ScriptObject::GetCompany(), group_id
, engine_id
);
122 /* static */ SQInteger
ScriptGroup::GetNumVehicles(GroupID group_id
, ScriptVehicle::VehicleType vehicle_type
)
124 EnforceCompanyModeValid(-1);
125 bool valid_group
= IsValidGroup(group_id
);
126 if (!valid_group
&& group_id
!= GROUP_DEFAULT
&& group_id
!= GROUP_ALL
) return -1;
127 if (!valid_group
&& (vehicle_type
< ScriptVehicle::VT_RAIL
|| vehicle_type
> ScriptVehicle::VT_AIR
)) return -1;
129 return GetGroupNumVehicle(ScriptObject::GetCompany(), group_id
, valid_group
? ::Group::Get(group_id
)->vehicle_type
: (::VehicleType
)vehicle_type
);
132 /* static */ bool ScriptGroup::MoveVehicle(GroupID group_id
, VehicleID vehicle_id
)
134 EnforceCompanyModeValid(false);
135 EnforcePrecondition(false, IsValidGroup(group_id
) || group_id
== GROUP_DEFAULT
);
136 EnforcePrecondition(false, ScriptVehicle::IsPrimaryVehicle(vehicle_id
));
138 return ScriptObject::Command
<CMD_ADD_VEHICLE_GROUP
>::Do(group_id
, vehicle_id
, false, VehicleListIdentifier
{});
141 /* static */ bool ScriptGroup::EnableWagonRemoval(bool enable_removal
)
143 EnforceCompanyModeValid(false);
144 if (HasWagonRemoval() == enable_removal
) return true;
146 return ScriptObject::Command
<CMD_CHANGE_COMPANY_SETTING
>::Do("company.renew_keep_length", enable_removal
? 1 : 0);
149 /* static */ bool ScriptGroup::HasWagonRemoval()
151 EnforceCompanyModeValid(false);
152 return ::Company::Get(ScriptObject::GetCompany())->settings
.renew_keep_length
;
155 /* static */ bool ScriptGroup::SetAutoReplace(GroupID group_id
, EngineID engine_id_old
, EngineID engine_id_new
)
157 EnforceCompanyModeValid(false);
158 EnforcePrecondition(false, IsValidGroup(group_id
) || group_id
== GROUP_DEFAULT
|| group_id
== GROUP_ALL
);
159 EnforcePrecondition(false, ScriptEngine::IsBuildable(engine_id_new
));
161 return ScriptObject::Command
<CMD_SET_AUTOREPLACE
>::Do(group_id
, engine_id_old
, engine_id_new
, false);
164 /* static */ EngineID
ScriptGroup::GetEngineReplacement(GroupID group_id
, EngineID engine_id
)
166 EnforceCompanyModeValid(::INVALID_ENGINE
);
167 if (!IsValidGroup(group_id
) && group_id
!= GROUP_DEFAULT
&& group_id
!= GROUP_ALL
) return ::INVALID_ENGINE
;
169 return ::EngineReplacementForCompany(Company::Get(ScriptObject::GetCompany()), engine_id
, group_id
);
172 /* static */ bool ScriptGroup::StopAutoReplace(GroupID group_id
, EngineID engine_id
)
174 EnforceCompanyModeValid(false);
175 EnforcePrecondition(false, IsValidGroup(group_id
) || group_id
== GROUP_DEFAULT
|| group_id
== GROUP_ALL
);
177 return ScriptObject::Command
<CMD_SET_AUTOREPLACE
>::Do(group_id
, engine_id
, ::INVALID_ENGINE
, false);
180 /* static */ Money
ScriptGroup::GetProfitThisYear(GroupID group_id
)
182 if (!IsValidGroup(group_id
)) return -1;
186 for (const Vehicle
*v
: Vehicle::Iterate()) {
187 if (v
->group_id
!= group_id
) continue;
188 if (!v
->IsPrimaryVehicle()) continue;
190 profit
+= v
->GetDisplayProfitThisYear();
196 /* static */ Money
ScriptGroup::GetProfitLastYear(GroupID group_id
)
198 if (!IsValidGroup(group_id
)) return -1;
200 return ::Group::Get(group_id
)->statistics
.profit_last_year
;
203 /* static */ SQInteger
ScriptGroup::GetCurrentUsage(GroupID group_id
)
205 if (!IsValidGroup(group_id
)) return -1;
207 uint32_t occupancy
= 0;
208 uint32_t vehicle_count
= 0;
210 for (const Vehicle
*v
: Vehicle::Iterate()) {
211 if (v
->group_id
!= group_id
) continue;
212 if (!v
->IsPrimaryVehicle()) continue;
214 occupancy
+= v
->trip_occupancy
;
218 if (vehicle_count
== 0) return -1;
220 return occupancy
/ vehicle_count
;
223 /* static */ bool ScriptGroup::SetPrimaryColour(GroupID group_id
, ScriptCompany::Colours colour
)
225 EnforceCompanyModeValid(false);
226 EnforcePrecondition(false, IsValidGroup(group_id
));
228 return ScriptObject::Command
<CMD_SET_GROUP_LIVERY
>::Do(group_id
, true, (::Colours
)colour
);
231 /* static */ bool ScriptGroup::SetSecondaryColour(GroupID group_id
, ScriptCompany::Colours colour
)
233 EnforceCompanyModeValid(false);
234 EnforcePrecondition(false, IsValidGroup(group_id
));
236 return ScriptObject::Command
<CMD_SET_GROUP_LIVERY
>::Do(group_id
, false, (::Colours
)colour
);
239 /* static */ ScriptCompany::Colours
ScriptGroup::GetPrimaryColour(GroupID group_id
)
241 EnforcePrecondition(ScriptCompany::Colours::COLOUR_INVALID
, IsValidGroup(group_id
));
243 const Group
*g
= ::Group::GetIfValid(group_id
);
244 if (!HasBit(g
->livery
.in_use
, 0)) return ScriptCompany::Colours::COLOUR_INVALID
;
245 return (ScriptCompany::Colours
)g
->livery
.colour1
;
248 /* static */ ScriptCompany::Colours
ScriptGroup::GetSecondaryColour(GroupID group_id
)
250 EnforcePrecondition(ScriptCompany::Colours::COLOUR_INVALID
, IsValidGroup(group_id
));
252 const Group
*g
= ::Group::GetIfValid(group_id
);
253 if (!HasBit(g
->livery
.in_use
, 1)) return ScriptCompany::Colours::COLOUR_INVALID
;
254 return (ScriptCompany::Colours
)g
->livery
.colour2
;