1use crate::block::Block;
2use crate::ck3::modif::ModifKinds;
3use crate::ck3::validate::validate_traits;
4use crate::context::ScopeContext;
5use crate::db::{Db, DbKind};
6use crate::desc::validate_desc;
7use crate::everything::Everything;
8use crate::game::GameFlags;
9use crate::item::{Item, ItemLoader};
10use crate::modif::validate_modifs;
11use crate::scopes::Scopes;
12use crate::token::Token;
13use crate::tooltipped::Tooltipped;
14use crate::validator::Validator;
15
16#[derive(Clone, Debug)]
17pub struct DoctrineGroup {}
18#[derive(Clone, Debug)]
19pub struct Doctrine {}
20
21inventory::submit! {
22 ItemLoader::Normal(GameFlags::Ck3, Item::DoctrineGroup, DoctrineGroup::add)
23}
24inventory::submit! {
25 ItemLoader::Normal(GameFlags::Ck3, Item::Doctrine, Doctrine::add)
26}
27
28impl DoctrineGroup {
29 pub fn add(db: &mut Db, key: Token, block: Block) {
30 db.add(Item::DoctrineGroup, key, block, Box::new(Self {}));
31 }
32}
33impl Doctrine {
34 pub fn add(db: &mut Db, key: Token, block: Block) {
35 db.add(Item::Doctrine, key, block, Box::new(Self {}));
36 }
37}
38
39impl DbKind for DoctrineGroup {
40 fn validate(&self, key: &Token, block: &Block, data: &Everything) {
41 let mut vd = Validator::new(block, data);
42
43 let loca = format!("{key}_name");
44 data.verify_exists_implied(Item::Localization, &loca, key);
45
46 data.verify_icon("NGameIcons|DOCTRINE_GROUP_TYPE_ICON_PATH", key, ".dds");
47
48 vd.field_value("category");
49
50 vd.field_integer("number_of_picks");
51 vd.field_trigger_rooted("is_available_on_create", Tooltipped::No, Scopes::Faith);
52
53 vd.field_list_items("doctrine_types", Item::Doctrine);
54 }
55}
56
57impl DbKind for Doctrine {
58 fn has_property(
59 &self,
60 _key: &Token,
61 block: &Block,
62 property: &str,
63 _data: &Everything,
64 ) -> bool {
65 if property == "unreformed"
66 && let Some(parameters) = block.get_field_block("parameters")
67 {
68 for (key, _) in parameters.iter_assignments() {
69 if key.is("unreformed") {
70 return true;
71 }
72 }
73 }
74 false
75 }
76
77 fn add_subitems(&self, _key: &Token, block: &Block, db: &mut Db) {
78 if let Some(block) = block.get_field_block("parameters") {
79 for (key, value) in block.iter_assignments() {
80 if value.is("yes") || value.is("no") {
81 db.add_flag(Item::DoctrineBooleanParameter, key.clone());
82 }
83 db.add_flag(Item::DoctrineParameter, key.clone());
84 }
85 }
86 }
87
88 fn validate(&self, key: &Token, block: &Block, data: &Everything) {
89 let mut vd = Validator::new(block, data);
90 let mut sc = ScopeContext::new(Scopes::Faith, key);
91 sc.define_list("selected_doctrines", Scopes::Doctrine, key);
92
93 let icon = vd.field_value("icon").unwrap_or(key);
94 data.verify_icon("NGameIcons|DOCTRINE_TYPE_ICON_PATH", icon, ".dds");
95
96 if !vd.field_validated_sc("name", &mut sc, validate_desc) {
97 let loca = format!("{key}_name");
98 data.verify_exists_implied(Item::Localization, &loca, key);
99 }
100
101 if !vd.field_validated_sc("desc", &mut sc, validate_desc) {
102 let loca = format!("{key}_desc");
103 data.verify_exists_implied(Item::Localization, &loca, key);
104 }
105
106 vd.field_bool("visible");
107 vd.field_validated_block("parameters", validate_parameters);
108 vd.field_script_value("piety_cost", &mut sc);
109 vd.field_trigger("is_shown", Tooltipped::No, &mut sc);
110 vd.field_trigger("can_pick", Tooltipped::Yes, &mut sc);
111
112 vd.field_validated_block("character_modifier", |block, data| {
113 let mut vd = Validator::new(block, data);
114 vd.field_item("name", Item::Localization);
115 validate_modifs(block, data, ModifKinds::Character, vd);
116 });
117
118 vd.field_validated_block("clergy_modifier", |block, data| {
120 let vd = Validator::new(block, data);
121 validate_modifs(block, data, ModifKinds::Character, vd);
122 });
123
124 vd.field_validated_block("doctrine_character_modifier", |block, data| {
126 let mut vd = Validator::new(block, data);
127 vd.field_item("doctrine", Item::Doctrine);
128 validate_modifs(block, data, ModifKinds::Character, vd);
129 });
130
131 vd.field_validated_block("traits", validate_traits);
132 }
133}
134
135fn validate_parameters(block: &Block, data: &Everything) {
136 let mut vd = Validator::new(block, data);
137
138 vd.unknown_value_fields(|_, value| {
139 if value.is("yes") || value.is("no") {
140 return;
141 }
142 value.expect_number();
143 });
144}