From ea4cb2c14d7836ab639195e82d2465db972a844d Mon Sep 17 00:00:00 2001 From: Letter N <24603524+LetterN@users.noreply.github.com> Date: Thu, 4 Mar 2021 10:26:41 +0800 Subject: [PATCH] stop spamming text pls --- code/__HELPERS/roundend.dm | 268 ++++++++++++++++++-------- code/__HELPERS/text.dm | 4 +- code/controllers/subsystem/shuttle.dm | 50 ++--- code/controllers/subsystem/ticker.dm | 11 +- 4 files changed, 219 insertions(+), 114 deletions(-) diff --git a/code/__HELPERS/roundend.dm b/code/__HELPERS/roundend.dm index 658ed135e0..afd8a7c223 100644 --- a/code/__HELPERS/roundend.dm +++ b/code/__HELPERS/roundend.dm @@ -1,81 +1,102 @@ -#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend -#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped -#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only. +#define POPCOUNT_SURVIVORS "survivors" //Not dead at roundend +#define POPCOUNT_ESCAPEES "escapees" //Not dead and on centcom/shuttles marked as escaped +#define POPCOUNT_SHUTTLE_ESCAPEES "shuttle_escapees" //Emergency shuttle only. +#define PERSONAL_LAST_ROUND "personal last round" +#define SERVER_LAST_ROUND "server last round" /datum/controller/subsystem/ticker/proc/gather_roundend_feedback() - var/datum/station_state/end_state = new /datum/station_state() - end_state.count() - station_integrity = min(PERCENT(GLOB.start_state.score(end_state)), 100) gather_antag_data() record_nuke_disk_location() var/json_file = file("[GLOB.log_directory]/round_end_data.json") + // All but npcs sublists and ghost category contain only mobs with minds 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/num_survivors = 0 //Count of non-brain non-camera mobs with mind that are alive + var/num_escapees = 0 //Above and on centcom z + var/num_shuttle_escapees = 0 //Above and on escape shuttle var/list/area/shuttle_areas - if(SSshuttle && SSshuttle.emergency) + if(SSshuttle?.emergency) shuttle_areas = SSshuttle.emergency.shuttle_areas - for(var/mob/m in GLOB.mob_list) - var/escaped - var/category + + for(var/mob/M in GLOB.mob_list) var/list/mob_data = list() - if(isnewplayer(m)) + if(isnewplayer(M)) continue - if (m.client && m.client.prefs && m.client.prefs.auto_ooc) - if (!(m.client.prefs.chat_toggles & CHAT_OOC)) - m.client.prefs.chat_toggles ^= CHAT_OOC - if(m.mind) - if(m.stat != DEAD && !isbrain(m) && !iscameramob(m)) + // enable their ooc? + if (M.client?.prefs?.auto_ooc) + if (!(M.client.prefs.chat_toggles & CHAT_OOC)) + M.client.prefs.chat_toggles ^= CHAT_OOC + + var/escape_status = "abandoned" //default to abandoned + var/category = "npcs" //Default to simple count only bracket + var/count_only = TRUE //Count by name only or full info + + mob_data["name"] = M.name + if(M.mind) + count_only = FALSE + mob_data["ckey"] = M.mind.key + if(M.stat != DEAD && !isbrain(M) && !iscameramob(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(EMERGENCY_ESCAPED_OR_ENDGAMED && (M.onCentCom() || M.onSyndieBase())) + num_escapees++ + escape_status = "escapees" + if(shuttle_areas[get_area(M)]) + num_shuttle_escapees++ + if(isliving(M)) + var/mob/living/L = M + mob_data["location"] = get_area(L) + mob_data["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) + if(H.mind) + mob_data["job"] = H.mind.assigned_role + else + mob_data["job"] = "Unknown" + mob_data["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)) + mob_data["module"] = "AI" + else if(ispAI(L)) + mob_data["module"] = "pAI" + else if(iscyborg(L)) var/mob/living/silicon/robot/R = L - mob_data += list("module" = R.module) - else - category = "others" - mob_data += list("typepath" = m.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 - if(isobserver(m)) - var/pos = length(file_data["[escaped]"]) + 1 - file_data["[escaped]"]["[pos]"] = mob_data - else - if(!category) + mob_data["module"] = R.module.name + else category = "others" - mob_data += list("name" = m.name, "typepath" = m.type) - var/pos = length(file_data["[escaped]"]["[category]"]) + 1 - file_data["[escaped]"]["[category]"]["[pos]"] = mob_data + mob_data["typepath"] = M.type + //Ghosts don't care about minds, but we want to retain ckey data etc + if(isobserver(M)) + count_only = FALSE + escape_status = "ghosts" + if(!M.mind) + mob_data["ckey"] = M.key + category = null //ghosts are one list deep + //All other mindless stuff just gets counts by name + if(count_only) + var/list/npc_nest = file_data["[escape_status]"]["npcs"] + var/name_to_use = initial(M.name) + if(ishuman(M)) + name_to_use = "Unknown Human" //Monkeymen and other mindless corpses + if(npc_nest.Find(name_to_use)) + file_data["[escape_status]"]["npcs"][name_to_use] += 1 + else + file_data["[escape_status]"]["npcs"][name_to_use] = 1 + else + //Mobs with minds and ghosts get detailed data + if(category) + var/pos = length(file_data["[escape_status]"]["[category]"]) + 1 + file_data["[escape_status]"]["[category]"]["[pos]"] = mob_data + else + var/pos = length(file_data["[escape_status]"]) + 1 + file_data["[escape_status]"]["[pos]"] = mob_data + + var/datum/station_state/end_state = new /datum/station_state() + end_state.count() + 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")) @@ -191,10 +212,12 @@ else if(human_mob.onCentCom()) player_client.give_award(/datum/award/score/hardcore_random, human_mob, round(human_mob.hardcore_survival_score)) + /datum/controller/subsystem/ticker/proc/declare_completion() set waitfor = FALSE to_chat(world, "


The round has ended.") + log_game("The round has ended.") if(LAZYLEN(GLOB.round_end_notifiees)) world.TgsTargetedChatBroadcast("[GLOB.round_end_notifiees.Join(", ")] the round has ended.", FALSE) @@ -250,6 +273,11 @@ CHECK_TICK + // handle_hearts() + set_observer_default_invisibility(0, "The round is over! You are now visible to the living.") + + CHECK_TICK + //These need update to actually reflect the real antagonists //Print a list of antagonists to the server log var/list/total_antagonists = list() @@ -268,18 +296,13 @@ for(var/antag_name in total_antagonists) var/list/L = total_antagonists[antag_name] log_game("[antag_name]s :[L.Join(", ")].") - set_observer_default_invisibility(0, "The round is over! You are now visible to the living.") CHECK_TICK SSdbcore.SetRoundEnd() //Collects persistence features - if(mode.station_was_nuked) - SSpersistence.station_was_destroyed = TRUE - if(!mode.allow_persistence_save) - SSpersistence.station_persistence_save_disabled = TRUE - else + if(mode.allow_persistence_save) SSpersistence.SaveTCGCards() - SSpersistence.CollectData() + SSpersistence.CollectData() //stop collecting feedback during grifftime SSblackbox.Seal() @@ -314,11 +337,15 @@ //Antagonists parts += antag_report() + parts += hardcore_random_report() + CHECK_TICK //Medals parts += medal_report() //Station Goals parts += goal_report() + //Economy & Money + parts += market_report() listclearnulls(parts) @@ -361,9 +388,9 @@ parts += "[FOURSPACES]Nobody died this shift!" if(istype(SSticker.mode, /datum/game_mode/dynamic)) var/datum/game_mode/dynamic/mode = SSticker.mode - mode.update_playercounts() - parts += "[FOURSPACES]Final threat level: [mode.threat_level]" - parts += "[FOURSPACES]Final threat: [mode.threat]" + 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]Executed rules:" for(var/datum/dynamic_ruleset/rule in mode.executed_rules) @@ -380,20 +407,47 @@ /client/proc/roundend_report_file() return "data/roundend_reports/[ckey].html" -/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C, previous = FALSE) +/** + * Log the round-end report as an HTML file + * + * Composits the roundend report, and saves it in two locations. + * The report is first saved along with the round's logs + * Then, the report is copied to a fixed directory specifically for + * housing the server's last roundend report. In this location, + * the file will be overwritten at the end of each shift. + */ +/datum/controller/subsystem/ticker/proc/log_roundend_report() + var/roundend_file = file("[GLOB.log_directory]/round_end_data.html") + var/list/parts = list() + parts += "
" + parts += GLOB.survivor_report + parts += "
" + parts += GLOB.common_report + var/content = parts.Join() + //Log the rendered HTML in the round log directory + fdel(roundend_file) + WRITE_FILE(roundend_file, content) + //Place a copy in the root folder, to be overwritten each round. + roundend_file = file("data/server_last_roundend_report.html") + fdel(roundend_file) + WRITE_FILE(roundend_file, content) + +/datum/controller/subsystem/ticker/proc/show_roundend_report(client/C, report_type = null) var/datum/browser/roundend_report = new(C, "roundend") roundend_report.width = 800 roundend_report.height = 600 var/content var/filename = C.roundend_report_file() - if(!previous) + if(report_type == PERSONAL_LAST_ROUND) //Look at this player's last round + content = file2text(filename) + else if (report_type == SERVER_LAST_ROUND) //Look at the last round that this server has seen + content = file2text("data/server_last_roundend_report.html") + else //report_type is null, so make a new report based on the current round and show that to the player var/list/report_parts = list(personal_report(C), GLOB.common_report) content = report_parts.Join() - remove_verb(C, /client/proc/show_previous_roundend_report) fdel(filename) text2file(content, filename) - else - content = file2text(filename) + roundend_report.set_content(content) roundend_report.stylesheets = list() roundend_report.add_stylesheet("roundend", 'html/browser/roundend.css') @@ -430,8 +484,9 @@ /datum/controller/subsystem/ticker/proc/display_report(popcount) GLOB.common_report = build_roundend_report() GLOB.survivor_report = survivor_report(popcount) + log_roundend_report() for(var/client/C in GLOB.clients) - show_roundend_report(C, FALSE) + show_roundend_report(C) give_show_report_button(C) CHECK_TICK @@ -449,12 +504,11 @@ if (aiPlayer.connected_robots.len) var/borg_num = aiPlayer.connected_robots.len - var/robolist = "
[aiPlayer.real_name]'s minions were: " + parts += "
[aiPlayer.real_name]'s minions were:" for(var/mob/living/silicon/robot/robo in aiPlayer.connected_robots) borg_num-- if(robo.mind) - robolist += "[robo.name][robo.mind.hide_ckey ? "" : " (Played by: [robo.mind.key])"] [robo.stat == DEAD ? " (Deactivated)" : ""][borg_num ?", ":""]
" - parts += "[robolist]" + parts += "[robo.name][robo.mind.hide_ckey ? "" : " (Played by: [robo.mind.key])"] [robo.stat == DEAD ? " (Deactivated)" : ""][borg_num ?", ":""]" if(!borg_spacer) borg_spacer = TRUE @@ -481,6 +535,34 @@ parts += G.get_result() return "
" +///Generate a report for how much money is on station, as well as the richest crewmember on the station. +/datum/controller/subsystem/ticker/proc/market_report() + var/list/parts = list() + parts += "Station Economic Summary:" + ///This is the richest account on station at roundend. + var/datum/bank_account/mr_moneybags + ///This is the station's total wealth at the end of the round. + var/station_vault = 0 + ///How many players joined the round. + var/total_players = GLOB.joined_player_list.len + var/list/typecache_bank = typecacheof(list(/datum/bank_account/department, /datum/bank_account/remote)) + for(var/i in SSeconomy.generated_accounts) + var/datum/bank_account/current_acc = SSeconomy.generated_accounts[i] + if(typecache_bank[current_acc.type]) + continue + station_vault += current_acc.account_balance + if(!mr_moneybags || mr_moneybags.account_balance < current_acc.account_balance) + mr_moneybags = current_acc + parts += "
There were [station_vault] credits collected by crew this shift.
" + if(total_players > 0) + parts += "An average of [station_vault/total_players] credits were collected.
" + // log_econ("Roundend credit total: [station_vault] credits. Average Credits: [station_vault/total_players]") + if(mr_moneybags) + parts += "The most affluent crew member at shift end was [mr_moneybags.account_holder] with [mr_moneybags.account_balance] cr!
" + else + parts += "Somehow, nobody made any money this shift! This'll result in some budget cuts..." + return parts + /datum/controller/subsystem/ticker/proc/medal_report() if(GLOB.commendations.len) var/list/parts = list() @@ -490,16 +572,40 @@ return "
[parts.Join("
")]
" return "" +///Generate a report for all players who made it out alive with a hardcore random character and prints their final score +/datum/controller/subsystem/ticker/proc/hardcore_random_report() + . = list() + var/list/hardcores = list() + for(var/i in GLOB.player_list) + if(!ishuman(i)) + continue + var/mob/living/carbon/human/human_player = i + if(!human_player.hardcore_survival_score || !human_player.onCentCom() || human_player.stat == DEAD) ///gotta escape nerd + continue + if(!human_player.mind) + continue + hardcores += human_player + if(!length(hardcores)) + return + . += "
The following people made it out as a random hardcore character:" + . += "
" + /datum/controller/subsystem/ticker/proc/antag_report() var/list/result = list() var/list/all_teams = list() var/list/all_antagonists = list() + // for(var/datum/team/A in GLOB.antagonist_teams) + // all_teams |= A + for(var/datum/antagonist/A in GLOB.antagonists) if(!A.owner) continue all_teams |= A.get_team() - all_antagonists += A + all_antagonists |= A for(var/datum/team/T in all_teams) result += T.roundend_report() @@ -552,9 +658,9 @@ /datum/action/report/Trigger() if(owner && GLOB.common_report && SSticker.current_state == GAME_STATE_FINISHED) - SSticker.show_roundend_report(owner.client, FALSE) + SSticker.show_roundend_report(owner.client) -/datum/action/report/IsAvailable(silent = FALSE) +/datum/action/report/IsAvailable() return 1 /datum/action/report/Topic(href,href_list) @@ -569,7 +675,9 @@ var/jobtext = "" if(ply.assigned_role) jobtext = " the [ply.assigned_role]" - var/text = "[ply.hide_ckey ? "[ply.name][jobtext] " : "[ply.key] was [ply.name][jobtext] and "]" + var/text = (ply.hide_ckey ? \ + "[ply.key] was [ply.name][jobtext] and" \ + : "[ply.name][jobtext]") if(ply.current) if(ply.current.stat == DEAD) text += " died" diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index 53a6f54062..dec44653af 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -666,7 +666,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) if(fexists(log)) oldjson = json_decode(file2text(log)) oldentries = oldjson["data"] - if(!isemptylist(oldentries)) + if(length(oldentries)) for(var/string in accepted) for(var/old in oldentries) if(string == old) @@ -676,7 +676,7 @@ GLOBAL_LIST_INIT(binary, list("0","1")) var/list/finalized = list() finalized = accepted.Copy() + oldentries.Copy() //we keep old and unreferenced phrases near the bottom for culling listclearnulls(finalized) - if(!isemptylist(finalized) && length(finalized) > storemax) + if(length(finalized) > storemax) finalized.Cut(storemax + 1) fdel(log) diff --git a/code/controllers/subsystem/shuttle.dm b/code/controllers/subsystem/shuttle.dm index bd086ab245..bcf28839f0 100644 --- a/code/controllers/subsystem/shuttle.dm +++ b/code/controllers/subsystem/shuttle.dm @@ -26,6 +26,7 @@ SUBSYSTEM_DEF(shuttle) var/emergencyCallAmount = 0 //how many times the escape shuttle was called var/emergencyNoEscape var/emergencyNoRecall = FALSE + var/adminEmergencyNoRecall = FALSE var/list/hostileEnvironments = list() //Things blocking escape shuttle from leaving var/list/tradeBlockade = list() //Things blocking cargo from leaving. var/supplyBlocked = FALSE @@ -136,7 +137,7 @@ SUBSYSTEM_DEF(shuttle) break /datum/controller/subsystem/shuttle/proc/CheckAutoEvac() - if(emergencyNoEscape || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted()) + if(emergencyNoEscape || adminEmergencyNoRecall || emergencyNoRecall || !emergency || !SSticker.HasRoundStarted()) return var/threshold = CONFIG_GET(number/emergency_shuttle_autocall_threshold) @@ -181,38 +182,26 @@ SUBSYSTEM_DEF(shuttle) return S WARNING("couldn't find dock with id: [id]") -/datum/controller/subsystem/shuttle/proc/canEvac(mob/user, silent=FALSE) +/// Check if we can call the evac shuttle. +/// Returns TRUE if we can. Otherwise, returns a string detailing the problem. +/datum/controller/subsystem/shuttle/proc/canEvac(mob/user) var/srd = CONFIG_GET(number/shuttle_refuel_delay) if(world.time - SSticker.round_start_time < srd) - if(!silent) - to_chat(user, "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before trying again.") - return FALSE + return "The emergency shuttle is refueling. Please wait [DisplayTimeText(srd - (world.time - SSticker.round_start_time))] before attempting to call." switch(emergency.mode) if(SHUTTLE_RECALL) - if(!silent) - to_chat(user, "The emergency shuttle may not be called while returning to CentCom.") - return FALSE + return "The emergency shuttle may not be called while returning to CentCom." if(SHUTTLE_CALL) - if(!silent) - to_chat(user, "The emergency shuttle is already on its way.") - return FALSE + return "The emergency shuttle is already on its way." if(SHUTTLE_DOCKED) - if(!silent) - to_chat(user, "The emergency shuttle is already here.") - return FALSE + return "The emergency shuttle is already here." if(SHUTTLE_IGNITING) - if(!silent) - to_chat(user, "The emergency shuttle is firing its engines to leave.") - return FALSE + return "The emergency shuttle is firing its engines to leave." if(SHUTTLE_ESCAPE) - if(!silent) - to_chat(user, "The emergency shuttle is moving away to a safe distance.") - return FALSE + return "The emergency shuttle is moving away to a safe distance." if(SHUTTLE_STRANDED) - if(!silent) - to_chat(user, "The emergency shuttle has been disabled by CentCom.") - return FALSE + return "The emergency shuttle has been disabled by CentCom." return TRUE @@ -230,7 +219,9 @@ SUBSYSTEM_DEF(shuttle) Good luck.") emergency = backup_shuttle - if(!canEvac(user)) + var/can_evac_or_fail_reason = SSshuttle.canEvac(user) + if(can_evac_or_fail_reason != TRUE) + to_chat(user, "[can_evac_or_fail_reason]") return call_reason = trim(html_encode(call_reason)) @@ -259,10 +250,11 @@ SUBSYSTEM_DEF(shuttle) var/area/A = get_area(user) log_shuttle("[key_name(user)] has called the emergency shuttle.") - deadchat_broadcast(" has called the shuttle at [A.name].", "[user.real_name]", user) + deadchat_broadcast(" has called the shuttle at [A.name].", "[user.real_name]", user) //, message_type=DEADCHAT_ANNOUNCEMENT) if(call_reason) SSblackbox.record_feedback("text", "shuttle_reason", 1, "[call_reason]") log_shuttle("Shuttle call reason: [call_reason]") + SSticker.emergency_reason = call_reason message_admins("[ADMIN_LOOKUPFLW(user)] has called the shuttle. (TRIGGER CENTCOM RECALL)") /datum/controller/subsystem/shuttle/proc/centcom_recall(old_timer, admiral_message) @@ -297,7 +289,7 @@ SUBSYSTEM_DEF(shuttle) emergency.cancel(get_area(user)) log_shuttle("[key_name(user)] has recalled the shuttle.") message_admins("[ADMIN_LOOKUPFLW(user)] has recalled the shuttle.") - deadchat_broadcast(" has recalled the shuttle from [get_area_name(user, TRUE)].", "[user.real_name]", user) + deadchat_broadcast(" has recalled the shuttle from [get_area_name(user, TRUE)].", "[user.real_name]", user) //, message_type=DEADCHAT_ANNOUNCEMENT) return 1 /datum/controller/subsystem/shuttle/proc/canRecall() @@ -323,7 +315,7 @@ SUBSYSTEM_DEF(shuttle) if (!SSticker.IsRoundInProgress()) return - var/callShuttle = 1 + var/callShuttle = TRUE for(var/thing in GLOB.shuttle_caller_list) if(isAI(thing)) @@ -339,7 +331,7 @@ SUBSYSTEM_DEF(shuttle) var/turf/T = get_turf(thing) if(T && is_station_level(T.z)) - callShuttle = 0 + callShuttle = FALSE break if(callShuttle) @@ -415,7 +407,7 @@ SUBSYSTEM_DEF(shuttle) else if(M.initiate_docking(getDock(destination)) != DOCKING_SUCCESS) return 2 - return 0 //dock successful + return 0 //dock successful /datum/controller/subsystem/shuttle/proc/moveShuttle(shuttleId, dockId, timed) diff --git a/code/controllers/subsystem/ticker.dm b/code/controllers/subsystem/ticker.dm index 884e209512..f37feeea34 100755 --- a/code/controllers/subsystem/ticker.dm +++ b/code/controllers/subsystem/ticker.dm @@ -69,6 +69,7 @@ SUBSYSTEM_DEF(ticker) var/modevoted = FALSE //Have we sent a vote for the gamemode? var/station_integrity = 100 // stored at roundend for use in some antag goals + var/emergency_reason /datum/controller/subsystem/ticker/Initialize(timeofday) load_mode() @@ -563,7 +564,10 @@ SUBSYSTEM_DEF(ticker) if(STATION_DESTROYED_NUKE) news_message = "We would like to reassure all employees that the reports of a Syndicate backed nuclear attack on [station_name()] are, in fact, a hoax. Have a secure day!" if(STATION_EVACUATED) - news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity." + if(emergency_reason) + news_message = "[station_name()] has been evacuated after transmitting the following distress beacon:\n\n[emergency_reason]" + else + news_message = "The crew of [station_name()] has been evacuated amid unconfirmed reports of enemy activity." if(BLOB_WIN) news_message = "[station_name()] was overcome by an unknown biological outbreak, killing all crew on board. Don't let it happen to you! Remember, a clean work station is a safe work station." if(BLOB_NUKE) @@ -589,7 +593,7 @@ SUBSYSTEM_DEF(ticker) if(WIZARD_KILLED) news_message = "Tensions have flared with the Space Wizard Federation following the death of one of their members aboard [station_name()]." if(STATION_NUKED) - news_message = "[station_name()] activated its self destruct device for unknown reasons. Attempts to clone the Captain so he can be arrested and executed are underway." + news_message = "[station_name()] activated its self-destruct device for unknown reasons. Attempts to clone the Captain so he can be arrested and executed are underway." if(CLOCK_SUMMON) news_message = "The garbled messages about hailing a mouse and strange energy readings from [station_name()] have been discovered to be an ill-advised, if thorough, prank by a clown." if(CLOCK_SILICONS) @@ -604,7 +608,8 @@ SUBSYSTEM_DEF(ticker) if(SSblackbox.first_death) var/list/ded = SSblackbox.first_death if(ded.len) - news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : ""]" + var/last_words = ded["last_words"] ? " Their last words were: \"[ded["last_words"]]\"" : "" + news_message += " NT Sanctioned Psykers picked up faint traces of someone near the station, allegedly having had died. Their name was: [ded["name"]], [ded["role"]], at [ded["area"]].[last_words]" else news_message += " NT Sanctioned Psykers proudly confirm reports that nobody died this shift!"