tiger_lib/ck3/data/
character_templates.rs

1use crate::block::Block;
2use crate::ck3::validate::{
3    validate_random_culture, validate_random_faith, validate_random_traits_list,
4};
5use crate::context::ScopeContext;
6use crate::db::{Db, DbKind};
7use crate::effect::validate_effect;
8use crate::everything::Everything;
9use crate::game::GameFlags;
10use crate::item::{Item, ItemLoader};
11use crate::scopes::Scopes;
12use crate::token::Token;
13use crate::tooltipped::Tooltipped;
14use crate::trigger::validate_target_ok_this;
15use crate::validator::Validator;
16
17#[derive(Clone, Debug)]
18pub struct CharacterTemplate {}
19
20inventory::submit! {
21    ItemLoader::Normal(GameFlags::Ck3, Item::CharacterTemplate, CharacterTemplate::add)
22}
23
24impl CharacterTemplate {
25    pub fn add(db: &mut Db, key: Token, block: Block) {
26        db.add(Item::CharacterTemplate, key, block, Box::new(Self {}));
27    }
28}
29
30impl DbKind for CharacterTemplate {
31    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
32        let mut sc = ScopeContext::new_unrooted(Scopes::all(), key);
33        sc.set_strict_scopes(false);
34        let b = Block::new(key.loc);
35        self.validate_call(key, block, key, &b, data, &mut sc);
36    }
37
38    // TODO: lots of duplication between this and "create_character" effect
39    fn validate_call(
40        &self,
41        _key: &Token,
42        block: &Block,
43        _from: &Token,
44        from_block: &Block,
45        data: &Everything,
46        sc: &mut ScopeContext,
47    ) {
48        // `from_block` is used to suppress warnings about targets that won't be used
49        let mut vd = Validator::new(block, data);
50        if from_block.has_key("name") {
51            vd.field_value("name");
52        } else {
53            vd.field_item("name", Item::Localization);
54        }
55        for field in &[
56            "age",
57            "health",
58            "diplomacy",
59            "intrigue",
60            "learning",
61            "martial",
62            "prowess",
63            "stewardship",
64        ] {
65            if from_block.has_key(field) {
66                vd.field(field);
67            } else {
68                vd.field_script_value(field, sc);
69            }
70        }
71        if from_block.has_key("gender") {
72            vd.field_value("gender");
73            vd.field("gender_female_chance");
74        } else {
75            if let Some(token) = vd.field_value("gender") {
76                if !token.is("male") && !token.is("female") {
77                    validate_target_ok_this(token, data, sc, Scopes::Character);
78                }
79            }
80            if from_block.has_key("gender_female_chance") {
81                vd.field("gender_female_chance");
82            } else {
83                vd.field_script_value("gender_female_chance", sc);
84            }
85        }
86        vd.multi_field_item("trait", Item::Trait);
87        vd.multi_field_validated_block_sc("random_traits_list", sc, validate_random_traits_list);
88        vd.field_bool("random_traits");
89        if from_block.has_key("culture") {
90            vd.field_value("culture");
91            vd.multi_field_block("random_culture");
92        } else {
93            vd.field_target("culture", sc, Scopes::Culture);
94            vd.multi_field_validated_block_sc("random_culture", sc, validate_random_culture);
95        }
96        if from_block.has_key("faith") {
97            vd.field_value("faith");
98            vd.multi_field_block("random_faith");
99        } else {
100            vd.field_target("faith", sc, Scopes::Faith);
101            vd.multi_field_validated_block_sc("random_faith", sc, validate_random_faith);
102        }
103        if from_block.has_key("dynasty_house") {
104            vd.field_value("dynasty_house");
105        } else {
106            vd.field_target("dynasty_house", sc, Scopes::DynastyHouse);
107        }
108        if from_block.has_key("dynasty") {
109            vd.field_value("dynasty");
110        } else {
111            vd.field_choice("dynasty", &["generate", "inherit", "none"]);
112        }
113        if from_block.has_key("after_creation") {
114            vd.field_block("after_creation");
115        } else {
116            vd.field_validated_key_block("after_creation", |key, block, data| {
117                sc.open_scope(Scopes::Character, key.clone());
118                validate_effect(block, data, sc, Tooltipped::No);
119                sc.close();
120            });
121        }
122    }
123}