diff --git a/code/__DEFINES/logs.dm b/code/__DEFINES/logs.dm
index 268ecb73ab3..5fd66c88f4a 100644
--- a/code/__DEFINES/logs.dm
+++ b/code/__DEFINES/logs.dm
@@ -4,5 +4,6 @@
#define SAY_LOG "Say"
#define EMOTE_LOG "Emote"
#define MISC_LOG "Misc"
+#define DEAD_CHAT_LOG "Dead chat"
-#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG)
+#define ALL_LOGS list(ATTACK_LOG, DEFENSE_LOG, CONVERSION_LOG, SAY_LOG, EMOTE_LOG, MISC_LOG, DEAD_CHAT_LOG)
diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index 2121ce8aee6..aedc16c4162 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -1946,16 +1946,6 @@ GLOBAL_DATUM_INIT(dview_mob, /mob/dview, new)
return pois
-/*
- * Returns all player mobs in an assoc list with ckey as key and the mob as value
-*/
-/proc/get_assoc_mob_list_by_ckey()
- var/list/mob/mobs = list()
- for(var/i in GLOB.player_list)
- var/mob/M = i
- mobs[M.ckey] = M
- return mobs
-
/proc/flash_color(mob_or_client, flash_color="#960000", flash_time=20)
var/client/C
if(istype(mob_or_client, /mob))
diff --git a/code/datums/log_viewer.dm b/code/datums/log_viewer.dm
index c9bad8a6736..5084feb1a9f 100644
--- a/code/datums/log_viewer.dm
+++ b/code/datums/log_viewer.dm
@@ -1,14 +1,23 @@
+#define UPDATE_CKEY_MOB(__ckey) var/mob/result = selected_ckeys_mobs[__ckey];\
+if(!result || result.ckey != __ckey){\
+ result = get_mob_by_ckey(__ckey);\
+ selected_ckeys_mobs[__ckey] = result;\
+}
+
/datum/log_viewer
var/time_from = 0
var/time_to = 4 HOURS // 4 Hours should be enough. INFINITY would screw the UI up
var/list/selected_mobs = list() // The mobs in question.
var/list/selected_ckeys = list() // The ckeys selected to search for. Will show all mobs the ckey is attached to
+ var/list/mob/selected_ckeys_mobs = list()
var/list/selected_log_types = ALL_LOGS // The log types being searched for
var/list/log_records = list() // Found and sorted records
/datum/log_viewer/proc/clear_all()
selected_mobs.Cut()
selected_log_types = ALL_LOGS
+ selected_ckeys.Cut()
+ selected_ckeys_mobs.Cut()
time_from = initial(time_from)
time_to = initial(time_to)
log_records.Cut()
@@ -103,15 +112,12 @@
if(!user || !user)
return
selected_ckeys |= ckey
+ UPDATE_CKEY_MOB(ckey)
show_ui(user)
/datum/log_viewer/proc/add_mob(mob/user, mob/M, show_the_ui = TRUE)
if(!M || !user)
return
- if(!M.ckey)
- if(alert(user, "No ckey found on the mob [M]. Use the last known ckey? This will add the ckey to the list of ckeys.", "No ckey bound to mob", "Yes", "No") == "Yes")
- add_ckey(user, M.last_known_ckey)
- return
selected_mobs |= M
@@ -123,7 +129,7 @@
var/trStyle = "border-top:1px solid; border-bottom:1px solid; padding-top: 5px; padding-bottom: 5px;"
var/dat
dat += "
"
- dat += ""
+ dat += "
"
dat += "
Time Search Range: [gameTimestamp(wtime = time_from)]"
dat += " To:
[gameTimestamp(wtime = time_to)]"
dat += "
"
@@ -133,26 +139,24 @@
var/mob/M = i
dat += "
[get_display_name(M)]"
dat += "
Add Mob"
- dat += "
Add Mob (by ckey)"
dat += "
Clear All Mobs"
dat += "
"
dat += "
Ckeys being used:"
for(var/ckey in selected_ckeys)
- dat += "
[ckey]"
+ dat += "
[get_ckey_name(ckey)]"
dat += "
Add ckey"
dat += "
Clear All ckeys"
dat += "
"
dat += "
Log Types:"
- for(var/i in all_log_types)
- var/log_type = i
+ for(var/log_type in all_log_types)
var/enabled = (log_type in selected_log_types)
var/text
var/style
if(enabled)
text = "
[log_type]"
- style = "background: [get_logtype_color(i)]"
+ style = "background: [get_logtype_color(log_type)]"
else
text = log_type
@@ -168,7 +172,7 @@
var/tdStyleType = "width:80px; text-align:center;"
var/tdStyleWho = "width:400px; text-align:center;"
var/tdStyleWhere = "width:150px; text-align:center;"
- dat += "
"
+ dat += "
"
dat += "
"
dat += "| When | Type | Who | What | Target | Where |
"
for(var/i in log_records)
@@ -224,6 +228,7 @@
return
if(href_list["clear_ckeys"])
selected_ckeys.Cut()
+ selected_ckeys_mobs.Cut()
show_ui(usr)
return
if(href_list["add_mob"])
@@ -231,11 +236,6 @@
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a mob: ", mobs)
A.on_close(CALLBACK(src, .proc/add_mob, usr))
return
- if(href_list["add_mob_ckey"])
- var/list/mobs = get_assoc_mob_list_by_ckey()
- var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a ckey: ", mobs)
- A.on_close(CALLBACK(src, .proc/add_mob, usr))
- return
if(href_list["add_ckey"])
var/list/ckeys = SSlogging.get_ckeys_logged()
var/datum/async_input/A = input_autocomplete_async(usr, "Please, select a ckey: ", ckeys)
@@ -274,6 +274,8 @@
return "deepskyblue"
if(MISC_LOG)
return "gray"
+ if(DEAD_CHAT_LOG)
+ return "#cc00c6"
return "slategray"
/datum/log_viewer/proc/get_display_name(mob/M)
@@ -282,4 +284,12 @@
name = "[name] ([M.real_name])"
if(isobserver(M))
name = "[name] (DEAD)"
- return name
+ return "\[[M.last_known_ckey]\] [name]"
+
+/datum/log_viewer/proc/get_ckey_name(ckey)
+ UPDATE_CKEY_MOB(ckey)
+ var/mob/M = selected_ckeys_mobs[ckey]
+
+ return get_display_name(M)
+
+#undef UPDATE_CKEY_MOB
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 386f395363e..33bef79fba1 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -1268,8 +1268,11 @@ GLOBAL_LIST_INIT(slot_equipment_priority, list( \
/mob/proc/create_log(log_type, what, target = null, turf/where = get_turf(src))
if(!ckey)
return
+ var/real_ckey = ckey
+ if(ckey[1] == "@") // Admin aghosting will do this
+ real_ckey = copytext(ckey, 2)
var/datum/log_record/record = new(log_type, src, what, target, where, world.time)
- SSlogging.add_log(ckey, record)
+ SSlogging.add_log(real_ckey, record)
/proc/create_log_in_list(list/target, text, collapse = TRUE, last_log)//forgive me code gods for this shitcode proc
//this proc enables lovely stuff like an attack log that looks like this: "[18:20:29-18:20:45]21x John Smith attacked Andrew Jackson with a crowbar."
diff --git a/code/modules/mob/say.dm b/code/modules/mob/say.dm
index 81d22e40a0b..87446bcf79e 100644
--- a/code/modules/mob/say.dm
+++ b/code/modules/mob/say.dm
@@ -55,6 +55,7 @@
return
say_dead_direct("[pick("complains", "moans", "whines", "laments", "blubbers", "salts")], \"[message]\"", src)
+ create_log(DEAD_CHAT_LOG, message)
/mob/proc/say_understands(var/mob/other, var/datum/language/speaking = null)
if(stat == DEAD)