[MIRROR] Relaymove Moved To Remote Views (#11914)

Co-authored-by: Will <7099514+Willburd@users.noreply.github.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-11-05 16:56:44 -07:00
committed by GitHub
parent 4d41a742cd
commit 953250b06a
45 changed files with 560 additions and 418 deletions

View File

@@ -21,8 +21,6 @@
var/insistinga = 0
/obj/machinery/wish_granter_dark/attack_hand(var/mob/living/carbon/human/user)
user.set_machine(src)
if(chargesa <= 0)
to_chat(user, "The Wish Granter lies silent.")
return

View File

@@ -323,6 +323,8 @@
///from base of /obj/item/dice/proc/rollDice(mob/user as mob, var/silent = 0). Has the arguments of 'src, silent, result'
#define COMSIG_MOB_ROLLED_DICE "mob_rolled_dice" //can give a return value if we want it to make the dice roll a specific number!
///from base of /client/Move(n, direct) : (direction) returns bool, if component handled movement
#define COMSIG_MOB_RELAY_MOVEMENT "mob_relay_movement"
///from base of obj/allowed(mob/M): (/obj) returns bool, if TRUE the mob has id access to the obj
#define COMSIG_MOB_ALLOWED "mob_allowed"
///from base of mob/anti_magic_check(): (mob/user, magic, holy, tinfoil, chargecost, self, protection_sources)
@@ -415,6 +417,12 @@
#define COMSIG_LIVING_HANDLE_VISION "living_handle_vision"
///From /mob/handle_regular_hud_updates().
#define COMSIG_LIVING_HANDLE_HUD "living_handle_hud"
#define COMSIG_COMPONENT_HANDLED_HUD (1<<0)
///From /mob/living/proc/handle_hud_icons_health().
#define COMSIG_LIVING_HANDLE_HUD_HEALTH_ICON "living_handle_hud_health_icon"
#define COMSIG_COMPONENT_HANDLED_HEALTH_ICON (1<<0)
///From /mob/living/proc/handle_darksight().
#define COMSIG_LIVING_HANDLE_HUD_DARKSIGHT "living_handle_hud_darksight"
// Damage specific signals for /mob/living

View File

@@ -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

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.

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)

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)

View File

@@ -244,7 +244,7 @@
break
if (user.stat == 2) return
user.AddComponent(/datum/component/remote_view/item_zoom, focused_on = target, our_item = src, viewsize = null, tileoffset = 0, show_visible_messages = FALSE)
user.AddComponent(/datum/component/remote_view/item_zoom, focused_on = target, vconfig_path = /datum/remote_view_config/camera_standard, our_item = src, viewsize = null, tileoffset = 0, show_visible_messages = FALSE)
/*
/obj/item/cigarpacket

View File

@@ -64,6 +64,7 @@
icon_state = "scanner_0"
density = TRUE
anchored = TRUE
flags = REMOTEVIEW_ON_ENTER
use_power = USE_POWER_IDLE
idle_power_usage = 50
active_power_usage = 300

View File

@@ -91,6 +91,7 @@
density = TRUE
anchored = TRUE
unacidable = TRUE
flags = REMOTEVIEW_ON_ENTER
circuit = /obj/item/circuitboard/sleeper
var/mob/living/carbon/human/occupant = null
var/list/available_chemicals = list()

View File

@@ -9,6 +9,7 @@
density = TRUE
anchored = TRUE
unacidable = TRUE
flags = REMOTEVIEW_ON_ENTER
circuit = /obj/item/circuitboard/body_scanner
use_power = USE_POWER_IDLE
idle_power_usage = 60

View File

@@ -300,11 +300,6 @@
status = newstatus
update_coverage()
/obj/machinery/camera/check_eye(mob/user)
if(!can_use()) return -1
if(isXRay()) return SEE_TURFS|SEE_MOBS|SEE_OBJS
return 0
/obj/machinery/camera/update_icon()
if (!status || (stat & BROKEN))
icon_state = "[initial(icon_state)]1"
@@ -407,7 +402,6 @@
to_chat(user, span_warning("\The [src] is broken."))
return
user.set_machine(src)
wires.Interact(user)
/obj/machinery/camera/proc/add_network(var/network_name)

View File

@@ -30,6 +30,7 @@
desc = "An electronically-lockable pod for growing organic tissue."
density = TRUE
anchored = TRUE
flags = REMOTEVIEW_ON_ENTER
circuit = /obj/item/circuitboard/clonepod
icon = 'icons/obj/cloning.dmi'
icon_state = "pod_0"

View File

@@ -7,6 +7,7 @@
icon_state = "pod_preview"
density = TRUE
anchored = TRUE
flags = REMOTEVIEW_ON_ENTER
layer = UNDER_JUNK_LAYER
interact_offline = 1

View File

@@ -554,10 +554,3 @@ Class Procs:
spark_system.start()
qdel(spark_system)
qdel(src)
/datum/proc/apply_visual(mob/M)
M.sight = 0 //Just reset their mesons and stuff so they can't use them, by default.
return
/datum/proc/remove_visual(mob/M)
return

View File

@@ -3,7 +3,6 @@
set name = ".map"
set category = "Object"
set src in view(1)
usr.set_machine(src)
if(!mapping) return
log_game("[usr]([usr.key]) used station map L[z] in [src.loc.loc]")
drawmap(usr)
@@ -332,4 +331,3 @@
qdel(O)
mapobjs = null
src.unset_machine()

View File

@@ -852,7 +852,7 @@ GLOBAL_LIST_EMPTY(blood_overlays_by_type)
can_zoom = FALSE
if(!zoom && can_zoom)
M.AddComponent(/datum/component/remote_view/item_zoom/allow_moving, focused_on = M, our_item = src, viewsize = viewsize, tileoffset = tileoffset, show_visible_messages = TRUE)
M.AddComponent(/datum/component/remote_view/item_zoom, focused_on = M, vconfig_path = /datum/remote_view_config/allow_movement, our_item = src, viewsize = viewsize, tileoffset = tileoffset, show_visible_messages = TRUE)
return
SEND_SIGNAL(src,COMSIG_REMOTE_VIEW_CLEAR)

View File

@@ -190,8 +190,12 @@
if(in_use)
return
if(cameras.len == 1 && user.is_remote_viewing())
user.reset_perspective()
return
if(!can_use_cam(user))
return
if(cameras.len == 1)
selected_camera = cameras[1]
else
@@ -209,7 +213,7 @@
unpair(selected_camera)
selected_camera = null
return
user.AddComponent(/datum/component/remote_view/item_zoom, focused_on = selected_camera, our_item = src, viewsize = null, tileoffset = 0, show_visible_messages = TRUE)
user.AddComponent(/datum/component/remote_view/item_zoom, focused_on = selected_camera, vconfig_path = /datum/remote_view_config/camera_standard, our_item = src, viewsize = null, tileoffset = 0, show_visible_messages = TRUE)
/obj/item/bug_monitor/proc/can_use_cam(mob/user)
if(!cameras.len)
@@ -231,9 +235,6 @@
if(Adjacent(user))
. += "The time '12:00' is blinking in the corner of the screen and \the [src] looks very cheaply made."
/obj/machinery/camera/bug/check_eye(var/mob/user as mob)
return 0
/obj/machinery/camera/bug
network = list(NETWORK_SECURITY)

View File

@@ -281,12 +281,6 @@
/obj/item/uav/proc/remove_master(var/mob/living/M)
LAZYREMOVE(masters, WEAKREF(M))
/obj/item/uav/check_eye()
if(state == UAV_ON)
return 0
else
return -1
/obj/item/uav/proc/start_hover()
if(!ion_trail.on) //We'll just use this to store if we're floating or not
ion_trail.start()

View File

@@ -92,7 +92,6 @@
/obj/item/assembly/attack_self(mob/user as mob)
if(!user)
return 0
user.set_machine(src)
tgui_interact(user)
return 1

View File

@@ -85,7 +85,7 @@
if(!src.eyeobj)
return
if(client.eye)
if(client && client.eye)
reset_perspective(src)
for(var/datum/chunk/c in eyeobj.visibleChunks)

View File

@@ -113,26 +113,6 @@
if(!.)
return
if (healths)
if (stat != 2)
switch(health)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
else
healths.icon_state = "health7"
client.screen.Remove(GLOB.global_hud.blurry,GLOB.global_hud.druggy,GLOB.global_hud.vimpaired)
if ( stat != 2)
@@ -144,6 +124,31 @@
set_fullscreen(eye_blurry, "blurry", /atom/movable/screen/fullscreen/blurry)
set_fullscreen(druggy, "high", /atom/movable/screen/fullscreen/high)
/mob/living/carbon/alien/handle_hud_icons_health()
. = ..()
if(!. || !healths)
return
if (stat == DEAD)
healths.icon_state = "health7"
return
switch(health)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/carbon/alien/handle_environment(var/datum/gas_mixture/environment)
// Both alien subtypes survive in vaccum and suffer in high temperatures,
// so I'll just define this once, for both (see radiation comment above)

View File

@@ -177,26 +177,6 @@
if(!.)
return
if (healths)
if (stat != DEAD)
switch(health)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
else
healths.icon_state = "health7"
client.screen.Remove(GLOB.global_hud.blurry,GLOB.global_hud.druggy,GLOB.global_hud.vimpaired)
if (stat != DEAD)
@@ -207,3 +187,28 @@
set_fullscreen(disabilities & NEARSIGHTED, "impaired", /atom/movable/screen/fullscreen/impaired, 1)
set_fullscreen(eye_blurry, "blurry", /atom/movable/screen/fullscreen/blurry)
set_fullscreen(druggy, "high", /atom/movable/screen/fullscreen/high)
/mob/living/carbon/brain/handle_hud_icons_health()
. = ..()
if(!. || !healths)
return
if (stat == DEAD)
healths.icon_state = "health7"
return
switch(health)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"

View File

@@ -1006,7 +1006,7 @@
var/mob/target = input ("Who do you want to project your mind to?") as mob in creatures
if(target)
AddComponent(/datum/component/remote_view/mremote_mutation, target)
AddComponent(/datum/component/remote_view/mremote_mutation, focused_on = target, vconfig_path = null)
return
/mob/living/carbon/human/get_visible_gender(mob/user, force)
@@ -1548,11 +1548,6 @@
return remove_from_mob(W, src.loc)
return ..()
/mob/living/carbon/human/reset_perspective(atom/A, update_hud = 1)
..()
if(update_hud)
handle_regular_hud_updates()
/mob/living/carbon/human/Check_Shoegrip()
if(shoes && (shoes.item_flags & NOSLIP) && istype(shoes, /obj/item/clothing/shoes/magboots)) //magboots + dense_object = no floating
return 1

View File

@@ -1455,7 +1455,6 @@
if(stat == DEAD) //Dead
if(!druggy) see_invisible = SEE_INVISIBLE_LEVEL_TWO
if(healths) healths.icon_state = "health7" //DEAD healthmeter
else if(stat == UNCONSCIOUS && health <= 0) //Crit
//Critical damage passage overlay
@@ -1533,48 +1532,6 @@
else
clear_fullscreen("fear")
if(healths)
if(chem_effects[CE_PAINKILLER] > 100)
healths.icon_state = "health_numb"
else
// Generate a by-limb health display.
var/mutable_appearance/healths_ma = new(healths)
healths_ma.icon_state = "blank"
healths_ma.overlays = null
healths_ma.plane = PLANE_PLAYER_HUD
var/no_damage = 1
var/trauma_val = 0 // Used in calculating softcrit/hardcrit indicators.
if(!(species.flags & NO_PAIN))
trauma_val = max(traumatic_shock,halloss)/species.total_health
var/limb_trauma_val = trauma_val*0.3
// Collect and apply the images all at once to avoid appearance churn.
var/list/health_images = list()
for(var/obj/item/organ/external/E in organs)
if(no_damage && (E.brute_dam || E.burn_dam))
no_damage = 0
health_images += E.get_damage_hud_image(limb_trauma_val)
// Apply a fire overlay if we're burning.
if(on_fire || get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_ONFIRE)
health_images += image('icons/mob/OnFire.dmi',"[get_fire_icon_state()]")
// Show a general pain/crit indicator if needed.
if(get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_CRIT)
trauma_val = 2
if(trauma_val)
if(!(species.flags & NO_PAIN))
if(trauma_val > 0.7)
health_images += image('icons/mob/screen1_health.dmi',"softcrit")
if(trauma_val >= 1)
health_images += image('icons/mob/screen1_health.dmi',"hardcrit")
else if(no_damage)
health_images += image('icons/mob/screen1_health.dmi',"fullhealth")
healths_ma.add_overlay(health_images)
healths.appearance = healths_ma
var/fat_alert = /atom/movable/screen/alert/fat
var/hungry_alert = /atom/movable/screen/alert/hungry
var/starving_alert = /atom/movable/screen/alert/starving
@@ -1658,10 +1615,58 @@
if(found_welder)
client.screen |= GLOB.global_hud.darkMask
/mob/living/carbon/human/reset_perspective(atom/A)
..()
if(machine_visual && machine_visual != A)
machine_visual.remove_visual(src)
/mob/living/carbon/human/handle_hud_icons_health()
. = ..()
if(!. || !healths)
return
if(stat == DEAD) //Dead
healths.icon_state = "health7" //DEAD healthmeter
return
if(stat == UNCONSCIOUS && health <= 0) //Crit
return
if(chem_effects[CE_PAINKILLER] > 100)
healths.icon_state = "health_numb"
return
// Generate a by-limb health display.
var/mutable_appearance/healths_ma = new(healths)
healths_ma.icon_state = "blank"
healths_ma.overlays = null
healths_ma.plane = PLANE_PLAYER_HUD
var/no_damage = 1
var/trauma_val = 0 // Used in calculating softcrit/hardcrit indicators.
if(!(species.flags & NO_PAIN))
trauma_val = max(traumatic_shock,halloss)/species.total_health
var/limb_trauma_val = trauma_val*0.3
// Collect and apply the images all at once to avoid appearance churn.
var/list/health_images = list()
for(var/obj/item/organ/external/E in organs)
if(no_damage && (E.brute_dam || E.burn_dam))
no_damage = 0
health_images += E.get_damage_hud_image(limb_trauma_val)
// Apply a fire overlay if we're burning.
if(on_fire || get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_ONFIRE)
health_images += image('icons/mob/OnFire.dmi',"[get_fire_icon_state()]")
// Show a general pain/crit indicator if needed.
if(get_hallucination_component()?.get_hud_state() == HUD_HALLUCINATION_CRIT)
trauma_val = 2
if(trauma_val)
if(!(species.flags & NO_PAIN))
if(trauma_val > 0.7)
health_images += image('icons/mob/screen1_health.dmi',"softcrit")
if(trauma_val >= 1)
health_images += image('icons/mob/screen1_health.dmi',"hardcrit")
else if(no_damage)
health_images += image('icons/mob/screen1_health.dmi',"fullhealth")
healths_ma.add_overlay(health_images)
healths.appearance = healths_ma
/mob/living/carbon/human/handle_vision()
if(stat == DEAD)
@@ -1739,7 +1744,7 @@
if(!seer && !glasses_processed && seedarkness)
see_invisible = see_invisible_default
if(!get_current_machine() && eyeobj && eyeobj.owner != src)
if(eyeobj && eyeobj.owner != src)
reset_perspective()
// Call parent to handle signals

View File

@@ -236,7 +236,7 @@
if(!.)
return
handle_darksight()
handle_hud_icons()
handle_hud_icons_health()
/mob/living/proc/update_sight()
if(!seedarkness)
@@ -252,12 +252,11 @@
return
/mob/living/proc/handle_hud_icons()
handle_hud_icons_health()
return
/mob/living/proc/handle_hud_icons_health()
return
SHOULD_CALL_PARENT(TRUE)
if(SEND_SIGNAL(src,COMSIG_LIVING_HANDLE_HUD_HEALTH_ICON) & COMSIG_COMPONENT_HANDLED_HEALTH_ICON)
return FALSE
return TRUE
/mob/living/proc/handle_light()
if(glow_override)
@@ -277,6 +276,7 @@
return FALSE
/mob/living/proc/handle_darksight()
SEND_SIGNAL(src,COMSIG_LIVING_HANDLE_HUD_DARKSIGHT)
if(!seedarkness) //Cheap 'always darksight' var
dsoverlay.alpha = 255
return

View File

@@ -45,5 +45,6 @@
voice_sounds_list = DEFAULT_TALK_SOUNDS
resize(size_multiplier, animate = FALSE, uncapped = has_large_resize_bounds(), ignore_prefs = TRUE, aura_animation = FALSE)
init_vore(TRUE)
handle_regular_hud_updates()
return .

View File

@@ -441,10 +441,6 @@ var/list/ai_verbs_default = list(
emergency_message_cooldown = 1
spawn(300)
emergency_message_cooldown = 0
/mob/living/silicon/ai/check_eye(var/mob/user as mob)
if (!camera)
return -1
return 0
/mob/living/silicon/ai/restrained()
return 0
@@ -513,21 +509,23 @@ var/list/ai_verbs_default = list(
if(.)
end_multicam()
/mob/living/silicon/ai/reset_perspective(atom/A)
/mob/living/silicon/ai/reset_perspective(atom/new_eye)
if(camera)
camera.set_light(0)
if(istype(A,/obj/machinery/camera))
camera = A
if(A != GLOB.ai_camera_room_landmark)
if(istype(new_eye,/obj/machinery/camera))
camera = new_eye
if(new_eye != GLOB.ai_camera_room_landmark)
end_multicam()
. = ..()
if(.)
if(!A && isturf(loc) && eyeobj)
if(!new_eye && isturf(loc) && eyeobj)
end_multicam()
reset_perspective(eyeobj)
if(istype(A,/obj/machinery/camera))
if(camera_light_on) A.set_light(AI_CAMERA_LUMINOSITY)
else A.set_light(0)
if(istype(new_eye,/obj/machinery/camera))
if(camera_light_on)
new_eye.set_light(AI_CAMERA_LUMINOSITY)
else
new_eye.set_light(0)
/mob/living/silicon/ai/proc/switchCamera(var/obj/machinery/camera/C)

View File

@@ -131,11 +131,6 @@
. += ""
. += show_silenced()
/mob/living/silicon/pai/check_eye(var/mob/user as mob)
if (!src.current)
return -1
return 0
/mob/living/silicon/pai/restrained()
if(istype(src.loc,/obj/item/paicard))
return 0
@@ -177,16 +172,13 @@
/mob/living/silicon/pai/proc/switchCamera(var/obj/machinery/camera/C)
if (!C)
src.unset_machine()
src.reset_perspective()
return 0
if (stat == 2 || !C.status || !(src.network in C.network)) return 0
// ok, we're alive, camera is good and in our network...
src.set_machine(src)
src.current = C
src.AddComponent(/datum/component/remote_view, C)
src.AddComponent(/datum/component/remote_view, focused_on = C, vconfig_path = /datum/remote_view_config/camera_standard)
return 1
/mob/living/silicon/pai/verb/reset_record_view()
@@ -205,9 +197,11 @@
/mob/living/silicon/pai/cancel_camera()
set category = "Abilities.pAI Commands"
set name = "Cancel Camera View"
src.reset_perspective()
src.unset_machine()
src.cameraFollow = null
reset_perspective()
/mob/living/silicon/pai/reset_perspective(atom/new_eye)
. = ..()
current = null
// Procs/code after this point is used to convert the stationary pai item into a
// mobile pai mob. This also includes handling some of the general shit that can occur

View File

@@ -393,33 +393,38 @@
if(!.)
return
if(healths)
if(stat != DEAD)
var/heal_per = (health / getMaxHealth()) * 100
switch(heal_per)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
else
healths.icon_state = "health7"
if(pai_fold_display)
if(loc == card)
pai_fold_display.icon_state = "folded"
else
pai_fold_display.icon_state = "unfolded"
/mob/living/silicon/pai/handle_hud_icons_health()
. = ..()
if(!. || !healths)
return
if(stat == DEAD)
healths.icon_state = "health7"
return
var/heal_per = (health / getMaxHealth()) * 100
switch(heal_per)
if(100 to INFINITY)
healths.icon_state = "health0"
if(80 to 100)
healths.icon_state = "health1"
if(60 to 80)
healths.icon_state = "health2"
if(40 to 60)
healths.icon_state = "health3"
if(20 to 40)
healths.icon_state = "health4"
if(0 to 20)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/silicon/pai/toggle_hud_vis(full)
if(!client)
return FALSE

View File

@@ -228,42 +228,6 @@
if(!.)
return
if (healths)
if (stat != 2)
if(istype(src,/mob/living/silicon/robot/drone))
switch(health)
if(35 to INFINITY)
healths.icon_state = "health0"
if(25 to 34)
healths.icon_state = "health1"
if(15 to 24)
healths.icon_state = "health2"
if(5 to 14)
healths.icon_state = "health3"
if(0 to 4)
healths.icon_state = "health4"
if(-35 to 0)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
else
if(health >= 200)
healths.icon_state = "health0"
else if(health >= 150)
healths.icon_state = "health1"
else if(health >= 100)
healths.icon_state = "health2"
else if(health >= 50)
healths.icon_state = "health3"
else if(health >= 0)
healths.icon_state = "health4"
else if(health >= (-getMaxHealth()))
healths.icon_state = "health5"
else
healths.icon_state = "health6"
else
healths.icon_state = "health7"
if (syndicate)
for(var/datum/mind/tra in traitors.current_antagonists)
if(tra.current)
@@ -294,9 +258,9 @@
else
throw_alert("temp", /atom/movable/screen/alert/cold/robot, COLD_ALERT_SEVERITY_MODERATE)
//Oxygen and fire does nothing yet!!
// if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]"
// if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]"
//Oxygen and fire does nothing yet!!
//if (oxygen) oxygen.icon_state = "oxy[oxygen_alert ? 1 : 0]"
//if (fire) fire.icon_state = "fire[fire_alert ? 1 : 0]"
if(stat != 2)
if(blinded)
@@ -312,6 +276,49 @@
else
clear_alert("hacked")
/mob/living/silicon/robot/handle_hud_icons_health()
. = ..()
if(!. || !healths)
return
if(stat == DEAD)
healths.icon_state = "health7"
return
if(istype(src,/mob/living/silicon/robot/drone))
switch(health)
if(35 to INFINITY)
healths.icon_state = "health0"
if(25 to 34)
healths.icon_state = "health1"
if(15 to 24)
healths.icon_state = "health2"
if(5 to 14)
healths.icon_state = "health3"
if(0 to 4)
healths.icon_state = "health4"
if(-35 to 0)
healths.icon_state = "health5"
else
healths.icon_state = "health6"
return
// Not a switch because of the -max_health() case
if(health >= 200)
healths.icon_state = "health0"
else if(health >= 150)
healths.icon_state = "health1"
else if(health >= 100)
healths.icon_state = "health2"
else if(health >= 50)
healths.icon_state = "health3"
else if(health >= 0)
healths.icon_state = "health4"
else if(health >= (-getMaxHealth()))
healths.icon_state = "health5"
else
healths.icon_state = "health6"
/mob/living/silicon/robot/proc/update_cell()
if(cell)
var/cellcharge = cell.charge/cell.maxcharge

View File

@@ -710,7 +710,7 @@
I.brute = C.brute_damage
I.burn = C.electronics_damage
I.loc = src.loc
I.forceMove(loc)
if(C.installed == 1)
C.uninstall()

View File

@@ -398,8 +398,7 @@
/mob/living/silicon/reset_perspective(atom/new_eye)
. = ..()
if(cameraFollow)
cameraFollow = null
cameraFollow = null
/mob/living/silicon/flash_eyes(intensity = FLASH_PROTECTION_MODERATE, override_blindness_check = FALSE, affect_silicon = FALSE, visual = FALSE, type = /atom/movable/screen/fullscreen/flash)
if(affect_silicon)

View File

@@ -306,10 +306,10 @@
if(remote_comp?.looking_at_target_already(loc))
return FALSE
if(isitem(loc) || isbelly(loc)) // Requires more careful handling than structures because they are held by mobs
AddComponent(/datum/component/remote_view/mob_holding_item, loc)
AddComponent(/datum/component/remote_view/mob_holding_item, focused_on = loc, vconfig_path = null)
return TRUE
if(loc.flags & REMOTEVIEW_ON_ENTER) // Handle atoms that begin a remote view upon entering them.
AddComponent(/datum/component/remote_view, loc)
AddComponent(/datum/component/remote_view, focused_on = loc, vconfig_path = null)
return TRUE
return FALSE
@@ -564,7 +564,7 @@
var/mob/mob_eye = targets[eye_name]
if(client && mob_eye)
AddComponent(/datum/component/remote_view, focused_on = mob_eye)
AddComponent(/datum/component/remote_view, focused_on = mob_eye, vconfig_path = null)
if(is_admin)
client.adminobs = TRUE
if(mob_eye == client.mob || !is_remote_viewing())
@@ -573,7 +573,6 @@
/mob/verb/cancel_camera()
set name = "Cancel Camera View"
set category = "OOC.Game"
unset_machine()
reset_perspective()
/mob/Topic(href, href_list)

View File

@@ -561,7 +561,6 @@ var/list/intents = list(I_HELP,I_DISARM,I_GRAB,I_HURT)
/mob/proc/switch_to_camera(var/obj/machinery/camera/C)
if (!C.can_use() || stat || (get_dist(C, src) > 1 || !check_current_machine(src) || blinded || !canmove))
return 0
check_eye(src)
return 1
/mob/living/silicon/ai/switch_to_camera(var/obj/machinery/camera/C)
@@ -716,12 +715,13 @@ var/list/global/organ_rel_size = list(
/mob/proc/recalculate_vis()
return
/// General HUD updates done regularly (health puppet things, etc). Returns true if the mob has a client.
/// General HUD updates done regularly (health puppet things, etc). Returns true if the mob has a client and is allowed to update its hud.
/mob/proc/handle_regular_hud_updates()
SHOULD_CALL_PARENT(TRUE)
if(!client)
return FALSE
SEND_SIGNAL(src,COMSIG_LIVING_HANDLE_HUD)
if(SEND_SIGNAL(src,COMSIG_LIVING_HANDLE_HUD) & COMSIG_COMPONENT_HANDLED_HUD)
return FALSE
return TRUE
/// Handle eye things like the Byond SEE_TURFS, SEE_OBJS, etc.

View File

@@ -214,11 +214,8 @@
return
// Relaymove could handle it
var/obj/machine = my_mob.get_current_machine()
if(machine)
var/result = machine.relaymove(my_mob, direct)
if(result)
return result
if(SEND_SIGNAL(my_mob, COMSIG_MOB_RELAY_MOVEMENT, direct))
return TRUE
// Can't control ourselves when drifting
if((isspace(loc) || my_mob.lastarea?.get_gravity() == 0) && isturf(loc))

View File

@@ -271,24 +271,6 @@
update_uis()
// Used by camera monitor program
/obj/item/modular_computer/check_eye(var/mob/user)
if(active_program)
return active_program.check_eye(user)
else
return ..()
/obj/item/modular_computer/apply_visual(var/mob/user)
if(active_program)
return active_program.apply_visual(user)
/obj/item/modular_computer/remove_visual(var/mob/user)
if(active_program)
return active_program.remove_visual(user)
/obj/item/modular_computer/relaymove(var/mob/user, direction)
if(active_program)
return active_program.relaymove(user, direction)
/obj/item/modular_computer/proc/set_autorun(program)
if(!hard_drive)
return

View File

@@ -219,24 +219,3 @@
if(istype(user))
computer.tgui_interact(user) // Re-open the UI on this computer. It should show the main screen now.
// Relays the call to nano module, if we have one
/datum/computer_file/program/proc/check_eye(var/mob/user)
if(TM)
return TM.check_eye(user)
else
return -1
/datum/computer_file/program/apply_visual(mob/M)
if(TM)
return TM.apply_visual(M)
/datum/computer_file/program/remove_visual(mob/M)
if(TM)
return TM.remove_visual(M)
/datum/computer_file/program/proc/relaymove(var/mob/M, direction)
if(TM)
return TM.relaymove(M, direction)

View File

@@ -102,6 +102,7 @@
stored_mmi.forceMove(drop_location())
if(owner.mind)
owner.mind.transfer_to(stored_mmi.brainmob)
stored_mmi.brainmob.reset_perspective()
..()
var/mob/living/holder_mob = loc

View File

@@ -270,11 +270,11 @@ GLOBAL_LIST_EMPTY(all_waypoints)
. = TRUE
if("manual")
if(check_eye(ui.user) < 0)
if(!get_dist(ui.user, src) > 1 || ui.user.blinded || !linked)
return FALSE
else if(!viewing_overmap(ui.user) && linked)
if(!viewers) viewers = list() // List must exist for pass by reference to work
start_coordinated_remoteview(ui.user, linked, viewers)
start_coordinated_remoteview(ui.user, linked, viewers, /datum/remote_view_config/overmap_ship_control)
else
ui.user.reset_perspective()
. = TRUE

View File

@@ -89,7 +89,7 @@
switch(action)
if("viewing")
if(ui.user && !isAI(ui.user))
if(check_eye(ui.user) < 0)
if(!get_dist(ui.user, src) > 1 || ui.user.blinded || !linked)
. = FALSE
else if(!viewing_overmap(ui.user) && linked)
if(!viewers) viewers = list() // List must exist for pass by reference to work

View File

@@ -67,22 +67,13 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
// Management of mob view displacement. look to shift view to the ship on the overmap; unlook to shift back.
/obj/machinery/computer/ship/look(var/mob/user)
apply_visual(user)
if(linked.real_appearance)
user.client?.images += linked.real_appearance
user.set_machine(src)
if(isliving(user))
var/mob/living/L = user
L.handle_vision()
user.set_viewsize(world.view + extra_view)
/obj/machinery/computer/ship/unlook(var/mob/user)
user.unset_machine()
if(linked && linked.real_appearance && user.client)
user.client.images -= linked.real_appearance
if(isliving(user))
var/mob/living/L = user
L.handle_vision()
user.set_viewsize() // reset to default
/obj/machinery/computer/ship/proc/viewing_overmap(mob/user)
@@ -92,13 +83,6 @@ somewhere on that shuttle. Subtypes of these can be then used to perform ship ov
. = ..()
user.reset_perspective()
/obj/machinery/computer/ship/check_eye(var/mob/user)
if(user.blinded || !linked)
user.reset_perspective()
return -1
else
return 0
/obj/machinery/computer/ship/sensors/Destroy()
sensors = null
. = ..()

View File

@@ -37,9 +37,6 @@ Code is pretty much ripped verbatim from nano modules, but with un-needed stuff
if(host)
host.tgui_close(user)
/datum/tgui_module/proc/check_eye(mob/user)
return -1
/datum/tgui_module/proc/can_still_topic(mob/user, datum/tgui_state/state)
return (tgui_status(user, state) == STATUS_INTERACTIVE)

View File

@@ -70,14 +70,14 @@
if(!current_uav)
return FALSE
if(current_uav.check_eye(ui.user) < 0)
if(!current_uav.state)
to_chat(ui.user,span_warning("The screen freezes for a moment, before returning to the UAV selection menu. It's not able to connect to that UAV."))
else
if(check_eye(ui.user) < 0)
if(get_dist(ui.user, tgui_host()) > 1 || ui.user.blinded)
return FALSE
else if(!viewing_uav(ui.user))
if(!viewers) viewers = list() // List must exist for pass by reference to work
start_coordinated_remoteview(ui.user, current_uav, viewers)
start_coordinated_remoteview(ui.user, current_uav, viewers, /datum/remote_view_config/uav_control)
else
ui.user.reset_perspective()
return TRUE
@@ -173,17 +173,12 @@
if(issilicon(user)) //Too complicated for me to want to mess with at the moment
to_chat(user, span_warning("Regulations prevent you from controlling several corporeal forms at the same time!"))
return
if(!current_uav)
return
if(!user.check_current_machine(tgui_host()))
user.set_machine(tgui_host())
current_uav.add_master(user)
LAZYDISTINCTADD(viewers, WEAKREF(user))
/datum/tgui_module/uav/unlook(mob/user)
user.unset_machine()
if(current_uav)
current_uav.remove_master(user)
LAZYREMOVE(viewers, WEAKREF(user))
@@ -192,45 +187,77 @@
. = ..()
user.reset_perspective()
/datum/tgui_module/uav/check_eye(mob/user)
if(get_dist(user, tgui_host()) > 1 || user.blinded || !current_uav)
user.reset_perspective()
return -1
var/viewflag = current_uav.check_eye(user)
if(viewflag < 0) //camera doesn't work
user.reset_perspective()
return -1
return viewflag
////
//// Relaying movements to the UAV
//// Settings for remote view
////
/datum/tgui_module/uav/relaymove(var/mob/user, direction)
if(current_uav)
return current_uav.relaymove(user, direction, signal_strength)
/datum/remote_view_config/uav_control
relay_movement = TRUE
override_health_hud = TRUE
var/original_health_hud_icon
////
//// The effects when looking through a UAV
////
/datum/tgui_module/uav/apply_visual(mob/M)
if(!M.client)
/datum/remote_view_config/uav_control/handle_relay_movement( datum/component/remote_view/owner_component, mob/host_mob, direction)
var/datum/tgui_module/uav/tgui_owner = owner_component.get_coordinator()
if(tgui_owner?.current_uav)
return tgui_owner.current_uav.relaymove(host_mob, direction, tgui_owner.signal_strength)
return FALSE
/datum/remote_view_config/uav_control/handle_apply_visuals( datum/component/remote_view/owner_component, mob/host_mob)
var/datum/tgui_module/uav/tgui_owner = owner_component.get_coordinator()
if(!tgui_owner)
return
if(WEAKREF(M) in viewers)
M.overlay_fullscreen("fishbed",/atom/movable/screen/fullscreen/fishbed)
M.overlay_fullscreen("scanlines",/atom/movable/screen/fullscreen/scanline)
if(signal_strength <= 1)
M.overlay_fullscreen("whitenoise",/atom/movable/screen/fullscreen/noise)
else
M.clear_fullscreen("whitenoise", 0)
if(get_dist(host_mob, tgui_owner.tgui_host()) > 1 || !tgui_owner.current_uav)
host_mob.reset_perspective()
return
// Apply hud
host_mob.overlay_fullscreen("fishbed",/atom/movable/screen/fullscreen/fishbed)
host_mob.overlay_fullscreen("scanlines",/atom/movable/screen/fullscreen/scanline)
if(tgui_owner.signal_strength <= 1)
host_mob.overlay_fullscreen("whitenoise",/atom/movable/screen/fullscreen/noise)
else
remove_visual(M)
host_mob.clear_fullscreen("whitenoise", 0)
/datum/tgui_module/uav/remove_visual(mob/M)
if(!M.client)
return
M.clear_fullscreen("fishbed",0)
M.clear_fullscreen("scanlines",0)
M.clear_fullscreen("whitenoise",0)
/datum/remote_view_config/uav_control/handle_remove_visuals( datum/component/remote_view/owner_component, mob/host_mob)
// Clear hud
host_mob.clear_fullscreen("fishbed",0)
host_mob.clear_fullscreen("scanlines",0)
host_mob.clear_fullscreen("whitenoise",0)
// We are responsible for restoring the health UI's icons on removal
/datum/remote_view_config/uav_control/attached_to_mob( datum/component/remote_view/owner_component, mob/host_mob)
original_health_hud_icon = host_mob.healths?.icon
/datum/remote_view_config/uav_control/detatch_from_mob( datum/component/remote_view/owner_component, mob/host_mob)
if(host_mob.healths && original_health_hud_icon)
host_mob.healths.icon = original_health_hud_icon
host_mob.healths.appearance = null
// Show the uav health instead of the mob's while it is viewing
/datum/remote_view_config/uav_control/handle_hud_health( datum/component/remote_view/owner_component, mob/host_mob)
var/datum/tgui_module/uav/tgui_owner = owner_component.get_coordinator()
var/mutable_appearance/MA = new (host_mob.healths)
MA.icon = 'icons/mob/screen1_robot_minimalist.dmi'
MA.cut_overlays()
if(!tgui_owner?.current_uav)
MA.icon_state = "health7"
else
switch(tgui_owner.current_uav.health)
if(100 to INFINITY)
MA.icon_state = "health0"
if(80 to 100)
MA.icon_state = "health1"
if(60 to 80)
MA.icon_state = "health2"
if(40 to 60)
MA.icon_state = "health3"
if(20 to 40)
MA.icon_state = "health4"
if(0 to 20)
MA.icon_state = "health5"
else
MA.icon_state = "health6"
host_mob.healths.icon_state = "blank"
host_mob.healths.appearance = MA
return COMSIG_COMPONENT_HANDLED_HEALTH_ICON

View File

@@ -73,13 +73,6 @@
/datum/tgui_module/ship/proc/viewing_overmap(mob/user)
return (WEAKREF(user) in viewers)
/datum/tgui_module/ship/check_eye(var/mob/user)
if(!get_dist(user, tgui_host()) > 1 || user.blinded || !linked)
user.reset_perspective()
return -1
else
return 0
// Navigation
/datum/tgui_module/ship/nav
name = "Navigation Display"
@@ -136,11 +129,11 @@
return FALSE
if(action == "viewing")
if(check_eye(ui.user) < 0)
if(!get_dist(ui.user, src) > 1 || ui.user.blinded || !linked)
return FALSE
else if(!viewing_overmap(ui.user))
if(!viewers) viewers = list() // List must exist for pass by reference to work
start_coordinated_remoteview(ui.user, linked, viewers)
start_coordinated_remoteview(ui.user, linked, viewers, /datum/remote_view_config/overmap_ship_control)
else
ui.user.reset_perspective()
return TRUE
@@ -406,11 +399,11 @@
. = TRUE
if("manual")
if(check_eye(ui.user) < 0)
if(ui.user.blinded || !linked)
return FALSE
else if(!viewing_overmap(ui.user))
if(!viewers) viewers = list()
start_coordinated_remoteview(ui.user, linked, viewers)
start_coordinated_remoteview(ui.user, linked, viewers, /datum/remote_view_config/overmap_ship_control)
else
ui.user.reset_perspective()
. = TRUE
@@ -479,3 +472,23 @@
return
/datum/tgui_module/ship/fullmonty/attempt_hook_up()
return
////
//// Settings for remote view
////
/datum/remote_view_config/overmap_ship_control
relay_movement = TRUE
/datum/remote_view_config/overmap_ship_control/handle_relay_movement( datum/component/remote_view/owner_component, mob/host_mob, direction)
var/datum/tgui_module/ship/tgui_owner = owner_component.get_coordinator()
if(tgui_owner?.linked)
return tgui_owner.relaymove(host_mob, direction)
return FALSE
/datum/remote_view_config/overmap_ship_control/handle_apply_visuals( datum/component/remote_view/owner_component, mob/host_mob)
var/datum/tgui_module/ship/tgui_owner = owner_component.get_coordinator()
if(!tgui_owner)
return
if(get_dist(host_mob, tgui_owner.tgui_host()) > 1 || !tgui_owner.linked)
host_mob.reset_perspective()
return

View File

@@ -568,6 +568,7 @@
#include "code\datums\organs.dm"
#include "code\datums\position_point_vector.dm"
#include "code\datums\progressbar.dm"
#include "code\datums\remote_view_config.dm"
#include "code\datums\riding.dm"
#include "code\datums\signals.dm"
#include "code\datums\soul_link.dm"