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
+1 -1
View File
@@ -86,7 +86,7 @@
if(!src.eyeobj)
return
if(client.eye)
if(client && client.eye)
reset_perspective(src)
for(var/datum/chunk/c in eyeobj.visibleChunks)
+25 -20
View File
@@ -111,26 +111,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)
@@ -142,6 +122,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)
+25 -20
View File
@@ -174,26 +174,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)
@@ -204,3 +184,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"
@@ -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
+53 -48
View File
@@ -1444,7 +1444,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
@@ -1522,48 +1521,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
@@ -1647,10 +1604,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)
@@ -1728,7 +1733,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
+6 -6
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
+1
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 .
+10 -12
View File
@@ -443,10 +443,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
@@ -515,21 +511,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)
+6 -12
View File
@@ -130,11 +130,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
@@ -176,16 +171,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()
@@ -204,9 +196,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
+26 -21
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
+46 -39
View File
@@ -220,42 +220,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)
@@ -286,9 +250,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)
@@ -304,6 +268,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
@@ -707,7 +707,7 @@
I.brute = C.brute_damage
I.burn = C.electronics_damage
I.loc = src.loc
I.forceMove(loc)
if(C.installed == 1)
C.uninstall()
+1 -2
View File
@@ -397,8 +397,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)
+3 -4
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)
+3 -3
View File
@@ -557,7 +557,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)
@@ -712,12 +711,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.
+2 -5
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))