Relaymove Moved To Remote Views (#18714)

* Remote view setting datums

* remote view handles relayed move

* setting up checks

* many fixes

* small fixes

* default relay behavior

* use camera settings

* coordinated for overmap shuttle

* lock this down

* not needed

* not needed

* inaccurate doc

* small fixes

* various set machine calls no longer needed

* runtime

* health hud moved to signal controls

* overriding huds

* allow signal based huds entirely

* uav health icon

* fix

* oops that's important

* more return types

* mmis view fix

* not needed

* protect against instantly deleted ghosts

* all of these need remote on enter

* these too

* order
This commit is contained in:
Will
2025-11-05 17:47:58 -05:00
committed by GitHub
parent 8f08fd5500
commit fd60bee1cb
45 changed files with 560 additions and 418 deletions
@@ -15,7 +15,6 @@
// Mob
host_mob = parent
RegisterSignal(host_mob, COMSIG_LIVING_LIFE, PROC_REF(on_mob_action))
RegisterSignal(host_mob, COMSIG_LIVING_HANDLE_VISION, PROC_REF(on_mob_vision_update))
RegisterSignal(host_mob, COMSIG_OBSERVER_MOVED, PROC_REF(on_mob_action))
RegisterSignal(host_mob, COMSIG_MOB_LOGOUT, PROC_REF(on_mob_logout))
@@ -23,7 +22,6 @@
linked_machine = machine
RegisterSignal(linked_machine, COMSIG_QDELETING, PROC_REF(on_machine_qdelete))
linked_machine.in_use = TRUE
on_mob_vision_update()
// Lets complain if an object uses TGUI but is still setting the machine.
if(length(linked_machine.tgui_data()))
@@ -35,12 +33,10 @@
linked_machine.balloon_alert(host_mob,"you stop using \the [linked_machine]")
// Machine
UnregisterSignal(linked_machine, COMSIG_QDELETING)
linked_machine.remove_visual(host_mob)
linked_machine.in_use = FALSE
linked_machine = null
// Mob
UnregisterSignal(host_mob, COMSIG_OBSERVER_MOVED)
UnregisterSignal(host_mob, COMSIG_LIVING_HANDLE_VISION)
UnregisterSignal(host_mob, COMSIG_LIVING_LIFE)
UnregisterSignal(host_mob, COMSIG_MOB_LOGOUT)
host_mob.reset_perspective() // Required, because our machine may have been operating a remote view
@@ -51,31 +47,14 @@
PRIVATE_PROC(TRUE)
SIGNAL_HANDLER
if(host_mob.stat == DEAD || !host_mob.client || !host_mob.Adjacent(linked_machine))
on_mob_vision_update()
qdel(src)
/datum/component/using_machine_shim/proc/on_machine_qdelete()
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
SIGNAL_HANDLER
on_mob_vision_update()
qdel(src)
/datum/component/using_machine_shim/proc/on_mob_vision_update()
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
SIGNAL_HANDLER
if(host_mob.stat == DEAD)
return
var/viewflags = linked_machine.check_eye(host_mob)
if(viewflags < 0)
return
if(host_mob.is_remote_viewing())
linked_machine.apply_visual(host_mob)
return
host_mob.sight |= viewflags
/datum/component/using_machine_shim/proc/on_mob_logout()
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
@@ -116,12 +95,6 @@
return
AddComponent(/datum/component/using_machine_shim, O)
/// deprecated, do not use, return flags that should be added to the viewer's sight var. Otherwise return a negative number to indicate that the view should be cancelled.
/atom/proc/check_eye(user as mob)
if (isAI(user)) // WHYYYY
return 0
return -1
/// deprecated, do not use
/obj/item/proc/updateSelfDialog()
var/mob/M = src.loc
+136 -43
View File
@@ -2,37 +2,55 @@
* Use this if you need to remote view something. Remote view will end if you move or the remote view target is deleted. Cleared automatically if another remote view begins.
*/
/datum/component/remote_view
VAR_PROTECTED/datum/remote_view_config/settings = null
VAR_PROTECTED/mob/host_mob
VAR_PROTECTED/atom/remote_view_target
VAR_PROTECTED/forbid_movement = TRUE
/datum/component/remote_view/allow_moving
forbid_movement = FALSE
/datum/component/remote_view/Initialize(atom/focused_on)
/datum/component/remote_view/Initialize(atom/focused_on, vconfig_path)
. = ..()
if(!ismob(parent))
return COMPONENT_INCOMPATIBLE
// Set config
if(!vconfig_path)
vconfig_path = /datum/remote_view_config
settings = new vconfig_path
// Safety check, focus on ourselves if the target is deleted, and flag any movement to end the view.
host_mob = parent
if(QDELETED(focused_on))
focused_on = host_mob
forbid_movement = TRUE
settings.forbid_movement = TRUE
// Begin remoteview
host_mob.reset_perspective(focused_on) // Must be done before registering the signals
if(forbid_movement)
if(settings.forbid_movement)
RegisterSignal(host_mob, COMSIG_MOVABLE_MOVED, PROC_REF(handle_hostmob_moved))
else
RegisterSignal(host_mob, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(handle_hostmob_moved))
RegisterSignal(host_mob, COMSIG_MOB_RESET_PERSPECTIVE, PROC_REF(on_reset_perspective))
RegisterSignal(host_mob, COMSIG_MOB_DEATH, PROC_REF(handle_endview))
RegisterSignal(host_mob, COMSIG_REMOTE_VIEW_CLEAR, PROC_REF(handle_forced_endview))
// Upon any disruptive status effects
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_STUN, PROC_REF(handle_status_effects))
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_WEAKEN, PROC_REF(handle_status_effects))
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_PARALYZE, PROC_REF(handle_status_effects))
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_SLEEP, PROC_REF(handle_status_effects))
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_BLIND, PROC_REF(handle_status_effects))
if(settings.will_stun)
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_STUN, PROC_REF(handle_status_effects))
if(settings.will_weaken)
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_WEAKEN, PROC_REF(handle_status_effects))
if(settings.will_paralyze)
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_PARALYZE, PROC_REF(handle_status_effects))
if(settings.will_sleep)
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_SLEEP, PROC_REF(handle_status_effects))
if(settings.will_blind)
RegisterSignal(host_mob, COMSIG_LIVING_STATUS_BLIND, PROC_REF(handle_status_effects))
if(settings.will_death)
RegisterSignal(host_mob, COMSIG_MOB_DEATH, PROC_REF(handle_endview))
// Handle relayed movement
if(settings.relay_movement)
RegisterSignal(host_mob, COMSIG_MOB_RELAY_MOVEMENT, PROC_REF(handle_relay_movement))
RegisterSignal(host_mob, COMSIG_LIVING_HANDLE_VISION, PROC_REF(handle_mob_vision_update))
// Hud overrides
if(settings.override_entire_hud)
RegisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD, PROC_REF(handle_hud_override))
if(settings.override_health_hud)
RegisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD_HEALTH_ICON, PROC_REF(handle_hud_health))
if(settings.override_darkvision_hud)
RegisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD_DARKSIGHT, PROC_REF(handle_hud_darkvision))
// Recursive move component fires this, we only want it to handle stuff like being inside a paicard when releasing turf lock
if(isturf(focused_on))
RegisterSignal(host_mob, COMSIG_OBSERVER_MOVED, PROC_REF(handle_recursive_moved))
@@ -43,34 +61,68 @@
RegisterSignal(remote_view_target, COMSIG_MOB_RESET_PERSPECTIVE, PROC_REF(on_remotetarget_reset_perspective))
RegisterSignal(remote_view_target, COMSIG_REMOTE_VIEW_CLEAR, PROC_REF(handle_forced_endview))
/datum/component/remote_view/RegisterWithParent()
// Update the mob's vision after we attach.
host_mob.handle_vision()
host_mob.handle_regular_hud_updates()
settings.attached_to_mob(src, host_mob)
/datum/component/remote_view/Destroy(force)
. = ..()
if(forbid_movement)
// Basic handling
if(settings.forbid_movement)
UnregisterSignal(host_mob, COMSIG_MOVABLE_MOVED)
else
UnregisterSignal(host_mob, COMSIG_MOVABLE_Z_CHANGED)
UnregisterSignal(host_mob, COMSIG_MOB_RESET_PERSPECTIVE)
UnregisterSignal(host_mob, COMSIG_MOB_DEATH)
UnregisterSignal(host_mob, COMSIG_REMOTE_VIEW_CLEAR)
// Status effects
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_STUN)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_WEAKEN)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_PARALYZE)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_SLEEP)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_BLIND)
if(settings.will_stun)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_STUN)
if(settings.will_weaken)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_WEAKEN)
if(settings.will_paralyze)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_PARALYZE)
if(settings.will_sleep)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_SLEEP)
if(settings.will_blind)
UnregisterSignal(host_mob, COMSIG_LIVING_STATUS_BLIND)
if(isturf(remote_view_target))
UnregisterSignal(host_mob, COMSIG_OBSERVER_MOVED)
if(settings.will_death)
UnregisterSignal(host_mob, COMSIG_MOB_DEATH)
// Handle relayed movement
if(settings.relay_movement)
UnregisterSignal(host_mob, COMSIG_MOB_RELAY_MOVEMENT)
UnregisterSignal(host_mob, COMSIG_LIVING_HANDLE_VISION)
// Hud overrides
if(settings.override_entire_hud)
UnregisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD)
if(settings.override_health_hud)
UnregisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD_HEALTH_ICON)
if(settings.override_darkvision_hud)
UnregisterSignal(host_mob, COMSIG_LIVING_HANDLE_HUD_DARKSIGHT)
// Cleanup remote view
if(host_mob != remote_view_target)
if(host_mob != remote_view_target) // If target is not ourselves
UnregisterSignal(remote_view_target, COMSIG_QDELETING)
UnregisterSignal(remote_view_target, COMSIG_MOB_RESET_PERSPECTIVE)
UnregisterSignal(remote_view_target, COMSIG_REMOTE_VIEW_CLEAR)
// Update the mob's vision right away
settings.detatch_from_mob(src, host_mob)
settings.handle_remove_visuals(src, host_mob)
host_mob.handle_vision()
host_mob.handle_regular_hud_updates()
host_mob = null
remote_view_target = null
// Clear settings
QDEL_NULL(settings)
// Signal handlers
/datum/component/remote_view/proc/handle_hostmob_moved(atom/source, atom/oldloc, direction, forced, movetime)
SIGNAL_HANDLER
PROTECTED_PROC(TRUE)
RETURN_TYPE(null)
if(!host_mob)
return
end_view()
@@ -79,6 +131,7 @@
/datum/component/remote_view/proc/handle_recursive_moved(atom/source, atom/oldloc, atom/new_loc)
SIGNAL_HANDLER
PROTECTED_PROC(TRUE)
RETURN_TYPE(null)
ASSERT(isturf(remote_view_target))
// This signal handler is for recursive move decoupling us from /datum/component/remote_view/mob_holding_item's turf focusing when dropped in an item like a paicard
// This signal is only hooked when we focus on a turf. Check the subtype for more info, this horrorshow took several days to make consistently behave.
@@ -91,12 +144,14 @@
/datum/component/remote_view/proc/handle_forced_endview(datum/source)
SIGNAL_HANDLER
PROTECTED_PROC(TRUE)
RETURN_TYPE(null)
handle_endview(source)
/datum/component/remote_view/proc/handle_endview(datum/source)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
RETURN_TYPE(null)
if(!host_mob)
return
end_view()
@@ -105,6 +160,7 @@
/datum/component/remote_view/proc/handle_status_effects(datum/source, amount, ignore_canstun)
SIGNAL_HANDLER
PROTECTED_PROC(TRUE)
RETURN_TYPE(null)
if(!host_mob)
return
// We don't really care what effect was caused, just that it was increasing the value and thus negatively affecting us.
@@ -117,6 +173,7 @@
/datum/component/remote_view/proc/on_reset_perspective(datum/source)
SIGNAL_HANDLER
PRIVATE_PROC(TRUE)
RETURN_TYPE(null)
if(!host_mob)
return
// Check if we're still remote viewing the SAME target!
@@ -128,6 +185,7 @@
/datum/component/remote_view/proc/on_remotetarget_reset_perspective(datum/source)
SIGNAL_HANDLER
PRIVATE_PROC(TRUE)
RETURN_TYPE(null)
// Non-mobs can't do this anyway
if(!host_mob)
return
@@ -151,14 +209,56 @@
/datum/component/remote_view/proc/end_view()
PROTECTED_PROC(TRUE)
RETURN_TYPE(null)
host_mob.reset_perspective()
// Optional signal handlers for more advanced remote views
/datum/component/remote_view/proc/handle_relay_movement(datum/source, direction)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
return settings.handle_relay_movement(src, host_mob, direction)
/datum/component/remote_view/proc/handle_hud_override(datum/source)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
return settings.handle_hud_override(src, host_mob)
/datum/component/remote_view/proc/handle_hud_health(datum/source)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
return settings.handle_hud_health(src, host_mob)
/datum/component/remote_view/proc/handle_hud_darkvision(datum/source)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
RETURN_TYPE(null)
PRIVATE_PROC(TRUE)
settings.handle_hud_darkvision(src, host_mob)
/datum/component/remote_view/proc/handle_mob_vision_update(datum/source)
SIGNAL_HANDLER
SHOULD_NOT_OVERRIDE(TRUE)
PRIVATE_PROC(TRUE)
return settings.handle_apply_visuals(src, host_mob)
// Accessors
/datum/component/remote_view/proc/get_host()
RETURN_TYPE(/mob)
return host_mob
/datum/component/remote_view/proc/get_target()
RETURN_TYPE(/atom)
return remote_view_target
/datum/component/remote_view/proc/get_coordinator()
RETURN_TYPE(/atom)
return null // For subtype
/datum/component/remote_view/proc/looking_at_target_already(atom/target)
return (remote_view_target == target)
@@ -170,11 +270,7 @@
VAR_PRIVATE/obj/item/host_item
VAR_PRIVATE/show_message
/datum/component/remote_view/item_zoom/allow_moving
forbid_movement = FALSE
/datum/component/remote_view/item_zoom/Initialize(atom/focused_on, obj/item/our_item, viewsize, tileoffset, show_visible_messages)
/datum/component/remote_view/item_zoom/Initialize(atom/focused_on, vconfig_path, obj/item/our_item, viewsize, tileoffset, show_visible_messages)
. = ..()
host_item = our_item
RegisterSignal(host_item, COMSIG_QDELETING, PROC_REF(handle_endview))
@@ -240,10 +336,7 @@
*/
/datum/component/remote_view/mremote_mutation
/datum/component/remote_view/mremote_mutation/allow_moving
forbid_movement = FALSE
/datum/component/remote_view/mremote_mutation/Initialize(atom/focused_on)
/datum/component/remote_view/mremote_mutation/Initialize(atom/focused_on, vconfig_path)
if(!ismob(focused_on)) // What are you doing? This gene only works on mob targets, if you adminbus this I will personally eat your face.
return COMPONENT_INCOMPATIBLE
. = ..()
@@ -277,10 +370,7 @@
VAR_PRIVATE/datum/view_coordinator // The object containing the viewer_list, with look() and unlook() logic
VAR_PRIVATE/list/viewers // list from the view_coordinator, lists in byond are pass by reference, so this is the SAME list as on the coordinator! If you pass a null this will explode.
/datum/component/remote_view/viewer_managed/allow_moving
forbid_movement = FALSE
/datum/component/remote_view/viewer_managed/Initialize(atom/focused_on, datum/coordinator, list/viewer_list)
/datum/component/remote_view/viewer_managed/Initialize(atom/focused_on, vconfig_path, datum/coordinator, list/viewer_list)
. = ..()
if(!islist(viewer_list)) // BAD BAD BAD NO
CRASH("Passed a viewer_list that was not a list, or was null, to /datum/component/remote_view/viewer_managed component. Ensure the viewer_list exists before passing it into AddComponent.")
@@ -289,9 +379,6 @@
view_coordinator.look(host_mob)
LAZYDISTINCTADD(viewers, WEAKREF(host_mob))
RegisterSignal(view_coordinator, COMSIG_REMOTE_VIEW_CLEAR, PROC_REF(handle_forced_endview))
// If you get this crash, it's because check_eye() in look() failed
if(!parent)
CRASH("Remoteview failed, look() cancelled view during component Initilize. Usually this is caused by check_eye().")
/datum/component/remote_view/viewer_managed/Destroy(force)
UnregisterSignal(view_coordinator, COMSIG_REMOTE_VIEW_CLEAR)
@@ -301,6 +388,8 @@
viewers = null
. = ..()
/datum/component/remote_view/viewer_managed/get_coordinator()
return view_coordinator
/**
* Remote view subtype that is handling a byond bug where mobs changing their client eye from inside of
@@ -313,7 +402,7 @@
/datum/component/remote_view/mob_holding_item
var/needs_to_decouple = FALSE // if the current top level atom is a mob
/datum/component/remote_view/mob_holding_item/Initialize(atom/focused_on)
/datum/component/remote_view/mob_holding_item/Initialize(atom/focused_on, vconfig_path)
if(!isobj(focused_on)) // You shouldn't be using this if so.
return COMPONENT_INCOMPATIBLE
. = ..()
@@ -384,11 +473,15 @@
// Yes this spawn is needed, yes I wish it wasn't.
spawn(0)
// Decouple the view to the turf on drop, or we'll be stuck on the mob that dropped us forever
cache_mob.AddComponent(/datum/component/remote_view, release_turf)
cache_mob.client.eye = release_turf // Yes--
cache_mob.client.perspective = EYE_PERSPECTIVE // --this is required too.
if(!isturf(cache_mob.loc)) // For stuff like paicards
cache_mob.AddComponent(/datum/component/recursive_move) // Will rebuild parent chain.
if(!QDELETED(cache_mob))
cache_mob.AddComponent(/datum/component/remote_view, release_turf)
cache_mob.client.eye = release_turf // Yes--
cache_mob.client.perspective = EYE_PERSPECTIVE // --this is required too.
if(!isturf(cache_mob.loc)) // For stuff like paicards
cache_mob.AddComponent(/datum/component/recursive_move) // Will rebuild parent chain.
// If you somehow deleted before the decouple... Just fix this mess.
else
cache_mob.reset_perspective()
// Because nested vore bellies do NOT get handled correctly for recursive prey. We need to tell the belly's occupants to decouple too... Then their own belly's occupants...
// Yes, two loops is faster. Because we skip typechecking byondcode side and instead do it engine side when getting the contents of the mob,
// we also skip typechecking every /obj in the mob on the byondcode side... Evil wizard knowledge.
+2 -2
View File
@@ -374,9 +374,9 @@
return "Image icon: [icon] - icon_state: [icon_state] [loc ? "loc: [loc] ([loc.x],[loc.y],[loc.z])" : ""]"
/// Begin coordinated remote viewing, this will call look() when the view begins, and unlook() when it ends.
/datum/proc/start_coordinated_remoteview(mob/user, atom/target, list/viewer_managed_list)
/datum/proc/start_coordinated_remoteview(mob/user, atom/target, list/viewer_managed_list, remote_view_config_path = null)
ASSERT(islist(viewer_managed_list))
user.AddComponent(/datum/component/remote_view/viewer_managed, focused_on = target, coordinator = src, viewer_list = viewer_managed_list)
user.AddComponent(/datum/component/remote_view/viewer_managed, focused_on = target, vconfig_path = remote_view_config_path, coordinator = src, viewer_list = viewer_managed_list)
/// Called from /datum/component/remote_view/viewer_managed during Initilize().
/datum/proc/look(mob/user)
+92
View File
@@ -0,0 +1,92 @@
/datum/remote_view_config
// Signal config for remote view component. This controls what signals will be subbed to during init.
var/forbid_movement = TRUE
var/relay_movement = FALSE
// Status effects that will knock us out of remote view
var/will_death = TRUE
var/will_stun = TRUE
var/will_weaken = TRUE
var/will_paralyze = TRUE
var/will_sleep = TRUE
var/will_blind = TRUE
// Hud overrides, datum is responsible for restoring the hud state on attach and detatch
var/override_entire_hud = FALSE // Overrides all others, only this needs to be set if you do a fully custom hud
var/override_health_hud = FALSE
var/override_darkvision_hud = FALSE
/// Called when remote view component finishes attaching to the mob
/datum/remote_view_config/proc/attached_to_mob( datum/component/remote_view/owner_component, mob/host_mob)
RETURN_TYPE(null)
return
/// Called when remote view component is destroyed
/datum/remote_view_config/proc/detatch_from_mob( datum/component/remote_view/owner_component, mob/host_mob)
RETURN_TYPE(null)
return
/// Handles relayed movement during a remote view. Override this in a subtype to handle specialized logic. If it returns true, the mob will not move, allowing you to handle remotely controlled movement.
/datum/remote_view_config/proc/handle_relay_movement( datum/component/remote_view/owner_component, mob/host_mob, datum/coordinator, atom/movable/remote_view_target, direction)
SIGNAL_HANDLER
// By default, we ask our remote_view_target to handle relaymove for us.
if(!remote_view_target)
return FALSE
return remote_view_target.relaymove(host_mob, direction)
/// Handles visual changes to mob's hud or flags when in use, it is fired every life tick.
/datum/remote_view_config/proc/handle_apply_visuals( datum/component/remote_view/owner_component, mob/host_mob)
SIGNAL_HANDLER
RETURN_TYPE(null)
return
/// Handles visual changes when ending the view
/datum/remote_view_config/proc/handle_remove_visuals( datum/component/remote_view/owner_component, mob/host_mob)
SIGNAL_HANDLER
RETURN_TYPE(null)
return
/// Handles hud health indicator being replaced with a custom one (like showing the remote_view_target's health).
/datum/remote_view_config/proc/handle_hud_override( datum/component/remote_view/owner_component, mob/host_mob)
SIGNAL_HANDLER
return COMSIG_COMPONENT_HANDLED_HUD
/// Handles hud health indicator being replaced with a custom one (like showing the remote_view_target's health).
/datum/remote_view_config/proc/handle_hud_health( datum/component/remote_view/owner_component, mob/host_mob)
SIGNAL_HANDLER
return COMSIG_COMPONENT_HANDLED_HEALTH_ICON
/// Handles hud darkvision for if the remote view uses it's own logic for darkvision, or asks the remote_view_target to calculate it.
/datum/remote_view_config/proc/handle_hud_darkvision( datum/component/remote_view/owner_component, mob/host_mob)
SIGNAL_HANDLER
RETURN_TYPE(null)
return
//////////////////////////////////////////////////////////////////////////////////////////////////
// Basic subtypes
//////////////////////////////////////////////////////////////////////////////////////////////////
/// Remote view that allows moving without clearing the remote view.
/datum/remote_view_config/allow_movement
forbid_movement = FALSE
/// Remote view that ignores stuns and other status effects ending the view
/datum/remote_view_config/effect_immune
will_stun = FALSE
will_weaken = FALSE
will_paralyze = FALSE
will_sleep = FALSE
will_blind = FALSE
/// Remote view that relays movement to the remote_view_target
/datum/remote_view_config/relay_movement
relay_movement = TRUE
/// Remote view that respects camera vision flags and checking for functionality of the camera.
/datum/remote_view_config/camera_standard
/datum/remote_view_config/camera_standard/handle_apply_visuals( datum/component/remote_view/owner_component, mob/host_mob)
var/obj/machinery/camera/view_camera = owner_component.get_target()
if(!view_camera || !view_camera.can_use())
host_mob.reset_perspective()
return
if(view_camera.isXRay())
host_mob.sight |= (SEE_TURFS|SEE_MOBS|SEE_OBJS)