From 11382bea91901437f47d0651a3b317944696821b Mon Sep 17 00:00:00 2001 From: MrMelbert <51863163+MrMelbert@users.noreply.github.com> Date: Thu, 2 Nov 2023 14:31:25 -0500 Subject: [PATCH] Minor Illusion Major Buff (#365) --- .../modules/magic/story_spells/illusion.dm | 102 +++++++++++++++++- .../icons/hud/screen_alert.dmi | Bin 0 -> 731 bytes 2 files changed, 98 insertions(+), 4 deletions(-) create mode 100644 maplestation_modules/icons/hud/screen_alert.dmi diff --git a/maplestation_modules/code/modules/magic/story_spells/illusion.dm b/maplestation_modules/code/modules/magic/story_spells/illusion.dm index e269cde1cba8..a5b3de4c6e6f 100644 --- a/maplestation_modules/code/modules/magic/story_spells/illusion.dm +++ b/maplestation_modules/code/modules/magic/story_spells/illusion.dm @@ -27,7 +27,7 @@ cast_range = 20 // For camera memes /// Duration of the illusionary mob - var/conjured_duration = 8 SECONDS + var/conjured_duration = 8 MINUTES /// HP of the illusionary mob var/conjured_hp = 10 @@ -35,18 +35,25 @@ . = ..() AddComponent(/datum/component/uses_mana/story_spell/pointed/illusion) +/datum/action/cooldown/spell/pointed/illusion/Remove(mob/living/remove_from) + . = ..() + remove_from.remove_status_effect(/datum/status_effect/maintaining_illusion) + /datum/action/cooldown/spell/pointed/illusion/is_valid_target(atom/cast_on) var/turf/castturf = get_turf(cast_on) return isopenturf(castturf) && !isgroundlessturf(castturf) /datum/action/cooldown/spell/pointed/illusion/cast(atom/cast_on) . = ..() + var/mob/living/caster = usr || owner + caster.remove_status_effect(/datum/status_effect/maintaining_illusion) // One at a time + var/turf/castturf = get_turf(cast_on) var/mob/copy_target = select_copy_target() var/mob/living/simple_animal/hostile/illusion/conjured/decoy = new(castturf) if(!isnull(copy_target)) decoy.Copy_Parent(copy_target, conjured_duration, conjured_hp) - decoy.face_atom(usr || owner || copy_target) + decoy.face_atom(caster || copy_target) decoy.spin(0.4 SECONDS, 0.1 SECONDS) // alpha is based on how bright the turf is. Darker = weaker illusion @@ -54,14 +61,101 @@ animate(decoy, alpha = clamp(255 * castturf.get_lumcount(), 75, 225), time = 0.2 SECONDS) // with a snap of course - owner?.emote("snap") - owner?.face_atom(castturf) + caster.emote("snap") + caster.face_atom(castturf) + caster.apply_status_effect(/datum/status_effect/maintaining_illusion, decoy) /// Determines what mob to copy for the illusion /datum/action/cooldown/spell/pointed/illusion/proc/select_copy_target() RETURN_TYPE(/mob) return owner +/// Status effect that tracks the current illusion being maintained +/datum/status_effect/maintaining_illusion + id = "maintaining_illusion" + tick_interval = -1 // Or maybe we tick and give it a mana cost, to sustain it? + alert_type = /atom/movable/screen/alert/status_effect/maintaining_illusion + + /// Whether we've initiated fade out and thus are about to stop maintaining shortly + VAR_FINAL/fading = FALSE + /// Reference to the illusion being maintained + VAR_FINAL/mob/living/simple_animal/hostile/illusion/conjured/copy + /// List of generic signals that, when caught, will break the illusion + var/static/list/generic_break_signals = list( + COMSIG_LIVING_DEATH, + SIGNAL_ADDTRAIT(TRAIT_INCAPACITATED), + ) + +/datum/status_effect/maintaining_illusion/on_creation(mob/living/new_owner, mob/living/simple_animal/hostile/illusion/conjured/copy) + . = ..() + if(!.) + return + + ASSERT(istype(copy)) + src.copy = copy + RegisterSignal(copy, COMSIG_PARENT_QDELETING, PROC_REF(copy_gone)) + +/datum/status_effect/maintaining_illusion/on_apply() + RegisterSignal(owner, COMSIG_MOVABLE_MOVED, PROC_REF(check_distance)) + RegisterSignals(owner, generic_break_signals, PROC_REF(break_illusion)) + return TRUE + +/datum/status_effect/maintaining_illusion/on_remove() + UnregisterSignal(owner, COMSIG_MOVABLE_MOVED) + UnregisterSignal(owner, generic_break_signals) + fade_out_copy() + +/datum/status_effect/maintaining_illusion/Destroy() + . = ..() + copy = null // Has to come after parent call, because on_remove is called in parent + +/datum/status_effect/maintaining_illusion/proc/fade_out_copy() + if(fading || QDELETED(copy)) + return + + fading = TRUE + animate(copy, time = 0.5 SECONDS, alpha = 0, easing = CUBIC_EASING) + addtimer(CALLBACK(copy, TYPE_PROC_REF(/mob/living, death), 0.5 SECONDS)) + UnregisterSignal(copy, COMSIG_PARENT_QDELETING) + + if(!QDELING(src)) + qdel(src) + +/datum/status_effect/maintaining_illusion/proc/break_illusion(mob/living/source, ...) + SIGNAL_HANDLER + + if(source.stat <= SOFT_CRIT) + source.balloon_alert(source, "the illusion breaks!") + fade_out_copy() + +/datum/status_effect/maintaining_illusion/proc/check_distance(mob/living/source, ...) + SIGNAL_HANDLER + + // The metric behind this number: Is there enough distance such that, + // on Metastation, you can put an illusion in Medbay Lobby and go to the bar. + if(get_dist(source, copy) <= 32) + return + + break_illusion(source) + +/datum/status_effect/maintaining_illusion/proc/copy_gone(datum/source) + SIGNAL_HANDLER + qdel(src) + +/atom/movable/screen/alert/status_effect/maintaining_illusion + name = "Maintaining Illusion" + desc = "You're maintaining an illusion. Moving too far away or a lapse in concentration will break it. \ + Or you can click this to cancel it." + icon = 'maplestation_modules/icons/hud/screen_alert.dmi' + icon_state = "illusion" + +/atom/movable/screen/alert/status_effect/maintaining_illusion/Click(location, control, params) + . = ..() + if(!.) + return + var/datum/status_effect/maintaining_illusion/effect = attached_effect + effect.fade_out_copy() + // Illusion subtype for summon illusion /mob/living/simple_animal/hostile/illusion/conjured desc = "An illusion! What are you hiding..?" diff --git a/maplestation_modules/icons/hud/screen_alert.dmi b/maplestation_modules/icons/hud/screen_alert.dmi new file mode 100644 index 0000000000000000000000000000000000000000..8b3b3a641dd77e29621eb3ec849b09ee4865d4c0 GIT binary patch literal 731 zcmV<10wn#3P)V=-0C=1w$Gr-GAQT4B+4~e9xkrDiOBmr$?+|2p!4%Z$^&8sGkr=1htk8?0 z$EM6NKw+pG5-;z?L80$RILoIie{$K1g+j&N-*1dM@r!b3(MZSnYXjE?2I=U z46wWV_6{q+@$sjpUaR%&E{fW#@DC|dJh2vnWjKza_LSyYfRt&_Y&NmJ-kRD!e0}jg zr1`5K@3K743*UX;*YnfU&zifn^(M1zjYhYDlxaXB^btsz25W246aY*IS35_cZKQM3 zFBt}a%gdi7ZX9DCB@r zO7Gs~oN%^r7*Zr$&Iw5}3@H-kag_uJAz+{HEZDoL!}Wb1382h6c~e!v>uJU_^6Zm+k^a(lh)64%5+IdHad7y|dVVO9<#$uI=& zZ-bo!Yy_$jkZ`qg6jmi5!MqJl0ZJ*oySni9zt!d@$uOLm1HWE>oXhzlA}%hz7kv0G z;2|7niFKT()aRfZMGr0<*Yw1f2B%w}U!sRou#&5CALUAtGRu z<-CBKo9lpUOn~_!Fqur8YopO^;CY^2FZ71XZp}))q1m%73*M^R^FR25E6)keJ81v_ N002ovPDHLkV1i18Qi}ip literal 0 HcmV?d00001