From ce669c3924464e765f9a8d1ff6ddb8b6a7872abd Mon Sep 17 00:00:00 2001 From: Jacquerel Date: Sun, 23 Mar 2025 19:00:23 +0000 Subject: [PATCH] Makes your current position clearer while jaunting (#90173) ## About The Pull Request I was fucking around testing the Voidwalker earlier for a different issue and didn't like that I couldn't see myself while in space. This PR makes it so that Voidwalkers and also any variant of Ethereal Jaunt place an icon visible only to you at your current position (it's like your _soul_) so that you can see where you are going. Nobody else can see it. ![dreamseeker_qCXrCwHaUW](https://github.com/user-attachments/assets/3d6d1136-1658-4701-af78-057b2cfeb059) ![dreamseeker_hqH73zu66P](https://github.com/user-attachments/assets/4f620711-9a1a-4f8e-be3b-1c3367b9f9dc) There are almost certainly some other sources of being invisible which could use this so let me know if you are aware of one. Although if you do that I may need to make my code more generic. ## Why It's Good For The Game It's nice to be able to see where you are precisely rather than just it being the centre of the screen ## Changelog :cl: qol: It is now easier to see where you currently are while jaunting /:cl: --- code/datums/components/space_camo.dm | 48 ++++++++++++++++++- code/datums/components/space_dive.dm | 1 + code/game/objects/effects/phased_mob.dm | 31 +++++++++--- .../antagonists/heretic/magic/ash_jaunt.dm | 1 + .../antagonists/heretic/magic/space_crawl.dm | 6 +++ .../spells/spell_types/jaunt/bloodcrawl.dm | 6 +++ .../spell_types/jaunt/ethereal_jaunt.dm | 7 +++ .../spells/spell_types/jaunt/shadow_walk.dm | 1 + 8 files changed, 93 insertions(+), 8 deletions(-) diff --git a/code/datums/components/space_camo.dm b/code/datums/components/space_camo.dm index 08b6c106494..50ccab7b181 100644 --- a/code/datums/components/space_camo.dm +++ b/code/datums/components/space_camo.dm @@ -8,6 +8,12 @@ var/reveal_after_combat /// The world time after we can camo again VAR_PRIVATE/next_camo + /// Image we show to our jaunter so they can see where they are + var/image/position_indicator + /// Icon we draw our position indicator from + var/phased_mob_icon = 'icons/obj/weapons/guns/projectiles.dmi' + /// Icon state we use for our position indicator + var/phased_mob_icon_state = "solarflare" /datum/component/space_camo/Initialize(space_alpha, non_space_alpha, reveal_after_combat) if(!ismovable(parent)) @@ -17,10 +23,36 @@ src.non_space_alpha = non_space_alpha src.reveal_after_combat = reveal_after_combat +/datum/component/space_camo/RegisterWithParent() RegisterSignal(parent, COMSIG_ATOM_ENTERING, PROC_REF(on_atom_entering)) + if(!isliving(parent)) + return - if(isliving(parent)) - RegisterSignals(parent, list(COMSIG_ATOM_WAS_ATTACKED, COMSIG_MOB_ITEM_ATTACK, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_REVEAL), PROC_REF(force_exit_camo)) + var/mob/living/living_parent = parent + position_indicator = image(phased_mob_icon, living_parent, phased_mob_icon_state, ABOVE_LIGHTING_PLANE) + SET_PLANE_EXPLICIT(position_indicator, ABOVE_LIGHTING_PLANE, living_parent) + position_indicator.appearance_flags |= RESET_ALPHA + position_indicator.alpha = 0 + + RegisterSignals(parent, list(COMSIG_ATOM_WAS_ATTACKED, COMSIG_MOB_ITEM_ATTACK, COMSIG_LIVING_UNARMED_ATTACK, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_REVEAL), PROC_REF(force_exit_camo)) + RegisterSignal(parent, COMSIG_MOB_LOGIN, PROC_REF(show_client_image)) + show_client_image(parent) + +/datum/component/space_camo/UnregisterFromParent() + UnregisterSignal(parent, list( + COMSIG_ATOM_ENTERING, + COMSIG_ATOM_WAS_ATTACKED, + COMSIG_MOB_ITEM_ATTACK, + COMSIG_LIVING_UNARMED_ATTACK, + COMSIG_ATOM_BULLET_ACT, + COMSIG_ATOM_REVEAL, + COMSIG_MOB_LOGIN, + )) + remove_client_image(parent) + +/datum/component/space_camo/Destroy(force) + . = ..() + position_indicator = null /datum/component/space_camo/proc/on_atom_entering(atom/movable/entering, atom/entered) SIGNAL_HANDLER @@ -45,10 +77,22 @@ /datum/component/space_camo/proc/enter_camo(atom/movable/parent) if(parent.alpha != space_alpha) animate(parent, alpha = space_alpha, time = 0.5 SECONDS) + if (position_indicator) + animate(position_indicator, alpha = 255, time = 0.5 SECONDS) parent.remove_from_all_data_huds() parent.add_atom_colour(SSparallax.get_parallax_color(), TEMPORARY_COLOUR_PRIORITY) /datum/component/space_camo/proc/exit_camo(atom/movable/parent) animate(parent, alpha = non_space_alpha, time = 0.5 SECONDS) + if (position_indicator) + animate(position_indicator, alpha = 0, time = 0.5 SECONDS) parent.add_to_all_human_data_huds() parent.remove_atom_colour(TEMPORARY_COLOUR_PRIORITY) + +/datum/component/space_camo/proc/show_client_image(mob/show_to) + SIGNAL_HANDLER + show_to.client?.images |= position_indicator + +/datum/component/space_camo/proc/remove_client_image(mob/remove_from) + SIGNAL_HANDLER + remove_from.client?.images -= position_indicator diff --git a/code/datums/components/space_dive.dm b/code/datums/components/space_dive.dm index bbbeb0bb168..3a172307aab 100644 --- a/code/datums/components/space_dive.dm +++ b/code/datums/components/space_dive.dm @@ -82,3 +82,4 @@ /obj/effect/dummy/phased_mob/space_dive movespeed = 1 + phased_mob_icon_state = "solarflare" diff --git a/code/game/objects/effects/phased_mob.dm b/code/game/objects/effects/phased_mob.dm index 357e9683072..69fe4cb2250 100644 --- a/code/game/objects/effects/phased_mob.dm +++ b/code/game/objects/effects/phased_mob.dm @@ -1,16 +1,22 @@ /obj/effect/dummy/phased_mob - name = "water" + name = "ethereal form" anchored = TRUE flags_1 = PREVENT_CONTENTS_EXPLOSION_1 resistance_flags = LAVA_PROOF | FIRE_PROOF | UNACIDABLE | ACID_PROOF | SHUTTLE_CRUSH_PROOF invisibility = INVISIBILITY_OBSERVER movement_type = FLOATING - /// The movable which's jaunting in this dummy + /// The movable which is jaunting in this dummy var/atom/movable/jaunter /// The delay between moves while jaunted var/movedelay = 0 /// The speed of movement while jaunted var/movespeed = 0 + /// Image we show to our jaunter so they can see where they are + var/image/position_indicator + /// Icon we draw our position indicator from + var/phased_mob_icon = 'icons/obj/weapons/guns/projectiles.dmi' + /// Icon state we use for our position indicator + var/phased_mob_icon_state = "ice_1" /obj/effect/dummy/phased_mob/Initialize(mapload, atom/movable/jaunter) . = ..() @@ -21,13 +27,25 @@ /obj/effect/dummy/phased_mob/proc/set_jaunter(atom/movable/new_jaunter) jaunter = new_jaunter jaunter.forceMove(src) - if(ismob(jaunter)) - var/mob/mob_jaunter = jaunter - RegisterSignal(mob_jaunter, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change)) - mob_jaunter.reset_perspective(src) + if(!ismob(jaunter)) + return + var/mob/mob_jaunter = jaunter + position_indicator = image(phased_mob_icon, src, phased_mob_icon_state, ABOVE_LIGHTING_PLANE) + position_indicator.appearance_flags |= RESET_ALPHA + SET_PLANE_EXPLICIT(position_indicator, ABOVE_LIGHTING_PLANE, src) + RegisterSignal(mob_jaunter, COMSIG_MOB_LOGIN, PROC_REF(show_client_image)) + RegisterSignal(mob_jaunter, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change)) + mob_jaunter.reset_perspective(src) + show_client_image(mob_jaunter) + +/// Displays our position indicator to a client +/obj/effect/dummy/phased_mob/proc/show_client_image(mob/show_to) + SIGNAL_HANDLER + show_to.client?.images |= position_indicator /obj/effect/dummy/phased_mob/Destroy() jaunter = null // If a mob was left in the jaunter on qdel, they'll be dumped into nullspace + position_indicator = null return ..() /// Removes [jaunter] from our phased mob @@ -57,6 +75,7 @@ . = ..() if(gone == jaunter) UnregisterSignal(jaunter, COMSIG_MOB_STATCHANGE) + UnregisterSignal(jaunter, COMSIG_MOB_LOGIN) SEND_SIGNAL(src, COMSIG_MOB_EJECTED_FROM_JAUNT, jaunter) jaunter = null diff --git a/code/modules/antagonists/heretic/magic/ash_jaunt.dm b/code/modules/antagonists/heretic/magic/ash_jaunt.dm index 41242063a90..4db891a38c7 100644 --- a/code/modules/antagonists/heretic/magic/ash_jaunt.dm +++ b/code/modules/antagonists/heretic/magic/ash_jaunt.dm @@ -18,6 +18,7 @@ jaunt_duration = 1.1 SECONDS jaunt_in_time = 1.3 SECONDS jaunt_out_time = 0.6 SECONDS + jaunt_type = /obj/effect/dummy/phased_mob/spell_jaunt/red jaunt_in_type = /obj/effect/temp_visual/dir_setting/ash_shift jaunt_out_type = /obj/effect/temp_visual/dir_setting/ash_shift/out diff --git a/code/modules/antagonists/heretic/magic/space_crawl.dm b/code/modules/antagonists/heretic/magic/space_crawl.dm index 74b02c59c10..6a170247937 100644 --- a/code/modules/antagonists/heretic/magic/space_crawl.dm +++ b/code/modules/antagonists/heretic/magic/space_crawl.dm @@ -18,6 +18,8 @@ invocation_type = INVOCATION_NONE spell_requirements = NONE + + jaunt_type = /obj/effect/dummy/phased_mob/spell_jaunt/space ///List of traits that are added to the heretic while in space phase jaunt var/static/list/jaunting_traits = list(TRAIT_RESISTLOWPRESSURE, TRAIT_RESISTCOLD, TRAIT_NOBREATH) @@ -138,4 +140,8 @@ . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) +/// Different graphic for position indicator +/obj/effect/dummy/phased_mob/spell_jaunt/space + phased_mob_icon_state = "solarflare" + #undef SPACE_PHASING diff --git a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm index ea9cdc27a44..56fcc898767 100644 --- a/code/modules/spells/spell_types/jaunt/bloodcrawl.dm +++ b/code/modules/spells/spell_types/jaunt/bloodcrawl.dm @@ -14,6 +14,8 @@ spell_requirements = NONE + jaunt_type = /obj/effect/dummy/phased_mob/blood + /// The time it takes to enter blood var/enter_blood_time = 0 SECONDS /// The time it takes to exit blood @@ -375,3 +377,7 @@ /obj/item/bloodcrawl/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) + +/// Different graphic for the position indicator +/obj/effect/dummy/phased_mob/blood + phased_mob_icon_state = "mini_leaper" diff --git a/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm b/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm index e020ec1d5b1..6592660474e 100644 --- a/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm +++ b/code/modules/spells/spell_types/jaunt/ethereal_jaunt.dm @@ -153,6 +153,7 @@ cast_on.setDir(holder.dir) if(jaunt_in_time > 0) + cast_on.Immobilize(jaunt_in_time, ignore_canstun = TRUE) addtimer(CALLBACK(src, PROC_REF(end_jaunt), cast_on, holder, final_point), jaunt_in_time) else end_jaunt(cast_on, holder, final_point) @@ -219,6 +220,7 @@ jaunt_duration = 5 SECONDS jaunt_in_time = 0.6 SECONDS jaunt_out_time = 0.6 SECONDS + jaunt_type = /obj/effect/dummy/phased_mob/spell_jaunt/red jaunt_in_type = /obj/effect/temp_visual/dir_setting/wraith jaunt_out_type = /obj/effect/temp_visual/dir_setting/wraith/out @@ -238,6 +240,7 @@ /datum/action/cooldown/spell/jaunt/ethereal_jaunt/shift/golem name = "Runic Phase Shift" cooldown_time = 80 SECONDS + jaunt_type = /obj/effect/dummy/phased_mob/spell_jaunt/red jaunt_in_type = /obj/effect/temp_visual/dir_setting/cult/phase jaunt_out_type = /obj/effect/temp_visual/dir_setting/cult/phase/out @@ -257,3 +260,7 @@ if (locate(/obj/effect/blessing) in .) to_chat(user, span_warning("Holy energies block your path!")) return null + +/// Red coloured variant +/obj/effect/dummy/phased_mob/spell_jaunt/red + phased_mob_icon_state = "red_1" diff --git a/code/modules/spells/spell_types/jaunt/shadow_walk.dm b/code/modules/spells/spell_types/jaunt/shadow_walk.dm index c869fb19913..33215acb1e9 100644 --- a/code/modules/spells/spell_types/jaunt/shadow_walk.dm +++ b/code/modules/spells/spell_types/jaunt/shadow_walk.dm @@ -53,6 +53,7 @@ /obj/effect/dummy/phased_mob/shadow name = "shadows" + phased_mob_icon_state = "purple_laser" /// Max amount of light permitted before being kicked out var/light_max = SHADOW_SPECIES_LIGHT_THRESHOLD /// The amount that shadow heals us per SSobj tick (times seconds_per_tick)