diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm
index 623a7482a4..be81becdbf 100644
--- a/code/__HELPERS/roundend.dm
+++ b/code/__HELPERS/roundend.dm
@@ -1,25 +1,80 @@
#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend
#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped
-#define POPCOUNT_GHOSTS "ghosts" //Ghosts on roundend
-#define POPCOUNT_HUMAN_ESCAPEES "human_escapees" //Same as escapees but human only
-#define POPCOUNT_HUMAN_SURVIVORS "human_survivors" //Same as survivors but human only
#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only.
/datum/controller/subsystem/ticker/proc/gather_roundend_feedback()
- //Survivor numbers
- var/clients = GLOB.player_list.len
- var/popcount = count_survivors()
- SSblackbox.record_feedback("nested tally", "round_end_stats", clients, list("clients"))
- SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_GHOSTS], list("ghosts"))
- SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_SURVIVORS], list("survivors", "human"))
- SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_SURVIVORS], list("survivors", "total"))
- SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_HUMAN_ESCAPEES], list("escapees", "human"))
- SSblackbox.record_feedback("nested tally", "round_end_stats", popcount[POPCOUNT_ESCAPEES], list("escapees", "total"))
- //Antag information
gather_antag_data()
-
- //Nuke disk
record_nuke_disk_location()
+ var/json_file = file("[GLOB.log_directory]/round_end_data.json")
+ var/list/file_data = list("escapees" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "abandoned" = list("humans" = list(), "silicons" = list(), "others" = list(), "npcs" = list()), "ghosts" = list(), "additional data" = list())
+ var/num_survivors = 0
+ var/num_escapees = 0
+ var/num_shuttle_escapees = 0
+ var/list/area/shuttle_areas
+ if(SSshuttle && SSshuttle.emergency)
+ shuttle_areas = SSshuttle.emergency.shuttle_areas
+ for(var/mob/m in GLOB.mob_list)
+ var/escaped
+ var/category
+ var/list/mob_data = list()
+ if(isnewplayer(m))
+ continue
+ if(m.mind)
+ if(m.stat != DEAD && !isbrain(m))
+ num_survivors++
+ mob_data += list("name" = m.name, "ckey" = ckey(m.mind.key))
+ if(isobserver(m))
+ escaped = "ghosts"
+ else if(isliving(m))
+ var/mob/living/L = m
+ mob_data += list("location" = get_area(L), "health" = L.health)
+ if(ishuman(L))
+ var/mob/living/carbon/human/H = L
+ category = "humans"
+ mob_data += list("job" = H.mind.assigned_role, "species" = H.dna.species.name)
+ else if(issilicon(L))
+ category = "silicons"
+ if(isAI(L))
+ mob_data += list("module" = "AI")
+ if(isAI(L))
+ mob_data += list("module" = "pAI")
+ if(iscyborg(L))
+ var/mob/living/silicon/robot/R = L
+ mob_data += list("module" = R.module)
+ else
+ category = "others"
+ mob_data += list("typepath" = L.type)
+ if(!escaped)
+ if(EMERGENCY_ESCAPED_OR_ENDGAMED && (m.onCentCom() || m.onSyndieBase()))
+ escaped = "escapees"
+ num_escapees++
+ if(shuttle_areas[get_area(m)])
+ num_shuttle_escapees++
+ else
+ escaped = "abandoned"
+ if(!m.mind && (!ishuman(m) || !issilicon(m)))
+ var/list/npc_nest = file_data["[escaped]"]["npcs"]
+ if(npc_nest.Find(initial(m.name)))
+ file_data["[escaped]"]["npcs"]["[initial(m.name)]"] += 1
+ else
+ file_data["[escaped]"]["npcs"]["[initial(m.name)]"] = 1
+ else
+ var/pos = length(file_data["[escaped]"]["[category]"]) + 1
+ file_data["[escaped]"]["[category]"]["[pos]"] = mob_data
+ var/datum/station_state/end_state = new /datum/station_state()
+ end_state.count()
+ var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
+ file_data["additional data"]["station integrity"] = station_integrity
+ WRITE_FILE(json_file, json_encode(file_data))
+ SSblackbox.record_feedback("nested tally", "round_end_stats", num_survivors, list("survivors", "total"))
+ SSblackbox.record_feedback("nested tally", "round_end_stats", num_escapees, list("escapees", "total"))
+ SSblackbox.record_feedback("nested tally", "round_end_stats", GLOB.joined_player_list.len, list("players", "total"))
+ SSblackbox.record_feedback("nested tally", "round_end_stats", GLOB.joined_player_list.len - num_survivors, list("players", "dead"))
+ . = list()
+ .[POPCOUNT_SURVIVORS] = num_survivors
+ .[POPCOUNT_ESCAPEES] = num_escapees
+ .[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees
+ .["station_integrity"] = station_integrity
/datum/controller/subsystem/ticker/proc/gather_antag_data()
var/team_gid = 1
@@ -109,9 +164,8 @@
C.RollCredits()
C.playtitlemusic(40)
- display_report()
-
- gather_roundend_feedback()
+ var/popcount = gather_roundend_feedback()
+ display_report(popcount)
CHECK_TICK
@@ -202,56 +256,12 @@
return parts.Join()
-/datum/controller/subsystem/ticker/proc/count_survivors()
- . = list()
- var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
- var/num_survivors = 0
- var/num_escapees = 0
- var/num_shuttle_escapees = 0
- var/num_ghosts = 0
- var/num_human_survivors = 0
- var/num_human_escapees = 0
-
- //Player status report
- for(var/i in GLOB.mob_list)
- var/mob/Player = i
- if(Player.mind && !isnewplayer(Player))
- if(isobserver(Player))
- num_ghosts++
- if(Player.stat != DEAD && !isbrain(Player))
- num_survivors++
- if(ishuman(Player))
- num_human_survivors++
- if(station_evacuated) //If the shuttle has already left the station
- var/list/area/shuttle_areas
- if(SSshuttle && SSshuttle.emergency)
- shuttle_areas = SSshuttle.emergency.shuttle_areas
- if(Player.onCentCom() || Player.onSyndieBase())
- num_escapees++
- if(ishuman(Player))
- num_human_escapees++
- if(shuttle_areas[get_area(Player)])
- num_shuttle_escapees++
-
- .[POPCOUNT_SURVIVORS] = num_survivors
- .[POPCOUNT_ESCAPEES] = num_escapees
- .[POPCOUNT_SHUTTLE_ESCAPEES] = num_shuttle_escapees
- .[POPCOUNT_HUMAN_SURVIVORS] = num_human_survivors
- .[POPCOUNT_HUMAN_ESCAPEES] = num_human_escapees
- .[POPCOUNT_GHOSTS] = num_ghosts
-
-/datum/controller/subsystem/ticker/proc/survivor_report()
+/datum/controller/subsystem/ticker/proc/survivor_report(popcount)
var/list/parts = list()
var/station_evacuated = EMERGENCY_ESCAPED_OR_ENDGAMED
- var/popcount = count_survivors()
-
- //Round statistics report
- var/datum/station_state/end_state = new /datum/station_state()
- end_state.count()
- var/station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100)
parts += "[GLOB.TAB]Shift Duration: [DisplayTimeText(world.time - SSticker.round_start_time)]"
- parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[station_integrity]%"]"
+ parts += "[GLOB.TAB]Station Integrity: [mode.station_was_nuked ? "Destroyed" : "[popcount["station_integrity"]]%"]"
var/total_players = GLOB.joined_player_list.len
if(total_players)
parts+= "[GLOB.TAB]Total Population: [total_players]"
@@ -261,10 +271,10 @@
parts += "[GLOB.TAB]Survival Rate: [popcount[POPCOUNT_SURVIVORS]] ([PERCENT(popcount[POPCOUNT_SURVIVORS]/total_players)]%)"
return parts.Join("
")
-/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report)
+/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C,common_report, popcount)
var/list/report_parts = list()
- report_parts += personal_report(C)
+ report_parts += personal_report(C, popcount)
report_parts += common_report
var/datum/browser/roundend_report = new(C, "roundend")
@@ -276,7 +286,7 @@
roundend_report.open(0)
-/datum/controller/subsystem/ticker/proc/personal_report(client/C)
+/datum/controller/subsystem/ticker/proc/personal_report(client/C, popcount)
var/list/parts = list()
var/mob/M = C.mob
if(M.mind && !isnewplayer(M))
@@ -298,19 +308,17 @@
else
parts += "