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_technologies", Item::Technology);
58        vd.multi_field_list_items("unlocking_production_methods", Item::ProductionMethod);
59        vd.multi_field_list_items("unlocking_global_technologies", Item::Technology);
60        vd.multi_field_list_items("unlocking_principles", Item::Principle);
61        vd.multi_field_item("unlocking_identity", Item::PowerBlocIdentity);
62
63        // TODO: verify ai_weight and ai_value; do both work?
64        // Only ai_value is used in vanilla (once). ai_weight is not used.
65        vd.field_numeric("ai_weight");
66        vd.field_numeric("ai_value");
67        vd.field_numeric("pollution_generation");
68
69        // TODO: comment says "needs to match city_graphics_data.settings color array"
70        vd.field_integer("city_lights_color_index");
71
72        // undocumented
73
74        vd.field_item("replacement_if_valid", Item::ProductionMethod);
75        vd.field_bool("is_hidden_when_unavailable");
76        vd.multi_field_item("required_input_goods", Item::Goods);
77        vd.multi_field_list_choice("unlocking_company_categories", COMPANY_CATEGORIES);
78        vd.multi_field_list_items("unlocking_geographic_regions", Item::GeographicRegion);
79    }
80}
81
82fn validate_modifier_block(block: &Block, data: &Everything, kinds: ModifKinds) {
83    let mut vd = Validator::new(block, data);
84    vd.field_validated_block("workforce_scaled", |block, data| {
85        let vd = Validator::new(block, data);
86        validate_modifs(block, data, kinds, vd);
87    });
88    vd.field_validated_block("level_scaled", |block, data| {
89        let vd = Validator::new(block, data);
90        validate_modifs(block, data, kinds, vd);
91    });
92    vd.field_validated_block("throughput_scaled", |block, data| {
93        let vd = Validator::new(block, data);
94        validate_modifs(block, data, kinds, vd);
95    });
96    vd.field_validated_block("unscaled", |block, data| {
97        let vd = Validator::new(block, data);
98        validate_modifs(block, data, kinds, vd);
99    });
100}
101
102#[derive(Clone, Debug)]
103pub struct ProductionMethodGroup {}
104
105inventory::submit! {
106    ItemLoader::Normal(GameFlags::Vic3, Item::ProductionMethodGroup, ProductionMethodGroup::add)
107}
108
109impl ProductionMethodGroup {
110    pub fn add(db: &mut Db, key: Token, block: Block) {
111        db.add(Item::ProductionMethodGroup, key, block, Box::new(Self {}));
112    }
113
114    #[allow(clippy::unused_self)] // don't want to bake into the API that no self fields are used
115    pub fn contains_production_method(
116        &self,
117        contains_pm: &Token,
118        block: &Block,
119        _data: &Everything,
120    ) -> bool {
121        block.get_multi_field_list("production_methods").iter().any(|pm| pm == contains_pm)
122    }
123}
124
125impl DbKind for ProductionMethodGroup {
126    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
127        let mut vd = Validator::new(block, data);
128
129        data.verify_exists(Item::Localization, key);
130
131        if !key.is("pmg_dummy") {
132            vd.req_field("texture");
133        }
134        vd.field_item("texture", Item::File);
135        vd.field_bool("is_hidden_when_unavailable");
136
137        vd.req_field("production_methods");
138        vd.multi_field_list_items("production_methods", Item::ProductionMethod);
139
140        vd.field_choice("ai_selection", &["most_profitable", "most_productive"]);
141    }
142}