1#![allow(non_upper_case_globals)]
2
3use std::sync::LazyLock;
4
5use crate::everything::Everything;
6use crate::helpers::TigerHashMap;
7use crate::imperator::modif::ModifKinds;
8use crate::item::Item;
9use crate::lowercase::Lowercase;
10use crate::report::{ErrorKey, Severity, report};
11use crate::token::Token;
12
13pub fn lookup_modif(name: &Token, data: &Everything, warn: Option<Severity>) -> Option<ModifKinds> {
16 let name_lc = Lowercase::new(name.as_str());
17
18 if let result @ Some(_) = MODIF_MAP.get(&name_lc).copied() {
19 return result;
20 }
21
22 if let Some(part) = name_lc.strip_prefix_unchecked("local_") {
28 for &sfx in &["_output", "_desired_pop_ratio", "_happyness"] {
29 if let Some(part) = part.strip_suffix_unchecked(sfx) {
30 maybe_warn(Item::PopType, &part, name, data, warn);
31 return Some(ModifKinds::Province | ModifKinds::State);
32 }
33 }
34 }
35
36 if let Some(part) = name_lc.strip_prefix_unchecked("global_") {
41 for &sfx in &["_output", "_city_desired_pop_ratio", "_desired_pop_ratio", "_happyness"] {
42 if let Some(part) = part.strip_suffix_unchecked(sfx) {
43 maybe_warn(Item::PopType, &part, name, data, warn);
44 return Some(ModifKinds::Country);
45 }
46 }
47 }
48
49 if let Some(part) = name_lc.strip_prefix_unchecked("culture_") {
52 for &sfx in &["_output", "_happiness"] {
53 if let Some(part) = part.strip_suffix_unchecked(sfx) {
54 maybe_warn(Item::PopType, &part, name, data, warn);
55 return Some(ModifKinds::Country);
56 }
57 }
58 }
59
60 if let Some(part) = name_lc.strip_suffix_unchecked("_cost_modifier") {
62 maybe_warn(Item::Price, &part, name, data, warn);
63 return Some(ModifKinds::Country);
64 }
65
66 if let Some(part) = name_lc.strip_suffix_unchecked("_influence") {
68 maybe_warn(Item::PartyType, &part, name, data, warn);
69 return Some(ModifKinds::Country);
70 }
71
72 if let Some(part) = name_lc.strip_prefix_unchecked("monthly_") {
74 if let Some(part) = part.strip_suffix_unchecked("_conviction") {
75 maybe_warn(Item::PartyType, &part, name, data, warn);
76 return Some(ModifKinds::Character);
77 }
78 }
79
80 for &sfx in &[
87 "_discipline",
88 "_morale",
89 "_offensive",
90 "_defensive",
91 "_maintenance_cost",
92 "_movement_speed",
93 ] {
94 if let Some(part) = name_lc.strip_suffix_unchecked(sfx) {
95 maybe_warn(Item::Unit, &part, name, data, warn);
96 return Some(ModifKinds::Country);
97 }
98 }
99
100 if let Some(part) = name_lc.strip_suffix_unchecked("_combat_bonus") {
103 for (i, _) in part.rmatch_indices_unchecked('_') {
106 if data.item_exists_lc(Item::Terrain, &part.slice(i + 1..)) {
107 maybe_warn(Item::Unit, &part.slice(..i), name, data, warn);
109 return Some(ModifKinds::Country);
110 }
111 }
112 maybe_warn(Item::Terrain, &part, name, data, warn);
114 return Some(ModifKinds::Country);
115 }
116
117 if let Some(part) = name_lc.strip_suffix_unchecked("_cost") {
120 if let Some(sev) = warn {
121 if !data.item_exists(Item::Unit, part.as_str())
122 && !data.item_exists(Item::Building, part.as_str())
123 {
124 let msg = format!("{part} not found as unit or building");
125 let info = format!("so the modifier {name} does not exist");
126 report(ErrorKey::MissingItem, sev).msg(msg).info(info).loc(name).push();
127 }
128 }
129 return Some(ModifKinds::Country);
130 }
131
132 if let Some(part) = name_lc.strip_suffix_unchecked("_investment") {
134 maybe_warn(Item::TechnologyTable, &part, name, data, warn);
135 return Some(ModifKinds::Country);
136 }
137
138 None
139}
140
141fn maybe_warn(itype: Item, s: &Lowercase, name: &Token, data: &Everything, warn: Option<Severity>) {
142 if let Some(sev) = warn {
143 if !data.item_exists_lc(itype, s) {
144 let msg = format!("could not find {itype} {s}");
145 let info = format!("so the modifier {name} does not exist");
146 report(ErrorKey::MissingItem, sev).strong().msg(msg).info(info).loc(name).push();
147 }
148 }
149}
150
151static MODIF_MAP: LazyLock<TigerHashMap<Lowercase<'static>, ModifKinds>> = LazyLock::new(|| {
152 let mut hash = TigerHashMap::default();
153 for (s, kind) in MODIF_TABLE.iter().copied() {
154 hash.insert(Lowercase::new_unchecked(s), kind);
155 }
156 hash
157});
158
159const MODIF_TABLE: &[(&str, ModifKinds)] = &[
163 ("happiness_for_wrong_religion_modifier", ModifKinds::Country),
164 ("local_happiness_for_wrong_religion_modifier", ModifKinds::Province),
165 ("cultural_assimilation_speed_modifier", ModifKinds::Country),
166 ("build_cost", ModifKinds::Country),
167 ("build_time", ModifKinds::Country),
168 ("desert_hills_combat_bonus", ModifKinds::Country),
169 ("minimum_unrest", ModifKinds::Province.union(ModifKinds::State)),
170 ("local_unrest", ModifKinds::Province.union(ModifKinds::State)),
171 ("global_unrest", ModifKinds::Country),
172 ("tax_income", ModifKinds::Province.union(ModifKinds::State)),
173 ("global_tax_income", ModifKinds::Country),
174 ("local_tax_modifier", ModifKinds::Province.union(ModifKinds::State)),
175 ("global_tax_modifier", ModifKinds::Country),
176 ("local_population_growth", ModifKinds::Province.union(ModifKinds::State)),
177 ("global_population_growth", ModifKinds::Country),
178 ("local_population_capacity", ModifKinds::Province.union(ModifKinds::State)),
179 ("local_population_capacity_modifier", ModifKinds::Province.union(ModifKinds::State)),
180 ("global_population_capacity_modifier", ModifKinds::Country),
181 ("total_population_capacity_modifier", ModifKinds::Province.union(ModifKinds::Country)),
182 ("local_building_slot", ModifKinds::Province.union(ModifKinds::State)),
183 ("global_building_slot", ModifKinds::Country),
184 ("global_monthly_state_loyalty", ModifKinds::Country),
185 ("local_monthly_state_loyalty", ModifKinds::Province.union(ModifKinds::State)),
186 ("city_monthly_state_loyalty", ModifKinds::Province.union(ModifKinds::State)),
187 ("happiness_for_wrong_culture_modifier", ModifKinds::Province.union(ModifKinds::Country)),
188 ("happiness_for_wrong_culture_group_modifier", ModifKinds::Province.union(ModifKinds::Country)),
189 ("happiness_for_same_culture_modifier", ModifKinds::Country),
190 ("local_happiness_for_same_culture_modifier", ModifKinds::Province.union(ModifKinds::State)),
191 ("happiness_for_same_religion_modifier", ModifKinds::Country),
192 ("local_happiness_for_same_religion_modifier", ModifKinds::Province.union(ModifKinds::State)),
193 ("global_population_happiness", ModifKinds::Country),
194 ("local_population_happiness", ModifKinds::Province.union(ModifKinds::State)),
195 ("land_morale", ModifKinds::Country),
196 ("naval_morale", ModifKinds::Country),
197 ("land_morale_modifier", ModifKinds::Country),
198 ("naval_morale_modifier", ModifKinds::Country),
199 ("non_retinue_morale_modifier", ModifKinds::Country),
200 ("local_manpower", ModifKinds::Province.union(ModifKinds::State)),
201 ("global_manpower", ModifKinds::Country),
202 ("local_manpower_modifier", ModifKinds::Province.union(ModifKinds::State)),
203 ("global_manpower_modifier", ModifKinds::Country),
204 ("manpower_recovery_speed", ModifKinds::Country),
205 ("attrition", ModifKinds::Province.union(ModifKinds::State)),
206 ("land_unit_attrition", ModifKinds::Country.union(ModifKinds::Unit)),
207 ("naval_unit_attrition", ModifKinds::Country.union(ModifKinds::Unit)),
208 ("army_weight_modifier", ModifKinds::Country.union(ModifKinds::Unit)),
209 ("navy_weight_modifier", ModifKinds::Country.union(ModifKinds::Unit)),
210 ("max_attrition", ModifKinds::Province.union(ModifKinds::State)),
211 ("supply_limit", ModifKinds::Province.union(ModifKinds::State)),
212 ("supply_limit_modifier", ModifKinds::Province.union(ModifKinds::State)),
213 ("global_supply_limit_modifier", ModifKinds::Country),
214 ("war_exhaustion", ModifKinds::Country),
215 ("max_war_exhaustion", ModifKinds::Country),
216 ("fort_level", ModifKinds::Province.union(ModifKinds::State)),
217 ("blockade_efficiency", ModifKinds::Country),
218 ("monthly_centralization", ModifKinds::Country),
219 ("monthly_legitimacy", ModifKinds::Country),
220 ("agressive_expansion_impact", ModifKinds::Country),
221 ("agressive_expansion_monthly_change", ModifKinds::Country),
222 ("agressive_expansion_monthly_decay", ModifKinds::Country),
223 ("local_ship_recruit_speed", ModifKinds::Province.union(ModifKinds::State)),
224 ("local_cohort_recruit_speed", ModifKinds::Province.union(ModifKinds::State)),
225 ("global_ship_recruit_speed", ModifKinds::Country),
226 ("global_cohort_recruit_speed", ModifKinds::Country),
227 ("garrison_size", ModifKinds::Province.union(ModifKinds::Country)),
228 ("garrison_growth", ModifKinds::Province.union(ModifKinds::Country)),
229 ("technology_investment", ModifKinds::Country),
230 ("movement_cost", ModifKinds::Province.union(ModifKinds::State)),
231 ("army_movement_speed", ModifKinds::Unit.union(ModifKinds::Country)),
232 ("navy_movement_speed", ModifKinds::Unit.union(ModifKinds::Country)),
233 ("movement_speed_if_no_road", ModifKinds::Unit.union(ModifKinds::Country)),
234 ("local_state_trade_routes", ModifKinds::Province.union(ModifKinds::State)),
235 ("global_capital_trade_routes", ModifKinds::Country),
236 ("global_state_trade_routes", ModifKinds::Country),
237 ("research_points", ModifKinds::Country.union(ModifKinds::Province)),
238 ("research_points_modifier", ModifKinds::Country),
239 ("local_research_points_modifier", ModifKinds::Province.union(ModifKinds::State)),
240 ("omen_power", ModifKinds::Country),
241 ("omen_duration", ModifKinds::Country),
242 ("discipline", ModifKinds::Country.union(ModifKinds::Unit)),
243 ("local_defensive", ModifKinds::Province.union(ModifKinds::State)),
244 ("global_defensive", ModifKinds::Country),
245 ("commerce_value", ModifKinds::Province.union(ModifKinds::State)),
246 ("local_commerce_value_modifier", ModifKinds::Province.union(ModifKinds::State)),
247 ("global_commerce_modifier", ModifKinds::Country),
248 ("global_export_commerce_modifier", ModifKinds::Country),
249 ("global_import_commerce_modifier", ModifKinds::Country),
250 ("state_commerce_modifier", ModifKinds::Province.union(ModifKinds::State)),
251 ("tribute_income_modifier", ModifKinds::Country),
252 ("ruler_popularity_gain", ModifKinds::Country),
253 ("max_loyalty", ModifKinds::Country),
254 ("integrate_speed", ModifKinds::Country),
255 ("fabricate_claim_speed", ModifKinds::Country),
256 (
257 "monthly_wage_for_character",
258 ModifKinds::Character.union(ModifKinds::Country).union(ModifKinds::State),
259 ),
260 ("monthly_wage_modifier", ModifKinds::Country),
261 ("monthly_wage_on_character_modifier", ModifKinds::Character),
262 ("monthly_governor_wage", ModifKinds::Country.union(ModifKinds::Character)),
263 (
264 "monthly_local_governor_wage",
265 ModifKinds::Province.union(ModifKinds::State).union(ModifKinds::Country),
266 ),
267 ("monthly_character_popularity", ModifKinds::Character.union(ModifKinds::Country)),
268 ("monthly_character_popularity_decay", ModifKinds::Character.union(ModifKinds::Country)),
269 ("monthly_character_prominence", ModifKinds::Character.union(ModifKinds::Country)),
270 ("monthly_character_fam_prestige", ModifKinds::Character.union(ModifKinds::Country)),
271 ("cohort_reinforcement_speed", ModifKinds::Country.union(ModifKinds::Unit)),
272 ("land_morale_recovery", ModifKinds::Country.union(ModifKinds::Unit)),
273 ("naval_morale_recovery", ModifKinds::Country.union(ModifKinds::Unit)),
274 ("siege_ability", ModifKinds::Country.union(ModifKinds::Unit)),
275 ("assault_ability", ModifKinds::Country.union(ModifKinds::Unit)),
276 ("siege_engineers", ModifKinds::Country.union(ModifKinds::Legion)),
277 ("diplomatic_reputation", ModifKinds::Country),
278 ("diplomatic_relations", ModifKinds::Country),
279 ("max_rivals", ModifKinds::Character.union(ModifKinds::Country)),
280 ("max_friends", ModifKinds::Character.union(ModifKinds::Country)),
281 ("current_corruption", ModifKinds::Character.union(ModifKinds::Country)),
282 ("monthly_corruption", ModifKinds::Character.union(ModifKinds::Country)),
283 ("subject_opinions", ModifKinds::Country),
284 ("subject_loyalty", ModifKinds::Country),
285 ("loyalty_to_overlord", ModifKinds::Country),
286 ("fort_maintenance_cost", ModifKinds::Country.union(ModifKinds::State)),
287 ("army_maintenance_cost", ModifKinds::Country.union(ModifKinds::Unit)),
288 ("navy_maintenance_cost", ModifKinds::Country.union(ModifKinds::Unit)),
289 ("mercenary_land_maintenance_cost", ModifKinds::Country),
290 ("mercenary_naval_maintenance_cost", ModifKinds::Country),
291 ("country_civilization_value", ModifKinds::Country),
292 ("local_country_civilization_value", ModifKinds::Province.union(ModifKinds::State)),
293 ("local_monthly_civilization", ModifKinds::Province.union(ModifKinds::State)),
294 ("global_monthly_civilization", ModifKinds::Country),
295 ("global_start_experience", ModifKinds::Country),
296 ("local_start_experience", ModifKinds::Province.union(ModifKinds::State)),
297 ("global_cohort_start_experience", ModifKinds::Country),
298 ("local_cohort_start_experience", ModifKinds::Province.union(ModifKinds::State)),
299 ("global_ship_start_experience", ModifKinds::Country),
300 ("local_ship_start_experience", ModifKinds::Province.union(ModifKinds::State)),
301 ("experience_decay", ModifKinds::Country.union(ModifKinds::Unit)),
302 ("monthly_experience_gain", ModifKinds::Country.union(ModifKinds::Unit)),
303 ("martial", ModifKinds::Character),
304 ("finesse", ModifKinds::Character),
305 ("charisma", ModifKinds::Character),
306 ("zeal", ModifKinds::Character),
307 ("fertility", ModifKinds::Character.union(ModifKinds::Country)),
308 ("health", ModifKinds::Character.union(ModifKinds::Country)),
309 ("barbarian_growth", ModifKinds::Province),
310 ("barbarian_spawn_chance", ModifKinds::Province.union(ModifKinds::State)),
311 (
312 "loyalty_gain_chance",
313 ModifKinds::Country.union(ModifKinds::Character).union(ModifKinds::Unit),
314 ),
315 (
316 "loyalty_gain_chance_modifier",
317 ModifKinds::Country.union(ModifKinds::Character).union(ModifKinds::Unit),
318 ),
319 ("prominence", ModifKinds::Character.union(ModifKinds::Country)),
320 ("senate_influence", ModifKinds::Character),
321 ("monthly_party_approval", ModifKinds::Country),
322 ("monthly_tyranny", ModifKinds::Country),
323 ("monthly_political_influence", ModifKinds::Country),
324 ("monthly_political_influence_modifier", ModifKinds::Country),
325 ("retreat_delay", ModifKinds::Country),
326 ("improve_relation_impact", ModifKinds::Country),
327 ("hostile_attrition", ModifKinds::Country),
328 ("local_hostile_attrition", ModifKinds::Province.union(ModifKinds::State)),
329 ("election_term_duration", ModifKinds::Country),
330 ("ship_repair_at_sea", ModifKinds::Country),
331 ("war_score_cost", ModifKinds::Country),
332 ("base_resources", ModifKinds::Province.union(ModifKinds::State)),
333 ("local_goods_from_slaves", ModifKinds::Province.union(ModifKinds::State)),
334 ("global_goods_from_slaves", ModifKinds::Country),
335 ("disallow_job", ModifKinds::Character),
336 ("disallow_office", ModifKinds::Character),
337 ("disallow_command", ModifKinds::Character),
338 ("show_3d_fort", ModifKinds::Province),
339 ("control_range_modifier", ModifKinds::Country),
340 ("diplomatic_range_modifier", ModifKinds::Country),
341 ("monthly_character_wealth", ModifKinds::Character),
342 ("primary_heir_attraction", ModifKinds::Character.union(ModifKinds::Country)),
343 ("support_for_character_as_heir", ModifKinds::Character),
344 ("next_ruler_legitimacy", ModifKinds::Country),
345 ("num_of_clan_chiefs", ModifKinds::Country),
346 ("clan_retinue_size", ModifKinds::Country),
347 ("enslavement_efficiency", ModifKinds::Character.union(ModifKinds::Country)),
348 ("local_output_modifier", ModifKinds::Province.union(ModifKinds::State)),
349 ("holdings_possible_for_character", ModifKinds::Character),
350 ("available_holdings", ModifKinds::Character),
351 ("holding_income_modifier", ModifKinds::Character),
352 ("stability_monthly_change", ModifKinds::Country),
353 ("stability_monthly_decay", ModifKinds::Country),
354 ("civil_war_threshold", ModifKinds::Country),
355 ("ship_capture_chance", ModifKinds::Country),
356 ("naval_damage_done", ModifKinds::Country.union(ModifKinds::Unit)),
357 ("naval_damage_taken", ModifKinds::Country.union(ModifKinds::Unit)),
358 ("ship_cost", ModifKinds::Country),
359 ("cohort_cost", ModifKinds::Country),
360 ("pirate_haven", ModifKinds::Province),
361 ("pirate_plunder", ModifKinds::Province),
362 ("anti_piracy_cb", ModifKinds::Country),
363 ("naval_range", ModifKinds::Country),
364 ("monthly_military_experience", ModifKinds::Country),
365 ("monthly_military_experience_modifier", ModifKinds::Country),
366 ("local_pop_promotion_speed", ModifKinds::Province.union(ModifKinds::State)),
367 ("global_pop_promotion_speed", ModifKinds::Country),
368 ("local_pop_promotion_speed_modifier", ModifKinds::Province.union(ModifKinds::State)),
369 ("global_pop_promotion_speed_modifier", ModifKinds::Country),
370 ("local_pop_demotion_speed", ModifKinds::Province.union(ModifKinds::State)),
371 ("global_pop_demotion_speed", ModifKinds::Country),
372 ("local_pop_demotion_speed_modifier", ModifKinds::Province.union(ModifKinds::State)),
373 ("global_pop_demotion_speed_modifier", ModifKinds::Country),
374 ("local_migration_attraction", ModifKinds::Province.union(ModifKinds::State)),
375 ("local_migration_speed", ModifKinds::Province.union(ModifKinds::State)),
376 ("global_migration_speed", ModifKinds::Country),
377 ("local_migration_speed_modifier", ModifKinds::Province.union(ModifKinds::State)),
378 ("global_migration_speed_modifier", ModifKinds::Country),
379 ("local_pop_conversion_speed", ModifKinds::Province.union(ModifKinds::State)),
380 ("global_pop_conversion_speed", ModifKinds::Country),
381 ("local_pop_conversion_speed_modifier", ModifKinds::Province.union(ModifKinds::State)),
382 ("global_pop_conversion_speed_modifier", ModifKinds::Country),
383 ("local_pop_assimilation_speed", ModifKinds::Province.union(ModifKinds::State)),
384 ("global_pop_assimilation_speed", ModifKinds::Country),
385 ("local_pop_assimilation_speed_modifier", ModifKinds::Province.union(ModifKinds::State)),
386 ("global_pop_assimilation_speed_modifier", ModifKinds::Country),
387 ("cultural_integration_speed_modifier", ModifKinds::CountryCulture),
388 ("cultural_assimilation_speed_modifier", ModifKinds::CountryCulture),
389 ("culture_happiness_modifier", ModifKinds::CountryCulture),
390 ("local_monthly_food", ModifKinds::Province.union(ModifKinds::State)),
391 ("global_monthly_food_modifier", ModifKinds::Country),
392 ("global_food_capacity", ModifKinds::Country),
393 ("local_food_capacity", ModifKinds::Province.union(ModifKinds::State)),
394 ("local_monthly_food_modifier", ModifKinds::Province.union(ModifKinds::State)),
395 ("local_hostile_food_multiplier", ModifKinds::Province.union(ModifKinds::State)),
396 ("pop_food_consumption", ModifKinds::Province.union(ModifKinds::State)),
397 ("monthly_character_experience", ModifKinds::Character.union(ModifKinds::Country)),
398 ("monthly_character_experience_decay", ModifKinds::Character.union(ModifKinds::Country)),
399 ("monthly_conviction_for_head_of_family_party", ModifKinds::Character),
400 ("local_base_trade_routes", ModifKinds::Province.union(ModifKinds::State)),
401 ("local_base_trade_routes_modifier", ModifKinds::Province.union(ModifKinds::State)),
402 ("enable_intervene", ModifKinds::Country),
403 ("character_loyalty", ModifKinds::Country.union(ModifKinds::Character)),
404 ("general_loyalty", ModifKinds::Country),
405 ("admiral_loyalty", ModifKinds::Country),
406 ("governor_loyalty", ModifKinds::Country),
407 ("clan_chief_loyalty", ModifKinds::Country),
408 ("levy_size_multiplier", ModifKinds::Country),
409 ("movement_speed_if_no_road", ModifKinds::Country),
410 ("great_work_total_workrate_character_modifier", ModifKinds::Character),
411 ("great_work_slaves_workrate_character_modifier", ModifKinds::Character),
412 ("great_work_tribals_workrate_character_modifier", ModifKinds::Character),
413 ("great_work_freemen_workrate_character_modifier", ModifKinds::Character),
414 ("great_work_fixed_prestige_character_modifier", ModifKinds::Character),
415 ("local_combat_width_modifier", ModifKinds::Province.union(ModifKinds::State)),
416 ("watercrossing_enabled_for_river", ModifKinds::Country),
417 ("watercrossing_enabled_for_strait", ModifKinds::Country),
418 ("watercrossing_enabled_for_shore", ModifKinds::Country),
419 ("succession_value", ModifKinds::Character),
420 ("fort_limit", ModifKinds::Country),
421 ("local_fort_limit", ModifKinds::Province.union(ModifKinds::State)),
422 ("global_settlement_building_slot", ModifKinds::Country),
423 ("max_research_efficiency", ModifKinds::Country),
424 ("max_mercenary_stacks", ModifKinds::Country),
425];