diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm
index f3e067984a8..894b71d356b 100644
--- a/code/__HELPERS/unsorted.dm
+++ b/code/__HELPERS/unsorted.dm
@@ -542,6 +542,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
var/list/sortmob = sortAtom(mob_list)
for(var/mob/living/silicon/ai/M in sortmob)
moblist.Add(M)
+ if(M.eyeobj)
+ moblist.Add(M.eyeobj)
for(var/mob/living/silicon/pai/M in sortmob)
moblist.Add(M)
for(var/mob/living/silicon/robot/M in sortmob)
diff --git a/code/game/gamemodes/blob/overmind.dm b/code/game/gamemodes/blob/overmind.dm
index 5a9e5af05d7..daf7763b7da 100644
--- a/code/game/gamemodes/blob/overmind.dm
+++ b/code/game/gamemodes/blob/overmind.dm
@@ -92,7 +92,7 @@
for (var/mob/M in dead_mob_list)
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain)) //No meta-evesdropping
- rendered = "Blob Telepathy, [name] (follow) [verb] \"[message]\""
+ rendered = "Blob Telepathy, [name] ([ghost_follow_link(src, ghost=M)]) [verb] \"[message]\""
M.show_message(rendered, 2)
/mob/camera/blob/emote(var/act,var/m_type=1,var/message = null)
diff --git a/code/modules/admin/admin.dm b/code/modules/admin/admin.dm
index 06e13d53068..2d6be2a6dbb 100644
--- a/code/modules/admin/admin.dm
+++ b/code/modules/admin/admin.dm
@@ -56,7 +56,7 @@ var/global/nologevent = 0
TP -
PM -
SM -
- JMP\]
+ [admin_jump_link(M, src)]\]
Mob type = [M.type]
Kick |
Warn |
@@ -79,8 +79,13 @@ var/global/nologevent = 0
(toggle all)
"}
+ var/jumptoeye = ""
+ if(isAI(M))
+ var/mob/living/silicon/ai/A = M
+ if(A.client && A.eyeobj) // No point following clientless AI eyes
+ jumptoeye = " (Eye)"
body += {"
- Jump to |
+ Jump to[jumptoeye] |
Get |
Send To
diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm
index 3025296bb71..ff98278ce90 100644
--- a/code/modules/admin/player_panel.dm
+++ b/code/modules/admin/player_panel.dm
@@ -61,7 +61,7 @@
}
- function expand(id,job,name,real_name,image,key,ip,antagonist,ref){
+ function expand(id,job,name,real_name,image,key,ip,antagonist,ref,eyeref){
clearAll();
@@ -81,7 +81,10 @@
body += "TP - "
body += "PM - "
body += "SM - "
- body += "JMP
"
+ body += "JMP"
+ if(eyeref)
+ body += "|EYE"
+ body += "
"
if(antagonist > 0)
body += "Antagonist";
@@ -287,6 +290,11 @@
M_key = replacetext(M_key, "\"", "")
M_key = replacetext(M_key, "\\", "")
+ var/M_eyeref = ""
+ if(isAI(M))
+ var/mob/living/silicon/ai/A = M
+ if(A.client && A.eyeobj) // No point following clientless AI eyes
+ M_eyeref = "\ref[A.eyeobj]"
//output for each mob
dat += {"
@@ -294,7 +302,7 @@
[M_name] - [M_rname] - [M_key] ([M_job])
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index c34147845cb..93a1e32cd79 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1558,7 +1558,7 @@
src.owner << "Name = [M.name]; Real_name = [M.real_name]; Mind_name = [M.mind?"[M.mind.name]":""]; Key = [M.key];"
src.owner << "Location = [location_description];"
src.owner << "[special_role_description]"
- src.owner << "(PM) (PP) (VV) (SM) (JMP) (CA)"
+ src.owner << "(PM) (PP) (VV) (SM) ([admin_jump_link(M, src)]) (CA)"
else if(href_list["adminspawncookie"])
if(!check_rights(R_ADMIN|R_EVENT)) return
@@ -2990,3 +2990,26 @@
current_tab = text2num(href_list["tab"])
Secrets(usr)
return 1
+
+/proc/admin_jump_link(var/atom/target, var/source)
+ if(!target) return
+ // The way admin jump links handle their src is weirdly inconsistent...
+ if(istype(source, /datum/admins))
+ source = "src=\ref[source]"
+ else
+ source = "_src_=holder"
+
+ if(isAI(target)) // AI core/eye follow links
+ var/mob/living/silicon/ai/A = target
+ . = "JMP"
+ if(A.client && A.eyeobj) // No point following clientless AI eyes
+ . += "|EYE"
+ return
+ else if(istype(target, /mob/dead/observer))
+ var/mob/dead/observer/O = target
+ . = "JMP"
+ if(O.mind && O.mind.current)
+ . += "|BDY"
+ return
+ else
+ return "JMP"
diff --git a/code/modules/admin/verbs/adminhelp.dm b/code/modules/admin/verbs/adminhelp.dm
index 2dd6ed7f892..0a4b63a6892 100644
--- a/code/modules/admin/verbs/adminhelp.dm
+++ b/code/modules/admin/verbs/adminhelp.dm
@@ -94,7 +94,7 @@ var/list/adminhelp_ignored_words = list("unknown","the","a","an","of","monkey","
if(!mob) return //this doesn't happen
var/ref_mob = "\ref[mob]"
- msg = "\blue [selected_type]: [key_name(src, 1, 1, selected_type)] (?) (PP) (VV) (SM) (JMP) (CA) [ai_found ? " (CL)" : ""]: [msg]"
+ msg = "\blue [selected_type]: [key_name(src, 1, 1, selected_type)] (?) (PP) (VV) (SM) ([admin_jump_link(mob, "holder")]) (CA) [ai_found ? " (CL)" : ""]: [msg]"
//send this msg to all admins
var/admin_number_afk = 0
diff --git a/code/modules/admin/verbs/adminsay.dm b/code/modules/admin/verbs/adminsay.dm
index 209ce6b0b32..cf0ec78a9b5 100644
--- a/code/modules/admin/verbs/adminsay.dm
+++ b/code/modules/admin/verbs/adminsay.dm
@@ -12,7 +12,7 @@
if(check_rights(R_ADMIN,0))
for(var/client/C in admins)
if(R_ADMIN & C.holder.rights)
- C << "ADMIN: [key_name(usr, 1)] (JMP): [msg]"
+ C << "ADMIN: [key_name(usr, 1)] ([admin_jump_link(mob, "holder")]): [msg]"
feedback_add_details("admin_verb","M") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -34,6 +34,6 @@
spanclass = "mod_channel_admin"
for(var/client/C in admins)
if(R_MOD & C.holder.rights)
- C << "MOD: [key_name(usr, 1)] (JMP): [msg]"
+ C << "MOD: [key_name(usr, 1)] ([admin_jump_link(mob, C.holder)]): [msg]"
feedback_add_details("admin_verb","MS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
\ No newline at end of file
diff --git a/code/modules/admin/verbs/pray.dm b/code/modules/admin/verbs/pray.dm
index f259207dcc4..3fa1386aa07 100644
--- a/code/modules/admin/verbs/pray.dm
+++ b/code/modules/admin/verbs/pray.dm
@@ -13,7 +13,7 @@
return
var/image/cross = image('icons/obj/storage.dmi',"bible")
- msg = "\blue \icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) (JMP) (CA) (SC): [msg]"
+ msg = "\blue \icon[cross] PRAY: [key_name(src, 1)] (?) (PP) (VV) (SM) ([admin_jump_link(src, "holder")]) (CA) (SC): [msg]"
for(var/client/X in admins)
if(R_EVENT & X.holder.rights)
@@ -26,7 +26,7 @@
/proc/Centcomm_announce(var/text , var/mob/Sender)
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
- msg = "\blue CENTCOMM:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]"
+ msg = "\blue CENTCOMM:[key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (RPLY): [msg]"
for(var/client/X in admins)
if(R_EVENT & X.holder.rights)
@@ -34,7 +34,7 @@
/proc/Syndicate_announce(var/text , var/mob/Sender)
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
- msg = "\blue SYNDICATE: [key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (REPLY): [msg]"
+ msg = "\blue SYNDICATE: [key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (REPLY): [msg]"
for(var/client/X in admins)
if(R_EVENT & X.holder.rights)
@@ -42,7 +42,7 @@
/proc/HONK_announce(var/text , var/mob/Sender)
var/msg = sanitize(copytext(text, 1, MAX_MESSAGE_LEN))
- msg = "\blue HONK:[key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (RPLY): [msg]"
+ msg = "\blue HONK:[key_name(Sender, 1)] (PP) (VV) (SM) ([admin_jump_link(Sender, "holder")]) (CA) (BSA) (RPLY): [msg]"
for(var/client/X in admins)
if(R_EVENT & X.holder.rights)
diff --git a/code/modules/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index d92ef4d3047..0635d5aa894 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -499,6 +499,23 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
return ..()
+/proc/ghost_follow_link(var/atom/target, var/atom/ghost)
+ if((!target) || (!ghost)) return
+ if(isAI(target)) // AI core/eye follow links
+ var/mob/living/silicon/ai/A = target
+ . = "core"
+ if(A.client && A.eyeobj) // No point following clientless AI eyes
+ . += "|eye"
+ return
+ else if(istype(target, /mob/dead/observer))
+ var/mob/dead/observer/O = target
+ . = "follow"
+ if(O.mind && O.mind.current)
+ . += "|body"
+ return
+ else
+ return "follow"
+
//BEGIN TELEPORT HREF CODE
/mob/dead/observer/Topic(href, href_list)
if(usr != src)
@@ -512,26 +529,8 @@ This is the proc mobs get to turn into a ghost. Forked from ghostize due to comp
if (href_list["follow"])
var/atom/target = locate(href_list["follow"])
- var/mob/A = usr;
- A << "You are now following [target]"
- //var/mob/living/silicon/ai/A = locate(href_list["track2"]) in mob_list
- if(target && target != usr)
- following = target
- spawn(0)
- var/turf/pos = get_turf(A)
- while(A.loc == pos)
-
- var/turf/T = get_turf(target)
- if(!T)
- break
- if(following != target)
- break
- if(!client)
- break
- A.loc = T
- pos = A.loc
- sleep(15)
- following = null
+ if(target)
+ ManualFollow(target)
if (href_list["jump"])
var/mob/target = locate(href_list["jump"])
diff --git a/code/modules/mob/hear_say.dm b/code/modules/mob/hear_say.dm
index 1a5272b63fd..34176d34108 100644
--- a/code/modules/mob/hear_say.dm
+++ b/code/modules/mob/hear_say.dm
@@ -55,7 +55,7 @@
return
if(speaker_name != speaker.real_name && speaker.real_name)
speaker_name = "[speaker.real_name] ([speaker_name])"
- track = "(follow) "
+ track = "([ghost_follow_link(speaker, ghost=src)]) "
if(client.prefs.toggles & CHAT_GHOSTEARS && speaker in view(src))
message = "[message]"
@@ -170,7 +170,7 @@
if(istype(src, /mob/dead/observer))
if(speaker_name != speaker.real_name && !isAI(speaker)) //Announce computer and various stuff that broadcasts doesn't use it's real name but AI's can't pretend to be other mobs.
speaker_name = "[speaker.real_name] ([speaker_name])"
- track = "[speaker_name] (follow)"
+ track = "[speaker_name] ([ghost_follow_link(follow_target, ghost=src)])"
var/formatted
if(language)
diff --git a/code/modules/mob/language.dm b/code/modules/mob/language.dm
index 60b2c20636a..29b1f465b60 100644
--- a/code/modules/mob/language.dm
+++ b/code/modules/mob/language.dm
@@ -104,7 +104,7 @@
for(var/mob/player in player_list)
if(istype(player,/mob/dead) && follow)
- var/msg_dead = "[name], [speaker_mask] (follow) [format_message(message, get_spoken_verb(message))]"
+ var/msg_dead = "[name], [speaker_mask] ([ghost_follow_link(speaker, ghost=player)]) [format_message(message, get_spoken_verb(message))]"
player << msg_dead
continue
@@ -446,7 +446,7 @@
for (var/mob/M in dead_mob_list)
if(!istype(M,/mob/new_player) && !istype(M,/mob/living/carbon/brain))
- var/message_start_dead = "[name], [speaker.name] (follow)"
+ var/message_start_dead = "[name], [speaker.name] ([ghost_follow_link(speaker, ghost=M)])"
M.show_message("[message_start_dead] [message_body]", 2)
for (var/mob/living/S in living_mob_list)
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index ee033e91935..3383ad1eab9 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -473,9 +473,9 @@ var/list/intents = list("help","disarm","grab","harm")
var/lname
if(subject)
if(subject != M)
- follow = "(follow) "
+ follow = "([ghost_follow_link(subject, ghost=M)]) "
if(M.stat != DEAD && M.client.holder)
- follow = "(JMP) "
+ follow = "([admin_jump_link(subject, M.client.holder)]) "
var/mob/dead/observer/DM
if(istype(subject, /mob/dead/observer))
DM = subject
diff --git a/code/modules/paperwork/faxmachine.dm b/code/modules/paperwork/faxmachine.dm
index f01aa60d704..80319363248 100644
--- a/code/modules/paperwork/faxmachine.dm
+++ b/code/modules/paperwork/faxmachine.dm
@@ -260,7 +260,7 @@ var/list/alldepartments = list()
/obj/machinery/photocopier/faxmachine/proc/message_admins(var/mob/sender, var/faxname, var/faxtype, var/obj/item/sent, font_colour="#006100")
- var/msg = "\blue [faxname]: [key_name(sender, 1)] (PP) (VV) (SM) (JMP) (CA) (BSA) (REPLY): Receiving '[sent.name]' via secure connection... view message"
+ var/msg = "\blue [faxname]: [key_name(sender, 1)] (PP) (VV) (SM) ([admin_jump_link(sender, "holder")]) (CA) (BSA) (REPLY): Receiving '[sent.name]' via secure connection... view message"
for(var/client/C in admins)
if(R_EVENT & C.holder.rights)
|