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 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 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}