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 vd.field_value("local_var");
465}