1use std::fmt::{Display, Formatter};
4
5use bitflags::bitflags;
6
7use crate::context::ScopeContext;
8use crate::everything::Everything;
9use crate::game::Game;
10use crate::helpers::{camel_case_to_separated_words, display_choices, snake_case_to_camel_case};
11use crate::item::Item;
12use crate::lowercase::Lowercase;
13use crate::report::{ErrorKey, err};
14use crate::token::Token;
15
16#[cfg(any(feature = "vic3", feature = "ck3", feature = "eu5"))]
18type ScopesBits = u128;
19#[cfg(not(any(feature = "vic3", feature = "ck3", feature = "eu5")))]
20type ScopesBits = u64;
21
22bitflags! {
23 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
36 #[rustfmt::skip] pub struct Scopes: ScopesBits {
38 const None = 1<<0;
40 const Value = 1<<1;
41 const Bool = 1<<2;
42 const Flag = 1<<3;
43
44 #[cfg(any(feature = "vic3", feature = "imperator", feature = "eu5"))]
47 const Color = 1<<4;
48 #[cfg(any(feature = "vic3", feature = "imperator", feature = "eu5", feature = "hoi4"))]
49 const Country = 1<<5;
50 const Character = 1<<6;
51 #[cfg(any(feature = "ck3", feature = "vic3", feature = "eu5", feature = "imperator"))]
52 const Culture = 1<<7;
53 #[cfg(any(feature = "ck3", feature = "vic3", feature = "imperator", feature = "eu5"))]
54 const Province = 1<<8;
55 #[cfg(any(feature = "vic3", feature = "imperator", feature = "eu5"))]
56 const Pop = 1<<9;
57 #[cfg(any(feature = "vic3", feature = "imperator"))]
58 const Party = 1<<10;
59 #[cfg(feature = "eu5")]
60 const PopType = 1<<10; #[cfg(any(feature = "ck3", feature = "vic3", feature = "imperator", feature = "eu5"))]
62 const Religion = 1<<11;
63 #[cfg(any(feature = "vic3", feature = "imperator", feature = "hoi4"))]
64 const State = 1<<12;
65 #[cfg(feature = "eu5")]
66 const Trait = 1<<12; #[cfg(any(feature = "ck3", feature = "vic3", feature = "imperator", feature = "eu5"))]
68 const War = 1<<13;
69 #[cfg(any(feature = "vic3", feature = "hoi4"))]
70 const StrategicRegion = 1<<14;
71 #[cfg(feature = "eu5")]
72 const Invalid = 1<<14; #[cfg(any(feature = "ck3", feature = "vic3"))]
74 const Decision = 1<<15;
75 #[cfg(feature = "eu5")]
76 const Date = 1<<15; #[cfg(feature = "ck3")] const Accolade = 1<<16;
80 #[cfg(feature = "ck3")] const AccoladeType = 1<<17;
81 #[cfg(feature = "ck3")] const Activity = 1<<18;
82 #[cfg(feature = "ck3")] const ActivityType = 1<<19;
83 #[cfg(feature = "ck3")] const Army = 1<<20;
84 #[cfg(feature = "ck3")] const Artifact = 1<<21;
85 #[cfg(feature = "ck3")] const CasusBelli = 1<<22;
86 #[cfg(feature = "ck3")] const CharacterMemory = 1<<23;
87 #[cfg(feature = "ck3")] const Combat = 1<<24;
88 #[cfg(feature = "ck3")] const CombatSide = 1<<25;
89 #[cfg(feature = "ck3")] const CouncilTask = 1<<26;
90 #[cfg(feature = "ck3")] const CulturePillar = 1<<27;
91 #[cfg(feature = "ck3")] const CultureTradition = 1<<28;
92 #[cfg(feature = "ck3")] const Doctrine = 1<<29;
93 #[cfg(feature = "ck3")] const Dynasty = 1<<30;
94 #[cfg(feature = "ck3")] const DynastyHouse = 1<<31;
95 #[cfg(feature = "ck3")] const Faction = 1<<32;
96 #[cfg(feature = "ck3")] const Faith = 1<<33;
97 #[cfg(feature = "ck3")] const GovernmentType = 1<<34;
98 #[cfg(feature = "ck3")] const GreatHolyWar = 1<<35;
99 #[cfg(feature = "ck3")] const HolyOrder = 1<<36;
100 #[cfg(feature = "ck3")] const Inspiration = 1<<37;
101 #[cfg(feature = "ck3")] const LandedTitle = 1<<38;
102 #[cfg(feature = "ck3")] const MercenaryCompany = 1<<39;
103 #[cfg(feature = "ck3")] const Scheme = 1<<40;
104 #[cfg(feature = "ck3")] const Secret = 1<<41;
105 #[cfg(feature = "ck3")] const StoryCycle = 1<<42;
106 #[cfg(feature = "ck3")] const Struggle = 1<<43;
107 #[cfg(feature = "ck3")] const TitleAndVassalChange = 1<<44;
108 #[cfg(feature = "ck3")] const Trait = 1<<45;
109 #[cfg(feature = "ck3")] const TravelPlan = 1<<46;
110 #[cfg(feature = "ck3")] const VassalContract = 1<<47;
111 #[cfg(feature = "ck3")] const VassalObligationLevel = 1<<48;
112 #[cfg(feature = "ck3")] const HoldingType = 1<<49;
114 #[cfg(feature = "ck3")] const TaxSlot = 1<<50;
115 #[cfg(feature = "ck3")] const EpidemicType = 1<<51;
117 #[cfg(feature = "ck3")] const Epidemic = 1<<52;
118 #[cfg(feature = "ck3")] const LegendType = 1<<53;
119 #[cfg(feature = "ck3")] const Legend = 1<<54;
120 #[cfg(feature = "ck3")] const GeographicalRegion = 1<<55;
121 #[cfg(feature = "ck3")] const Domicile = 1<<56;
123 #[cfg(feature = "ck3")] const AgentSlot = 1<<57;
124 #[cfg(feature = "ck3")] const TaskContract = 1<<58;
125 #[cfg(feature = "ck3")] const TaskContractType = 1<<59;
126 #[cfg(feature = "ck3")] const Regiment = 1<<60;
127 #[cfg(feature = "ck3")] const CasusBelliType = 1<<61;
128 #[cfg(feature = "ck3")] const CourtPosition = 1<<62;
130 #[cfg(feature = "ck3")] const CourtPositionType = 1<<63;
131 #[cfg(feature = "ck3")] const Situation = 1<<64;
133 #[cfg(feature = "ck3")] const SituationParticipantGroup = 1<<65;
134 #[cfg(feature = "ck3")] const SituationSubRegion = 1<<66;
135 #[cfg(feature = "ck3")] const Confederation = 1<<67;
136 #[cfg(feature = "ck3")] const HouseAspiration = 1<<68;
138 #[cfg(feature = "ck3")] const HouseRelation = 1<<69;
139 #[cfg(feature = "ck3")] const HouseRelationType = 1<<70;
140 #[cfg(feature = "ck3")] const HouseRelationLevel = 1<<71;
141 #[cfg(feature = "ck3")] const ConfederationType = 1<<72;
142 #[cfg(feature = "ck3")] const GreatProject = 1<<73;
143 #[cfg(feature = "ck3")] const ProjectContribution = 1<<74;
144 #[cfg(feature = "ck3")] const CultureInnovation = 1<<75;
145 #[cfg(feature = "ck3")] const GreatProjectType = 1<<76;
146
147 #[cfg(feature = "vic3")] const Battle = 1<<16;
148 #[cfg(feature = "vic3")] const BattleSide = 1<<17;
149 #[cfg(feature = "vic3")] const Building = 1<<18;
150 #[cfg(feature = "vic3")] const BuildingType = 1<<19;
151 #[cfg(feature = "vic3")] const CanalType = 1<<20;
152 #[cfg(feature = "vic3")] const CivilWar = 1<<21;
153 #[cfg(feature = "vic3")] const CulturalCommunity = 1<<22;
154 #[cfg(feature = "vic3")] const NewCombatUnit = 1<<23;
155 #[cfg(feature = "vic3")] const CommanderOrderType = 1<<24;
156 #[cfg(feature = "vic3")] const CountryCreation = 1<<25;
157 #[cfg(feature = "vic3")] const CountryDefinition = 1<<26;
158 #[cfg(feature = "vic3")] const CountryFormation = 1<<27;
159 #[cfg(feature = "vic3")] const Decree = 1<<28;
160 #[cfg(feature = "vic3")] const DiplomaticAction = 1<<29;
161 #[cfg(feature = "vic3")] const DiplomaticPact = 1<<30;
162 #[cfg(feature = "vic3")] const DiplomaticPlay = 1<<31;
163 #[cfg(feature = "vic3")] const DiplomaticRelations = 1<<32;
164 #[cfg(feature = "vic3")] const Front = 1<<33;
165 #[cfg(feature = "vic3")] const Goods = 1<<34;
166 #[cfg(feature = "vic3")] const Hq = 1<<35;
167 #[cfg(feature = "vic3")] const Ideology = 1<<36;
168 #[cfg(feature = "vic3")] const Institution = 1<<37;
169 #[cfg(feature = "vic3")] const InstitutionType = 1<<38;
170 #[cfg(feature = "vic3")] const InterestMarker = 1<<39;
171 #[cfg(feature = "vic3")] const InterestGroup = 1<<40;
172 #[cfg(feature = "vic3")] const InterestGroupTrait = 1<<41;
173 #[cfg(feature = "vic3")] const InterestGroupType = 1<<42;
174 #[cfg(feature = "vic3")] const JournalEntry = 1<<43;
175 #[cfg(feature = "vic3")] const Law = 1<<44;
176 #[cfg(feature = "vic3")] const LawType = 1<<45;
177 #[cfg(feature = "vic3")] const Market = 1<<46;
178 #[cfg(feature = "vic3")] const MarketGoods = 1<<47;
179 #[cfg(feature = "vic3")] const Objective = 1<<48;
180 #[cfg(feature = "vic3")] const PoliticalMovement = 1<<49;
181 #[cfg(feature = "vic3")] const PopType = 1<<50;
182 #[cfg(feature = "vic3")] const ShippingLanes = 1<<51;
183 #[cfg(feature = "vic3")] const StateRegion = 1<<52;
184 #[cfg(feature = "vic3")] const StateTrait = 1<<53;
185 #[cfg(feature = "vic3")] const Technology = 1<<54;
186 #[cfg(feature = "vic3")] const TechnologyStatus = 1<<55;
187 #[cfg(feature = "vic3")] const Theater = 1<<56;
188 #[cfg(feature = "vic3")] const CombatUnitType = 1<<57;
189 #[cfg(feature = "vic3")] const MilitaryFormation = 1<<58;
190 #[cfg(feature = "vic3")] const Sway = 1<<59;
191 #[cfg(feature = "vic3")] const StateGoods = 1<<60;
192 #[cfg(feature = "vic3")] const DiplomaticDemand = 1<<61;
193 #[cfg(feature = "vic3")] const Company = 1<<62;
194 #[cfg(feature = "vic3")] const CompanyType = 1<<63;
195 #[cfg(feature = "vic3")] const TravelNode = 1<<64;
196 #[cfg(feature = "vic3")] const TravelNodeDefinition = 1<<65;
197 #[cfg(feature = "vic3")] const TravelConnection = 1<<66;
198 #[cfg(feature = "vic3")] const TravelConnectionDefinition = 1<<67;
199 #[cfg(feature = "vic3")] const Invasion = 1<<68;
200 #[cfg(feature = "vic3")] const MobilizationOption = 1<<69;
201 #[cfg(feature = "vic3")] const PowerBlocPrincipleGroup = 1<<70;
202 #[cfg(feature = "vic3")] const DiplomaticPlayType = 1<<71;
203 #[cfg(feature = "vic3")] const DiplomaticCatalyst = 1<<72;
204 #[cfg(feature = "vic3")] const DiplomaticCatalystType = 1<<73;
205 #[cfg(feature = "vic3")] const DiplomaticCatalystCategory = 1<<74;
206 #[cfg(feature = "vic3")] const PoliticalLobby = 1<<75;
207 #[cfg(feature = "vic3")] const PoliticalLobbyType = 1<<76;
208 #[cfg(feature = "vic3")] const PoliticalLobbyAppeasement = 1<<77;
209 #[cfg(feature = "vic3")] const PowerBloc = 1<<78;
210 #[cfg(feature = "vic3")] const PowerBlocIdentity = 1<<79;
211 #[cfg(feature = "vic3")] const PowerBlocPrinciple = 1<<80;
212 #[cfg(feature = "vic3")] const HarvestCondition = 1<<81;
213 #[cfg(feature = "vic3")] const PoliticalMovementType = 1<<82;
214 #[cfg(feature = "vic3")] const HarvestConditionType = 1<<83;
215 #[cfg(feature = "vic3")] const TreatyArticle = 1<<84;
216 #[cfg(feature = "vic3")] const TreatyOptions = 1<<85;
217 #[cfg(feature = "vic3")] const TreatyArticleOptions = 1<<86;
218 #[cfg(feature = "vic3")] const Treaty = 1<<87;
219 #[cfg(feature = "vic3")] const BuildingGroup = 1<<88;
220 #[cfg(feature = "vic3")] const Amendment = 1<<89;
221 #[cfg(feature = "vic3")] const AmendmentType = 1<<90;
222 #[cfg(feature = "vic3")] const GeographicRegion = 1<<91;
223 #[cfg(feature = "vic3")] const WarGoal = 1<<92;
224 #[cfg(feature = "vic3")] const WarGoalType = 1<<93;
225
226 #[cfg(feature = "imperator")] const Area = 1<<16;
227 #[cfg(feature = "imperator")] const CountryCulture = 1<<17;
228 #[cfg(feature = "imperator")] const CultureGroup = 1<<18;
229 #[cfg(feature = "imperator")] const Deity = 1<<19;
230 #[cfg(feature = "imperator")] const Family = 1<<20;
231 #[cfg(feature = "imperator")] const Governorship = 1<<21;
232 #[cfg(feature = "imperator")] const GreatWork = 1<<22;
233 #[cfg(feature = "imperator")] const Job = 1<<23;
234 #[cfg(feature = "imperator")] const Legion = 1<<24;
235 #[cfg(feature = "imperator")] const LevyTemplate = 1<<25;
236 #[cfg(feature = "imperator")] const Region = 1<<26;
237 #[cfg(feature = "imperator")] const Siege = 1<<27;
238 #[cfg(feature = "imperator")] const SubUnit = 1<<28;
239 #[cfg(feature = "imperator")] const Treasure = 1<<29;
240 #[cfg(feature = "imperator")] const Unit = 1<<30;
241
242 #[cfg(feature = "eu5")] const Location = 1<<16;
243 #[cfg(feature = "eu5")] const Unit = 1<<17;
244 #[cfg(feature = "eu5")] const SubUnit = 1<<18;
245 #[cfg(feature = "eu5")] const Dynasty = 1<<19;
246 #[cfg(feature = "eu5")] const Combat = 1<<20;
247 #[cfg(feature = "eu5")] const CombatSide = 1<<21;
248 #[cfg(feature = "eu5")] const Siege = 1<<22;
249 #[cfg(feature = "eu5")] const ColonialCharter = 1<<23;
250 #[cfg(feature = "eu5")] const Market = 1<<24;
251 #[cfg(feature = "eu5")] const ProvinceDefinition = 1<<25;
252 #[cfg(feature = "eu5")] const Area = 1<<26;
253 #[cfg(feature = "eu5")] const Region = 1<<27;
254 #[cfg(feature = "eu5")] const SubContinent = 1<<28;
255 #[cfg(feature = "eu5")] const Continent = 1<<29;
256 #[cfg(feature = "eu5")] const Group = 1<<30;
257 #[cfg(feature = "eu5")] const Language = 1<<31;
258 #[cfg(feature = "eu5")] const Rebels = 1<<32;
259 #[cfg(feature = "eu5")] const Trade = 1<<33;
260 #[cfg(feature = "eu5")] const ReligiousSchool = 1<<34;
261 #[cfg(feature = "eu5")] const Goods = 1<<35;
262 #[cfg(feature = "eu5")] const Demand = 1<<36;
263 #[cfg(feature = "eu5")] const Privateer = 1<<37;
264 #[cfg(feature = "eu5")] const Exploration = 1<<38;
265 #[cfg(feature = "eu5")] const Mercenary = 1<<39;
266 #[cfg(feature = "eu5")] const WorkOfArt = 1<<40;
267 #[cfg(feature = "eu5")] const Government = 1<<41;
268 #[cfg(feature = "eu5")] const InternationalOrganization = 1<<42;
269 #[cfg(feature = "eu5")] const HolySite = 1<<43;
270 #[cfg(feature = "eu5")] const Institution = 1<<44;
271 #[cfg(feature = "eu5")] const Loan = 1<<45;
272 #[cfg(feature = "eu5")] const Building = 1<<46;
273 #[cfg(feature = "eu5")] const Law = 1<<47;
274 #[cfg(feature = "eu5")] const Policy = 1<<48;
275 #[cfg(feature = "eu5")] const Price = 1<<49;
276 #[cfg(feature = "eu5")] const Situation = 1<<50;
277 #[cfg(feature = "eu5")] const BuildingType = 1<<51;
278 #[cfg(feature = "eu5")] const Disaster = 1<<52;
279 #[cfg(feature = "eu5")] const ReligiousAspect = 1<<53;
280 #[cfg(feature = "eu5")] const EstatePrivilege = 1<<54;
281 #[cfg(feature = "eu5")] const CabinetAction = 1<<55;
282 #[cfg(feature = "eu5")] const GovernmentReform = 1<<56;
283 #[cfg(feature = "eu5")] const Cabinet = 1<<57;
284 #[cfg(feature = "eu5")] const ProductionMethod = 1<<58;
285 #[cfg(feature = "eu5")] const GraphicalCulture = 1<<59;
286 #[cfg(feature = "eu5")] const DiseaseOutbreak = 1<<60;
287 #[cfg(feature = "eu5")] const Disease = 1<<61;
288 #[cfg(feature = "eu5")] const ParliamentIssue = 1<<62;
289 #[cfg(feature = "eu5")] const ParliamentType = 1<<63;
290 #[cfg(feature = "eu5")] const Resolution = 1<<64;
291 #[cfg(feature = "eu5")] const God = 1<<65;
292 #[cfg(feature = "eu5")] const Avatar = 1<<66;
293 #[cfg(feature = "eu5")] const ReligiousFaction = 1<<67;
294 #[cfg(feature = "eu5")] const SubjectType = 1<<68;
295 #[cfg(feature = "eu5")] const Cardinal = 1<<69;
296 #[cfg(feature = "eu5")] const ActiveResolution = 1<<70;
297 #[cfg(feature = "eu5")] const Estate = 1<<71;
298 #[cfg(feature = "eu5")] const AudioCulture = 1<<72;
299 #[cfg(feature = "eu5")] const AdvanceType = 1<<73;
300 #[cfg(feature = "eu5")] const CharacterInteraction = 1<<74;
301 #[cfg(feature = "eu5")] const CountryInteraction = 1<<75;
302 #[cfg(feature = "eu5")] const GenericAction = 1<<76;
303 #[cfg(feature = "eu5")] const UnitType = 1<<77;
304 #[cfg(feature = "eu5")] const LevySetup = 1<<78;
305 #[cfg(feature = "eu5")] const ParliamentAgenda = 1<<79;
306 #[cfg(feature = "eu5")] const CasusBelli = 1<<80;
307 #[cfg(feature = "eu5")] const RelationType = 1<<81;
308 #[cfg(feature = "eu5")] const DisasterType = 1<<82;
309 #[cfg(feature = "eu5")] const SubUnitCategory = 1<<83;
310 #[cfg(feature = "eu5")] const PeaceTreaty = 1<<84;
311 #[cfg(feature = "eu5")] const ArtistType = 1<<85;
312 #[cfg(feature = "eu5")] const WorkOfArtType = 1<<86;
313 #[cfg(feature = "eu5")] const ChildEducation = 1<<87;
314 #[cfg(feature = "eu5")] const Mission = 1<<88;
315 #[cfg(feature = "eu5")] const MissionTask = 1<<89;
316 #[cfg(feature = "eu5")] const RecruitmentMethod = 1<<90;
317 #[cfg(feature = "eu5")] const RegencyType = 1<<91;
318 #[cfg(feature = "eu5")] const UnitAbility = 1<<92;
319 #[cfg(feature = "eu5")] const SocietalValueType = 1<<93;
320 #[cfg(feature = "eu5")] const RoadType = 1<<94;
321 #[cfg(feature = "eu5")] const LanguageFamily = 1<<95;
322 #[cfg(feature = "eu5")] const CultureGroup = 1<<96;
323 #[cfg(feature = "eu5")] const HeirSelection = 1<<97;
324 #[cfg(feature = "eu5")] const EstateType = 1<<98;
325 #[cfg(feature = "eu5")] const Dialect = 1<<99;
326 #[cfg(feature = "eu5")] const Ethnicity = 1<<100;
327 #[cfg(feature = "eu5")] const InternationalOrganizationType = 1<<101;
328 #[cfg(feature = "eu5")] const Payment = 1<<102;
329 #[cfg(feature = "eu5")] const SpecialStatus = 1<<103;
330 #[cfg(feature = "eu5")] const LandOwnershipRule = 1<<104;
331 #[cfg(feature = "eu5")] const WeatherSystem = 1<<105;
332 #[cfg(feature = "eu5")] const FormableCountry = 1<<106;
333 #[cfg(feature = "eu5")] const Hegemony = 1<<107;
334 #[cfg(feature = "eu5")] const HolySiteDefinition = 1<<108;
335 #[cfg(feature = "eu5")] const HolySiteType = 1<<109;
336 #[cfg(feature = "eu5")] const CountryRank = 1<<110;
337 #[cfg(feature = "eu5")] const LocationRank = 1<<111;
338 #[cfg(feature = "eu5")] const ReligiousFocus = 1<<112;
339 #[cfg(feature = "eu5")] const ReligiousFigure = 1<<113;
340 #[cfg(feature = "eu5")] const Climate = 1<<114;
341 #[cfg(feature = "eu5")] const Vegetation = 1<<115;
342 #[cfg(feature = "eu5")] const Topography = 1<<116;
343 #[cfg(feature = "eu5")] const Age = 1<<117;
344 #[cfg(feature = "eu5")] const EmploymentSystem = 1<<118;
345 #[cfg(feature = "eu5")] const MilitaryStance = 1<<119;
346 #[cfg(feature = "eu5")] const UnitTemplate = 1<<120;
347 #[cfg(feature = "eu5")] const UnitFormationPreference = 1<<121;
348 #[cfg(feature = "eu5")] const ScriptableHintDefinition = 1<<122;
349 #[cfg(feature = "eu5")] const ScriptedGeography = 1<<123;
350 #[cfg(feature = "eu5")] const ReligionGroup = 1<<124;
351
352 #[cfg(feature = "hoi4")] const Ace = 1<<16;
353 #[cfg(feature = "hoi4")] const Combatant = 1<<17;
354 #[cfg(feature = "hoi4")] const Division = 1<<18;
355 #[cfg(feature = "hoi4")] const IndustrialOrg = 1<<19;
356 #[cfg(feature = "hoi4")] const Operation = 1<<20;
357 #[cfg(feature = "hoi4")] const PurchaseContract = 1<<21;
358 #[cfg(feature = "hoi4")] const RaidInstance = 1<<22;
359 #[cfg(feature = "hoi4")] const SpecialProject = 1<<23;
360 #[cfg(feature = "hoi4")] const CombinedCountryAndState = 1<<24;
362 #[cfg(feature = "hoi4")] const CombinedCountryAndCharacter = 1<<25;
363 }
364}
365
366impl Scopes {
369 pub const fn non_primitive() -> Scopes {
370 Scopes::all()
371 .difference(Scopes::None.union(Scopes::Value).union(Scopes::Bool).union(Scopes::Flag))
372 }
373
374 pub const fn primitive() -> Scopes {
375 Scopes::Value.union(Scopes::Bool).union(Scopes::Flag)
376 }
377
378 pub const fn all_but_none() -> Scopes {
379 Scopes::all().difference(Scopes::None)
380 }
381
382 pub fn from_snake_case(s: &str) -> Option<Scopes> {
384 #[cfg(feature = "ck3")]
385 if Game::is_ck3() {
386 match s {
388 "ghw" => return Some(Scopes::GreatHolyWar),
389 "story" => return Some(Scopes::StoryCycle),
390 "great_holy_war" | "story_cycle" => return None,
391 _ => (),
392 }
393 }
394
395 Scopes::from_name(&snake_case_to_camel_case(s))
396 }
397
398 pub fn from_snake_case_multi(s: &str) -> Option<Scopes> {
401 let mut scopes = Scopes::empty();
402 for part in s.split('|') {
403 if let Some(scope) = Scopes::from_snake_case(part) {
404 scopes |= scope;
405 } else {
406 return None;
407 }
408 }
409 if scopes == Scopes::empty() {
412 return None;
413 }
414 Some(scopes)
415 }
416}
417
418impl Display for Scopes {
419 fn fmt(&self, f: &mut Formatter) -> Result<(), std::fmt::Error> {
420 if *self == Scopes::all() {
421 write!(f, "any scope")
422 } else if *self == Scopes::primitive() {
423 write!(f, "any primitive scope")
424 } else if *self == Scopes::non_primitive() {
425 write!(f, "non-primitive scope")
426 } else if *self == Scopes::all_but_none() {
427 write!(f, "any except none scope")
428 } else {
429 let mut vec = Vec::new();
430 for (name, _) in self.iter_names() {
431 vec.push(camel_case_to_separated_words(name));
432 }
433 let vec: Vec<&str> = vec.iter().map(String::as_ref).collect();
434 display_choices(f, &vec, "or")
435 }
436 }
437}
438
439#[derive(Copy, Clone, Debug, Eq, PartialEq)]
441pub enum ArgumentValue {
442 #[cfg(any(feature = "ck3", feature = "vic3", feature = "eu5"))]
444 Scope(Scopes),
445 Item(Item),
447 #[cfg(any(feature = "ck3", feature = "vic3", feature = "eu5"))]
449 ScopeOrItem(Scopes, Item),
450 #[cfg(feature = "ck3")]
452 TraitTrack,
453 #[cfg(any(feature = "vic3", feature = "imperator", feature = "eu5"))]
455 Modif,
456 #[cfg(any(feature = "vic3", feature = "ck3", feature = "eu5"))]
458 Identifier(&'static str),
459 #[cfg(feature = "eu5")]
461 Multiple(&'static [ArgumentValue]),
462 UncheckedValue,
464 #[cfg(feature = "ck3")]
466 Removed(&'static str, &'static str),
467}
468
469#[allow(unused_variables)] pub fn scope_to_scope(name: &Token, inscopes: Scopes) -> Option<(Scopes, Scopes)> {
480 let scope_to_scope = match Game::game() {
481 #[cfg(feature = "ck3")]
482 Game::Ck3 => crate::ck3::tables::targets::scope_to_scope,
483 #[cfg(feature = "vic3")]
484 Game::Vic3 => crate::vic3::tables::targets::scope_to_scope,
485 #[cfg(feature = "imperator")]
486 Game::Imperator => crate::imperator::tables::targets::scope_to_scope,
487 #[cfg(feature = "eu5")]
488 Game::Eu5 => crate::eu5::tables::targets::scope_to_scope,
489 #[cfg(feature = "hoi4")]
490 Game::Hoi4 => crate::hoi4::tables::targets::scope_to_scope,
491 };
492 let scope_to_scope_removed = match Game::game() {
493 #[cfg(feature = "ck3")]
494 Game::Ck3 => crate::ck3::tables::targets::scope_to_scope_removed,
495 #[cfg(feature = "vic3")]
496 Game::Vic3 => crate::vic3::tables::targets::scope_to_scope_removed,
497 #[cfg(feature = "imperator")]
498 Game::Imperator => crate::imperator::tables::targets::scope_to_scope_removed,
499 #[cfg(feature = "eu5")]
500 Game::Eu5 => crate::eu5::tables::targets::scope_to_scope_removed,
501 #[cfg(feature = "hoi4")]
502 Game::Hoi4 => crate::hoi4::tables::targets::scope_to_scope_removed,
503 };
504
505 let name_lc = name.as_str().to_ascii_lowercase();
506 #[allow(unused_assignments)] if let scopes @ Some((from, _)) = scope_to_scope(&name_lc) {
508 #[cfg(feature = "vic3")]
509 if Game::is_vic3() && name_lc == "type" {
510 let mut outscopes = Scopes::empty();
513 if inscopes.contains(Scopes::Building) {
514 outscopes |= Scopes::BuildingType;
515 }
516 if inscopes.contains(Scopes::Company) {
517 outscopes |= Scopes::CompanyType;
518 }
519 if inscopes.contains(Scopes::DiplomaticPlay) {
520 outscopes |= Scopes::DiplomaticPlayType;
521 }
522 if inscopes.contains(Scopes::DiplomaticCatalyst) {
523 outscopes |= Scopes::DiplomaticCatalystType;
524 }
525 if inscopes.contains(Scopes::PoliticalLobby) {
526 outscopes |= Scopes::PoliticalLobbyType;
527 }
528 if inscopes.contains(Scopes::Institution) {
529 outscopes |= Scopes::InstitutionType;
530 }
531 if inscopes.contains(Scopes::InterestGroup) {
532 outscopes |= Scopes::InterestGroupType;
533 }
534 if inscopes.contains(Scopes::Law) {
535 outscopes |= Scopes::LawType;
536 }
537 if inscopes.contains(Scopes::PoliticalMovement) {
538 outscopes |= Scopes::PoliticalMovementType;
539 }
540 if inscopes.contains(Scopes::HarvestCondition) {
541 outscopes |= Scopes::HarvestConditionType;
542 }
543 if !outscopes.is_empty() {
544 return Some((from, outscopes));
545 }
546 }
547 scopes
548 } else if let Some((version, explanation)) = scope_to_scope_removed(&name_lc) {
549 let msg = format!("`{name}` was removed in {version}");
550 err(ErrorKey::Removed).strong().msg(msg).info(explanation).loc(name).push();
551 Some((Scopes::all(), Scopes::all_but_none()))
552 } else {
553 None
554 }
555}
556
557pub fn scope_prefix(prefix: &Token) -> Option<(Scopes, Scopes, ArgumentValue)> {
567 let scope_prefix = match Game::game() {
568 #[cfg(feature = "ck3")]
569 Game::Ck3 => crate::ck3::tables::targets::scope_prefix,
570 #[cfg(feature = "vic3")]
571 Game::Vic3 => crate::vic3::tables::targets::scope_prefix,
572 #[cfg(feature = "imperator")]
573 Game::Imperator => crate::imperator::tables::targets::scope_prefix,
574 #[cfg(feature = "eu5")]
575 Game::Eu5 => crate::eu5::tables::targets::scope_prefix,
576 #[cfg(feature = "hoi4")]
577 Game::Hoi4 => crate::hoi4::tables::targets::scope_prefix,
578 };
579 let prefix_lc = prefix.as_str().to_ascii_lowercase();
580 scope_prefix(&prefix_lc)
581}
582
583pub fn needs_prefix(arg: &str, data: &Everything, scopes: Scopes) -> Option<&'static str> {
591 match Game::game() {
592 #[cfg(feature = "ck3")]
593 Game::Ck3 => crate::ck3::scopes::needs_prefix(arg, data, scopes),
594 #[cfg(feature = "vic3")]
595 Game::Vic3 => crate::vic3::scopes::needs_prefix(arg, data, scopes),
596 #[cfg(feature = "imperator")]
597 Game::Imperator => crate::imperator::scopes::needs_prefix(arg, data, scopes),
598 #[cfg(feature = "eu5")]
599 Game::Eu5 => crate::eu5::scopes::needs_prefix(arg, data, scopes),
600 #[cfg(feature = "hoi4")]
601 Game::Hoi4 => crate::hoi4::scopes::needs_prefix(arg, data, scopes),
602 }
603}
604
605pub fn scope_iterator(
615 name: &Token,
616 data: &Everything,
617 sc: &mut ScopeContext,
618) -> Option<(Scopes, Scopes)> {
619 let scope_iterator = match Game::game() {
620 #[cfg(feature = "ck3")]
621 Game::Ck3 => crate::ck3::tables::iterators::iterator,
622 #[cfg(feature = "vic3")]
623 Game::Vic3 => crate::vic3::tables::iterators::iterator,
624 #[cfg(feature = "imperator")]
625 Game::Imperator => crate::imperator::tables::iterators::iterator,
626 #[cfg(feature = "eu5")]
627 Game::Eu5 => crate::eu5::tables::iterators::iterator,
628 #[cfg(feature = "hoi4")]
629 Game::Hoi4 => crate::hoi4::tables::iterators::iterator,
630 };
631 let scope_iterator_removed = match Game::game() {
632 #[cfg(feature = "ck3")]
633 Game::Ck3 => crate::ck3::tables::iterators::iterator_removed,
634 #[cfg(feature = "vic3")]
635 Game::Vic3 => crate::vic3::tables::iterators::iterator_removed,
636 #[cfg(feature = "imperator")]
637 Game::Imperator => crate::imperator::tables::iterators::iterator_removed,
638 #[cfg(feature = "eu5")]
639 Game::Eu5 => crate::eu5::tables::iterators::iterator_removed,
640 #[cfg(feature = "hoi4")]
641 Game::Hoi4 => crate::hoi4::tables::iterators::iterator_removed,
642 };
643
644 let name_lc = Lowercase::new(name.as_str());
645 if let scopes @ Some(_) = scope_iterator(&name_lc, name, data) {
646 return scopes;
647 }
648 if let Some((version, explanation)) = scope_iterator_removed(name_lc.as_str()) {
649 let msg = format!("`{name}` iterators were removed in {version}");
650 err(ErrorKey::Removed).strong().msg(msg).info(explanation).loc(name).push();
651 return Some((Scopes::all(), Scopes::all()));
652 }
653 #[cfg(feature = "jomini")]
654 if Game::is_jomini() && data.scripted_lists.exists(name.as_str()) {
655 data.scripted_lists.validate_call(name, data, sc);
656 return data
657 .scripted_lists
658 .base(name)
659 .and_then(|base| scope_iterator(&Lowercase::new(base.as_str()), base, data));
660 }
661 #[cfg(feature = "hoi4")]
662 let _ = &data; #[cfg(feature = "hoi4")]
664 let _ = ≻ None
666}