From f79cf4ea68417597d23bef4f434d35ebf3cff86a Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Wed, 8 May 2024 16:20:20 -0500 Subject: [PATCH] Implements dynamic scaling for spies (#82961) ## About The Pull Request Implements dynamic scaling for spies. TL;DR On average less spawn, but there is a chance it scales up to add even more. Old ![image](https://github.com/tgstation/tgstation/assets/51863163/5ecdf146-7922-42ea-8051-8a30cddde7a6) New ![image](https://github.com/tgstation/tgstation/assets/51863163/ce9f51a1-4d99-4fe7-be65-32003fbec605) ## Why It's Good For The Game Maybe more dynamic rounds? Just for testing really ## Changelog :cl: Melbert qol: Spies may spawn in less numbers, but rarely may also spawn in more numbers. /:cl: --- .../subsystem/dynamic/dynamic_rulesets.dm | 21 +++++++++++++--- .../dynamic/dynamic_rulesets_roundstart.dm | 25 +++++++++---------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm index 8b45b129c99..0ca3c84bb68 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets.dm @@ -140,28 +140,41 @@ /// This function is here to ensure the antag ratio is kept under control while scaling up. /// Returns how much threat to actually spend in the end. /datum/dynamic_ruleset/proc/scale_up(population, max_scale) + SHOULD_NOT_OVERRIDE(TRUE) if (!scaling_cost) return 0 var/antag_fraction = 0 - for(var/_ruleset in (SSdynamic.executed_rules + list(src))) // we care about the antags we *will* assign, too - var/datum/dynamic_ruleset/ruleset = _ruleset - antag_fraction += ((1 + ruleset.scaled_times) * ruleset.get_antag_cap(population)) / SSdynamic.roundstart_pop_ready + for(var/datum/dynamic_ruleset/ruleset as anything in (SSdynamic.executed_rules + list(src))) // we care about the antags we *will* assign, too + antag_fraction += ruleset.get_antag_cap_scaling_included(population) / SSdynamic.roundstart_pop_ready for(var/i in 1 to max_scale) if(antag_fraction < 0.25) scaled_times += 1 - antag_fraction += get_antag_cap(population) / SSdynamic.roundstart_pop_ready // we added new antags, gotta update the % + antag_fraction += get_scaling_antag_cap(population) / SSdynamic.roundstart_pop_ready // we added new antags, gotta update the % return scaled_times * scaling_cost +/// Returns how many more antags to add while scaling with a given population. +/// By default rulesets scale linearly, but you can override this to make them scale differently. +/datum/dynamic_ruleset/proc/get_scaling_antag_cap(population) + return get_antag_cap(population) + /// Returns what the antag cap with the given population is. /datum/dynamic_ruleset/proc/get_antag_cap(population) + SHOULD_NOT_OVERRIDE(TRUE) if (isnum(antag_cap)) return antag_cap return CEILING(population / antag_cap["denominator"], 1) + (antag_cap["offset"] || 0) +/// Gets the 'final' antag cap for this ruleset, which is the base cap plus the scaled cap. +/datum/dynamic_ruleset/proc/get_antag_cap_scaling_included(population) + SHOULD_NOT_OVERRIDE(TRUE) + var/base_cap = get_antag_cap(population) + var/modded_cap = scaled_times * get_scaling_antag_cap(population) + return base_cap + modded_cap + /// This is called if persistent variable is true everytime SSTicker ticks. /datum/dynamic_ruleset/proc/rule_process() return diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm index 1f315391a8f..12ec28c7072 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_roundstart.dm @@ -33,8 +33,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) /datum/dynamic_ruleset/roundstart/traitor/pre_execute(population) . = ..() - var/num_traitors = get_antag_cap(population) * (scaled_times + 1) - for (var/i = 1 to num_traitors) + for (var/i in 1 to get_antag_cap_scaling_included(population)) if(candidates.len <= 0) break var/mob/M = pick_n_take(candidates) @@ -121,7 +120,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) /datum/dynamic_ruleset/roundstart/traitorbro/pre_execute(population) . = ..() - for (var/_ in 1 to get_antag_cap(population) * (scaled_times + 1)) + for (var/i in 1 to get_antag_cap_scaling_included(population)) var/mob/candidate = pick_n_take(candidates) if (isnull(candidate)) break @@ -171,8 +170,7 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) /datum/dynamic_ruleset/roundstart/changeling/pre_execute(population) . = ..() - var/num_changelings = get_antag_cap(population) * (scaled_times + 1) - for (var/i = 1 to num_changelings) + for (var/i in 1 to get_antag_cap_scaling_included(population)) if(candidates.len <= 0) break var/mob/M = pick_n_take(candidates) @@ -717,13 +715,15 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) required_candidates = 3 // lives or dies by there being a few spies weight = 5 cost = 8 - scaling_cost = 101 // see below - minimum_players = 8 - antag_cap = list("denominator" = 8, "offset" = 1) // should have quite a few spies to work against each other + scaling_cost = 4 + minimum_players = 10 + antag_cap = list("denominator" = 20, "offset" = 1) requirements = list(8, 8, 8, 8, 8, 8, 8, 8, 8, 8) + /// What fraction is added to the antag cap for each additional scale + var/fraction_per_scale = 0.2 /datum/dynamic_ruleset/roundstart/spies/pre_execute(population) - for(var/i in 1 to get_antag_cap(population) * (scaled_times + 1)) + for(var/i in 1 to get_antag_cap_scaling_included(population)) if(length(candidates) <= 0) break var/mob/picked_player = pick_n_take(candidates) @@ -733,7 +733,6 @@ GLOBAL_VAR_INIT(revolutionary_win, FALSE) GLOB.pre_setup_antags += picked_player.mind return TRUE -/datum/dynamic_ruleset/roundstart/spies/scale_up(population, max_scale) - // Disabled (at least until dynamic can handle scaling this better) - // Because spies have a very low demoninator, this can easily spawn like 30 of them - return 0 +// Scaling adds a fraction of the amount of additional spies rather than the full amount. +/datum/dynamic_ruleset/roundstart/spies/get_scaling_antag_cap(population) + return ceil(..() * fraction_per_scale)