Skip to content
Draft
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
3 changes: 3 additions & 0 deletions C3X.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,9 @@ struct unit_type_limit {
int per_civ;
int per_city;
int cities_per;
int resource_id;
int per_resource;
int resource_per;
};

struct work_area_improvement {
Expand Down
6 changes: 3 additions & 3 deletions default.c3x_config.ini
Original file line number Diff line number Diff line change
Expand Up @@ -665,10 +665,10 @@ civ_aliases_by_era = []
leader_aliases_by_era = []

; Here it's possible to limit how many units of each type players may build. Example:
; ["Royal Guard": 3, Champion: 1 per-city, "Heavy Tank": 3 cities-per, "Heavy Infantry": 5 + 2 per-city]
; The limits may be constant values or vary depending on city counts. In the example above, players will each be limited to 3 Royal Guards. They may
; ["Royal Guard": 3, Champion: 1 per-city, "Heavy Tank": 3 cities-per, "Heavy Infantry": 5 + 2 per-city, Mercenary: 1 per-resource Gold, "ICBM": 2 resource-per Uranium]
; The limits may be constant values or vary depending on city and resource counts. In the example above, players will each be limited to 3 Royal Guards. They may
; build one Champion for each city they own. They may build one Heavy Tank for every 3 cities they own. It is also possible to combine terms with plus
; signs, as for Heavy Infantry.
; signs, as for Heavy Infantry. They can also depend on resources available.
; The unit limits apply to unit production by players, not all forms of unit creation. Specifically, they apply to city production, upgrading, and
; auto-production from wonders. They do not apply to all other ways units may be created including by being captured, enslaved, spawned from a razed
; city, spawned for barbarians, pre-placed in a scenario, spawned for the AI based on difficulty level, etc.
Expand Down
45 changes: 34 additions & 11 deletions injected_code.c
Original file line number Diff line number Diff line change
Expand Up @@ -1276,6 +1276,7 @@ parse_unit_type_limit (char ** p_cursor, struct error_line ** p_unrecognized_lin

struct string_slice name;
struct unit_type_limit limit = {0};
struct string_slice resource_name;
if (skip_white_space (&cur) &&
parse_string (&cur, &name) &&
(name.len < (sizeof out->name)) &&
Expand All @@ -1292,26 +1293,41 @@ parse_unit_type_limit (char ** p_cursor, struct error_line ** p_unrecognized_lin
limit.per_city += num;
else if (slice_matches_str (&ss, "cities-per"))
limit.cities_per += num;
else
else if (slice_matches_str (&ss, "per-resource")) {
if (!parse_string (&cur, &resource_name))
return RPR_PARSE_ERROR;
limit.per_resource += num;
} else if (slice_matches_str (&ss, "resource-per")) {
if (!parse_string (&cur, &resource_name))
return RPR_PARSE_ERROR;
limit.resource_per += num;
} else
return RPR_PARSE_ERROR;
} else
limit.per_civ += num;

} while (skip_punctuation (&cur, '+'));

int unused;
if (find_unit_type_id_by_name (&name, 0, &unused)) {
memset (out->name, 0, sizeof out->name);
strncpy (out->name, name.str, name.len);
out->limit = limit;
*p_cursor = cur;
return RPR_OK;
} else {
if (!find_unit_type_id_by_name (&name, 0, &unused)) {
add_unrecognized_line (p_unrecognized_lines, &name);
*p_cursor = cur;
return RPR_UNRECOGNIZED;
}

if (limit.per_resource > 0 || limit.resource_per > 0) {
int resource_id;
if (!find_resource_id_by_name (&resource_name, &resource_id)) {
add_unrecognized_line (p_unrecognized_lines, &resource_name);
*p_cursor = cur;
return RPR_UNRECOGNIZED;
}
limit.resource_id = resource_id;
}
memset (out->name, 0, sizeof out->name);
strncpy (out->name, name.str, name.len);
out->limit = limit;
*p_cursor = cur;
return RPR_OK;
} else
return RPR_PARSE_ERROR;
}
Expand Down Expand Up @@ -8693,9 +8709,16 @@ get_unit_limit (Leader * leader, int unit_type_id, int * out_limit)
if ((unit_type_id >= 0) && (unit_type_id < p_bic_data->UnitTypeCount) &&
stable_look_up (&is->current_config.unit_limits, type->Name, (int *)&lim)) {
int city_count = leader->Cities_Count;
int tr = lim->per_civ + lim->per_city * city_count;
char res_count = leader->Available_Resources_Counts[lim->resource_id];//SUPER DUPER DODGY.
//Only picks up local resources, has a habit of being 1 short, unless only 1 resource exists.
//It's weird enough that this logic tracks for so many resources, but I wouldn't be surprised at excessively large coincidences in testing.
int tr = lim->per_civ;
tr += lim->per_city * city_count;
if (lim->cities_per != 0)
tr += city_count / lim->cities_per;
tr += res_count / lim->cities_per;
tr += lim->per_resource * res_count;
if (lim->resource_per != 0)
tr += res_count / lim->resource_per;
*out_limit = tr;
return true;
} else
Expand Down