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/mob/dead/observer/observer.dm b/code/modules/mob/dead/observer/observer.dm
index d92ef4d3047..d4d4c53d74d 100644
--- a/code/modules/mob/dead/observer/observer.dm
+++ b/code/modules/mob/dead/observer/observer.dm
@@ -499,6 +499,17 @@ 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=src)
+ if(!target) 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
+ return "follow"
+
//BEGIN TELEPORT HREF CODE
/mob/dead/observer/Topic(href, href_list)
if(usr != src)
@@ -512,26 +523,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..e9e087ac366 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)]) "
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)])"
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..fb6dfa22f74 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -473,7 +473,7 @@ 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) "
var/mob/dead/observer/DM