mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-12 15:45:25 +01:00
Adds true observing -- letting you see what your target sees (#24855)
* bring it back now y'all * adds a bunch of other changes * pretty much works at this point * grep * Fixes some bugs, still chasing some down * Add observers to recursive mob check, ensuring they can see messages from their orbitted atom * tidy some things up * resolve * remove unnecessary checks * Address todos, minor cleanups * oh dear * initial testing * Fix some vulnerabilities (oops) * Fix some other bugs from testing * ci fixes * Add some contingencies against clicking things you shouldn't * fix some noted bugs * Add observe to admin jump, improve messaging * add a few more fixes that should mostly address some runtimes * oh this wasn't really great * one last thing * Fix suit inventory problem * Remove merge artifact * Add some missing parens * Prevents you from observing other ghosts, and should fix the getting stuck outside of your body issue. * we love testing * adds to player panel * Fix more bugs with observers getting stuck outside of their body * cleans up player panel, verb offerings * shit * Update code/_onclick/hud/alert.dm welp Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> * Fixes some targeting issues * Fixes targeting on aobserve * Fix some weird storage bugs * clean up some doulbed up follow links * Update code/modules/admin/player_panel.dm Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> * Adds some checks for ghost observe * Remove mentor debug log * ahhhhhhhhh that'll do it * Cleans up some additional checks that were not quite what they should have been * better logging, too * mochi review * one more thing * Gets robot huds mostly working * hopefully fix folks not getting observe * Fix order of operations causing a runtime on qdeleting * Remove some unnecessary stack traces * Apply suggestions from code review Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> * Fix bug with items in your inventory disappearing on changing HUD modes * Fix some bugs with the observe verbs * possibly fix nullspace issues * funny review * missed one --------- Signed-off-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com> Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com>
This commit is contained in:
@@ -12,6 +12,8 @@ GLOBAL_LIST_INIT(admin_verbs_admin, list(
|
||||
/client/proc/invisimin, /*allows our mob to go invisible/visible*/
|
||||
/datum/admins/proc/announce, /*priority announce something to all clients.*/
|
||||
/client/proc/admin_ghost, /*allows us to ghost/reenter body at will*/
|
||||
/client/proc/admin_observe, /*allows us to freely observe mobs */
|
||||
/client/proc/admin_observe_target, /*and gives it to us on right click*/
|
||||
/client/proc/toggle_view_range, /*changes how far we can see*/
|
||||
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
||||
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
||||
@@ -196,13 +198,17 @@ GLOBAL_LIST_INIT(admin_verbs_mod, list(
|
||||
/client/proc/dsay,
|
||||
/datum/admins/proc/show_player_panel,
|
||||
/client/proc/ban_panel,
|
||||
/client/proc/debug_variables /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
|
||||
/client/proc/debug_variables, /*allows us to -see- the variables of any instance in the game. +VAREDIT needed to modify*/
|
||||
/client/proc/admin_observe,
|
||||
/client/proc/admin_observe_target,
|
||||
))
|
||||
GLOBAL_LIST_INIT(admin_verbs_mentor, list(
|
||||
/client/proc/cmd_admin_pm_context, /*right-click adminPM interface*/
|
||||
/client/proc/cmd_admin_pm_panel, /*admin-pm list*/
|
||||
/client/proc/cmd_admin_pm_by_key_panel, /*admin-pm list by key*/
|
||||
/client/proc/openMentorTicketUI,
|
||||
/client/proc/admin_observe, /* Allow mentors to observe as well, though they face some limitations */
|
||||
/client/proc/admin_observe_target,
|
||||
/client/proc/cmd_mentor_say /* mentor say*/
|
||||
// cmd_mentor_say is added/removed by the toggle_mentor_chat verb
|
||||
))
|
||||
@@ -339,13 +345,22 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
|
||||
to_chat(src, "<span class='interface'>All of your adminverbs are now visible.</span>")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Show Admin Verbs") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/admin_ghost()
|
||||
set category = "Admin"
|
||||
set name = "Aghost"
|
||||
/client/proc/mentor_ghost()
|
||||
var/is_mentor = check_rights(R_MENTOR, FALSE)
|
||||
var/is_full_admin = check_rights(R_ADMIN|R_MOD, FALSE)
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
if(!is_mentor && !is_full_admin)
|
||||
to_chat(src, "<span class='warning'>You aren't allowed to use this!</span>")
|
||||
return
|
||||
|
||||
// mentors are allowed only if they have the observe trait, which is given on observe.
|
||||
// they should also not be given this proc.
|
||||
if(!is_full_admin && (is_mentor && !HAS_MIND_TRAIT(mob, TRAIT_MENTOR_OBSERVING) || !is_mentor))
|
||||
return
|
||||
|
||||
do_aghost()
|
||||
|
||||
/client/proc/do_aghost()
|
||||
if(isobserver(mob))
|
||||
//re-enter
|
||||
var/mob/dead/observer/ghost = mob
|
||||
@@ -372,6 +387,134 @@ GLOBAL_LIST_INIT(view_runtimes_verbs, list(
|
||||
// TODO: SStgui.on_transfer() to move windows from old and new
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Aghost") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
|
||||
/client/proc/admin_ghost()
|
||||
set category = "Admin"
|
||||
set name = "Aghost"
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD))
|
||||
return
|
||||
|
||||
do_aghost()
|
||||
|
||||
/// Allow an admin to observe someone.
|
||||
/// mentors are allowed to use this verb while living, but with some stipulations:
|
||||
/// if they attempt to do anything that would stop their orbit, they will immediately be returned to their body.
|
||||
/client/proc/admin_observe()
|
||||
set name = "Aobserve"
|
||||
set category = "Admin"
|
||||
if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
|
||||
return
|
||||
|
||||
if(isnewplayer(mob))
|
||||
to_chat(src, "<span class='warning'>You cannot aobserve while in the lobby. Please join or observe first.</span>")
|
||||
return
|
||||
|
||||
var/mob/target
|
||||
|
||||
target = tgui_input_list(mob, "Select a mob to observe", "Aobserve", GLOB.player_list)
|
||||
if(isnull(target))
|
||||
return
|
||||
if(target == src)
|
||||
to_chat(src, "<span class='warning'>You can't observe yourself!</span>")
|
||||
return
|
||||
|
||||
if(isobserver(target))
|
||||
to_chat(src, "<span class='warning'>[target] is a ghost, and cannot be observed.</span>")
|
||||
return
|
||||
|
||||
if(isnewplayer(target))
|
||||
to_chat(src, "<span class='warning'>[target] is in the lobby, and cannot be observed.</span>")
|
||||
return
|
||||
|
||||
admin_observe_target(target)
|
||||
|
||||
/client/proc/cleanup_admin_observe(mob/dead/observer/ghost)
|
||||
if(!istype(ghost) || !ghost.mob_observed)
|
||||
return FALSE
|
||||
|
||||
// un-follow them
|
||||
ghost.cleanup_observe()
|
||||
// if it's a mentor, make sure they go back to their body.
|
||||
if(HAS_TRAIT(mob.mind, TRAIT_MENTOR_OBSERVING))
|
||||
// handler will handle removing the trait
|
||||
mob.stop_orbit()
|
||||
log_admin("[key_name(src)] has de-activated Aobserve")
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Aobserve")
|
||||
return TRUE
|
||||
|
||||
/// targeted form of admin_observe: this should only appear in the right-click menu.
|
||||
/client/proc/admin_observe_target(mob/target as mob in GLOB.mob_list)
|
||||
set name = "\[Admin\] Aobserve"
|
||||
set category = null
|
||||
|
||||
if(!check_rights(R_ADMIN|R_MOD|R_MENTOR, mob))
|
||||
return
|
||||
|
||||
var/full_admin = check_rights(R_ADMIN|R_MOD, FALSE, mob)
|
||||
|
||||
if(isnewplayer(mob))
|
||||
to_chat(src, "<span class='warning'>You cannot aobserve while in the lobby. Please join or observe first.</span>")
|
||||
return
|
||||
|
||||
if(isnewplayer(target))
|
||||
to_chat(src, "<span class='warning'>[target] is currently in the lobby.</span>")
|
||||
return
|
||||
|
||||
if(isobserver(target))
|
||||
to_chat(src, "<span class='warning'>You can't observe a ghost.</span>")
|
||||
return
|
||||
|
||||
if(cleanup_admin_observe(mob))
|
||||
return
|
||||
|
||||
if(isnull(target) || target == src)
|
||||
// let the default one find the target if there isn't one
|
||||
admin_observe()
|
||||
return
|
||||
|
||||
// observers don't need to ghost, so we don't need to worry about adding any traits
|
||||
if(isobserver(mob))
|
||||
var/mob/dead/observer/ghost = mob
|
||||
SSblackbox.record_feedback("tally", "admin_verb", 1, "Aobserve")
|
||||
ghost.do_observe(target)
|
||||
return
|
||||
|
||||
log_admin("[key_name(src)] has Aobserved out of their body to follow [target]")
|
||||
do_aghost()
|
||||
var/mob/dead/observer/ghost = mob
|
||||
|
||||
if(!full_admin)
|
||||
// if they're a me and they're alive, add the MENTOR_OBSERVINGtrait to ensure that they can only go back to their body.
|
||||
// we need to handle this here because when you aghost, your mob gets set to the ghost. Oops!
|
||||
ADD_TRAIT(mob.mind, TRAIT_MENTOR_OBSERVING, MENTOR_OBSERVING)
|
||||
RegisterSignal(ghost, COMSIG_ATOM_ORBITER_STOP, PROC_REF(on_mentor_observe_end), override = TRUE)
|
||||
to_chat(src, "<span class='notice'>You have temporarily observed [target], either move or observe again to un-observe.</span>")
|
||||
log_admin("[key_name(src)] has mobserved out of their body to follow [target].")
|
||||
else
|
||||
log_admin("[key_name(src)] is aobserving [target].")
|
||||
|
||||
|
||||
ghost.do_observe(target)
|
||||
|
||||
/client/proc/on_mentor_observe_end(atom/movable/us, atom/movable/orbited)
|
||||
SIGNAL_HANDLER // COMSIG_ATOM_ORBITER_STOP
|
||||
if(!isobserver(mob))
|
||||
log_and_message_admins("A mentor somehow managed to end observing while not being a ghost. Please investigate and notify coders.")
|
||||
return
|
||||
var/mob/dead/observer/ghost = mob
|
||||
|
||||
// just to be safe
|
||||
ghost.cleanup_observe()
|
||||
|
||||
REMOVE_TRAIT(mob.mind, TRAIT_MENTOR_OBSERVING, MENTOR_OBSERVING)
|
||||
UnregisterSignal(mob, COMSIG_ATOM_ORBITER_STOP)
|
||||
|
||||
if(!ghost.reenter_corpse())
|
||||
// tell everyone since this is kinda nasty.
|
||||
log_debug("Mentor [key_name_mentor(src)] was unable to re-enter their body after mentor observing.")
|
||||
log_and_message_admins("[key_name_mentor(src)] was unable to re-enter their body after mentor observing.")
|
||||
to_chat(src, "<span class='userdanger'>Unable to return you to your body after mentor ghosting. If your body still exists, please contact a coder, and you should probably ahelp.</span>")
|
||||
|
||||
/client/proc/invisimin()
|
||||
set name = "Invisimin"
|
||||
set category = "Admin"
|
||||
|
||||
@@ -86,7 +86,8 @@
|
||||
body += "<a href='byond://?src=[usr.UID()];priv_msg="+client_ckey+"'>PM</a> - "
|
||||
body += "<a href='byond://?src=[UID()];subtlemessage="+mobUID+"'>SM</a> - "
|
||||
body += "<a href='byond://?src=[UID()];adminplayerobservefollow="+mobUID+"'>FLW</a> - "
|
||||
body += "<a href='byond://?src=[UID()];adminalert="+mobUID+"'>ALERT</a>"
|
||||
body += "<a href='byond://?src=[UID()];adminalert="+mobUID+"'>ALERT</a> - "
|
||||
body += "<a href='byond://?src=[UID()];adminobserve="+mobUID+"'>OBS</a>"
|
||||
if(eyeUID)
|
||||
body += "|<a href='byond://?src=[UID()];adminplayerobservefollow="+eyeUID+"'>EYE</a>"
|
||||
body += "<br>"
|
||||
|
||||
@@ -1613,6 +1613,17 @@
|
||||
show_player_panel(H)
|
||||
//H.regenerate_icons()
|
||||
|
||||
else if(href_list["adminobserve"])
|
||||
if(!check_rights(R_ADMIN|R_MOD|R_MENTOR))
|
||||
return
|
||||
var/client/C = usr.client
|
||||
var/mob/M = locateUID(href_list["adminobserve"])
|
||||
|
||||
if(!ismob(M))
|
||||
to_chat(usr, "<span class='warning'>This can only be used on instances of type /mob</span>")
|
||||
return
|
||||
C.admin_observe_target(M)
|
||||
|
||||
else if(href_list["adminplayeropts"])
|
||||
var/mob/M = locateUID(href_list["adminplayeropts"])
|
||||
|
||||
@@ -3586,3 +3597,5 @@
|
||||
var/mob/dead/observer/O = target
|
||||
if(O.mind && O.mind.current)
|
||||
. += "|[ADMIN_FLW(O.mind.current,"BDY")]"
|
||||
else if(ismob(target))
|
||||
. += "|[ADMIN_OBS(target, "OBS")]"
|
||||
|
||||
@@ -178,6 +178,7 @@
|
||||
var/ping_link = check_rights(R_ADMIN, 0, mob) ? "(<a href='byond://?src=[pm_tracker.UID()];ping=[C.key]'>PING</a>)" : ""
|
||||
var/ticket_link
|
||||
var/alert_link = check_rights(R_ADMIN, FALSE, mob) ? "(<a href='byond://?src=[pm_tracker.UID()];adminalert=[C.mob.UID()]'>ALERT</a>)" : ""
|
||||
var/observe_link = check_rights(R_MENTOR, FALSE, mob) ? "([ADMIN_OBS(C, "OBS")])" : ""
|
||||
if(ticket_id != -1)
|
||||
if(message_type == MESSAGE_TYPE_MENTORPM)
|
||||
ticket_link = "(<a href='byond://?_src_=holder;openticket=[ticket_id];is_mhelp=1'>TICKET</a>)"
|
||||
@@ -190,7 +191,7 @@
|
||||
receive_window_link = ticket_link
|
||||
else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, C.mob))
|
||||
receive_window_link = ticket_link
|
||||
receive_message = "<span class='[receive_span]'>[type] from-<b>[receive_pm_type] [C.holder ? key_name(src, TRUE, type, ticket_id = ticket_id) : key_name_hidden(src, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg][C.holder ? "<br>[ping_link] [receive_window_link] [alert_link]" : ""]</span>"
|
||||
receive_message = "<span class='[receive_span]'>[type] from-<b>[receive_pm_type] [C.holder ? key_name(src, TRUE, type, ticket_id = ticket_id) : key_name_hidden(src, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg][C.holder ? "<br>[ping_link] [receive_window_link] [alert_link] [observe_link]" : ""]</span>"
|
||||
if(message_type == MESSAGE_TYPE_MENTORPM)
|
||||
receive_message = chat_box_mhelp(receive_message)
|
||||
else
|
||||
@@ -202,7 +203,7 @@
|
||||
send_window_link = ticket_link
|
||||
else if(message_type == MESSAGE_TYPE_ADMINPM && check_rights(R_ADMIN, 0, mob))
|
||||
send_window_link = ticket_link
|
||||
var/send_message = "<span class='[send_span]'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg]</span><br>[ping_link] [send_window_link] [alert_link]"
|
||||
var/send_message = "<span class='[send_span]'>[send_pm_type][type] to-<b>[holder ? key_name(C, TRUE, type, ticket_id = ticket_id) : key_name_hidden(C, TRUE, type, ticket_id = ticket_id)]</b>:<br><br>[emoji_msg]</span><br>[ping_link] [send_window_link] [alert_link] [observe_link]"
|
||||
if(message_type == MESSAGE_TYPE_MENTORPM)
|
||||
send_message = chat_box_mhelp(send_message)
|
||||
else
|
||||
@@ -211,9 +212,9 @@
|
||||
|
||||
var/third_party_message
|
||||
if(message_type == MESSAGE_TYPE_MENTORPM)
|
||||
third_party_message = chat_box_mhelp("<span class='mentorhelp'>[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]:<br><br>[emoji_msg]<br>[ping_link] [ticket_link] [alert_link]</span>")
|
||||
third_party_message = chat_box_mhelp("<span class='mentorhelp'>[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]:<br><br>[emoji_msg]<br>[ping_link] [ticket_link] [alert_link] [observe_link]</span>")
|
||||
else
|
||||
third_party_message = chat_box_ahelp("<span class='adminhelp'>[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]:<br><br>[emoji_msg]<br>[ping_link] [ticket_link] [alert_link]</span>")
|
||||
third_party_message = chat_box_ahelp("<span class='adminhelp'>[type]: [key_name(src, TRUE, type, ticket_id = ticket_id)]->[key_name(C, TRUE, type, ticket_id = ticket_id)]:<br><br>[emoji_msg]<br>[ping_link] [ticket_link] [alert_link] [observe_link]</span>")
|
||||
|
||||
//play the recieving admin the adminhelp sound (if they have them enabled)
|
||||
//non-admins always hear the sound, as they cannot toggle it
|
||||
|
||||
Reference in New Issue
Block a user