Merge pull request #14513 from Putnam3145/chaos-for-secret

Makes threat a subsystem instead of dynamic-attached
This commit is contained in:
silicons
2021-03-27 01:33:27 -06:00
committed by GitHub
13 changed files with 117 additions and 57 deletions
+4
View File
@@ -24,6 +24,10 @@
// signals from globally accessible objects
/// from SSsun when the sun changes position : (primary_sun, suns)
#define COMSIG_SUN_MOVED "sun_moved"
/// from SSactivity for things that add threat but aren't "global" (e.g. phylacteries)
#define COMSIG_THREAT_CALC "threat_calculation"
//////////////////////////////////////////////////////////////////
// /datum signals
+1
View File
@@ -152,6 +152,7 @@
// If the subsystem isn't listed here it's either DEFAULT or PROCESS (if it's a processing subsystem child)
#define FIRE_PRIORITY_VORE 5
#define FIRE_PRIORITY_ACTIVITY 10
#define FIRE_PRIORITY_IDLE_NPC 10
#define FIRE_PRIORITY_SERVER_MAINT 10
#define FIRE_PRIORITY_RESEARCH 10
+10 -5
View File
@@ -386,12 +386,15 @@
//ignore this comment, it fixes the broken sytax parsing caused by the " above
else
parts += "[FOURSPACES]<i>Nobody died this shift!</i>"
var/avg_threat = SSactivity.get_average_threat()
var/max_threat = SSactivity.get_max_threat()
parts += "[FOURSPACES]Threat at round end: [SSactivity.current_threat]"
parts += "[FOURSPACES]Average threat: [avg_threat]"
parts += "[FOURSPACES]Max threat: [max_threat]"
if(istype(SSticker.mode, /datum/game_mode/dynamic))
var/datum/game_mode/dynamic/mode = SSticker.mode
mode.update_playercounts() // ?
parts += "[FOURSPACES]Threat level: [mode.threat_level]"
parts += "[FOURSPACES]Threat left: [mode.threat]"
parts += "[FOURSPACES]Average threat: [mode.threat_average]"
parts += "[FOURSPACES]Target threat: [mode.threat_level]"
parts += "[FOURSPACES]Executed rules:"
for(var/datum/dynamic_ruleset/rule in mode.executed_rules)
parts += "[FOURSPACES][FOURSPACES][rule.ruletype] - <b>[rule.name]</b>: -[rule.cost + rule.scaled_times * rule.scaling_cost] threat"
@@ -400,8 +403,10 @@
parts += "[FOURSPACES][FOURSPACES][str]"
for(var/entry in mode.threat_tallies)
parts += "[FOURSPACES][FOURSPACES][entry] added [mode.threat_tallies[entry]]"
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat_level,"Final threat level")
SSblackbox.record_feedback("tally","dynamic_threat",mode.threat,"Final Threat")
SSblackbox.record_feedback("tally","threat",mode.threat_level,"Target threat")
SSblackbox.record_feedback("tally","threat",SSactivity.current_threat,"Final Threat")
SSblackbox.record_feedback("tally","threat",avg_threat,"Average Threat")
SSblackbox.record_feedback("tally","threat",max_threat,"Max Threat")
return parts.Join("<br>")
/client/proc/roundend_report_file()
@@ -404,9 +404,9 @@ Example config:
if(!Get(/datum/config_entry/flag/no_storyteller_threat_removal))
var/min_chaos = (probabilities in storyteller_min_chaos) ? storyteller_min_chaos[config_tag] : initial(S.min_chaos)
var/max_chaos = (probabilities in storyteller_max_chaos) ? storyteller_max_chaos[config_tag] : initial(S.max_chaos)
if(SSpersistence.average_dynamic_threat < min_chaos)
if(SSpersistence.average_threat + 50 < min_chaos)
continue
if(SSpersistence.average_dynamic_threat > max_chaos)
if(SSpersistence.average_threat + 50 > max_chaos)
continue
if(SSpersistence.saved_storytellers.len == repeated_mode_adjust.len)
var/name = initial(S.name)
+75
View File
@@ -0,0 +1,75 @@
SUBSYSTEM_DEF(activity)
name = "Activity tracking"
flags = SS_BACKGROUND | SS_NO_TICK_CHECK
priority = FIRE_PRIORITY_ACTIVITY
wait = 1 MINUTES
var/list/deferred_threats = list()
var/current_threat = 0
var/list/threat_history = list()
var/list/threats = list()
/datum/controller/subsystem/activity/Initialize(timeofday)
RegisterSignal(SSdcs,COMSIG_GLOB_EXPLOSION,.proc/on_explosion)
RegisterSignal(SSdcs,COMSIG_GLOB_MOB_DEATH,.proc/on_death)
/datum/controller/subsystem/activity/fire(resumed = 0)
calculate_threat()
/datum/controller/subsystem/activity/proc/calculate_threat()
threats = deferred_threats.Copy()
deferred_threats.Cut()
threats["antagonists"] = 0
for(var/datum/antagonist/A in GLOB.antagonists)
if(A?.owner?.current && A.owner.current.stat != DEAD)
threats["antagonists"] += A.threat()
threats["events"] = 0
for(var/r in SSevents.running)
var/datum/round_event/R = r
threats["events"] += R.threat()
threats["players"] = 0
SEND_SIGNAL(src, COMSIG_THREAT_CALC, threats)
for(var/m in GLOB.player_list)
var/mob/M = m
if (M?.mind?.assigned_role && M.stat != DEAD)
var/datum/job/J = SSjob.GetJob(M.mind.assigned_role)
if(J)
if(length(M.mind.antag_datums))
threats["players"] += J.GetThreat()
else
threats["players"] -= J.GetThreat()
else if(M?.stat == DEAD && !M.voluntary_ghosted)
threats["dead_players"] += 1
current_threat = 0
for(var/threat_type in threats)
current_threat += threats[threat_type]
threat_history += "[world.time]"
threat_history["[world.time]"] = current_threat
/datum/controller/subsystem/activity/proc/get_average_threat()
if(!length(threat_history))
return 0
var/total_weight = 0
var/total_amt = 0
for(var/i in 1 to threat_history.len-1)
var/weight = (text2num(threat_history[i+1])-text2num(threat_history[i]))
total_weight += weight
total_amt += weight * (threat_history[threat_history[i]])
return round(total_amt / total_weight,0.1)
/datum/controller/subsystem/activity/proc/get_max_threat()
. = 0
for(var/threat in threat_history)
. = max(threat_history[threat], .)
/datum/controller/subsystem/activity/proc/on_explosion(atom/epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
if(!("explosions" in deferred_threats))
deferred_threats["explosions"] = 0
var/area/A = get_area(epicenter)
if(is_station_level(epicenter.z) && A.blob_allowed && !istype(A, /area/asteroid))
deferred_threats["explosions"] += devastation_range**2 + heavy_impact_range**2 / 4 + light_impact_range**2 / 8 // 75 for a maxcap
/datum/controller/subsystem/activity/proc/on_death(mob/M, gibbed)
if(!("crew_deaths" in deferred_threats))
deferred_threats["crew_deaths"] = 0
if(M?.mind && SSjob.GetJob(M.mind.assigned_role))
deferred_threats["crew_deaths"] += 1
@@ -6,7 +6,7 @@
var/list/saved_chaos = list(5,5,5)
var/list/saved_dynamic_rules = list(list(),list(),list())
var/list/saved_storytellers = list("foo","bar","baz")
var/list/average_dynamic_threat = 50
var/average_threat = 50
var/list/saved_maps
/datum/controller/subsystem/persistence/SaveServerPersistence()
@@ -38,9 +38,10 @@
saved_chaos[3] = saved_chaos[2]
saved_chaos[2] = saved_chaos[1]
saved_chaos[1] = SSticker.mode.get_chaos()
average_threat = (SSactivity.get_average_threat() + average_threat) / 2
json_file = file("data/RecentChaos.json")
file_data = list()
file_data["data"] = saved_chaos
file_data["data"] = saved_chaos + average_threat
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -49,10 +50,9 @@
saved_storytellers[3] = saved_storytellers[2]
saved_storytellers[2] = saved_storytellers[1]
saved_storytellers[1] = mode.storyteller.name
average_dynamic_threat = (mode.max_threat + average_dynamic_threat) / 2
var/json_file = file("data/RecentStorytellers.json")
var/list/file_data = list()
file_data["data"] = saved_storytellers + average_dynamic_threat
file_data["data"] = saved_storytellers
fdel(json_file)
WRITE_FILE(json_file, json_encode(file_data))
@@ -94,6 +94,9 @@
if(!json)
return
saved_chaos = json["data"]
if(saved_chaos.len > 3)
average_threat = saved_chaos[4]
saved_chaos.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentRulesets()
var/json_file = file("data/RecentRulesets.json")
@@ -112,9 +115,6 @@
if(!json)
return
saved_storytellers = json["data"]
if(saved_storytellers.len > 3)
average_dynamic_threat = saved_storytellers[4]
saved_storytellers.len = 3
/datum/controller/subsystem/persistence/proc/LoadRecentMaps()
var/json_file = file("data/RecentMaps.json")
+2
View File
@@ -317,6 +317,8 @@ GLOBAL_LIST_EMPTY(explosions)
var/took = (REALTIMEOFDAY - started_at) / 10
SEND_GLOBAL_SIGNAL(COMSIG_GLOB_EXPLOSION,epicenter, devastation_range, heavy_impact_range, light_impact_range, took, orig_dev_range, orig_heavy_range, orig_light_range)
//You need to press the DebugGame verb to see these now....they were getting annoying and we've collected a fair bit of data. Just -test- changes to explosion code using this please so we can compare
if(GLOB.Debug2)
log_world("## DEBUG: Explosion([x0],[y0],[z0])(d[devastation_range],h[heavy_impact_range],l[light_impact_range]): Took [took] seconds.")
+1 -19
View File
@@ -58,14 +58,6 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
var/threat_level = 0
/// The current antag threat. Recalculated every time a ruletype starts or ends.
var/threat = 0
/// Threat average over the course of the round, for endgame logs.
var/threat_average = 0
/// Number of times threat average has been calculated, for calculating above.
var/threat_average_weight = 0
/// Last time a threat average sample was taken. Used for weighting the rolling average.
var/last_threat_sample_time = 0
/// Maximum threat recorded so far, for cross-round chaos adjustment.
var/max_threat = 0
/// Things that cause a rolling threat adjustment to be displayed at roundend.
var/list/threat_tallies = list()
/// Running information about the threat. Can store text or datum entries.
@@ -745,17 +737,7 @@ GLOBAL_VAR_INIT(dynamic_forced_storyteller, null)
continue
if(!M.voluntary_ghosted)
current_players[CURRENT_DEAD_PLAYERS].Add(M) // Players who actually died (and admins who ghosted, would be nice to avoid counting them somehow)
threat = storyteller.calculate_threat() + added_threat
max_threat = max(max_threat,threat)
if(threat_average_weight)
var/cur_sample_weight = world.time - last_threat_sample_time
threat_average = ((threat_average * threat_average_weight) + (threat * cur_sample_weight)) / (threat_average_weight + cur_sample_weight)
threat_average_weight += cur_sample_weight
last_threat_sample_time = world.time
else
threat_average = threat
threat_average_weight++
last_threat_sample_time = world.time
threat = (SSactivity.current_threat * 0.6 + SSactivity.get_max_threat() * 0.2 + SSactivity.get_average_threat() * 0.2) + added_threat
/// Removes type from the list
/datum/game_mode/dynamic/proc/remove_from_list(list/type_list, type)
@@ -45,27 +45,6 @@ Property weights are added to the config weight of the ruleset. They are:
var/midround_injection_cooldown_middle = 0.5*(GLOB.dynamic_first_midround_delay_min + GLOB.dynamic_first_midround_delay_max)
mode.midround_injection_cooldown = round(clamp(EXP_DISTRIBUTION(midround_injection_cooldown_middle), GLOB.dynamic_first_midround_delay_min, GLOB.dynamic_first_midround_delay_max)) + world.time
/datum/dynamic_storyteller/proc/calculate_threat()
var/threat = 0
for(var/datum/antagonist/A in GLOB.antagonists)
if(A?.owner?.current && A.owner.current.stat != DEAD)
threat += A.threat()
for(var/r in SSevents.running)
var/datum/round_event/R = r
threat += R.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)
if(J)
if(length(M.mind.antag_datums))
threat += J.GetThreat()
else
threat -= J.GetThreat()
threat += (mode.current_players[CURRENT_DEAD_PLAYERS].len)*dead_player_weight
return round(threat,0.1)
/datum/dynamic_storyteller/proc/do_process()
return
@@ -95,7 +74,7 @@ Property weights are added to the config weight of the ruleset. They are:
if(voters)
GLOB.dynamic_curve_centre += (mean/voters)
if(flags & USE_PREV_ROUND_WEIGHTS)
GLOB.dynamic_curve_centre += (50 - SSpersistence.average_dynamic_threat) / 10
GLOB.dynamic_curve_centre += (SSpersistence.average_threat) / 10
GLOB.dynamic_forced_threat_level = forced_threat_level
/datum/dynamic_storyteller/proc/get_midround_cooldown()
+4 -1
View File
@@ -409,7 +409,10 @@
visible_message("<span class='notice'>\The [src] hums and hisses as it moves [mob_occupant.real_name] into storage.</span>")
// Ghost and delete the mob.
if(!mob_occupant.get_ghost(1))
var/mob/dead/observer/G = mob_occupant.get_ghost(TRUE)
if(G)
G.voluntary_ghosted = TRUE
else
mob_occupant.ghostize(FALSE, penalize = TRUE, voluntary = TRUE, cryo = TRUE)
QDEL_NULL(occupant)
+1 -1
View File
@@ -87,7 +87,7 @@
addtimer(CALLBACK(src, .proc/med_hud_set_status), (DEFIB_TIME_LIMIT * 10) + 1)
stop_pulling()
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed)
var/signal = SEND_SIGNAL(src, COMSIG_MOB_DEATH, gibbed) | SEND_GLOBAL_SIGNAL(COMSIG_GLOB_MOB_DEATH, src, gibbed)
var/turf/T = get_turf(src)
if(mind && mind.name && mind.active && !istype(T.loc, /area/ctf) && !(signal & COMPONENT_BLOCK_DEATH_BROADCAST))
@@ -93,12 +93,14 @@
active_phylacteries++
GLOB.poi_list |= src
START_PROCESSING(SSobj, src)
RegisterSignal(SSactivity, COMSIG_THREAT_CALC, .proc/get_threat)
set_light(lon_range)
if(initial(SSticker.mode.round_ends_with_antag_death))
SSticker.mode.round_ends_with_antag_death = FALSE
/obj/item/phylactery/Destroy(force=FALSE)
STOP_PROCESSING(SSobj, src)
UnregisterSignal(SSactivity, COMSIG_THREAT_CALC)
active_phylacteries--
GLOB.poi_list -= src
if(!active_phylacteries)
@@ -113,6 +115,12 @@
if(!mind.current || (mind.current && mind.current.stat == DEAD))
addtimer(CALLBACK(src, .proc/rise), respawn_time, TIMER_UNIQUE)
/obj/item/phylactery/proc/get_threat(list/threat_list)
if(mind?.current?.stat == DEAD)
if(!("phylactery" in threat_list))
threat_list["phylactery"] = 0
threat_list["phylactery"] += 25
/obj/item/phylactery/proc/rise()
if(mind.current && mind.current.stat != DEAD)
return "[mind] already has a living body: [mind.current]"
+1
View File
@@ -303,6 +303,7 @@
#include "code\controllers\configuration\entries\stamina_combat.dm"
#include "code\controllers\subsystem\achievements.dm"
#include "code\controllers\subsystem\acid.dm"
#include "code\controllers\subsystem\activity.dm"
#include "code\controllers\subsystem\adjacent_air.dm"
#include "code\controllers\subsystem\air.dm"
#include "code\controllers\subsystem\air_turfs.dm"