tiger_lib/ck3/data/
factions.rs

1use crate::block::{Block, BV};
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        if !vd.field_validated_rooted("description", Scopes::Faction, validate_desc) {
37            let loca = format!("{key}_desc");
38            data.verify_exists_implied(Item::Localization, &loca, key);
39        }
40
41        vd.req_field("short_effect_desc");
42        vd.field_validated_rooted("short_effect_desc", Scopes::Faction, validate_desc);
43
44        vd.field_effect_rooted("demand", Tooltipped::No, Scopes::Faction);
45        vd.field_effect_rooted("update_effect", Tooltipped::No, Scopes::Faction);
46        // docs say "on_declaration"
47        vd.field_effect_rooted("on_war_start", Tooltipped::No, Scopes::Faction);
48        vd.field_effect_rooted("character_leaves", Tooltipped::No, Scopes::Faction);
49        vd.field_effect_builder("leader_leaves", Tooltipped::No, |key| {
50            let mut sc = ScopeContext::new(Scopes::Faction, key);
51            sc.define_name("faction_member", Scopes::Character, key);
52            sc
53        });
54        vd.field_validated_key_block("ai_join_score", |key, block, data| {
55            let mut sc = ScopeContext::new(Scopes::Character, key);
56            sc.define_name("faction", Scopes::Faction, key);
57            validate_modifiers_with_base(block, data, &mut sc);
58        });
59        vd.field_validated_key_block("ai_create_score", |key, block, data| {
60            let mut sc = ScopeContext::new(Scopes::Character, key);
61            sc.define_name("target", Scopes::Character, key);
62            // TODO: check if it's a claimant faction before setting claimant and title
63            sc.define_name("claimant", Scopes::Character, key);
64            sc.define_name("title", Scopes::LandedTitle, key);
65            validate_modifiers_with_base(block, data, &mut sc);
66        });
67        vd.field_validated_key_block("county_join_score", |key, block, data| {
68            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
69            sc.define_name("faction", Scopes::Faction, key);
70            validate_modifiers_with_base(block, data, &mut sc);
71        });
72        vd.field_validated_key_block("county_create_score", |key, block, data| {
73            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
74            sc.define_name("target", Scopes::Character, key);
75            validate_modifiers_with_base(block, data, &mut sc);
76        });
77        vd.field_script_value_rooted("county_power", Scopes::LandedTitle);
78        vd.field_validated_block_rooted(
79            "ai_demand_chance",
80            Scopes::Faction,
81            validate_modifiers_with_base,
82        );
83        vd.field_validated_block_rooted(
84            "discontent_progress",
85            Scopes::Faction,
86            validate_modifiers_with_base,
87        );
88        vd.field_validated_rooted("power_threshold", Scopes::Faction, |bv, data, sc| match bv {
89            BV::Value(t) => _ = t.expect_integer(),
90            BV::Block(b) => validate_modifiers_with_base(b, data, sc),
91        });
92        vd.field_trigger_rooted("is_valid", Tooltipped::No, Scopes::Faction);
93        vd.field_trigger_builder("is_character_valid", Tooltipped::No, |key| {
94            let mut sc = ScopeContext::new(Scopes::Character, key);
95            sc.define_name("faction", Scopes::Faction, key);
96            sc
97        });
98        vd.field_trigger_builder("is_county_valid", Tooltipped::No, |key| {
99            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
100            sc.define_name("faction", Scopes::Faction, key);
101            sc
102        });
103        vd.field_trigger_builder("can_character_join", Tooltipped::Yes, |key| {
104            let mut sc = ScopeContext::new(Scopes::Character, key);
105            sc.define_name("faction", Scopes::Faction, key);
106            sc
107        });
108        vd.field_trigger_builder("can_character_create", Tooltipped::Yes, |key| {
109            let mut sc = ScopeContext::new(Scopes::Character, key);
110            sc.define_name("target", Scopes::Character, key);
111            sc
112        });
113        vd.field_trigger_builder("can_character_create_ui", Tooltipped::Yes, |key| {
114            let mut sc = ScopeContext::new(Scopes::Character, key);
115            sc.define_name("target", Scopes::Character, key);
116            sc
117        });
118        vd.field_trigger_builder("can_character_become_leader", Tooltipped::No, |key| {
119            let mut sc = ScopeContext::new(Scopes::Character, key);
120            sc.define_name("faction", Scopes::Faction, key);
121            sc
122        });
123        vd.field_trigger_builder("can_county_join", Tooltipped::No, |key| {
124            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
125            sc.define_name("faction", Scopes::Faction, key);
126            sc
127        });
128        vd.field_trigger_builder("can_county_create", Tooltipped::No, |key| {
129            let mut sc = ScopeContext::new(Scopes::LandedTitle, key);
130            sc.define_name("target", Scopes::Character, key);
131            sc
132        });
133
134        vd.field_bool("character_allow_create");
135        vd.field_bool("character_allow_join");
136        vd.field_bool("county_allow_create");
137        vd.field_bool("county_allow_join");
138        vd.field_bool("leaders_allowed_to_leave");
139        vd.field_bool("player_can_join");
140        vd.field_bool("multiple_targeting");
141
142        vd.field_item("casus_belli", Item::CasusBelli);
143        vd.field_item("special_character_title", Item::Localization);
144
145        vd.field_bool("ignore_soft_block");
146        vd.field_bool("inherit_membership");
147        vd.field_bool("requires_county");
148        vd.field_bool("requires_character");
149        vd.field_bool("requires_leader");
150        vd.field_bool("county_can_switch_to_other_faction");
151        vd.field_integer("sort_order");
152        vd.field_bool("show_special_title");
153
154        // undocumented fields follow
155        vd.field_effect_rooted("on_creation", Tooltipped::No, Scopes::Faction);
156        vd.field_effect_rooted("on_destroy", Tooltipped::No, Scopes::Faction);
157    }
158}