tiger_lib/imperator/
effect_validation.rs

1use crate::block::{BV, Block};
2use crate::context::ScopeContext;
3use crate::effect::validate_effect_internal;
4use crate::everything::Everything;
5use crate::imperator::modif::ModifKinds;
6use crate::item::Item;
7use crate::lowercase::Lowercase;
8use crate::modif::validate_modifs;
9use crate::scopes::Scopes;
10use crate::special_tokens::SpecialTokens;
11use crate::token::Token;
12use crate::tooltipped::Tooltipped;
13use crate::trigger::validate_target;
14use crate::validate::{ListType, validate_optional_duration};
15use crate::validator::{Validator, ValueValidator};
16
17pub fn validate_trade_route(
18    _key: &Token,
19    _block: &Block,
20    _data: &Everything,
21    sc: &mut ScopeContext,
22    mut vd: Validator,
23    _tooltipped: Tooltipped,
24) {
25    vd.field_target("target", sc, Scopes::State);
26    vd.field_item("goods", Item::TradeGood);
27}
28
29pub fn validate_add_deity_to_pantheon(
30    _key: &Token,
31    _block: &Block,
32    _data: &Everything,
33    sc: &mut ScopeContext,
34    mut vd: Validator,
35    _tooltipped: Tooltipped,
36) {
37    vd.field_target("deity", sc, Scopes::Deity);
38}
39
40pub fn validate_remove_subunit_loyalty(
41    _key: &Token,
42    mut vd: ValueValidator,
43    sc: &mut ScopeContext,
44    _tooltipped: Tooltipped,
45) {
46    vd.maybe_is("yes");
47    vd.target_ok_this(sc, Scopes::SubUnit);
48}
49
50pub fn validate_add_modifier(
51    _key: &Token,
52    bv: &BV,
53    data: &Everything,
54    sc: &mut ScopeContext,
55    _tooltipped: Tooltipped,
56) {
57    match bv {
58        BV::Value(value) => {
59            data.verify_exists(Item::Modifier, value);
60        }
61        BV::Block(block) => {
62            let mut vd = Validator::new(block, data);
63            vd.set_case_sensitive(false);
64            vd.req_field("name");
65            vd.field_item("name", Item::Modifier);
66            vd.field_choice("mode", &["add", "add_and_extend", "extend"]);
67            validate_optional_duration(&mut vd, sc);
68        }
69    }
70}
71
72pub fn validate_add_party_conviction_or_approval(
73    _key: &Token,
74    _block: &Block,
75    _data: &Everything,
76    sc: &mut ScopeContext,
77    mut vd: Validator,
78    _tooltipped: Tooltipped,
79) {
80    vd.req_field("value");
81    vd.field_item_or_target("party", sc, Item::PartyType, Scopes::Party);
82    vd.field_item_or_target("party_type", sc, Item::PartyType, Scopes::Party);
83    vd.field_script_value("value", sc);
84}
85
86pub fn validate_death(
87    _key: &Token,
88    _block: &Block,
89    _data: &Everything,
90    sc: &mut ScopeContext,
91    mut vd: Validator,
92    _tooltipped: Tooltipped,
93) {
94    vd.field_item("death_reason", Item::DeathReason);
95    vd.field_target("killer", sc, Scopes::Character);
96    vd.field_bool("silent");
97}
98
99pub fn validate_deify_character(
100    _key: &Token,
101    _block: &Block,
102    _data: &Everything,
103    sc: &mut ScopeContext,
104    mut vd: Validator,
105    _tooltipped: Tooltipped,
106) {
107    vd.req_field("deity");
108    vd.req_field("country");
109    vd.field_target("deity", sc, Scopes::Deity);
110    vd.field_item_or_target("country", sc, Item::Localization, Scopes::Country);
111}
112
113pub fn validate_legion_history(
114    _key: &Token,
115    _block: &Block,
116    _data: &Everything,
117    sc: &mut ScopeContext,
118    mut vd: Validator,
119    _tooltipped: Tooltipped,
120) {
121    vd.req_field("key");
122    vd.req_field("commander");
123    vd.req_field("province");
124    vd.field_item("key", Item::Localization);
125    vd.field_target("commander", sc, Scopes::Character);
126    vd.field_item_or_target("province", sc, Item::Province, Scopes::Province);
127    vd.field_date("date");
128}
129
130pub fn validate_make_pregnant(
131    _key: &Token,
132    _block: &Block,
133    _data: &Everything,
134    sc: &mut ScopeContext,
135    mut vd: Validator,
136    _tooltipped: Tooltipped,
137) {
138    vd.req_field("father");
139    vd.field_target("father", sc, Scopes::Character);
140    vd.field_bool("known_bastard");
141    vd.field_integer("number_of_children");
142}
143
144pub fn validate_change_opinion(
145    _key: &Token,
146    _block: &Block,
147    _data: &Everything,
148    sc: &mut ScopeContext,
149    mut vd: Validator,
150    _tooltipped: Tooltipped,
151) {
152    vd.req_field("modifier");
153    vd.req_field("target");
154    vd.field_item("modifier", Item::Opinion);
155    vd.field_item_or_target("target", sc, Item::Localization, Scopes::Country);
156}
157
158pub fn validate_add_research(
159    _key: &Token,
160    _block: &Block,
161    _data: &Everything,
162    sc: &mut ScopeContext,
163    mut vd: Validator,
164    _tooltipped: Tooltipped,
165) {
166    vd.req_field("technology");
167    vd.req_field("value");
168    vd.field_item("technology", Item::TechnologyTable);
169    vd.field_script_value("value", sc);
170}
171
172pub fn validate_add_to_war(
173    _key: &Token,
174    _block: &Block,
175    _data: &Everything,
176    sc: &mut ScopeContext,
177    mut vd: Validator,
178    _tooltipped: Tooltipped,
179) {
180    vd.req_field("target");
181    vd.req_field("attacker");
182    vd.field_target("target", sc, Scopes::War);
183    vd.field_bool("attacker");
184    vd.field_bool("leader");
185}
186
187pub fn validate_add_truce(
188    _key: &Token,
189    _block: &Block,
190    _data: &Everything,
191    sc: &mut ScopeContext,
192    mut vd: Validator,
193    _tooltipped: Tooltipped,
194) {
195    vd.req_field("target");
196    vd.req_field("duration");
197    vd.field_item_or_target("target", sc, Item::Localization, Scopes::Country);
198    vd.field_integer("duration");
199}
200
201pub fn validate_declare_war(
202    _key: &Token,
203    _block: &Block,
204    _data: &Everything,
205    sc: &mut ScopeContext,
206    mut vd: Validator,
207    _tooltipped: Tooltipped,
208) {
209    vd.req_field("war_goal");
210    vd.req_field("target");
211    vd.field_item("war_goal", Item::Wargoal);
212    vd.field_item_or_target("target", sc, Item::Localization, Scopes::Country);
213    vd.field_item_or_target("province", sc, Item::Province, Scopes::Province);
214}
215
216pub fn validate_imprison(
217    _key: &Token,
218    _block: &Block,
219    _data: &Everything,
220    sc: &mut ScopeContext,
221    mut vd: Validator,
222    _tooltipped: Tooltipped,
223) {
224    vd.req_field("target");
225    vd.field_target("target", sc, Scopes::Character);
226}
227
228pub fn validate_make_subject(
229    _key: &Token,
230    _block: &Block,
231    _data: &Everything,
232    sc: &mut ScopeContext,
233    mut vd: Validator,
234    _tooltipped: Tooltipped,
235) {
236    vd.req_field("target");
237    vd.req_field("type");
238    vd.field_item_or_target("target", sc, Item::Localization, Scopes::Country);
239    vd.field_item("type", Item::SubjectType);
240}
241
242pub fn validate_release_prisoner(
243    _key: &Token,
244    bv: &BV,
245    data: &Everything,
246    sc: &mut ScopeContext,
247    _tooltipped: Tooltipped,
248) {
249    match bv {
250        BV::Value(token) => {
251            validate_target(token, data, sc, Scopes::Character);
252        }
253        BV::Block(block) => {
254            let mut vd = Validator::new(block, data);
255            vd.set_case_sensitive(false);
256            vd.req_field("target");
257            vd.field_target("target", sc, Scopes::Character);
258        }
259    }
260}
261
262pub fn validate_define_pop(
263    _key: &Token,
264    _block: &Block,
265    _data: &Everything,
266    sc: &mut ScopeContext,
267    mut vd: Validator,
268    _tooltipped: Tooltipped,
269) {
270    vd.req_field("type");
271    vd.req_field("religion");
272    vd.req_field("culture");
273    vd.field_item("type", Item::PopType);
274    vd.field_item_or_target("religion", sc, Item::Religion, Scopes::Religion);
275    vd.field_item_or_target("culture", sc, Item::Culture, Scopes::Culture);
276}
277
278pub fn validate_create_treasure(
279    _key: &Token,
280    _block: &Block,
281    _data: &Everything,
282    _sc: &mut ScopeContext,
283    mut vd: Validator,
284    _tooltipped: Tooltipped,
285) {
286    vd.req_field("key");
287    vd.req_field("icon");
288    vd.field_validated_block("modifier", |block, data| {
289        let vd = Validator::new(block, data);
290        validate_modifs(block, data, ModifKinds::Country | ModifKinds::Province, vd);
291    });
292    vd.field_validated_block("character_modifier", |block, data| {
293        let vd = Validator::new(block, data);
294        validate_modifs(block, data, ModifKinds::Character, vd);
295    });
296}
297
298pub fn validate_raise_legion(
299    key: &Token,
300    block: &Block,
301    data: &Everything,
302    sc: &mut ScopeContext,
303    mut vd: Validator,
304    tooltipped: Tooltipped,
305    special_tokens: &mut SpecialTokens,
306) -> bool {
307    let caller = Lowercase::new(key.as_str());
308    sc.open_scope(Scopes::Legion, key.clone());
309    vd.req_field_warn("create_unit");
310    let has_tooltip = validate_effect_internal(
311        &caller,
312        ListType::None,
313        block,
314        data,
315        sc,
316        &mut vd,
317        tooltipped,
318        special_tokens,
319    );
320    sc.close();
321    has_tooltip
322}
323
324pub fn validate_create_character(
325    key: &Token,
326    block: &Block,
327    data: &Everything,
328    sc: &mut ScopeContext,
329    mut vd: Validator,
330    tooltipped: Tooltipped,
331    special_tokens: &mut SpecialTokens,
332) -> bool {
333    let caller = Lowercase::new(key.as_str());
334    sc.open_scope(Scopes::Character, key.clone());
335    vd.field_item("first_name", Item::Localization);
336    vd.field_item("family_name", Item::Localization);
337    vd.field_item("nickname", Item::Localization);
338    vd.field_value("dna");
339    vd.field_item_or_target("culture", sc, Item::Culture, Scopes::Culture);
340    vd.field_item_or_target("religion", sc, Item::Religion, Scopes::Religion);
341    vd.field_target("family", sc, Scopes::Family);
342    vd.field_target("father", sc, Scopes::Character);
343    vd.field_target("mother", sc, Scopes::Character);
344    vd.field_bool("female");
345    vd.field_bool("no_stats");
346    vd.field_bool("no_traits");
347    vd.field_script_value("age", sc);
348    vd.field_date("birth_date");
349    vd.field_date("death_date");
350    vd.field_item_or_target("birth_province", sc, Item::Province, Scopes::Province);
351    let has_tooltip = validate_effect_internal(
352        &caller,
353        ListType::None,
354        block,
355        data,
356        sc,
357        &mut vd,
358        tooltipped,
359        special_tokens,
360    );
361    sc.close();
362    has_tooltip
363}
364
365pub fn validate_create_unit(
366    key: &Token,
367    block: &Block,
368    data: &Everything,
369    sc: &mut ScopeContext,
370    mut vd: Validator,
371    tooltipped: Tooltipped,
372    special_tokens: &mut SpecialTokens,
373) -> bool {
374    let caller = Lowercase::new(key.as_str());
375    sc.open_scope(Scopes::Unit, key.clone());
376    vd.field_item("name", Item::Localization);
377    vd.field_item_or_target("location", sc, Item::Province, Scopes::Province);
378    vd.field_target("commander", sc, Scopes::Character);
379    vd.field_bool("navy");
380    vd.field_item("sub_unit", Item::Unit);
381    let has_tooltip = validate_effect_internal(
382        &caller,
383        ListType::None,
384        block,
385        data,
386        sc,
387        &mut vd,
388        tooltipped,
389        special_tokens,
390    );
391    sc.close();
392    has_tooltip
393}
394
395pub fn validate_create_country(
396    key: &Token,
397    block: &Block,
398    data: &Everything,
399    sc: &mut ScopeContext,
400    mut vd: Validator,
401    tooltipped: Tooltipped,
402    special_tokens: &mut SpecialTokens,
403) -> bool {
404    let caller = Lowercase::new(key.as_str());
405    sc.open_scope(Scopes::Country, key.clone());
406    vd.field_validated_block("name", |block, data| {
407        let mut vd = Validator::new(block, data);
408        vd.field_item("name", Item::Localization);
409        vd.field_item("adjective", Item::Localization);
410    });
411    let has_tooltip = validate_effect_internal(
412        &caller,
413        ListType::None,
414        block,
415        data,
416        sc,
417        &mut vd,
418        tooltipped,
419        special_tokens,
420    );
421    sc.close();
422    has_tooltip
423}
424
425pub fn validate_pay_gold(
426    _key: &Token,
427    _block: &Block,
428    _data: &Everything,
429    sc: &mut ScopeContext,
430    mut vd: Validator,
431    _tooltipped: Tooltipped,
432) {
433    vd.req_field("target");
434    vd.req_field("gold");
435    vd.field_item_or_target("target", sc, Item::Localization, Scopes::Country);
436    vd.field_numeric("gold");
437}
438
439pub fn validate_great_work_construction(
440    _key: &Token,
441    _block: &Block,
442    _data: &Everything,
443    _sc: &mut ScopeContext,
444    mut vd: Validator,
445    _tooltipped: Tooltipped,
446) {
447    vd.field_item("great_work", Item::GreatWorkTemplate);
448    vd.field_choice("locator", &["primary_great_work", "secondary_great_work", "great_work"]);
449    vd.field_bool("is_ancient");
450}
451
452pub fn validate_war_score_value(
453    _key: &Token,
454    _block: &Block,
455    _data: &Everything,
456    sc: &mut ScopeContext,
457    mut vd: Validator,
458    _tooltipped: Tooltipped,
459) {
460    vd.req_field("target");
461    vd.req_field("local_var");
462    vd.field_target("target", sc, Scopes::Country);
463    // TODO: when local variables are tracked, also track this one
464    vd.field_value("local_var");
465}