diff --git a/src/economy/economy_government.cpp b/src/economy/economy_government.cpp index 8f3b09107..ff4576d14 100644 --- a/src/economy/economy_government.cpp +++ b/src/economy/economy_government.cpp @@ -22,7 +22,15 @@ namespace economy { // // employed people in administration influence the maximum amount of taxes the nation can collect +// to avoid death traps +inline constexpr float base_tax_collection_capacity = 5000.f; + inline constexpr float base_population_per_admin = 50.f; + +float population_per_admin(sys::state& state, dcon::nation_id n) { + return base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); +} + inline constexpr float base_admin_employment = 500.f; inline constexpr float base_tax_collection = 10000.f; @@ -31,10 +39,16 @@ inline constexpr float base_tax_collection = 10000.f; inline constexpr float tax_collection_multiplier = 10.f; +float required_labour_in_capital_administration(sys::state& state, dcon::nation_id n) { + auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); + auto total_population = state.world.nation_get_demographics(n, demographics::total); + return total_population / admin_efficiency + base_admin_employment; +} + float tax_collection_capacity(sys::state& state, dcon::nation_id n, dcon::state_instance_id sid) { auto local_market = state.world.state_instance_get_market_from_local_market(sid); auto tax_collection_global = 1.f + global_admin_ratio(state, n); - auto local_tax_collectors = state.world.nation_get_administration_employment_target_in_capital(n) + auto local_tax_collectors = state.world.market_get_administration_employment_target(local_market) * state.world.market_get_labor_demand_satisfaction(local_market, economy::labor::high_education); auto collection_rate_per_tax_collector = @@ -48,6 +62,9 @@ float tax_collection_capacity(sys::state& state, dcon::nation_id n, dcon::state_ + float(state.world.nation_get_rich_tax(n)); return + base_tax_collection_capacity + * collection_rate_per_tax_collector + + tax_collection_global * (1.f + state.world.nation_get_administrative_efficiency(n)) * nations::tax_efficiency(state, n) @@ -62,14 +79,7 @@ float global_admin_ratio(sys::state& state, dcon::nation_id n) { auto capital_state = state.world.province_get_state_membership(capital); auto capital_market = state.world.state_instance_get_market_from_local_market(capital_state); - auto total_budget = std::max(0.f, state.world.nation_get_stockpiles(n, economy::money)); - auto admin_budget = total_budget * state.world.nation_get_spending_level(n) * float(state.world.nation_get_administrative_spending(n)) / 100.f; - - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - - auto total_population = state.world.nation_get_demographics(n, demographics::total); - auto required_labor_capital = total_population / admin_efficiency + base_admin_employment; - + auto required_labor_capital = required_labour_in_capital_administration(state, n); auto current_labor_capital = state.world.nation_get_administration_employment_target_in_capital(n) * state.world.market_get_labor_demand_satisfaction(capital_market, economy::labor::high_education_and_accepted); @@ -79,33 +89,23 @@ float global_admin_ratio(sys::state& state, dcon::nation_id n) { float local_admin_ratio(sys::state& state, dcon::nation_id n, dcon::state_instance_id sid) { auto local_market = state.world.state_instance_get_market_from_local_market(sid); - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - auto local_population = state.world.state_instance_get_demographics(sid, demographics::total); - float required_labor_local = local_population / admin_efficiency; + float required_labor_local = local_population / population_per_admin(state, n); auto current_labor_local = - state.world.nation_get_administration_employment_target_in_capital(n) + state.world.market_get_administration_employment_target(local_market) * state.world.market_get_labor_demand_satisfaction(local_market, economy::labor::high_education); return current_labor_local / required_labor_local; } -float required_labour_in_capital_administration(sys::state& state, dcon::nation_id n, float budget_priority) { - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - auto total_population = state.world.nation_get_demographics(n, demographics::total); - return total_population / admin_efficiency; -} - float estimate_spendings_administration_capital(sys::state& state, dcon::nation_id n, float budget_priority) { auto total_budget = std::max(0.f, state.world.nation_get_stockpiles(n, economy::money)); auto admin_budget = total_budget * budget_priority; auto capital = state.world.nation_get_capital(n); auto capital_state = state.world.province_get_state_membership(capital); auto capital_market = state.world.state_instance_get_market_from_local_market(capital_state); - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - auto total_population = state.world.nation_get_demographics(n, demographics::total); - auto required_labor_capital = total_population / admin_efficiency + base_admin_employment; + auto required_labor_capital = required_labour_in_capital_administration(state, n); auto labor_price_capital = state.world.market_get_labor_price(capital_market, economy::labor::high_education_and_accepted); float required_budget = required_labor_capital * labor_price_capital * state.world.market_get_labor_demand_satisfaction(capital_market, labor::high_education_and_accepted); @@ -114,11 +114,8 @@ float estimate_spendings_administration_capital(sys::state& state, dcon::nation_ float estimate_spendings_administration_state(sys::state& state, dcon::nation_id n, dcon::state_instance_id sid, float budget_priority) { auto local_market = state.world.state_instance_get_market_from_local_market(sid); - - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - auto local_population = state.world.state_instance_get_demographics(sid, demographics::total); - float required_labor_local = local_population / admin_efficiency; + float required_labor_local = local_population / population_per_admin(state, n); float labor_price_local = state.world.market_get_labor_price(local_market, economy::labor::high_education); return @@ -128,31 +125,12 @@ float estimate_spendings_administration_state(sys::state& state, dcon::nation_id } float estimate_spendings_administration(sys::state& state, dcon::nation_id n, float budget_priority) { - auto capital = state.world.nation_get_capital(n); - auto capital_state = state.world.province_get_state_membership(capital); - auto capital_market = state.world.state_instance_get_market_from_local_market(capital_state); - auto total_budget = std::max(0.f, state.world.nation_get_stockpiles(n, economy::money)); auto admin_budget = total_budget * budget_priority; - - auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - - auto total_population = state.world.nation_get_demographics(n, demographics::total); - auto required_labor_capital = total_population / admin_efficiency + base_admin_employment; - auto labor_price_capital = state.world.market_get_labor_price(capital_market, economy::labor::high_education_and_accepted); - float required_budget = required_labor_capital * labor_price_capital * state.world.market_get_labor_demand_satisfaction(capital_market, labor::high_education_and_accepted); - + float required_budget = estimate_spendings_administration_capital(state, n, budget_priority); state.world.nation_for_each_state_ownership(n, [&](auto soid) { - auto local_state = state.world.state_ownership_get_state(soid); - auto local_market = state.world.state_instance_get_market_from_local_market(local_state); - - auto local_population = state.world.state_instance_get_demographics(local_state, demographics::total); - - float required_labor_local = local_population / admin_efficiency; - float labor_price_local = state.world.market_get_labor_price(local_market, economy::labor::high_education); - required_budget += required_labor_local * labor_price_local * state.world.market_get_labor_demand_satisfaction(local_market, labor::high_education); + required_budget += estimate_spendings_administration_state(state, n, state.world.state_ownership_get_state(soid), budget_priority); }); - return std::min(required_budget, admin_budget); } @@ -165,19 +143,17 @@ float full_spendings_administration(sys::state& state, dcon::nation_id n) { auto total_budget = std::max(0.f, state.world.nation_get_stockpiles(n, economy::money)); auto admin_budget = total_budget * float(state.world.nation_get_administrative_spending(n)) / 100.f; - auto labor_in_capital = + total_cost += state.world.nation_get_administration_employment_target_in_capital(n) - * state.world.market_get_labor_demand_satisfaction(capital_market, economy::labor::high_education_and_accepted); - - total_cost += labor_in_capital * state.world.market_get_labor_price(capital_market, economy::labor::high_education_and_accepted); + * state.world.market_get_labor_demand_satisfaction(capital_market, economy::labor::high_education_and_accepted) + * state.world.market_get_labor_price(capital_market, economy::labor::high_education_and_accepted); state.world.nation_for_each_state_ownership(n, [&](auto soid) { auto local_state = state.world.state_ownership_get_state(soid); auto local_market = state.world.state_instance_get_market_from_local_market(local_state); - float target = state.world.market_get_administration_employment_target(local_market); total_cost += - target + state.world.market_get_administration_employment_target(local_market) * state.world.market_get_labor_demand_satisfaction(local_market, labor::high_education) * state.world.market_get_labor_price(local_market, labor::high_education); }); @@ -197,8 +173,7 @@ void update_consumption_administration(sys::state& state, dcon::nation_id n) { auto admin_efficiency = base_population_per_admin * (1.f + state.world.nation_get_administrative_efficiency(n)); - auto total_population = state.world.nation_get_demographics(n, demographics::total); - auto required_labor_capital = total_population / admin_efficiency + base_admin_employment; + auto required_labor_capital = required_labour_in_capital_administration(state, n); auto labor_price_capital = state.world.market_get_labor_price(capital_market, economy::labor::high_education_and_accepted); auto effective_demand = std::min(required_labor_capital, admin_budget / labor_price_capital); @@ -247,8 +222,6 @@ void update_consumption_administration(sys::state& state, dcon::nation_id n) { } void collect_taxes(sys::state& state, dcon::nation_id n) { - auto const tax_eff = nations::tax_efficiency(state, n); - float total_poor_tax_base = 0.0f; float total_mid_tax_base = 0.0f; float total_rich_tax_base = 0.0f; @@ -263,6 +236,10 @@ void collect_taxes(sys::state& state, dcon::nation_id n) { float potential_tax_rich = 0.f; province::for_each_province_in_state_instance(state, s, [&](auto province) { + float province_potential_tax_poor = 0.f; + float province_potential_tax_mid = 0.f; + float province_potential_tax_rich = 0.f; + if( state.world.province_get_nation_from_province_ownership(province) == @@ -272,15 +249,23 @@ void collect_taxes(sys::state& state, dcon::nation_id n) { auto& pop_money = pl.get_pop().get_savings(); auto strata = culture::pop_strata(pl.get_pop().get_poptype().get_strata()); if(strata == culture::pop_strata::poor) { - potential_tax_poor += pop_money; + province_potential_tax_poor += pop_money; } else if(strata == culture::pop_strata::middle) { - potential_tax_mid += pop_money; + province_potential_tax_mid += pop_money; } else if(strata == culture::pop_strata::rich) { - potential_tax_rich += pop_money; + province_potential_tax_rich += pop_money; } assert(std::isfinite(pl.get_pop().get_savings())); } } + + state.world.province_set_tax_base_poor(province, province_potential_tax_poor); + state.world.province_set_tax_base_middle(province, province_potential_tax_mid); + state.world.province_set_tax_base_rich(province, province_potential_tax_rich); + + potential_tax_poor += province_potential_tax_poor; + potential_tax_mid += province_potential_tax_mid; + potential_tax_rich += province_potential_tax_rich; }); total_poor_tax_base += potential_tax_poor; @@ -288,19 +273,18 @@ void collect_taxes(sys::state& state, dcon::nation_id n) { total_rich_tax_base += potential_tax_rich; - float local_target_tax = std::min( - potential_tax_poor * float(state.world.nation_get_poor_tax(n)) / 100.f + auto local_tax = potential_tax_poor * float(state.world.nation_get_poor_tax(n)) / 100.f + potential_tax_mid * float(state.world.nation_get_middle_tax(n)) / 100.0f - + potential_tax_rich * float(state.world.nation_get_rich_tax(n)) / 100.0f, - max_tax_capacity - ); + + potential_tax_rich * float(state.world.nation_get_rich_tax(n)) / 100.0f; + auto total_possible = std::min(local_tax, max_tax_capacity); - auto collected_ratio = 1.f; - if(local_target_tax > 0.f) { - collected_ratio = std::min(local_target_tax, max_tax_capacity) / local_target_tax; + + auto collected_ratio = 0.f; + if(total_possible > 0.f) { + collected_ratio = total_possible / local_tax; } - collected_tax += std::min(local_target_tax, max_tax_capacity); + collected_tax += local_tax * collected_ratio; // apply actual tax @@ -350,44 +334,24 @@ void collect_taxes(sys::state& state, dcon::nation_id n) { tax_information explain_tax_income_local(sys::state& state, dcon::nation_id n, dcon::state_instance_id s) { tax_information result{ }; - result.capacity = tax_collection_capacity(state, n, s); - province::for_each_province_in_state_instance(state, s, [&](auto province) { - if( - state.world.province_get_nation_from_province_ownership(province) - == - state.world.province_get_nation_from_province_control(province) - ) { - for(auto pl : state.world.province_get_pop_location(province)) { - auto& pop_money = pl.get_pop().get_savings(); - auto strata = culture::pop_strata(pl.get_pop().get_poptype().get_strata()); - if(strata == culture::pop_strata::poor) { - result.poor_potential += pop_money; - } else if(strata == culture::pop_strata::middle) { - result.mid_potential += pop_money; - } else if(strata == culture::pop_strata::rich) { - result.rich_potential += pop_money; - } - assert(std::isfinite(pl.get_pop().get_savings())); - } - } + result.poor_potential += state.world.province_get_tax_base_poor(province); + result.mid_potential += state.world.province_get_tax_base_middle(province); + result.rich_potential += state.world.province_get_tax_base_rich(province); }); - result.poor = result.poor_potential * float(state.world.nation_get_poor_tax(n)) / 100.f; result.mid = result.mid_potential * float(state.world.nation_get_middle_tax(n)) / 100.0f; result.rich = result.rich_potential * float(state.world.nation_get_rich_tax(n)) / 100.0f; auto total = result.poor + result.mid + result.rich; - - auto collected_ratio = 1.f; - if(total > 0.f) { - collected_ratio = std::min(total, result.capacity) / total; + auto total_possible = std::min(total, result.capacity); + auto collected_ratio = 0.f; + if(total_possible > 0.f) { + collected_ratio = total_possible / total; } - result.poor *= collected_ratio; result.mid *= collected_ratio; result.rich *= collected_ratio; - return result; } diff --git a/src/gamestate/dcon_generated.txt b/src/gamestate/dcon_generated.txt index af458f681..dbb4959af 100644 --- a/src/gamestate/dcon_generated.txt +++ b/src/gamestate/dcon_generated.txt @@ -1561,6 +1561,23 @@ object { name{ rgo_actual_production_per_good } type{ array{commodity_id}{float} } } + + property{ + name{ tax_base_poor } + type{ float } + tag{ save } + } + property{ + name{ tax_base_middle } + type{ float } + tag{ save } + } + property{ + name{ tax_base_rich } + type{ float } + tag{ save } + } + property{ name{ daily_net_migration } type{ float } diff --git a/src/gui/budgetwindow.cpp b/src/gui/budgetwindow.cpp index 4f7bedafb..1e55812ab 100644 --- a/src/gui/budgetwindow.cpp +++ b/src/gui/budgetwindow.cpp @@ -3173,12 +3173,14 @@ void budgetwindow_main_expenses_table_t::on_update(sys::state& state) noexcept { state.world.nation_for_each_state_ownership(state.local_player_nation, [&](auto soid) { auto local_state = state.world.state_ownership_get_state(soid); auto market = state.world.state_instance_get_market_from_local_market(local_state); - float total = economy::estimate_spendings_administration_state( - state, state.local_player_nation, local_state, fraction + add_value( + std::pair( + text::get_dynamic_state_name(state, local_state), + economy::estimate_spendings_administration_state( + state, state.local_player_nation, local_state, fraction + ) + ) ); - if(total > 0.0f) { - add_value(std::pair(text::get_dynamic_state_name(state, local_state), total * fraction)); - } }); add_insert_bottom_spacer(state); } else {