Fixing client eye (#18577)

* signal foundation

* reset_perspective implemented

* you too

* setting mob

* no

* fix

* tweak

* remote view element

* these too

* use element

* cleanup more manual code

* fix element

* mutation signal

* handle being dropped from holders, and fix pai hud

* handle qdel

* it's a component now

* ugly holder fix

* another fix

* follow view target

* item remote view

* doc update

* unneeded

* this needs a recode to work better

* many fixes

* these are all unneeded

* almost working viewerlist remotes

* this uses component too

* this needs to die to it's item

* don't allow spamming tgui menus

* tg style args

* fixing behaviors

* fuk

* working view release from holders

* only final matters

* comment order and disposal fix

* cryotube loc fix

* no mob should reset its view every life tick

* major improvements

* still forbid z level change even if we allow moving

* this too

* don't doubledip

* qdel on self is unneeded

* wipe remote views on logout

* vore bellies need to manually clear views

* fixAI hud

* belly release fixes

* cannot use binoculars in a vore belly

* pai card can be picked up and dropped correctly

* ventcrawl fix and distracted fix

* this is better

* forcemove

* vr console fix

* use flag for this

* belly stuff

* various cleanups

* oops

* fixes statue spell

* unneeded perspective clear

* automatic instead

* continued cleanup

* that was dumb

* needed

* none of this works

* are these even needed

* lets lock down to these

* lets try to make this work

* extremely close to working

* needs to solve final pai issues

* mob eye change signal

* Revert "mob eye change signal"

This reverts commit eedd5da934.

* significant progress

* safety

* expected to be not null

* likely not needed

* don't spam component changes

* endview on logout

* accessors

* egg fixing

* Revert "egg fixing"

This reverts commit 6a54049c69.

* getting closer

* even closer

* needs type

* close...

* extremely close to working

* fixing pai stuff

* this too

* promising fixes

* docs

* this is recursive move's responsibility tbh

* unneeded now

* oops

* better decouple

* topmost check

* cleanup

* holder released from egg fix

* pai fix for reset view

* debug info

* some better pai ejection code

* better way

* unneeded

* needs to be null

* better vision restore

* use correct handling

* no longer needed

* required

* handle decouple on mecha too

* name clarity

* do not allow double dipping zoom items

* ethereal jaunt needs a full cleanup later

* fix blackscreen flicker

* remove set machine from pda

* Update code/game/objects/items.dm

* Update code/game/objects/items.dm

* Update code/game/objects/items.dm

* Update code/game/objects/items.dm

---------

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
Will
2025-10-12 22:18:08 -04:00
committed by GitHub
parent 994be6bf05
commit 2194b87de0
95 changed files with 762 additions and 710 deletions
+18 -68
View File
@@ -421,8 +421,6 @@
// apparently called whenever an item is removed from a slot, container, or anything else.
/obj/item/proc/dropped(mob/user)
SHOULD_CALL_PARENT(TRUE)
if(zoom)
zoom() //binoculars, scope, etc
appearance_flags &= ~NO_CLIENT_COLOR
// Remove any item actions we temporary gave out.
for(var/datum/action/action_item_has as anything in actions)
@@ -432,6 +430,7 @@
qdel(src)
SEND_SIGNAL(src, COMSIG_ITEM_DROPPED, user)
SEND_SIGNAL(user, COMSIG_MOB_DROPPED_ITEM, src)
if(my_augment && !QDELETED(src))
forceMove(my_augment)
@@ -820,91 +819,42 @@ GLOBAL_LIST_EMPTY(blood_overlays_by_type)
if(I && !I.abstract)
I.showoff(src)
/*
For zooming with scope or binoculars. This is called from
modules/mob/mob_movement.dm if you move you will be zoomed out
modules/mob/living/carbon/human/life.dm if you die, you will be zoomed out.
*/
//Looking through a scope or binoculars should /not/ improve your periphereal vision. Still, increase viewsize a tiny bit so that sniping isn't as restricted to NSEW
/obj/item/var/ignore_visor_zoom_restriction = FALSE
/// For zooming with scope or binoculars. Uses remote_view/item component for disabling when you move or drop the item
/obj/item/proc/zoom(var/mob/living/M, var/tileoffset = 14,var/viewsize = 9) //tileoffset is client view offset in the direction the user is facing. viewsize is how far out this thing zooms. 7 is normal view
SIGNAL_HANDLER
if(isliving(usr)) //Always prefer usr if set
M = usr
if(!M.client)
return FALSE
if(!isliving(M))
return 0
return FALSE
if(isbelly(M.loc) || istype(M.loc,/obj/item/dogborg/sleeper))
return FALSE
if(M.is_remote_viewing())
to_chat(M, span_warning("You are too distracted to do that."))
return FALSE
var/devicename
if(zoomdevicename)
devicename = zoomdevicename
else
devicename = src.name
var/cannotzoom
var/can_zoom = TRUE
if((M.stat && !zoom) || !(ishuman(M)))
to_chat(M, span_filter_notice("You are unable to focus through the [devicename]."))
cannotzoom = 1
can_zoom = FALSE
else if(!zoom && (GLOB.global_hud.darkMask[1] in M.client.screen))
to_chat(M, span_filter_notice("Your visor gets in the way of looking through the [devicename]."))
cannotzoom = 1
can_zoom = FALSE
else if(!zoom && M.get_active_hand() != src)
to_chat(M, span_filter_notice("You are too distracted to look through the [devicename], perhaps if it was in your active hand this might work better."))
cannotzoom = 1
can_zoom = FALSE
//We checked above if they are a human and returned already if they weren't.
var/mob/living/carbon/human/H = M
if(!zoom && !cannotzoom)
if(H.hud_used.hud_shown)
H.toggle_zoom_hud() // If the user has already limited their HUD this avoids them having a HUD when they zoom in
H.set_viewsize(viewsize)
zoom = 1
H.AddComponent(/datum/component/recursive_move)
RegisterSignal(H, COMSIG_OBSERVER_MOVED, PROC_REF(zoom), override = TRUE)
var/tilesize = 32
var/viewoffset = tilesize * tileoffset
switch(H.dir)
if (NORTH)
H.client.pixel_x = 0
H.client.pixel_y = viewoffset
if (SOUTH)
H.client.pixel_x = 0
H.client.pixel_y = -viewoffset
if (EAST)
H.client.pixel_x = viewoffset
H.client.pixel_y = 0
if (WEST)
H.client.pixel_x = -viewoffset
H.client.pixel_y = 0
H.visible_message(span_filter_notice("[M] peers through the [zoomdevicename ? "[zoomdevicename] of the [src.name]" : "[src.name]"]."))
if(!ignore_visor_zoom_restriction)
H.looking_elsewhere = TRUE
H.handle_vision()
else
H.set_viewsize() // Reset to default
if(!H.hud_used.hud_shown)
H.toggle_zoom_hud()
zoom = 0
UnregisterSignal(H, COMSIG_OBSERVER_MOVED)
H.client.pixel_x = 0
H.client.pixel_y = 0
H.looking_elsewhere = FALSE
H.handle_vision()
if(!cannotzoom)
M.visible_message(span_filter_notice("[zoomdevicename ? "[M] looks up from the [src.name]" : "[M] lowers the [src.name]"]."))
return
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)
return
SEND_SIGNAL(src,COMSIG_REMOTE_VIEW_CLEAR)
/obj/item/proc/pwr_drain()
return 0 // Process Kill
@@ -87,16 +87,14 @@
/obj/item/chameleon/proc/eject_all()
for(var/atom/movable/A in active_dummy)
A.loc = active_dummy.loc
if(ismob(A))
var/mob/M = A
M.reset_view(null)
A.forceMove(get_turf(active_dummy))
/obj/effect/dummy/chameleon
name = ""
desc = ""
density = FALSE
anchored = TRUE
flags = REMOTEVIEW_ON_ENTER
var/can_move = 1
var/obj/item/chameleon/master = null
@@ -107,7 +105,7 @@
icon_state = new_iconstate
overlays = new_overlays
set_dir(O.dir)
M.loc = src
M.forceMove(src)
master = C
master.active_dummy = src
+3 -3
View File
@@ -460,16 +460,16 @@
paicard = card
user.unEquip(card)
card.forceMove(src)
AI.client.eye = src
AI.reset_perspective(src) // focus this machine
to_chat(AI, span_notice("Your location is [card.loc].")) // DEBUG. TODO: Make unfolding the chassis trigger an eject.
name = AI.name
to_chat(AI, span_notice("You feel a tingle in your circuits as your systems interface with \the [initial(src.name)]."))
/obj/machinery/proc/ejectpai(mob/user)
if(paicard)
paicard.forceMove(get_turf(src))
var/mob/living/silicon/pai/AI = paicard.pai
paicard.forceMove(src.loc)
AI.client.eye = AI
AI.reset_perspective() // return to the card
paicard = null
name = initial(src.name)
to_chat(AI, span_notice("You feel a tad claustrophobic as your mind closes back into your card, ejecting from \the [initial(src.name)]."))
+22 -37
View File
@@ -33,7 +33,6 @@
spawn(0)
qdel(src)
/* else
user.set_machine(radio)
radio.interact(user)
*/
/obj/item/camerabug/verb/reset()
@@ -159,7 +158,6 @@
w_class = ITEMSIZE_SMALL
origin_tech = list(TECH_DATA = 1, TECH_ENGINEERING = 1)
var/operating = 0
// var/obj/item/radio/bug/radio
var/obj/machinery/camera/bug/selected_camera
var/list/obj/machinery/camera/bug/cameras = new()
@@ -172,17 +170,14 @@
radio = new(src)
*/
/obj/item/bug_monitor/attack_self(mob/user)
if(operating)
return
// radio.attack_self(user)
view_cameras(user)
/obj/item/bug_monitor/attackby(obj/item/W as obj, mob/living/user as mob)
if(istype(W, /obj/item/camerabug))
W.attackby(src, user)
else
return ..()
return
. = ..()
/obj/item/bug_monitor/proc/unpair(var/obj/item/camerabug/SB)
if(SB.camera in cameras)
@@ -192,46 +187,36 @@
cameras += SB.camera
/obj/item/bug_monitor/proc/view_cameras(mob/user)
if(in_use)
return
if(!can_use_cam(user))
return
selected_camera = cameras[1]
user.reset_view(selected_camera)
if(cameras.len == 1)
selected_camera = cameras[1]
else
in_use = TRUE // Don't allow spamming tgui menus
selected_camera = tgui_input_list(user, "Select camera to view.", "Camera Choice", cameras)
in_use = FALSE
view_camera(user)
operating = 1
while(selected_camera && Adjacent(user))
selected_camera = tgui_input_list(user, "Select camera to view.", "Camera Choice", cameras)
selected_camera = null
operating = 0
/obj/item/bug_monitor/proc/view_camera(mob/user)
spawn(0)
while(selected_camera && Adjacent(user))
var/turf/T = get_turf(selected_camera)
if(!T || !is_on_same_plane_or_station(T.z, user.z) || !selected_camera.can_use())
user.unset_machine()
user.reset_view(null)
to_chat(user, span_notice("Link to [selected_camera] has been lost."))
src.unpair(selected_camera.loc)
sleep(90)
else
user.set_machine(selected_camera)
user.reset_view(selected_camera)
sleep(10)
user.unset_machine()
user.reset_view(null)
if(loc != user) // Nice try smartass, must be in your hand and not in a box in your inventory
return
var/turf/T = get_turf(selected_camera)
if(!T || !is_on_same_plane_or_station(T.z, user.z) || !selected_camera.can_use())
to_chat(user, span_notice("Link to [selected_camera] has been lost."))
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)
/obj/item/bug_monitor/proc/can_use_cam(mob/user)
if(operating)
return
if(!cameras.len)
to_chat(user, span_warning("No paired cameras detected!"))
to_chat(user, span_warning("Bring a camera in contact with this device to pair the camera."))
return
return 1
return FALSE
return TRUE
/obj/item/bug_monitor/spy
name = "\improper PDA"
@@ -88,10 +88,7 @@
return
if(M == occupant) // so that the guy inside can't eject himself -Agouri
return
if (src.occupant.client)
src.occupant.client.eye = src.occupant.client.mob
src.occupant.client.perspective = MOB_PERSPECTIVE
src.occupant.loc = src.loc
src.occupant.forceMove(get_turf(src))
if(injecting)
implant(src.occupant)
injecting = 0
@@ -107,11 +104,8 @@
if(src.occupant)
to_chat(usr, span_warning("\The [src] is already occupied!"))
return
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.stop_pulling()
M.loc = src
M.forceMove(src)
src.occupant = M
src.add_fingerprint(usr)
icon_state = "implantchair_on"
@@ -128,9 +128,6 @@
for(var/mob/M in src)
M.forceMove(loc)
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
/obj/structure/closet/proc/open()
if(opened)
@@ -201,9 +198,6 @@
continue
if(stored_units + added_units + M.mob_size > storage_capacity)
break
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.forceMove(src)
added_units += M.mob_size
return added_units
@@ -7,6 +7,7 @@
anchored = TRUE
health = 0 //destroying the statue kills the mob within
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
closet_appearance = null
var/intialTox = 0 //these are here to keep the mob from taking damage from things that logically wouldn't affect a rock
var/intialFire = 0 //it's a little sloppy I know but it was this or the GODMODE flag. Lesser of two evils.
var/intialBrute = 0
@@ -19,10 +20,7 @@
if(L.buckled)
L.buckled = 0
L.anchored = FALSE
if(L.client)
L.client.perspective = EYE_PERSPECTIVE
L.client.eye = src
L.loc = src
L.forceMove(src)
L.sdisabilities |= MUTE
health = L.health + 100 //stoning damaged mobs will result in easier to shatter statues
intialTox = L.getToxLoss()
@@ -61,15 +59,13 @@
/obj/structure/closet/statue/dump_contents()
for(var/obj/O in src)
O.loc = src.loc
O.forceMove(get_turf(src))
for(var/mob/living/M in src)
M.loc = src.loc
M.forceMove(loc) // Might be in a belly
M.sdisabilities &= ~MUTE
M.take_overall_damage((M.health - health - 100),0) //any new damage the statue incurred is transfered to the mob
if(M.client)
M.client.eye = M.client.mob
M.client.perspective = MOB_PERSPECTIVE
M.reset_perspective() // Fixes a blackscreen flicker
/obj/structure/closet/statue/open()
return
@@ -32,7 +32,7 @@
/obj/structure/toilet/attack_ai(mob/user as mob)
if(isrobot(user))
if(user.client && user.client.eye == user)
if(user.client && !user.is_remote_viewing())
return attack_hand(user)
else
return attack_hand(user)
-6
View File
@@ -24,9 +24,6 @@
playsound(src, 'sound/effects/clang.ogg', 25, 1, -1)
visible_message(span_warning("[M] [pick("tripped", "stumbled")] into \the [src]!"))
log_and_message_admins("stumbled into \the [src]", M)
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.apply_damage(5, BRUTE)
M.Weaken(2)
M.forceMove(src)
@@ -126,9 +123,6 @@
return ..()
playsound(src, 'sound/effects/clang.ogg', 25, 1, -1)
visible_message(span_warning("[M] [pick("tripped", "stumbled")] into \the [src]!"))
if(M.client)
M.client.perspective = EYE_PERSPECTIVE
M.client.eye = src
M.forceMove(src)
OCCUPANT = M
isopen = 0