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 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 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 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 vd.field_effect_rooted("on_creation", Tooltipped::No, Scopes::Faction);
156 vd.field_effect_rooted("on_destroy", Tooltipped::No, Scopes::Faction);
157 }
158}