1use crate::block::Block;
2use crate::context::ScopeContext;
3use crate::db::{Db, DbKind};
4use crate::everything::Everything;
5use crate::game::GameFlags;
6use crate::imperator::modif::ModifKinds;
7use crate::item::{Item, ItemLoader};
8use crate::modif::validate_modifs;
9use crate::scopes::Scopes;
10use crate::token::Token;
11use crate::tooltipped::Tooltipped;
12use crate::validator::Validator;
13
14#[derive(Clone, Debug)]
15pub struct GreatWorkEffect {}
16
17inventory::submit! {
18 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkEffect, GreatWorkEffect::add)
19}
20
21impl GreatWorkEffect {
22 pub fn add(db: &mut Db, key: Token, block: Block) {
23 db.add(Item::GreatWorkEffect, key, block, Box::new(Self {}));
24 }
25}
26
27impl DbKind for GreatWorkEffect {
28 fn add_subitems(&self, key: &Token, _block: &Block, db: &mut Db) {
29 for tier in 1..5 {
30 let tier_key = format!("{}:{}", key.as_str(), tier);
31 let tier_token = Token::new(&tier_key, key.loc);
32 db.add_flag(Item::GreatWorkEffect, tier_token);
33 }
34 }
35
36 fn validate(&self, key: &Token, block: &Block, data: &Everything) {
37 let mut vd = Validator::new(block, data);
38 let mut sc = ScopeContext::new(Scopes::Country, key);
39
40 vd.field_value("icon");
41 vd.field_list("flags");
42
43 vd.field_trigger("allow", Tooltipped::Yes, &mut sc);
44
45 vd.field_validated_block("great_work_tier_effect_modifiers", |block, data| {
46 let mut vd = Validator::new(block, data);
47 for tier in 1..5 {
48 let tier_str = format!("{}_tier_{}", key.as_str(), tier);
49 vd.field_validated_block(&tier_str, |block, data| {
50 let mut vd = Validator::new(block, data);
51 vd.field_item("great_work_effect_tier", Item::GreatWorkEffectTier);
52 vd.field_item("tier_modifier_tooltip_override", Item::Localization);
53 vd.field_validated_block("country_modifier", |block, data| {
54 let vd = Validator::new(block, data);
55 validate_modifs(block, data, ModifKinds::Country, vd);
56 });
57 vd.field_validated_block("state_modifier", |block, data| {
58 let vd = Validator::new(block, data);
59 validate_modifs(block, data, ModifKinds::Province | ModifKinds::State, vd);
60 });
61 });
62 }
63 });
64 }
65}
66
67#[derive(Clone, Debug)]
68pub struct GreatWorkEffectTier {}
69
70inventory::submit! {
71 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkEffectTier, GreatWorkEffectTier::add)
72}
73
74impl GreatWorkEffectTier {
75 pub fn add(db: &mut Db, key: Token, block: Block) {
76 db.add(Item::GreatWorkEffectTier, key, block, Box::new(Self {}));
77 }
78}
79
80impl DbKind for GreatWorkEffectTier {
81 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
82 let mut vd = Validator::new(block, data);
83
84 vd.field_value("icon");
85 vd.field_numeric("level");
86 vd.field_numeric("tier_threshold");
87 vd.field_numeric("tier_cost_factor");
88
89 vd.field_validated_block("great_work_effect_upgrade_costs", |block, data| {
90 let mut vd = Validator::new(block, data);
91 vd.validated_blocks(|block, data| {
92 let mut vd = Validator::new(block, data);
93 vd.field_numeric("level");
94 vd.field_validated_block("price", |block, data| {
95 let mut vd = Validator::new(block, data);
96 vd.field_numeric("political_influence");
97 vd.field_numeric("stability");
98 vd.field_numeric("gold");
99 });
100 });
101 });
102
103 vd.field_validated_block("great_work_effect_tier_addition_cost", |block, data| {
104 let mut vd = Validator::new(block, data);
105 vd.field_numeric("level");
106 vd.field_validated_block("price", |block, data| {
107 let mut vd = Validator::new(block, data);
108 vd.field_numeric("political_influence");
109 vd.field_numeric("stability");
110 vd.field_numeric("gold");
111 });
112 });
113 }
114}
115
116#[derive(Clone, Debug)]
117pub struct GreatWorkCategory {}
118
119inventory::submit! {
120 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkCategory, GreatWorkCategory::add)
121}
122
123impl GreatWorkCategory {
124 pub fn add(db: &mut Db, key: Token, block: Block) {
125 db.add(Item::GreatWorkCategory, key, block, Box::new(Self {}));
126 }
127}
128
129impl DbKind for GreatWorkCategory {
130 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
131 let mut vd = Validator::new(block, data);
132
133 vd.field_numeric("great_work_prestige");
134
135 vd.field_validated_block("price", |block, data| {
136 let mut vd = Validator::new(block, data);
137 vd.field_numeric("gold");
138 });
139 vd.field_validated_block("material_price", |block, data| {
140 let mut vd = Validator::new(block, data);
141 vd.field_numeric("gold");
142 });
143
144 vd.field_validated_block("great_work_material", |block, data| {
145 let mut vd = Validator::new(block, data);
146 vd.unknown_value_fields(|key, value| {
147 data.verify_exists(Item::GreatWorkMaterial, key);
148 value.expect_number();
149 });
150 });
151
152 vd.field_validated_block("great_work_surface_materials", |block, data| {
153 let mut vd = Validator::new(block, data);
154 vd.unknown_value_fields(|key, value| {
155 data.verify_exists(Item::GreatWorkMaterial, key);
156 value.expect_number();
157 });
158 });
159
160 let choices = &["base", "middle", "top", "pillar", "roof"];
161 vd.field_validated_block("great_work_category_slots", |block, data| {
162 let mut vd = Validator::new(block, data);
163 vd.validated_blocks(|block, data| {
164 let mut vd = Validator::new(block, data);
165 vd.field_choice("key", choices);
166 vd.field_numeric("index");
167 vd.field_item("localization_key", Item::Localization);
168 vd.field_validated_block("attachments", |block, data| {
169 let mut vd = Validator::new(block, data);
170 vd.validated_blocks(|block, data| {
171 let mut vd = Validator::new(block, data);
172 vd.field_choice("key", choices);
173 vd.field_choice(
174 "function",
175 &[
176 "great_work_function_attach_one_and_scale",
177 "great_work_function_attach_multiple",
178 ],
179 );
180 });
181 });
182 });
183 });
184 }
185}
186
187#[derive(Clone, Debug)]
188pub struct GreatWorkMaterial {}
189
190inventory::submit! {
191 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkMaterial, GreatWorkMaterial::add)
192}
193
194impl GreatWorkMaterial {
195 pub fn add(db: &mut Db, key: Token, block: Block) {
196 db.add(Item::GreatWorkMaterial, key, block, Box::new(Self {}));
197 }
198}
199
200impl DbKind for GreatWorkMaterial {
201 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
202 let mut vd = Validator::new(block, data);
203
204 vd.field_value("icon");
205 vd.field_numeric("great_work_prestige");
206 vd.field_item("great_work_trade_good", Item::TradeGood);
207 vd.field_list_numeric_exactly("great_work_uv_offset", 2);
208 }
209}
210
211#[derive(Clone, Debug)]
212pub struct GreatWorkModule {}
213
214inventory::submit! {
215 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkModule, GreatWorkModule::add)
216}
217
218impl GreatWorkModule {
219 pub fn add(db: &mut Db, key: Token, block: Block) {
220 db.add(Item::GreatWorkModule, key, block, Box::new(Self {}));
221 }
222}
223
224impl DbKind for GreatWorkModule {
225 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
226 let mut vd = Validator::new(block, data);
227
228 vd.field_value("icon");
229 vd.field_choice(
230 "great_work_category",
231 &["gw_category_ancient", "pyramid", "tower", "building"],
232 );
233 vd.field_numeric("great_work_category_slot");
234
235 vd.field_validated_list("entity_name", |token, data| {
236 data.verify_exists(Item::Entity, token);
237 });
238
239 vd.field_choice(
240 "great_work_building_type",
241 &[
242 "great_work_building_type_rectangular",
243 "great_work_building_type_square",
244 "great_work_building_type_round",
245 ],
246 );
247
248 vd.field_validated_block("great_work_attachment_data", |block, data| {
249 let mut vd = Validator::new(block, data);
250 vd.field_numeric("locator");
251 vd.field_numeric("min_distance");
252 vd.field_value("locator_min");
253 vd.field_value("locator_max");
254 });
255
256 vd.field_validated_block("great_work_attachments", |block, data| {
257 let mut vd = Validator::new(block, data);
258 vd.validated_blocks(|block, data| {
259 let mut vd = Validator::new(block, data);
260 vd.field_choice(
261 "function",
262 &[
263 "great_work_function_attach_one_and_scale",
264 "great_work_function_attach_multiple",
265 ],
266 );
267 vd.field_validated_block("data", |block, data| {
268 let mut vd = Validator::new(block, data);
269 vd.validated_blocks(|block, data| {
270 let mut vd = Validator::new(block, data);
271 vd.field_value("locator");
272 vd.field_value("locator_min");
273 vd.field_value("locator_max");
274 vd.field_value("attach_multiple_type");
275 vd.field_choice(
276 "attach_multiple_type",
277 &["attach_multiple_round", "attach_multiple_line"],
278 );
279 vd.field_bool("include_min");
280 vd.field_bool("include_max");
281 });
282 });
283 });
284 });
285 }
286}
287
288#[derive(Clone, Debug)]
289pub struct GreatWorkTemplate {}
290
291inventory::submit! {
292 ItemLoader::Normal(GameFlags::Imperator, Item::GreatWorkTemplate, GreatWorkTemplate::add)
293}
294
295impl GreatWorkTemplate {
296 pub fn add(db: &mut Db, key: Token, block: Block) {
297 db.add(Item::GreatWorkTemplate, key, block, Box::new(Self {}));
298 }
299}
300
301impl DbKind for GreatWorkTemplate {
302 fn validate(&self, _key: &Token, block: &Block, data: &Everything) {
303 let mut vd = Validator::new(block, data);
304
305 vd.field_choice(
306 "great_work_category",
307 &["gw_category_ancient", "pyramid", "tower", "building"],
308 );
309 vd.field_value("icon");
310 vd.field_bool("can_build");
311 vd.field_item("localization_key", Item::Localization);
312
313 vd.field_validated_block("great_work_components", |block, data| {
314 let mut vd = Validator::new(block, data);
315 vd.validated_blocks(|block, data| {
316 let mut vd = Validator::new(block, data);
317 vd.field_item("great_work_module", Item::GreatWorkModule);
318 vd.field_item("great_work_material", Item::GreatWorkMaterial);
319 });
320 });
321
322 vd.field_validated_block("great_work_effect_selections", |block, data| {
323 let mut vd = Validator::new(block, data);
324 vd.validated_blocks(|block, data| {
325 let mut vd = Validator::new(block, data);
326 vd.field_item("great_work_effect", Item::GreatWorkEffect);
327 vd.field_item("great_work_effect_tier", Item::GreatWorkEffectTier);
328 });
329 });
330 }
331}