tiger_lib/vic3/data/
lobbies.rs

1use crate::block::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::report::{ErrorKey, warn};
8use crate::scopes::Scopes;
9use crate::token::Token;
10use crate::tooltipped::Tooltipped;
11use crate::validate::validate_duration;
12use crate::validator::Validator;
13
14#[derive(Clone, Debug)]
15pub struct PoliticalLobby {}
16
17inventory::submit! {
18    ItemLoader::Normal(GameFlags::Vic3, Item::PoliticalLobby, PoliticalLobby::add)
19}
20
21impl PoliticalLobby {
22    pub fn add(db: &mut Db, key: Token, block: Block) {
23        db.add(Item::PoliticalLobby, key, block, Box::new(Self {}));
24    }
25}
26
27impl DbKind for PoliticalLobby {
28    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
29        fn sc_no_lobby(key: &Token) -> ScopeContext {
30            let mut sc = ScopeContext::new(Scopes::InterestGroup, key);
31            // sc.define_name("country", Scopes::Country, key); // Docs lie about this scope existing (1.9.6)
32            sc.define_name("target_country", Scopes::Country, key);
33            sc
34        }
35
36        fn sc_with_lobby(key: &Token) -> ScopeContext {
37            let mut sc = ScopeContext::new(Scopes::Country, key);
38            sc.define_name("target_country", Scopes::Country, key);
39            sc.define_name("political_lobby", Scopes::PoliticalLobby, key);
40            sc
41        }
42
43        // requirement_to_maintain is documented as having interest group scope,
44        // but it's actually country.
45        fn sc_rtm(key: &Token) -> ScopeContext {
46            let mut sc = ScopeContext::new(Scopes::Country, key);
47            sc.define_name("target_country", Scopes::Country, key);
48            sc.define_name("political_lobby", Scopes::PoliticalLobby, key);
49            sc
50        }
51
52        fn sc_jw(key: &Token) -> ScopeContext {
53            let mut sc = ScopeContext::new(Scopes::InterestGroup, key);
54            sc.define_name("country", Scopes::Country, key);
55            sc.define_name("target_country", Scopes::Country, key);
56            sc.define_name("political_lobby", Scopes::PoliticalLobby, key);
57            sc
58        }
59
60        let mut vd = Validator::new(block, data);
61
62        data.verify_exists(Item::Localization, key);
63        let loca = format!("{key}_name");
64        data.verify_exists_implied(Item::Localization, &loca, key);
65        let loca = format!("{key}_icon");
66        data.verify_exists_implied(Item::Localization, &loca, key);
67
68        vd.field_choice("category", &["foreign_pro_country", "foreign_anti_country", "foreign"]);
69        vd.field_item("texture", Item::File);
70
71        vd.field_trigger_builder("can_create", Tooltipped::No, sc_no_lobby);
72        vd.field_effect_builder("on_created", Tooltipped::No, sc_with_lobby);
73
74        vd.multi_field_validated_block("requirement_to_maintain", |block, data| {
75            let mut vd = Validator::new(block, data);
76            vd.field_trigger_builder("trigger", Tooltipped::No, sc_rtm);
77            vd.field_effect_builder("on_failed", Tooltipped::No, sc_rtm);
78            vd.field_item("swap_type_on_failed", Item::PoliticalLobby);
79        });
80
81        let appeasement_factors_validation = |value: &Token, data: &Everything| {
82            data.verify_exists(Item::PoliticalLobbyAppeasement, value);
83            if data.item_has_property(
84                Item::PoliticalLobbyAppeasement,
85                value.as_str(),
86                "is_always_usable",
87            ) {
88                let msg = "cannot contain appeasement factors marked as `is_always_usable`";
89                warn(ErrorKey::Validation).msg(msg).loc(value).push();
90            }
91        };
92
93        vd.field_validated_list("appeasement_factors_pro", appeasement_factors_validation);
94        vd.field_validated_list("appeasement_factors_anti", appeasement_factors_validation);
95
96        vd.field_trigger_builder("available_for_interest_group", Tooltipped::No, sc_no_lobby);
97
98        vd.field_script_value_no_breakdown_builder("join_weight", sc_jw);
99    }
100}
101
102#[derive(Clone, Debug)]
103pub struct PoliticalLobbyAppeasement {}
104
105inventory::submit! {
106    ItemLoader::Normal(GameFlags::Vic3, Item::PoliticalLobbyAppeasement, PoliticalLobbyAppeasement::add)
107}
108
109impl PoliticalLobbyAppeasement {
110    pub fn add(db: &mut Db, key: Token, block: Block) {
111        db.add(Item::PoliticalLobbyAppeasement, key, block, Box::new(Self {}));
112    }
113}
114
115impl DbKind for PoliticalLobbyAppeasement {
116    fn validate(&self, key: &Token, block: &Block, data: &Everything) {
117        let mut vd = Validator::new(block, data);
118
119        data.verify_exists(Item::Localization, key);
120        let loca = format!("{key}_desc");
121        data.verify_exists_implied(Item::Localization, &loca, key);
122
123        // TODO: verify if script values are allowed in these durations at all
124        let mut sc = ScopeContext::new(Scopes::PoliticalLobby, key);
125
126        vd.field_validated_block_sc("duration_to_show", &mut sc, validate_duration);
127        vd.field_bool("is_always_usable");
128    }
129
130    fn has_property(
131        &self,
132        _key: &Token,
133        block: &Block,
134        property: &str,
135        _data: &Everything,
136    ) -> bool {
137        block.get_field_bool(property).unwrap_or_default()
138    }
139}