tiger_lib/ck3/data/
factions.rs

1use crate::block::{BV, Block};
2use crate::context::ScopeContext;
3use crate::db::{Db, DbKind};
4use crate::desc::validate_desc;
5use crate::everything::Everything;
6use crate::game::GameFlags;
7use crate::item::{Item, ItemLoader};
8use crate::scopes::Scopes;
9use crate::token::Token;
10use crate::tooltipped::Tooltipped;
11use crate::validate::validate_modifiers_with_base;
12use crate::validator::Validator;
13
14#[derive(Clone, Debug)]
15pub struct Faction {}
16
17inventory::submit! {
18    ItemLoader::Normal(GameFlags::Ck3, Item::Faction, Faction::add)
19}
20
21impl Faction {
22    pub fn add(db: &mut Db, key: Token, block: Block) {
23        db.add(Item::Faction, key, block, Box::new(Self {}));
24    }
25}
26
27impl DbKind for Faction {
28    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
29        let mut vd = Validator::new(block, data);
30
31        if !vd.field_validated_rooted("name", Scopes::Faction, validate_desc) {
32            data.verify_exists(Item::Localization, key);
33        }
34
35        // TODO: docs say description but vanilla uses desc. Verify.
36        vd.field_validated_rooted("desc", Scopes::Faction, validate_desc);
37        if !vd.field_validated_rooted("description", Scopes::Faction, validate_desc) {
38            let loca = format!("{key}_desc");
39            data.verify_exists_implied(Item::Localization, &loca, key);
40        }
41
42        vd.req_field("short_effect_desc");
43        vd.field_validated_rooted("short_effect_desc", Scopes::Faction, validate_desc);
44
45        vd.field_bool("claimant");
46        vd.field_item("character_interaction", Item::CharacterInteraction);
47
48        vd.field_effect_rooted("on_creation", Tooltipped::No, Scopes::Faction);
49        vd.field_effect_rooted("on_destroy", Tooltipped::No, Scopes::Faction);
50
51        vd.field_effect_rooted("demand", Tooltipped::No, Scopes::Faction);
52        vd.field_effect_rooted("update_effect", Tooltipped::No, Scopes::Faction);
53        // docs say "on_declaration"
54        vd.field_effect_rooted("on_war_start", Tooltipped::No, Scopes::Faction);
55        vd.field_effect_builder("character_leaves", Tooltipped::No, |key| {
56            let mut sc = ScopeContext::new(Scopes::Faction, key);
57            sc.define_name("faction_member", Scopes::Character, key);
58            sc
59        });
60        vd.field_effect_builder("leader_leaves", Tooltipped::No, |key| {
61            let mut sc = ScopeContext::new(Scopes::Faction, key);
62            sc.define_name("faction_member", Scopes::Character, key);
63            sc
64        });
65        vd.field_validated_key_block("ai_join_score", |key, block, data| {
66            let mut sc = ScopeContext::new(Scopes::Character, key);
67            sc.define_name("faction", Scopes::Faction, key);
68            validate_modifiers_with_base(block, data, &mut sc);
69        });
70        vd.field_validated_key_block("ai_create_score", |key, block, data| {
71            let mut sc = ScopeContext::new(Scopes::Character, key);
72            sc.define_name("target", Scopes::Character, key);
73            if block.get_field_bool("claimant") == Some(true) {
74                sc.define_name("claimant", Scopes::Character, key);
75                sc.define_name("title", Scopes::LandedTitle, key);
76            }
77            validate_modifiers_with_base(block, data, &mut sc);
78        });
79        vd.field_validated_key_block("county_join_score", |key, block, data| {
80            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
81            sc.define_name("faction", Scopes::Faction, key);
82            validate_modifiers_with_base(block, data, &mut sc);
83        });
84        vd.field_validated_key_block("county_create_score", |key, block, data| {
85            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
86            sc.define_name("target", Scopes::Character, key);
87            validate_modifiers_with_base(block, data, &mut sc);
88        });
89        vd.field_script_value_rooted("county_power", Scopes::LandedTitle);
90        vd.field_validated_block_rooted(
91            "ai_demand_chance",
92            Scopes::Faction,
93            validate_modifiers_with_base,
94        );
95        vd.field_validated_block_rooted(
96            "discontent_progress",
97            Scopes::Faction,
98            validate_modifiers_with_base,
99        );
100        vd.field_validated_rooted("power_threshold", Scopes::Faction, |bv, data, sc| match bv {
101            BV::Value(t) => _ = t.expect_integer(),
102            BV::Block(b) => validate_modifiers_with_base(b, data, sc),
103        });
104        vd.field_trigger_rooted("is_valid", Tooltipped::No, Scopes::Faction);
105        vd.field_trigger_rooted("is_shown", Tooltipped::No, Scopes::Character);
106        vd.field_trigger_builder("is_character_valid", Tooltipped::No, |key| {
107            let mut sc = ScopeContext::new(Scopes::Character, key);
108            sc.define_name("faction", Scopes::Faction, key);
109            sc
110        });
111        vd.field_trigger_builder("is_county_valid", Tooltipped::No, |key| {
112            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
113            sc.define_name("faction", Scopes::Faction, key);
114            sc
115        });
116        vd.field_trigger_builder("can_character_join", Tooltipped::Yes, |key| {
117            let mut sc = ScopeContext::new(Scopes::Character, key);
118            sc.define_name("faction", Scopes::Faction, key);
119            sc
120        });
121        vd.field_trigger_builder("can_character_create", Tooltipped::Yes, |key| {
122            let mut sc = ScopeContext::new(Scopes::Character, key);
123            sc.define_name("target", Scopes::Character, key);
124            sc
125        });
126        vd.field_trigger_builder("can_character_create_ui", Tooltipped::Yes, |key| {
127            let mut sc = ScopeContext::new(Scopes::Character, key);
128            sc.define_name("target", Scopes::Character, key);
129            sc
130        });
131        vd.field_trigger_builder("can_character_become_leader", Tooltipped::No, |key| {
132            let mut sc = ScopeContext::new(Scopes::Character, key);
133            sc.define_name("faction", Scopes::Faction, key);
134            sc
135        });
136        vd.field_trigger_builder("can_county_join", Tooltipped::No, |key| {
137            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
138            sc.define_name("faction", Scopes::Faction, key);
139            sc
140        });
141        vd.field_trigger_builder("can_county_create", Tooltipped::No, |key| {
142            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
143            sc.define_name("target", Scopes::Character, key);
144            sc
145        });
146
147        vd.field_bool("character_allow_create");
148        vd.field_bool("character_allow_join");
149        vd.field_bool("county_allow_create");
150        vd.field_bool("county_allow_join");
151        vd.field_bool("leaders_allowed_to_leave");
152        vd.field_bool("player_can_join");
153        vd.field_bool("multiple_targeting");
154
155        vd.field_item("casus_belli", Item::CasusBelli);
156        vd.field_item("special_character_title", Item::Localization);
157
158        vd.field_bool("ignore_soft_block");
159        vd.field_bool("inherit_membership");
160        vd.field_bool("requires_county");
161        vd.field_bool("requires_character");
162        vd.field_bool("requires_leader");
163        vd.field_bool("county_can_switch_to_other_faction");
164        vd.field_integer("sort_order");
165        vd.field_bool("show_special_title");
166    }
167}