diff --git a/code/datums/brain_damage/imaginary_friend.dm b/code/datums/brain_damage/imaginary_friend.dm
index 0c7a5ae1728d..697f5d0749d5 100644
--- a/code/datums/brain_damage/imaginary_friend.dm
+++ b/code/datums/brain_damage/imaginary_friend.dm
@@ -102,6 +102,11 @@
/mob/camera/imaginary_friend/Initialize(mapload, mob/living/imaginary_friend_owner, datum/preferences/appearance_from_prefs = null)
. = ..()
+ //Monkestation Edit Begin
+ if(istype(src, /mob/camera/imaginary_friend/mentor))
+ return
+ //Monkestation Edit End
+
owner = imaginary_friend_owner
if(appearance_from_prefs)
diff --git a/code/modules/admin/admin_verbs.dm b/code/modules/admin/admin_verbs.dm
index 5f61e2bc7035..3996958b326d 100644
--- a/code/modules/admin/admin_verbs.dm
+++ b/code/modules/admin/admin_verbs.dm
@@ -274,6 +274,7 @@ GLOBAL_PROTECT(admin_verbs_poll)
var/rights = holder.rank_flags()
add_verb(src, GLOB.admin_verbs_default)
+ add_verb(GLOB.mentor_verbs) //Monkestation Edit
if(rights & R_BUILD)
add_verb(src, /client/proc/togglebuildmodeself)
if(rights & R_ADMIN)
@@ -320,7 +321,8 @@ GLOBAL_PROTECT(admin_verbs_poll)
/*Debug verbs added by "show debug verbs"*/
GLOB.admin_verbs_debug_mapping,
/client/proc/disable_mapping_verbs,
- /client/proc/readmin
+ /client/proc/readmin,
+ GLOB.mentor_verbs //Monkestation Edit
))
/client/proc/hide_verbs()
diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm
index 5e176fb3741d..733bb4b63c0b 100644
--- a/code/modules/client/client_procs.dm
+++ b/code/modules/client/client_procs.dm
@@ -115,6 +115,11 @@ GLOBAL_LIST_INIT(blacklisted_builds, list(
no_tgui_adminhelp(input(src, "Enter your ahelp", "Ahelp") as null|message)
return
+ //Monkestation Edit Begin
+ if(mentor_friend(href_list))
+ return
+ //Monkestation Edit End
+
switch(href_list["_src_"])
if("holder")
hsrc = holder
diff --git a/monkestation/code/modules/clothing/outfits/special.dm b/monkestation/code/modules/clothing/outfits/special.dm
new file mode 100644
index 000000000000..f05e87741a6a
--- /dev/null
+++ b/monkestation/code/modules/clothing/outfits/special.dm
@@ -0,0 +1,3 @@
+/datum/outfit/job/mentor
+ uniform = /obj/item/clothing/under/color/lightpurple
+ shoes = /obj/item/clothing/shoes/sneakers/purple
diff --git a/monkestation/code/modules/mentor/__GLOBALVARS.dm b/monkestation/code/modules/mentor/__GLOBALVARS.dm
index 877ff617abeb..d17b943e0fd1 100644
--- a/monkestation/code/modules/mentor/__GLOBALVARS.dm
+++ b/monkestation/code/modules/mentor/__GLOBALVARS.dm
@@ -7,4 +7,6 @@ GLOBAL_LIST_INIT(mentor_verbs, list(
/client/proc/cmd_mentor_say,
/client/proc/mentor_requests,
/client/proc/toggle_mentor_states,
+ /client/proc/imaginary_friend,
+ /client/proc/end_imaginary_friendship
))
diff --git a/monkestation/code/modules/mentor/mentor_friend.dm b/monkestation/code/modules/mentor/mentor_friend.dm
new file mode 100644
index 000000000000..06bfdf5810b4
--- /dev/null
+++ b/monkestation/code/modules/mentor/mentor_friend.dm
@@ -0,0 +1,174 @@
+//Section for the Mentor Friend verb run test
+
+/client/proc/imaginary_friend()
+ set category = "Mentor"
+ set name = "Become Imaginary Friend"
+
+ if(!usr.client.is_mentor())
+ return
+
+ if(istype(usr, /mob/camera/imaginary_friend/mentor))
+ to_chat(usr, span_warning("You are already someone's imaginary friend!"))
+ return
+
+ if(!isobserver(usr))
+ to_chat(usr, span_warning("You can only be an imaginary friend when you are observing."))
+ return
+
+ var/mob/living/mentee
+
+ switch(input("Select by:", "Imaginary Friend") as null|anything in list("Key", "Mob"))
+ if("Key")
+ var/client/friendclient = input("Please, select a key.", "Imaginary Friend") as null|anything in sort_key(GLOB.clients)
+ if(!friendclient)
+ return
+ mentee = friendclient.mob
+ if("Mob")
+ var/mob/friendmob = input("Please, select a mob.", "Imaginary Friend") as null|anything in sort_names(GLOB.alive_player_list)
+ if(!friendmob)
+ return
+ mentee = friendmob
+
+ if(!isobserver(usr))
+ return
+
+ if(!istype(mentee))
+ to_chat(usr, span_warning("Selected mob is not alive."))
+ return
+
+ var/mob/camera/imaginary_friend/mentor/mentorfriend = new(get_turf(mentee), mentee)
+ mentorfriend.key = usr.key
+
+ log_admin("[key_name(mentorfriend)] started being the imaginary friend of [key_name(mentee)].")
+ message_admins("[key_name(mentorfriend)] started being the imaginary friend of [key_name(mentee)].")
+
+/client/proc/end_imaginary_friendship()
+ set category = "Mentor"
+ set name = "End Imaginary Friendship"
+
+ if(!usr.client.is_mentor())
+ return
+
+ if(!istype(usr, /mob/camera/imaginary_friend/mentor))
+ to_chat(usr, span_warning("You aren't anybody's imaginary friend!"))
+ return
+
+ var/mob/camera/imaginary_friend/mentor/mentorfriend = usr
+ mentorfriend.unmentor()
+
+//Section for the Mentor Friend mob.
+/mob/camera/imaginary_friend/mentor
+ var/datum/action/innate/imaginary_leave/leave
+
+/mob/camera/imaginary_friend/mentor/greet()
+ to_chat(src, "You are the imaginary friend of [owner]!")
+ to_chat(src, "You are here to help [owner] in any way you can.")
+ to_chat(src, "You cannot directly influence the world around you, but you can see what [owner] cannot.")
+
+/mob/camera/imaginary_friend/mentor/Login()
+ . = ..()
+ setup_friend()
+ Show()
+
+/mob/camera/imaginary_friend/mentor/Logout()
+ . = ..()
+ if(!src.key)
+ return
+ unmentor()
+
+/mob/camera/imaginary_friend/mentor/Initialize(mapload, mob/imaginary_friend_owner, datum/preferences/appearance_from_prefs = null)
+ . = ..()
+
+ owner = imaginary_friend_owner
+
+ if(appearance_from_prefs)
+ INVOKE_ASYNC(src, PROC_REF(setup_friend_from_prefs), appearance_from_prefs)
+ else
+ INVOKE_ASYNC(src, PROC_REF(setup_friend))
+
+ join = new
+ join.Grant(src)
+ hide = new
+ hide.Grant(src)
+ leave = new
+ leave.Grant(src)
+
+ if(!owner.imaginary_group)
+ owner.imaginary_group = list(owner)
+ owner.imaginary_group += src
+
+/mob/camera/imaginary_friend/mentor/proc/unmentor()
+ icon = human_image
+ log_admin("[key_name(src)] stopped being the imaginary friend of [key_name(owner)].")
+ message_admins("[key_name(src)] stopped being the imaginary friend of [key_name(owner)].")
+ ghostize()
+ qdel(src)
+
+/mob/camera/imaginary_friend/mentor/recall()
+ if(QDELETED(owner))
+ unmentor()
+ return FALSE
+ if(loc == owner)
+ return FALSE
+ forceMove(owner)
+
+/datum/action/innate/imaginary_hide/mentor/Deactivate()
+ active = FALSE
+ var/mob/camera/imaginary_friend/I = owner
+ I.hidden = TRUE
+ I.Show()
+ name = "Show"
+ desc = "Become visible to your owner."
+ button_icon_state = "unhide"
+
+/datum/action/innate/imaginary_leave
+ name = "Leave"
+ desc = "Stop mentoring."
+ button_icon = 'icons/mob/actions/actions_spells.dmi'
+ background_icon_state = "bg_revenant"
+ button_icon_state = "mindswap"
+
+/datum/action/innate/imaginary_leave/Activate()
+ var/mob/camera/imaginary_friend/mentor/I = owner
+ I.unmentor()
+
+
+//For use with Mentor Friend (IF) topic calls
+
+/client/proc/create_ifriend(mob/living/friend_owner, seek_confirm = FALSE)
+ var/client/C = usr.client
+ if(!usr.client.is_mentor())
+ return
+
+ if(istype(C.mob, /mob/camera/imaginary_friend))
+ var/mob/camera/imaginary_friend/IF = C.mob
+ IF.ghostize()
+ return
+
+ if(!istype(friend_owner)) // living only
+ to_chat(usr, span_warning("That creature cannot have Imaginary Friends!"))
+ return
+
+ if(!isobserver(C.mob))
+ to_chat(usr, span_warning("You can only be an imaginary friend when you are observing."))
+ return
+
+
+ if(seek_confirm && alert(usr, "Become Imaginary Friend of [friend_owner]?", "Confirm" ,"Yes", "No") != "Yes")
+ return
+
+ var/mob/camera/imaginary_friend/mentor/mentorfriend = new(get_turf(friend_owner), friend_owner)
+ mentorfriend.key = usr.key
+
+ admin_ticket_log(friend_owner, "[key_name_admin(C)] became an imaginary friend of [key_name(friend_owner)]")
+ log_admin("[key_name(mentorfriend)] started being imaginary friend of [key_name(friend_owner)].")
+ message_admins("[key_name(mentorfriend)] started being the imaginary friend of [key_name(friend_owner)].")
+
+//topic call
+/client/proc/mentor_friend(href_list)
+ if(href_list["mentor_friend"])
+ var/mob/M = locate(href_list["mentor_friend"])
+ create_ifriend(M, TRUE)
+
+//for Mentor Chat Messages
+
diff --git a/monkestation/code/modules/mentor/mentor_help.dm b/monkestation/code/modules/mentor/mentor_help.dm
index 3ac1586ee6c8..0ab3587abcc2 100644
--- a/monkestation/code/modules/mentor/mentor_help.dm
+++ b/monkestation/code/modules/mentor/mentor_help.dm
@@ -75,7 +75,10 @@
return
msg = sanitize(copytext(msg,1,MAX_MESSAGE_LEN))
- var/mentor_msg = "MENTORHELP: [key_name_mentor(src, TRUE, FALSE)]: [msg]"
+ var/mentor_msg = "MENTORHELP: [key_name_mentor(src, TRUE, FALSE)] : [msg]"
+ //Monkestation Edit Begin
+ var/mentor_msg_observing = "MENTORHELP: [key_name_mentor(src, TRUE, FALSE)] (IF) : [msg]"
+ //Monkestation Edit End
log_mentor("MENTORHELP: [key_name_mentor(src, null, FALSE, FALSE)]: [msg]")
/// Send the Mhelp to all Mentors/Admins
@@ -83,10 +86,16 @@
if(QDELETED(honked_clients?.mentor_datum) || honked_clients?.mentor_datum?.not_active)
continue
SEND_SOUND(honked_clients, sound('sound/items/bikehorn.ogg'))
- to_chat(honked_clients,
- type = MESSAGE_TYPE_MODCHAT,
- html = mentor_msg,
- confidential = TRUE)
+ if(!isobserver(honked_clients.mob))
+ to_chat(honked_clients,
+ type = MESSAGE_TYPE_MODCHAT,
+ html = mentor_msg,
+ confidential = TRUE)
+ else
+ to_chat(honked_clients,
+ type = MESSAGE_TYPE_MODCHAT,
+ html = mentor_msg_observing,
+ confidential = TRUE)
/// Also show it to person Mhelping
to_chat(usr,
diff --git a/tgstation.dme b/tgstation.dme
index a27250eac80a..ee89f9f825bc 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -6605,6 +6605,7 @@
#include "monkestation\code\modules\clothing\neck\cloaks.dm"
#include "monkestation\code\modules\clothing\neck\neckties.dm"
#include "monkestation\code\modules\clothing\outfits\bunny.dm"
+#include "monkestation\code\modules\clothing\outfits\special.dm"
#include "monkestation\code\modules\clothing\shoes\clown.dm"
#include "monkestation\code\modules\clothing\shoes\shoe.dm"
#include "monkestation\code\modules\clothing\spacesuits\plasmamen.dm"
@@ -6878,6 +6879,7 @@
#include "monkestation\code\modules\mentor\keybinds.dm"
#include "monkestation\code\modules\mentor\mentor_datum.dm"
#include "monkestation\code\modules\mentor\mentor_follow.dm"
+#include "monkestation\code\modules\mentor\mentor_friend.dm"
#include "monkestation\code\modules\mentor\mentor_help.dm"
#include "monkestation\code\modules\mentor\mentor_logging.dm"
#include "monkestation\code\modules\mentor\mentor_manager.dm"