Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions C3X.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,12 @@ enum ai_auto_build_great_wall_strategy {
AAGWS_OTHER_CIV_BORDERED_ONLY
};

enum pollution_spawn_effect {
PSE_DEFAULT = 0,
PSE_REDUCE_POPULATION,
PSE_REDUCE_POPULATION_AND_POLLUTE_TILE
};

enum perfume_kind {
PK_PRODUCTION = 0,
PK_TECHNOLOGY,
Expand Down Expand Up @@ -327,6 +333,7 @@ struct c3x_config {
bool dont_end_units_turn_after_airdrop;
bool allow_airdrop_without_airport;
bool enable_negative_pop_pollution;
enum pollution_spawn_effect pollution_spawn_effect;
bool enable_pollution_from_free_improvements;
enum retreat_rules land_retreat_rules;
enum retreat_rules sea_retreat_rules;
Expand Down Expand Up @@ -669,6 +676,7 @@ enum c3x_label {
CL_OBSOLETED_BY,
CL_NO_STEALTH_ATTACK,
CL_DODGED_SAM,
CL_POLLUTION_REDUCES_POP,
CL_PREVIEW,
CL_CITY_TOO_CLOSE_BUTTON_TOOLTIP,
CL_TOTAL_CITIES,
Expand Down
3 changes: 3 additions & 0 deletions Text/c3x-labels.txt
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ Obsoleted By
; Pops up on the map when a bomber gets intercepted by enemy AA buildings but dodges the damage
We were chased off by enemy air defenses.

; Pops up on the map when pollution reduces a city's population instead of spawning on a tile.
Pollution reduces population of

; As in a "preview" version of the mod. Used on the mod info popup.
Preview

Expand Down
1 change: 1 addition & 0 deletions civ_prog_objects.csv
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@ inlead, 0x4BED80, 0x4C6350, 0x4BEE10, "City_cycle_specialist_type", "bool (
inlead, 0x4B1C10, 0x4B8BC0, 0x4B1CA0, "City_get_total_pollution", "int (__fastcall *) (City * this)"
inlead, 0x4B1B40, 0x4B8B00, 0x4B1BD0, "City_get_pollution_from_buildings", "int (__fastcall *) (City * this)"
inlead, 0x4B1A50, 0x4B8A10, 0x4B1AE0, "City_get_pollution_from_pop", "int (__fastcall *) (City * this)"
inlead, 0x4B2F80, 0x0, 0x0, "City_update_spawn_pollution", "void (__fastcall *) (City * this)"
inlead, 0x4ACF40, 0x4B3F20, 0x4ACFD0, "City_add_or_remove_improvement", "void (__fastcall *) (City * this, int edx, int improv_id, int add, bool param_3)"
define, 0x57E943, 0x58B68E, 0x57E6A3, "ADDR_RESOURCE_TILE_COUNT_MASK", "void *"
define, 0x57E5EB, 0x58B328, 0x57E34B, "ADDR_RESOURCE_TILE_COUNT_ZERO_COMPARE", "void *"
Expand Down
5 changes: 5 additions & 0 deletions default.c3x_config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,11 @@ dont_end_units_turn_after_airdrop = false
allow_airdrop_without_airport = false
enable_negative_pop_pollution = true

; Controls what happens when pollution may spawn from a city.
; Options are "default", "reduce-population", and "reduce-population-and-pollute-tile".
; In "reduce-population-and-pollute-tile" mode, the population reduction and tile pollution checks run independently.
pollution_spawn_effect = default

; Causes improvements granted for free by great or small wonders to contribute pollution as though they had been built in the city.
enable_pollution_from_free_improvements = false

Expand Down
38 changes: 38 additions & 0 deletions injected_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -2182,6 +2182,17 @@ read_ai_auto_build_great_wall_strategy (struct string_slice const * s, int * out
return false;
}

bool
read_pollution_spawn_effect (struct string_slice const * s, int * out_val)
{
struct string_slice trimmed = trim_string_slice (s, 1);
if (slice_matches_str (&trimmed, "default" )) { *out_val = PSE_DEFAULT; return true; }
else if (slice_matches_str (&trimmed, "reduce-population" )) { *out_val = PSE_REDUCE_POPULATION; return true; }
else if (slice_matches_str (&trimmed, "reduce-population-and-pollute-tile" )) { *out_val = PSE_REDUCE_POPULATION_AND_POLLUTE_TILE; return true; }
else
return false;
}

bool
read_tile_terrain_type_value (struct string_slice const * s, enum SquareTypes * out_type)
{
Expand Down Expand Up @@ -2754,6 +2765,9 @@ load_config (char const * file_path, int path_is_relative_to_mod_dir)
} else if (slice_matches_str (&p.key, "sea_retreat_rules")) {
if (! read_retreat_rules (&value, (int *)&cfg->sea_retreat_rules))
handle_config_error (&p, CPE_BAD_VALUE);
} else if (slice_matches_str (&p.key, "pollution_spawn_effect")) {
if (! read_pollution_spawn_effect (&value, (int *)&cfg->pollution_spawn_effect))
handle_config_error (&p, CPE_BAD_VALUE);
} else if (slice_matches_str (&p.key, "draw_lines_using_gdi_plus")) {
if (! read_line_drawing_override (&value, (int *)&cfg->draw_lines_using_gdi_plus))
handle_config_error (&p, CPE_BAD_VALUE);
Expand Down Expand Up @@ -19532,6 +19546,7 @@ patch_init_floating_point ()
base_config.distribution_hub_yield_division_mode = DHYDM_FLAT;
base_config.ai_distribution_hub_build_strategy = ADHBS_BY_CITY_COUNT;
base_config.ai_auto_build_great_wall_strategy = AAGWS_ALL_BORDERS;
base_config.pollution_spawn_effect = PSE_DEFAULT;
base_config.great_wall_auto_build_wonder_improv_id = -1;
for (int n = 0; n < ARRAY_LEN (boolean_config_options); n++)
*((char *)&base_config + boolean_config_options[n].offset) = boolean_config_options[n].base_val;
Expand Down Expand Up @@ -26287,6 +26302,29 @@ patch_City_get_total_pollution (City * this)
return patch_City_get_pollution_from_buildings (this) + patch_City_get_pollution_from_pop (this);
}

void __fastcall
patch_City_update_spawn_pollution (City * this)
{
enum pollution_spawn_effect effect = is->current_config.pollution_spawn_effect;
if (effect == PSE_DEFAULT) {
City_update_spawn_pollution (this);
return;
} else if (effect == PSE_REDUCE_POPULATION_AND_POLLUTE_TILE)
City_update_spawn_pollution (this);

int pollution = patch_City_get_total_pollution (this);
if ((pollution > 0) && (rand_int (p_rand_object, __, 100) < pollution) && (this->Body.Population.Size > 1)) {
City_remove_population (this, __, 1, -1, '\0');

if (this->Body.CivID == p_main_screen_form->Player_CivID) {
char msg[160];
snprintf (msg, sizeof msg, "%s %s", is->c3x_labels[CL_POLLUTION_REDUCES_POP], this->Body.CityName);
msg[(sizeof msg) - 1] = '\0';
show_map_specific_text (this->Body.X, this->Body.Y, msg, true);
}
}
}

void remove_extra_palaces (City * city, City * excluded_destination);

void
Expand Down