1use crate::block::{BV, Block};
2use crate::context::ScopeContext;
3use crate::db::{Db, DbKind};
4use crate::everything::Everything;
5use crate::game::GameFlags;
6use crate::item::{Item, ItemLoader};
7use crate::scopes::Scopes;
8use crate::token::Token;
9use crate::tooltipped::Tooltipped;
10use crate::validator::Validator;
11
12#[derive(Clone, Debug)]
13pub struct Story {}
14
15inventory::submit! {
16 ItemLoader::Normal(GameFlags::Ck3, Item::Story, Story::add)
17}
18
19impl Story {
20 pub fn add(db: &mut Db, key: Token, block: Block) {
21 db.add(Item::Story, key, block, Box::new(Self {}));
22 }
23}
24
25impl DbKind for Story {
26 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
27 let mut vd = Validator::new(block, data);
28
29 let sc_builder = |key: &Token| {
30 let mut sc = ScopeContext::new(Scopes::StoryCycle, key);
31 sc.define_name("story", Scopes::StoryCycle, key);
32 sc
33 };
34
35 vd.field_effect_builder("on_setup", Tooltipped::No, sc_builder);
36 vd.field_effect_builder("on_end", Tooltipped::No, sc_builder);
37 vd.field_effect_builder("on_owner_death", Tooltipped::No, sc_builder);
38
39 vd.field_bool("visible");
40 vd.multi_field_validated_block("icon", |block, data| {
42 let mut vd = Validator::new(block, data);
43 vd.field_trigger_builder("trigger", Tooltipped::No, sc_builder);
44 vd.field_item("reference", Item::File);
45 });
46
47 vd.multi_field_validated_block("background", |block, data| {
49 let mut vd = Validator::new(block, data);
50 vd.field_trigger_builder("trigger", Tooltipped::No, sc_builder);
51 vd.field_item("reference", Item::File);
52 });
53
54 vd.field_validated_block("visualization", |block, data| {
55 let mut vd = Validator::new(block, data);
56 for field in
57 &["character", "character_list", "title", "title_list", "artifact", "artifact_list"]
58 {
59 vd.multi_field_validated_block(field, |block, data| {
60 let mut vd = Validator::new(block, data);
61 vd.field_value("variable_name");
63 vd.field_item("label", Item::Localization);
64 });
65 }
66 vd.field_item("custom_string_key", Item::Localization);
68 for field in &["basic_counter", "tug_of_war_counter"] {
69 vd.multi_field_validated_block(field, |block, data| {
70 let mut vd = Validator::new(block, data);
71 vd.field_value("variable_name");
73 vd.field_numeric("min");
74 vd.field_numeric("max");
75 vd.field_item("label", Item::Localization);
76 vd.field_item("tooltip", Item::Localization);
77 vd.field_item("min_label", Item::Localization);
78 vd.field_item("max_label", Item::Localization);
79 });
80 }
81 vd.field_list_items("decisions", Item::Decision);
82 vd.field_list_items("modifiers", Item::Modifier);
83 vd.field_list_items("traits", Item::Trait);
84 });
85
86 vd.multi_field_validated_key_block("effect_group", |key, block, data| {
87 let mut sc = ScopeContext::new(Scopes::StoryCycle, key);
88 sc.define_name("story", Scopes::StoryCycle, key);
89 let mut vd = Validator::new(block, data);
90
91 for field in &["days", "weeks", "months", "years"] {
93 vd.field_validated(field, |bv, data| match bv {
94 BV::Value(token) => {
95 token.expect_integer();
96 }
97 BV::Block(block) => {
98 let mut vd = Validator::new(block, data);
99 vd.req_tokens_integers_exactly(2);
100 }
101 });
102 }
103 vd.field_numeric_range("chance", 0.0..=100.0);
104
105 vd.field_trigger("trigger", Tooltipped::No, &mut sc);
106
107 validate_complex_effect(&mut vd, &mut sc);
108 });
109 }
110}
111
112fn validate_complex_effect(vd: &mut Validator, sc: &mut ScopeContext) {
113 vd.multi_field_validated_block("first_valid", |block, data| {
114 let mut vd = Validator::new(block, data);
115 validate_complex_effect(&mut vd, sc);
116 });
117 vd.multi_field_validated_block("random_valid", |block, data| {
118 let mut vd = Validator::new(block, data);
119 validate_complex_effect(&mut vd, sc);
120 });
121 vd.multi_field_validated_block("triggered_effect", |block, data| {
122 let mut vd = Validator::new(block, data);
123 vd.field_trigger("trigger", Tooltipped::No, sc);
124 vd.field_effect("effect", Tooltipped::No, sc);
125 });
126 vd.field_effect("fallback", Tooltipped::No, sc);
127}