33using namespace OpenVic ;
44using namespace OpenVic ::NodeTools;
55
6- EmployedPop::EmployedPop (
7- PopType const * new_pop_type, bool new_artisan, effect_t new_effect, fixed_point_t new_effect_multiplier,
8- fixed_point_t new_amount
9- ) : pop_type { new_pop_type }, artisan { new_artisan }, effect { new_effect }, effect_multiplier { new_effect_multiplier },
10- amount { new_amount } {}
6+ Job::Job (
7+ PopType const * const new_pop_type, effect_t new_effect_type, fixed_point_t new_effect_multiplier,
8+ fixed_point_t new_desired_workforce_share
9+ )
10+ : pop_type { new_pop_type }, effect_type { new_effect_type }, effect_multiplier { new_effect_multiplier },
11+ desired_workforce_share { new_desired_workforce_share } {}
1112
1213ProductionType::ProductionType (
13- std::string_view new_identifier, EmployedPop new_owner, std::vector<EmployedPop> new_employees, type_t new_type,
14- Pop::pop_size_t new_workforce, Good::good_map_t && new_input_goods, Good const * new_output_goods,
15- fixed_point_t new_value, std::vector<bonus_t >&& new_bonuses, Good::good_map_t && new_efficiency, bool new_coastal,
16- bool new_farm, bool new_mine
17- ) : HasIdentifier { new_identifier }, owner { new_owner }, employees { new_employees }, type { new_type },
18- workforce { new_workforce }, input_goods { std::move (new_input_goods) }, output_goods { new_output_goods },
19- value { new_value }, bonuses { std::move (new_bonuses) }, efficiency { std::move (new_efficiency) },
20- coastal { new_coastal }, farm { new_farm }, mine { new_mine } {}
14+ std::string_view new_identifier, Job new_owner, std::vector<Job> new_jobs, template_type_t new_template_type,
15+ Pop::pop_size_t new_base_workforce_size, Good::good_map_t && new_input_goods, Good const * const new_output_goods,
16+ fixed_point_t new_base_output_quantity, std::vector<bonus_t >&& new_bonuses, Good::good_map_t && new_efficiency,
17+ bool new_is_coastal, bool new_is_farm, bool new_is_mine
18+ )
19+ : HasIdentifier { new_identifier }, owner { new_owner }, jobs { new_jobs }, template_type { new_template_type },
20+ base_workforce_size { new_base_workforce_size }, input_goods { std::move (new_input_goods) },
21+ output_goods { new_output_goods }, base_output_quantity { new_base_output_quantity }, bonuses { std::move (new_bonuses) },
22+ maintenance_requirements { std::move (new_efficiency) }, coastal { new_is_coastal }, farm { new_is_farm },
23+ mine { new_is_mine } {}
2124
2225bool ProductionType::parse_scripts (GameManager const & game_manager) {
2326 bool ret = true ;
@@ -29,96 +32,98 @@ bool ProductionType::parse_scripts(GameManager const& game_manager) {
2932
3033ProductionTypeManager::ProductionTypeManager () : rgo_owner_sprite { 0 } {}
3134
32- node_callback_t ProductionTypeManager::_expect_employed_pop (
33- GoodManager const & good_manager, PopManager const & pop_manager, callback_t <EmployedPop &&> cb
35+ node_callback_t ProductionTypeManager::_expect_job (
36+ GoodManager const & good_manager, PopManager const & pop_manager, callback_t <Job &&> cb
3437) {
3538
3639 return [this , &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
37- std::string_view pop_type;
38- EmployedPop::effect_t effect;
39- fixed_point_t effect_multiplier = 1 , amount = 1 ;
40+ using enum Job::effect_t ;
4041
41- using enum EmployedPop::effect_t ;
42- static const string_map_t <EmployedPop::effect_t > effect_map = {
42+ std::string_view pop_type {};
43+ Job::effect_t effect_type {THROUGHPUT};
44+ fixed_point_t effect_multiplier = 1 , desired_workforce_share = 1 ;
45+
46+ static const string_map_t <Job::effect_t > effect_map = {
4347 { " input" , INPUT }, { " output" , OUTPUT }, { " throughput" , THROUGHPUT }
4448 };
4549
4650 bool res = expect_dictionary_keys (
4751 " poptype" , ONE_EXACTLY, expect_identifier (assign_variable_callback (pop_type)),
48- " effect" , ONE_EXACTLY, expect_identifier (expect_mapped_string (effect_map, assign_variable_callback (effect ))),
52+ " effect" , ONE_EXACTLY, expect_identifier (expect_mapped_string (effect_map, assign_variable_callback (effect_type ))),
4953 " effect_multiplier" , ZERO_OR_ONE, expect_fixed_point (assign_variable_callback (effect_multiplier)),
50- " amount" , ZERO_OR_ONE, expect_fixed_point (assign_variable_callback (amount ))
54+ " amount" , ZERO_OR_ONE, expect_fixed_point (assign_variable_callback (desired_workforce_share ))
5155 )(node);
5256
53- const PopType* found_pop_type = pop_manager.get_pop_type_by_identifier (pop_type);
54- bool artisan = false ;
55- if (found_pop_type == nullptr ) {
56- if (pop_type == " artisan" ) {
57- artisan = true ;
58- } else {
59- Logger::error (" Found invalid pop type " , pop_type, " while parsing production types!" );
60- return false ;
61- }
62- }
63-
64- return res & cb ({ found_pop_type, artisan, effect, effect_multiplier, amount });
57+ PopType const * const found_pop_type = pop_manager.get_pop_type_by_identifier (pop_type);
58+ return res & cb ({ found_pop_type, effect_type, effect_multiplier, desired_workforce_share });
6559 };
6660}
6761
68- node_callback_t ProductionTypeManager::_expect_employed_pop_list (
69- GoodManager const & good_manager, PopManager const & pop_manager, callback_t <std::vector<EmployedPop >&&> cb
62+ node_callback_t ProductionTypeManager::_expect_job_list (
63+ GoodManager const & good_manager, PopManager const & pop_manager, callback_t <std::vector<Job >&&> cb
7064) {
7165 return [this , &good_manager, &pop_manager, cb](ast::NodeCPtr node) -> bool {
72- std::vector<EmployedPop> employed_pops ;
73- bool ret = expect_list (_expect_employed_pop (good_manager, pop_manager, vector_callback (employed_pops )))(node);
74- ret &= cb (std::move (employed_pops ));
66+ std::vector<Job> jobs ;
67+ bool ret = expect_list (_expect_job (good_manager, pop_manager, vector_callback (jobs )))(node);
68+ ret &= cb (std::move (jobs ));
7569 return ret;
7670 };
7771}
7872
79- #define POPTYPE_CHECK (employed_pop ) \
80- if ((employed_pop.pop_type == nullptr && !employed_pop.artisan) || \
81- (employed_pop.pop_type != nullptr && employed_pop.artisan)) { \
82- Logger::error (" Invalid pop type parsed for owner of production type " , identifier, " !" ); \
83- return false ; \
84- }
85-
8673bool ProductionTypeManager::add_production_type (
87- std::string_view identifier, EmployedPop owner, std::vector<EmployedPop> employees, ProductionType::type_t type,
88- Pop::pop_size_t workforce, Good::good_map_t && input_goods, Good const * output_goods, fixed_point_t value,
89- std::vector<ProductionType::bonus_t >&& bonuses, Good::good_map_t && efficiency, bool coastal, bool farm, bool mine
74+ std::string_view identifier, Job owner, std::vector<Job> jobs, ProductionType::template_type_t template_type,
75+ Pop::pop_size_t base_workforce_size, Good::good_map_t && input_goods, Good const * const output_goods,
76+ fixed_point_t base_output_quantity, std::vector<ProductionType::bonus_t >&& bonuses,
77+ Good::good_map_t && maintenance_requirements, bool is_coastal, bool is_farm, bool is_mine
9078) {
9179 if (identifier.empty ()) {
9280 Logger::error (" Invalid production type identifier - empty!" );
9381 return false ;
9482 }
9583
96- if (workforce <= 0 ) {
97- Logger::error (" Workforce for production type " , identifier, " was 0 or unset!" );
84+ if (base_workforce_size <= 0 ) {
85+ Logger::error (" Base workforce size ('workforce') for production type " , identifier, " was 0 or unset!" );
9886 return false ;
9987 }
10088
101- if (value <= 0 ) {
102- Logger::error (" Value for production type " , identifier, " was 0 or unset!" );
89+ if (base_output_quantity <= 0 ) {
90+ Logger::error (" Base output quantity ('value') for production type " , identifier, " was 0 or unset!" );
10391 return false ;
10492 }
10593
106- POPTYPE_CHECK (owner)
107-
108- for (EmployedPop const & ep : employees) {
109- POPTYPE_CHECK (ep)
110- }
111-
11294 if (output_goods == nullptr ) {
11395 Logger::error (" Output good for production type " , identifier, " was null!" );
11496 return false ;
11597 }
11698
99+ if (template_type == ProductionType::template_type_t ::ARTISAN) {
100+ if (owner.get_pop_type () != nullptr || !jobs.empty ()) {
101+ Logger::warning (" Artisanal production types don't use owner and employees. Effects are ignored." );
102+ }
103+ } else {
104+ if (owner.get_pop_type () == nullptr ) {
105+ Logger::error (" Production type " , identifier, " lacks owner or has an invalid pop type." );
106+ return false ;
107+ }
108+
109+ if (jobs.empty ()) {
110+ Logger::error (" Production type " , identifier, " lacks jobs ('employees')." );
111+ return false ;
112+ }
113+
114+ for (size_t i = 0 ; i < jobs.size (); i++) {
115+ if (jobs[i].get_pop_type () == nullptr ) {
116+ Logger::error (" Production type " , identifier, " has invalid pop type in employees[" , i, " ]." );
117+ return false ;
118+ }
119+ }
120+ }
121+
117122 const bool ret = production_types.add_item ({
118- identifier, owner, employees, type, workforce , std::move (input_goods),
119- output_goods, value , std::move (bonuses), std::move (efficiency ), coastal, farm, mine
123+ identifier, owner, jobs, template_type, base_workforce_size , std::move (input_goods),
124+ output_goods, base_output_quantity , std::move (bonuses), std::move (maintenance_requirements ), is_coastal, is_farm, is_mine
120125 });
121- if (rgo_owner_sprite <= 0 && ret && type == ProductionType::type_t ::RGO && owner.get_pop_type () != nullptr ) {
126+ if (rgo_owner_sprite <= 0 && ret && template_type == ProductionType::template_type_t ::RGO && owner.get_pop_type () != nullptr ) {
122127 /* Set rgo owner sprite to that of the first RGO owner we find. */
123128 rgo_owner_sprite = owner.get_pop_type ()->get_sprite ();
124129 }
@@ -171,50 +176,51 @@ bool ProductionTypeManager::load_production_types_file(
171176 ret &= expect_dictionary (
172177 [this , &good_manager, &pop_manager, &template_target_map, &template_node_map](
173178 std::string_view key, ast::NodeCPtr node) -> bool {
179+ using enum ProductionType::template_type_t ;
180+
174181 if (template_node_map.contains (key)) {
175182 return true ;
176183 }
177184
178- EmployedPop owner;
179- std::vector<EmployedPop> employees ;
180- ProductionType::type_t type ;
185+ Job owner {} ;
186+ std::vector<Job> jobs ;
187+ ProductionType::template_type_t template_type { FACTORY } ;
181188 Good const * output_goods = nullptr ;
182- Pop::pop_size_t workforce = 0 ; // 0 is a meaningless value -> unset
183- Good::good_map_t input_goods, efficiency ;
184- fixed_point_t value = 0 ; // 0 is a meaningless value -> unset
189+ Pop::pop_size_t base_workforce_size = 0 ; // 0 is a meaningless value -> unset
190+ Good::good_map_t input_goods, maintenance_requirements ;
191+ fixed_point_t base_output_quantity = 0 ; // 0 is a meaningless value -> unset
185192 std::vector<ProductionType::bonus_t > bonuses;
186- bool coastal = false , farm = false , mine = false ;
193+ bool is_coastal = false , is_farm = false , is_mine = false ;
187194
188195 bool ret = true ;
189196
190- using enum ProductionType::type_t ;
191- static const string_map_t <ProductionType::type_t > type_map = {
197+ static const string_map_t <ProductionType::template_type_t > template_type_map = {
192198 { " factory" , FACTORY }, { " rgo" , RGO }, { " artisan" , ARTISAN }
193199 };
194200
195201 const node_callback_t parse_node = expect_dictionary_keys (
196202 " template" , ZERO_OR_ONE, success_callback,
197203 " bonus" , ZERO_OR_MORE, [&bonuses](ast::NodeCPtr bonus_node) -> bool {
198204 ConditionScript trigger { scope_t ::STATE, scope_t ::NO_SCOPE, scope_t ::NO_SCOPE };
199- fixed_point_t value {};
205+ fixed_point_t bonus_value {};
200206 const bool ret = expect_dictionary_keys (
201207 " trigger" , ONE_EXACTLY, trigger.expect_script (),
202- " value" , ONE_EXACTLY, expect_fixed_point (assign_variable_callback (value ))
208+ " value" , ONE_EXACTLY, expect_fixed_point (assign_variable_callback (bonus_value ))
203209 )(bonus_node);
204- bonuses.emplace_back (std::move (trigger), value );
210+ bonuses.emplace_back (std::move (trigger), bonus_value );
205211 return ret;
206212 },
207- " owner" , ZERO_OR_ONE, _expect_employed_pop (good_manager, pop_manager, move_variable_callback (owner)),
208- " employees" , ZERO_OR_ONE, _expect_employed_pop_list (good_manager, pop_manager, move_variable_callback (employees )),
209- " type" , ZERO_OR_ONE, expect_identifier (expect_mapped_string (type_map , assign_variable_callback (type ))),
210- " workforce" , ZERO_OR_ONE, expect_uint (assign_variable_callback (workforce )),
213+ " owner" , ZERO_OR_ONE, _expect_job (good_manager, pop_manager, move_variable_callback (owner)),
214+ " employees" , ZERO_OR_ONE, _expect_job_list (good_manager, pop_manager, move_variable_callback (jobs )),
215+ " type" , ZERO_OR_ONE, expect_identifier (expect_mapped_string (template_type_map , assign_variable_callback (template_type ))),
216+ " workforce" , ZERO_OR_ONE, expect_uint (assign_variable_callback (base_workforce_size )),
211217 " input_goods" , ZERO_OR_ONE, good_manager.expect_good_decimal_map (move_variable_callback (input_goods)),
212218 " output_goods" , ZERO_OR_ONE, good_manager.expect_good_identifier (assign_variable_callback_pointer (output_goods)),
213- " value" , ZERO_OR_ONE, expect_fixed_point (assign_variable_callback (value )),
214- " efficiency" , ZERO_OR_ONE, good_manager.expect_good_decimal_map (move_variable_callback (efficiency )),
215- " is_coastal" , ZERO_OR_ONE, expect_bool (assign_variable_callback (coastal )),
216- " farm" , ZERO_OR_ONE, expect_bool (assign_variable_callback (farm )),
217- " mine" , ZERO_OR_ONE, expect_bool (assign_variable_callback (mine ))
219+ " value" , ZERO_OR_ONE, expect_fixed_point (assign_variable_callback (base_output_quantity )),
220+ " efficiency" , ZERO_OR_ONE, good_manager.expect_good_decimal_map (move_variable_callback (maintenance_requirements )),
221+ " is_coastal" , ZERO_OR_ONE, expect_bool (assign_variable_callback (is_coastal )),
222+ " farm" , ZERO_OR_ONE, expect_bool (assign_variable_callback (is_farm )),
223+ " mine" , ZERO_OR_ONE, expect_bool (assign_variable_callback (is_mine ))
218224 );
219225
220226 // apply template first
@@ -235,8 +241,8 @@ bool ProductionTypeManager::load_production_types_file(
235241 ret &= parse_node (node);
236242
237243 ret &= add_production_type (
238- key, owner, employees, type, workforce , std::move (input_goods), output_goods, value , std::move (bonuses),
239- std::move (efficiency ), coastal, farm, mine
244+ key, owner, jobs, template_type, base_workforce_size , std::move (input_goods), output_goods, base_output_quantity , std::move (bonuses),
245+ std::move (maintenance_requirements ), is_coastal, is_farm, is_mine
240246 );
241247 return ret;
242248 }
0 commit comments