Skip to main content

tiger_lib/vic3/data/
production_methods.rs

1use crate::block::Block;
2use crate::db::{Db, DbKind};
3use crate::everything::Everything;
4use crate::game::GameFlags;
5use crate::item::{Item, ItemLoader};
6use crate::modif::validate_modifs;
7use crate::token::Token;
8use crate::validator::Validator;
9use crate::vic3::modif::ModifKinds;
10use crate::vic3::tables::misc::COMPANY_CATEGORIES;
11
12#[derive(Clone, Debug)]
13pub struct ProductionMethod {}
14
15inventory::submit! {
16    ItemLoader::Normal(GameFlags::Vic3, Item::ProductionMethod, ProductionMethod::add)
17}
18
19impl ProductionMethod {
20    pub fn add(db: &mut Db, key: Token, block: Block) {
21        db.add(Item::ProductionMethod, key, block, Box::new(Self {}));
22    }
23}
24
25impl DbKind for ProductionMethod {
26    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
27        let mut vd = Validator::new(block, data);
28
29        data.verify_exists(Item::Localization, key);
30
31        vd.field_item("texture", Item::File);
32        vd.field_bool("is_default");
33        vd.field_bool("low_pop_method");
34
35        vd.field_validated_block("profession_ratio", |block, data| {
36            let mut vd = Validator::new(block, data);
37            vd.validate_item_key_values(Item::PopType, |_, mut vvd| {
38                vvd.numeric();
39            });
40        });
41
42        vd.field_validated_block("country_modifiers", |block, data| {
43            validate_modifier_block(block, data, ModifKinds::Country);
44        });
45        vd.field_validated_block("state_modifiers", |block, data| {
46            validate_modifier_block(block, data, ModifKinds::State);
47        });
48        vd.field_validated_block("building_modifiers", |block, data| {
49            validate_modifier_block(block, data, ModifKinds::Building);
50        });
51        vd.field_list_items("timed_modifiers", Item::Modifier);
52
53        vd.multi_field_list_items("unlocking_laws", Item::LawType);
54        vd.multi_field_list_items("disallowing_laws", Item::LawType);
55        vd.multi_field_list_items("unlocking_religions", Item::Religion);
56        vd.multi_field_list_items("disallowing_religions", Item::Religion);
57        vd.multi_field_list_items("unlocking_amendments", Item::Amendment);
58        vd.multi_field_list_items("disallowing_amendments", Item::Amendment);
59        vd.multi_field_list_items("unlocking_technologies", Item::Technology);
60        vd.multi_field_list_items("unlocking_production_methods", Item::ProductionMethod);
61        vd.multi_field_list_items("unlocking_global_technologies", Item::Technology);
62        vd.multi_field_list_items("unlocking_principles", Item::Principle);
63        vd.multi_field_item("unlocking_identity", Item::PowerBlocIdentity);
64
65        // TODO: verify ai_weight and ai_value; do both work?
66        // Only ai_value is used in vanilla (once). ai_weight is not used.
67        vd.field_numeric("ai_weight");
68        vd.field_numeric("ai_value");
69        vd.field_numeric("pollution_generation");
70
71        // TODO: comment says "needs to match city_graphics_data.settings color array"
72        vd.field_integer("city_lights_color_index");
73
74        // undocumented
75
76        vd.field_item("replacement_if_valid", Item::ProductionMethod);
77        vd.field_bool("is_hidden_when_unavailable");
78        vd.multi_field_item("required_input_goods", Item::Goods);
79        vd.multi_field_list_choice("unlocking_company_categories", COMPANY_CATEGORIES);
80        vd.multi_field_list_items("unlocking_geographic_regions", Item::GeographicRegion);
81    }
82}
83
84fn validate_modifier_block(block: &Block, data: &Everything, kinds: ModifKinds) {
85    let mut vd = Validator::new(block, data);
86    vd.field_validated_block("workforce_scaled", |block, data| {
87        let vd = Validator::new(block, data);
88        validate_modifs(block, data, kinds, vd);
89    });
90    vd.field_validated_block("level_scaled", |block, data| {
91        let vd = Validator::new(block, data);
92        validate_modifs(block, data, kinds, vd);
93    });
94    vd.field_validated_block("throughput_scaled", |block, data| {
95        let vd = Validator::new(block, data);
96        validate_modifs(block, data, kinds, vd);
97    });
98    vd.field_validated_block("unscaled", |block, data| {
99        let vd = Validator::new(block, data);
100        validate_modifs(block, data, kinds, vd);
101    });
102}
103
104#[derive(Clone, Debug)]
105pub struct ProductionMethodGroup {}
106
107inventory::submit! {
108    ItemLoader::Normal(GameFlags::Vic3, Item::ProductionMethodGroup, ProductionMethodGroup::add)
109}
110
111impl ProductionMethodGroup {
112    pub fn add(db: &mut Db, key: Token, block: Block) {
113        db.add(Item::ProductionMethodGroup, key, block, Box::new(Self {}));
114    }
115
116    #[allow(clippy::unused_self)] // don't want to bake into the API that no self fields are used
117    pub fn contains_production_method(
118        &self,
119        contains_pm: &Token,
120        block: &Block,
121        _data: &Everything,
122    ) -> bool {
123        block.get_multi_field_list("production_methods").iter().any(|pm| pm == contains_pm)
124    }
125}
126
127impl DbKind for ProductionMethodGroup {
128    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
129        let mut vd = Validator::new(block, data);
130
131        data.verify_exists(Item::Localization, key);
132
133        if !key.is("pmg_dummy") {
134            vd.req_field("texture");
135        }
136        vd.field_item("texture", Item::File);
137        vd.field_bool("is_hidden_when_unavailable");
138
139        vd.req_field("production_methods");
140        vd.multi_field_list_items("production_methods", Item::ProductionMethod);
141
142        vd.field_choice("ai_selection", &["most_profitable", "most_productive"]);
143    }
144}