From 93feb0277a18a5cb4b133655aeb98d984072d251 Mon Sep 17 00:00:00 2001 From: Putnam3145 Date: Fri, 3 Apr 2020 05:23:08 -0700 Subject: [PATCH] Further dynamic tweaks: "you can instamerge this time" edition (#11715) * Starting a replacement of how threat works. * no, we do it this way * Added threat levels to jobs * Added threat to... a lot. * Updated for traitor classes. * Fixed errors, except for one. It's consistently giving me "maximum number of internal arrays exceeded (65535)". I have no idea what could be causing this. * Added type annotation to GetJob. * This one I should change though * wow how'd that happen * spammable means low threat * Made story threat have initial threat level on average * Made somet rulesets force if they won the vote * ) * Gave EVERY job threat, added a config for it. * Rebalanced some numbers * Update code/game/gamemodes/dynamic/dynamic_storytellers.dm Co-Authored-By: Ghom <42542238+Ghommie@users.noreply.github.com> * Removes mush threat * Makes devil threat scale with form * reviewing reviewer's review of reviewer * Gutlunches can be friendly spawned, so no * Also made forced-friendly mobs not count * null checks better * Made antag threats in config, too * various fixes * Another couple dynamic fixes * Made an admin message chunk all one line. * Make roundstarts ignore current threat It's not even calculated yet, so this is probably better. * Minimum pop for chaotic/teamwork. * More conveyance issues, removed superfluous threat costs * More conveyance and tweaks * Makes storyteller min players use all players instead of ready * Lowered chaos weight with chaotic * Blob now has correct cost * Makes phylactery count for threat * Makes random storyteller have random threat level * Made starting rulesets scale up with threat LEVEL * Made "minor rulesets" never have lower weight * Makes chaotic not forced. * Made story about 25% less chaotic Co-authored-by: Ghom <42542238+Ghommie@users.noreply.github.com> --- code/game/gamemodes/dynamic/dynamic.dm | 2 +- .../dynamic/dynamic_rulesets_latejoin.dm | 2 +- .../gamemodes/dynamic/dynamic_storytellers.dm | 44 ++++++++++++------- 3 files changed, 29 insertions(+), 19 deletions(-) diff --git a/code/game/gamemodes/dynamic/dynamic.dm b/code/game/gamemodes/dynamic/dynamic.dm index de57bf0402..b8a5e72d55 100644 --- a/code/game/gamemodes/dynamic/dynamic.dm +++ b/code/game/gamemodes/dynamic/dynamic.dm @@ -511,7 +511,7 @@ GLOBAL_VAR_INIT(dynamic_storyteller_type, /datum/dynamic_storyteller/classic) drafted_rules -= starting_rule starting_rule.trim_candidates() - starting_rule.scale_up(extra_rulesets_amount, threat) + starting_rule.scale_up(extra_rulesets_amount, threat_level) if (starting_rule.pre_execute()) log_threat("[starting_rule.ruletype] - [starting_rule.name] [starting_rule.cost + starting_rule.scaled_times * starting_rule.scaling_cost] threat", verbose = TRUE) if(starting_rule.flags & HIGHLANDER_RULESET) diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm index f6755057e2..cec6f31e99 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_latejoin.dm @@ -241,5 +241,5 @@ requirements = list(10,10,10,10,10,10,10,10,10,10) high_population_requirement = 10 repeatable = TRUE - flags = TRAITOR_RULESET + flags = TRAITOR_RULESET | MINOR_RULESET property_weights = list("story_potential" = 2, "trust" = -1, "extended" = 2) diff --git a/code/game/gamemodes/dynamic/dynamic_storytellers.dm b/code/game/gamemodes/dynamic/dynamic_storytellers.dm index 71eb7ec533..35d5a04488 100644 --- a/code/game/gamemodes/dynamic/dynamic_storytellers.dm +++ b/code/game/gamemodes/dynamic/dynamic_storytellers.dm @@ -53,6 +53,8 @@ Property weights are: var/turf/T = get_turf(H) if(H.stat != DEAD && is_station_level(T.z) && !("Station" in H.faction)) threat += H.threat() + for(var/obj/item/phylactery/P in GLOB.poi_list) + threat += 25 // can't be giving them too much of a break for (var/mob/M in mode.current_players[CURRENT_LIVING_PLAYERS]) if (M?.mind?.assigned_role && M.stat != DEAD) var/datum/job/J = SSjob.GetJob(M.mind.assigned_role) @@ -135,17 +137,19 @@ Property weights are: if (GLOB.dynamic_classic_secret && !((rule.flags & TRAITOR_RULESET) || (rule.flags & MINOR_RULESET))) continue rule.trim_candidates() - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to - pick this particular ruleset. - Let's use a toy example: there's 60 threat level and 10 threat spent. - We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. - Ruleset 1 has 30 cost, ruleset 2 has 5 cost. - When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 - is 2.26 times as likely to be picked, all other things considered. - Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. - */ - var/threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)) + var/threat_weight = 1 + if(!(rule.flags & MINOR_RULESET)) // makes the traitor rulesets always possible anyway + var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) + /* Basically, the closer the cost is to the current threat-level-away-from-threat, the more likely it is to + pick this particular ruleset. + Let's use a toy example: there's 60 threat level and 10 threat spent. + We want to pick a ruleset that's close to that, so we run the below equation, on two rulesets. + Ruleset 1 has 30 cost, ruleset 2 has 5 cost. + When we do the math, ruleset 1's threat_weight is 0.538, and ruleset 2's is 0.238, meaning ruleset 1 + is 2.26 times as likely to be picked, all other things considered. + Of course, we don't want it to GUARANTEE the closest, that's no fun, so it's just a weight. + */ + threat_weight = 1-abs(1-LOGISTIC_FUNCTION(2,0.05,cost_difference,0)) if (rule.ready()) var/property_weight = 0 for(var/property in property_weights) @@ -168,8 +172,10 @@ Property weights are: rule.candidates = list(newPlayer) rule.trim_candidates() - var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) - var/threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) + var/threat_weight = 1 + if(!(rule.flags & MINOR_RULESET)) + var/cost_difference = abs(rule.cost-(mode.threat_level-mode.threat)) + threat_weight = 1-abs(1-(LOGISTIC_FUNCTION(2,0.05,cost_difference,0))) if (rule.ready()) var/property_weight = 0 for(var/property in property_weights) @@ -200,7 +206,7 @@ Property weights are: weight = 1 event_frequency_lower = 2 MINUTES event_frequency_upper = 10 MINUTES - flags = WAROPS_ALWAYS_ALLOWED | FORCE_IF_WON + flags = WAROPS_ALWAYS_ALLOWED min_players = 40 var/refund_cooldown = 0 @@ -245,7 +251,10 @@ Property weights are: config_tag = "random" weight = 1 desc = "No weighting at all; every ruleset has the same chance of happening. Cooldowns vary wildly. As random as it gets." - forced_threat_level = 100 + +/datum/dynamic_storyteller/random/on_start() + ..() + GLOB.dynamic_forced_threat_level = rand(0,100) /datum/dynamic_storyteller/random/get_midround_cooldown() return rand(GLOB.dynamic_midround_delay_min/2, GLOB.dynamic_midround_delay_max*2) @@ -318,9 +327,10 @@ Property weights are: property_weights = list("story_potential" = 2) -/datum/dynamic_storyteller/story/do_process() +/datum/dynamic_storyteller/story/calculate_threat() var/current_time = (world.time / SSautotransfer.targettime)*180 - mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.5),0.1) + mode.threat_level = round(mode.initial_threat_level*(sin(current_time)+0.25),0.1) + ..() /datum/dynamic_storyteller/classic name = "Classic"