Skip to content

Commit

Permalink
Makes observers able to see the UI of Xeno players (and also action b…
Browse files Browse the repository at this point in the history
…uttons) (#5751)

# About the pull request

Makes auto-observing work for xenomorphs *and* humans by moving it to
`/carbon`, and also makes it show the target's action buttons.

I'm pretty confident that this all works correctly, but I would still
recommend testmerging it anyway.
It's ~~probable~~possible that I missed something somewhere and an
observer could get stuck being unable to click anything, or something
like that.

# Explain why it's good for the game

This makes auto-observing a bit more consistent, more interesting for
observers, and could actually help newer players to learn how to play
some castes. (Which abilities to use and when, where to target, etc.)

# Testing Photographs and Procedure
<details>
<summary>Screenshots & Videos</summary>


https://github.com/cmss13-devs/cmss13/assets/57483089/54fbb8c6-f9fa-444b-b80c-228b4e6e3480

</details>

# Changelog
:cl:
add: Added 'observe' functionality to Xenomorphs, allowing observers to
view the target's UI.
add: Made observing a player also show their action buttons.
/:cl:
  • Loading branch information
SabreML authored Feb 21, 2024
1 parent 87f7b4b commit 8caa8b9
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 54 deletions.
10 changes: 6 additions & 4 deletions code/_onclick/hud/screen_objects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,11 @@
/atom/movable/screen/action_button/attack_ghost(mob/dead/observer/user)
return

/atom/movable/screen/action_button/clicked(mob/user)
/atom/movable/screen/action_button/clicked(mob/user, list/mods)
if(!user || !source_action)
return TRUE
if(source_action.owner != user)
return TRUE

if(source_action.can_use_action())
source_action.action_activate()
Expand Down Expand Up @@ -97,7 +99,7 @@
icon_state = "hide"
var/hidden = 0

/atom/movable/screen/action_button/hide_toggle/clicked(mob/user, mods)
/atom/movable/screen/action_button/hide_toggle/clicked(mob/user, list/mods)
user.hud_used.action_buttons_hidden = !user.hud_used.action_buttons_hidden
hidden = user.hud_used.action_buttons_hidden
if(hidden)
Expand All @@ -107,7 +109,7 @@
name = "Hide Buttons"
icon_state = "hide"
user.update_action_buttons()
return 1
return TRUE

/atom/movable/screen/action_button/ghost/minimap/get_button_screen_loc(button_number)
return "SOUTH:6,CENTER+1:24"
Expand Down Expand Up @@ -211,7 +213,7 @@
update_icon(user)
return 1

/atom/movable/screen/clicked(mob/user)
/atom/movable/screen/clicked(mob/user, list/mods)
if(!user)
return TRUE

Expand Down
78 changes: 28 additions & 50 deletions code/modules/mob/dead/observer/observer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -188,37 +188,38 @@
clean_observe_target()

/// When the observer target gets a screen, our observer gets a screen minus some game screens we don't want the observer to touch
/mob/dead/observer/proc/observe_target_screen_add(observe_target_mob_client, add_to_screen)
/mob/dead/observer/proc/observe_target_screen_add(observe_target_mob_client, screen_add)
SIGNAL_HANDLER

if(!client)
return

if(istype(add_to_screen, /atom/movable/screen/action_button))
return

if(istype(add_to_screen, /atom/movable/screen/fullscreen))
return
var/static/list/excluded_types = typecacheof(list(
/atom/movable/screen/fullscreen,
/atom/movable/screen/click_catcher,
/atom/movable/screen/escape_menu,
/atom/movable/screen/buildmode,
/obj/effect/detector_blip,
))

if(istype(add_to_screen, /atom/movable/screen/click_catcher))
if(!client)
return

if(istype(add_to_screen, /atom/movable/screen/escape_menu))
return
// `screen_add` can sometimes be a list, so it's safest to just handle everything as one.
var/list/stuff_to_add = (islist(screen_add) ? screen_add : list(screen_add))

if(istype(add_to_screen, /obj/effect/detector_blip))
return
for(var/item in stuff_to_add)
// Ignore anything that's in `excluded_types`.
if(is_type_in_typecache(item, excluded_types))
continue

client.add_to_screen(add_to_screen)
client.add_to_screen(screen_add)

/// When the observer target loses a screen, our observer loses it as well
/mob/dead/observer/proc/observe_target_screen_remove(observe_target_mob_client, remove_from_screen)
/mob/dead/observer/proc/observe_target_screen_remove(observe_target_mob_client, screen_remove)
SIGNAL_HANDLER

if(!client)
return

client.remove_from_screen(remove_from_screen)
client.remove_from_screen(screen_remove)

/// When the observe target ghosts our observer disconnect from their screen updates
/mob/dead/observer/proc/observe_target_ghosting(mob/observer_target_mob)
Expand Down Expand Up @@ -256,48 +257,25 @@
ManualFollow(target)
reset_perspective()

if(!ishuman(target) || !client.prefs?.auto_observe)
if(!iscarbon(target) || !client.prefs?.auto_observe)
return
var/mob/living/carbon/human/human_target = target

client.eye = human_target
observe_target_mob = human_target
RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target))
RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react))

if(!human_target.hud_used)
var/mob/living/carbon/carbon_target = target
if(!carbon_target.hud_used)
return

client.clear_screen()
LAZYINITLIST(human_target.observers)
human_target.observers |= src
human_target.hud_used.show_hud(human_target.hud_used.hud_version, src)

var/list/target_contents = human_target.get_contents()

//Handles any currently open storage containers the target is looking in when we observe
for(var/obj/item/storage/checked_storage in target_contents)
if(!(human_target in checked_storage.content_watchers))
continue

client.add_to_screen(checked_storage.closer)
client.add_to_screen(checked_storage.contents)

if(checked_storage.storage_slots)
client.add_to_screen(checked_storage.boxes)
else
client.add_to_screen(checked_storage.storage_start)
client.add_to_screen(checked_storage.storage_continue)
client.add_to_screen(checked_storage.storage_end)

break
client.eye = carbon_target
observe_target_mob = carbon_target
carbon_target.auto_observed(src)

RegisterSignal(src, COMSIG_MOVABLE_MOVED, PROC_REF(observer_move_react))
RegisterSignal(observe_target_mob, COMSIG_PARENT_QDELETING, PROC_REF(clean_observe_target))
RegisterSignal(observe_target_mob, COMSIG_MOB_GHOSTIZE, PROC_REF(observe_target_ghosting))
RegisterSignal(observe_target_mob, COMSIG_MOB_NEW_MIND, PROC_REF(observe_target_new_mind))
RegisterSignal(observe_target_mob, COMSIG_MOB_LOGIN, PROC_REF(observe_target_login))

if(human_target.client)
observe_target_client = human_target.client
if(observe_target_mob.client)
observe_target_client = observe_target_mob.client
RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_ADD, PROC_REF(observe_target_screen_add))
RegisterSignal(observe_target_client, COMSIG_CLIENT_SCREEN_REMOVE, PROC_REF(observe_target_screen_remove))

Expand Down
19 changes: 19 additions & 0 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,25 @@
<BR>"}
show_browser(user, dat, name, "mob[name]")

/**
* Called by [/mob/dead/observer/proc/do_observe] when a carbon mob is observed by a ghost with [/datum/preferences/var/auto_observe] enabled.
*
* Any HUD changes past this point are handled by [/mob/dead/observer/proc/observe_target_screen_add]
* and [/mob/dead/observer/proc/observe_target_screen_remove].
*
* Override on subtype mobs if they have any extra HUD elements/behaviour.
*/
/mob/living/carbon/proc/auto_observed(mob/dead/observer/observer)
SHOULD_CALL_PARENT(TRUE)

LAZYINITLIST(observers)
observers |= observer
hud_used.show_hud(hud_used.hud_version, observer)

for(var/datum/action/action as anything in actions)
// Add the action's button (not the action itself) to the observer's screen.
observer.client.add_to_screen(action.button)

//generates realistic-ish pulse output based on preset levels
/mob/living/carbon/proc/get_pulse(method) //method 0 is for hands, 1 is for machines, more accurate
var/temp = 0 //see setup.dm:694
Expand Down
23 changes: 23 additions & 0 deletions code/modules/mob/living/carbon/human/human.dm
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,29 @@
<BR>"}
show_browser(user, dat, name, "mob[name]")

/**
* Handles any storage containers that the human is looking inside when auto-observed.
*/
/mob/living/carbon/human/auto_observed(mob/dead/observer/observer)
. = ..()

// If `src` doesn't have an inventory open.
if(!s_active)
return

// Add the storage interface to `observer`'s screen.
observer.client.add_to_screen(s_active.closer)
observer.client.add_to_screen(s_active.contents)

// If the storage has a set number of item slots.
if(s_active.storage_slots)
observer.client.add_to_screen(s_active.boxes)
// If the storage instead has a maximum combined item 'weight'.
else
observer.client.add_to_screen(s_active.storage_start)
observer.client.add_to_screen(s_active.storage_continue)
observer.client.add_to_screen(s_active.storage_end)

// called when something steps onto a human
// this handles mulebots and vehicles
/mob/living/carbon/human/Crossed(atom/movable/AM)
Expand Down
1 change: 1 addition & 0 deletions strings/metatips.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ As a mentor, you can become the imaginary friend of a new player to teach them!
You shouldn't ignore what your allies are up to. Sometimes they can be organizing a flank in hivemind/radio, sometimes they can be walking up behind you with a slug-loaded shotgun. Either way, it pays to be alert to what they're doing, as much to as what the enemies are.
The Wiki (https://cm-ss13.com/wiki) is a very useful repository of information about the game, such as weapons, equipment, xenomorph castes and their strains. It may not be fully up to date much of the time, but the basics are usually accurate.
As an observer, you may see how much remaining hijack time is left in the status panel.
As an observer, you can quickly follow someone by ctrl-clicking on their sprite.
You can always AdminHelp with the F1 key to question a member of staff regarding rules or game bugs.
As ghost you are given extra tools for spectating the round: you can jump and follow specific players, get notifications about CAS and OB strikes, can see all health bars, and such.
You can press ESC key to bring up the game pause menu. It allows you change settings, AdminHelp and MentorHelp, and even access the Web Maps of game by clicking at top right.
Expand Down

0 comments on commit 8caa8b9

Please sign in to comment.