tiger_lib/ck3/data/
accolades.rs

1use crate::block::Block;
2use crate::ck3::data::maa::{
3    validate_holding_bonus, validate_terrain_bonus, validate_winter_bonus,
4};
5use crate::ck3::modif::ModifKinds;
6use crate::context::ScopeContext;
7use crate::db::{Db, DbKind};
8use crate::desc::validate_desc;
9use crate::everything::Everything;
10use crate::game::GameFlags;
11use crate::item::{Item, ItemLoader};
12use crate::modif::validate_modifs;
13use crate::report::{ErrorKey, err};
14use crate::scopes::Scopes;
15use crate::token::Token;
16use crate::tooltipped::Tooltipped;
17use crate::validator::Validator;
18
19#[derive(Clone, Debug)]
20pub struct AccoladeIcon {}
21
22inventory::submit! {
23    ItemLoader::Normal(GameFlags::Ck3, Item::AccoladeIcon, AccoladeIcon::add)
24}
25
26impl AccoladeIcon {
27    pub fn add(db: &mut Db, key: Token, block: Block) {
28        db.add(Item::AccoladeIcon, key, block, Box::new(Self {}));
29    }
30}
31
32impl DbKind for AccoladeIcon {
33    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
34        let mut vd = Validator::new(block, data);
35        let mut sc = ScopeContext::new(Scopes::AccoladeType, key);
36        sc.define_name("accolade", Scopes::Accolade, key);
37
38        if let Some(token) = vd.field_value("texture") {
39            let pathname = format!("gfx/interface/icons/knight_badge/icons/{token}");
40            data.verify_exists_implied(Item::File, &pathname, token);
41        }
42
43        vd.field_trigger("potential", Tooltipped::No, &mut sc);
44    }
45}
46
47#[derive(Clone, Debug)]
48pub struct AccoladeName {}
49
50inventory::submit! {
51    ItemLoader::Normal(GameFlags::Ck3, Item::AccoladeName, AccoladeName::add)
52}
53
54impl AccoladeName {
55    pub fn add(db: &mut Db, key: Token, block: Block) {
56        db.add(Item::AccoladeName, key, block, Box::new(Self {}));
57    }
58}
59
60impl DbKind for AccoladeName {
61    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
62        let mut vd = Validator::new(block, data);
63        let mut sc = ScopeContext::new(Scopes::Character, key);
64        sc.define_name("owner", Scopes::Character, key);
65        sc.define_name("accolade_type", Scopes::AccoladeType, key);
66
67        vd.req_field("key");
68        vd.req_field("num_options");
69
70        vd.field_item("key", Item::Localization);
71        vd.field_integer("num_options");
72        if let Some(key) = block.get_field_value("key") {
73            if let Some(n) = block.get_field_integer("num_options") {
74                data.localization.verify_key_has_options(key.as_str(), key, n, "OPTION_");
75            }
76        }
77
78        let mut count = 0;
79        vd.multi_field_validated("option", |bv, data| {
80            count += 1;
81            validate_desc(bv, data, &mut sc);
82        });
83
84        if let Some(n) = block.get_field_integer("num_options") {
85            if count != n {
86                let msg = format!("expected {n} `option` blocks, found {count}");
87                err(ErrorKey::Validation).msg(msg).loc(block).push();
88            }
89        }
90
91        vd.field_trigger("potential", Tooltipped::No, &mut sc);
92
93        vd.field_script_value("weight", &mut sc);
94    }
95}
96
97#[derive(Clone, Debug)]
98pub struct AccoladeType {}
99
100inventory::submit! {
101    ItemLoader::Normal(GameFlags::Ck3, Item::AccoladeType, AccoladeType::add)
102}
103
104impl AccoladeType {
105    pub fn add(db: &mut Db, key: Token, block: Block) {
106        db.add(Item::AccoladeType, key, block, Box::new(Self {}));
107    }
108}
109
110impl DbKind for AccoladeType {
111    fn add_subitems(&self, _key: &Token, block: &Block, db: &mut Db) {
112        if let Some(vec) = block.get_field_list("accolade_categories") {
113            for token in vec {
114                db.add_flag(Item::AccoladeCategory, token);
115            }
116        }
117        if let Some(block) = block.get_field_block("ranks") {
118            for (key, block) in block.iter_definitions() {
119                if key.is_integer() {
120                    if let Some(vec) = block.get_field_list("accolade_parameters") {
121                        for token in vec {
122                            db.add_flag(Item::AccoladeParameter, token);
123                        }
124                    }
125                }
126            }
127        }
128    }
129
130    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
131        let mut vd = Validator::new(block, data);
132        let mut sc = ScopeContext::new(Scopes::Character, key);
133
134        data.verify_exists(Item::Localization, key);
135        let loca = format!("{key}_modifier");
136        data.verify_exists_implied(Item::Localization, &loca, key);
137
138        vd.field_item("adjective", Item::Localization);
139        vd.field_item("noun", Item::Localization);
140        vd.field_list("accolade_categories");
141
142        vd.field_trigger("potential", Tooltipped::Yes, &mut sc);
143
144        sc.define_name("owner", Scopes::Character, key);
145        vd.field_script_value("weight", &mut sc);
146
147        vd.field_validated_block("ranks", |block, data| {
148            let mut vd = Validator::new(block, data);
149            for (_, block) in vd.integer_blocks() {
150                let mut vd = Validator::new(block, data);
151                vd.field_validated_block("liege_modifier", |block, data| {
152                    let vd = Validator::new(block, data);
153                    validate_modifs(block, data, ModifKinds::Character, vd);
154                });
155                vd.field_validated_block("knight_modifier", |block, data| {
156                    let vd = Validator::new(block, data);
157                    validate_modifs(block, data, ModifKinds::Character, vd);
158                });
159                vd.field_validated_block("knight_army_modifier", |block, data| {
160                    let vd = Validator::new(block, data);
161                    validate_modifs(block, data, ModifKinds::Character, vd);
162                });
163                vd.field_list_items("men_at_arms", Item::MenAtArms);
164                vd.field_validated_block("terrain_bonus", |block, data| {
165                    let mut vd = Validator::new(block, data);
166                    vd.unknown_block_fields(|key, block| {
167                        data.verify_exists(Item::MenAtArms, key);
168                        validate_terrain_bonus(block, data);
169                    });
170                });
171                vd.field_validated_block("holding_bonus", |block, data| {
172                    let mut vd = Validator::new(block, data);
173                    vd.unknown_block_fields(|key, block| {
174                        data.verify_exists(Item::MenAtArms, key);
175                        validate_holding_bonus(block, data);
176                    });
177                });
178                vd.field_validated_block("winter_bonus", |block, data| {
179                    let mut vd = Validator::new(block, data);
180                    vd.unknown_block_fields(|key, block| {
181                        data.verify_exists(Item::MenAtArms, key);
182                        validate_winter_bonus(block, data);
183                    });
184                });
185                vd.field_list_items("accolade_parameters", Item::Localization);
186            }
187        });
188    }
189}