From 8535bb846120a6b1bb0a7cbffe624019c9df5d31 Mon Sep 17 00:00:00 2001 From: HMBGERDO <61080616+HMBGERDO@users.noreply.github.com> Date: Tue, 18 Feb 2025 13:50:39 +0100 Subject: [PATCH] [s] Shadow demon Shadow Crawl abuse fix (#28439) * shadow demon shadow crawl fix * var --- code/__DEFINES/is_helpers.dm | 2 + code/datums/spells/bloodcrawl.dm | 11 ++++++ .../demons/shadow_demon/shadow_demon.dm | 39 ++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm index 2e889278c1e..5f49361842e 100644 --- a/code/__DEFINES/is_helpers.dm +++ b/code/__DEFINES/is_helpers.dm @@ -45,6 +45,8 @@ #define ispulsedemon(A) (istype(A, /mob/living/simple_animal/demon/pulse_demon)) +#define isshadowdemon(A) (istype(A, /mob/living/simple_animal/demon/shadow)) + // Objects #define isobj(A) istype(A, /obj) //override the byond proc because it returns true on children of /atom/movable that aren't objs diff --git a/code/datums/spells/bloodcrawl.dm b/code/datums/spells/bloodcrawl.dm index 9bc2864a656..fec91009b90 100644 --- a/code/datums/spells/bloodcrawl.dm +++ b/code/datums/spells/bloodcrawl.dm @@ -273,6 +273,17 @@ action_background_icon_state = "shadow_demon_bg" action_icon_state = "shadow_crawl" +/datum/spell/bloodcrawl/shadow_crawl/can_cast(mob/user, charge_check, show_message) + var/mob/living/simple_animal/demon/shadow/current_demon = user + if(!istype(current_demon)) + return ..() + + if(current_demon.block_shadow_crawl) + to_chat(user, "You are too concentrated to activate [name].") + return FALSE + + return ..() + /datum/spell/bloodcrawl/shadow_crawl/valid_target(turf/target, user) return target.get_lumcount() < 0.2 diff --git a/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm b/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm index 25ce0ee4d66..ddc98d0d7b6 100644 --- a/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm +++ b/code/game/gamemodes/miniantags/demons/shadow_demon/shadow_demon.dm @@ -11,6 +11,10 @@ death_sound = 'sound/shadowdemon/shadowdeath.ogg' var/thrown_alert = FALSE var/wrapping = FALSE + /// Should only be TRUE if we're shooting the Shadow Grapple right now. If its TRUE, the demon wont be able to shadow crawl. + var/block_shadow_crawl = FALSE + /// Used for fault tolerance. If you set it manually, it may fuck up shooting_grapple var. + var/last_block_shadow_crawl = 0 /mob/living/simple_animal/demon/shadow/Login() ..() @@ -66,6 +70,21 @@ target.forceMove(C) wrapping = FALSE +/mob/living/simple_animal/demon/shadow/proc/block_shadow_crawl() + last_block_shadow_crawl = world.time + block_shadow_crawl = TRUE + addtimer(CALLBACK(src, PROC_REF(check_block_shadow_crawl), last_block_shadow_crawl), 10 SECONDS) + +/mob/living/simple_animal/demon/shadow/proc/unblock_shadow_crawl() + last_block_shadow_crawl = 0 + block_shadow_crawl = FALSE + +/mob/living/simple_animal/demon/shadow/proc/check_block_shadow_crawl(block_time) + if(block_time == last_block_shadow_crawl) + /// it means 10 seconds passed from last shadow grapple shot and it didnt unset block_shadow_crawl + to_chat(src, "You feel good enough to use Shadow Crawl again.") + unblock_shadow_crawl() + /obj/structure/shadowcocoon name = "shadowy cocoon" desc = "Something wrapped in what seems to be manifested darkness. Its surface distorts unnaturally, and it emanates deep shadows." @@ -204,6 +223,9 @@ /obj/item/projectile/magic/shadow_hand/fire(setAngle) if(firer) + var/mob/living/simple_animal/demon/shadow/current_demon = firer + if(istype(current_demon)) + current_demon.block_shadow_crawl() firer.Beam(src, icon_state = "grabber_beam", time = INFINITY, maxdistance = INFINITY, beam_sleep_time = 1, beam_type = /obj/effect/ebeam/floor) return ..() @@ -215,7 +237,12 @@ for(var/atom/extinguish_target in range(2, src)) extinguish_target.extinguish_light(TRUE) if(!isliving(target)) - firer.throw_at(get_step(target, get_dir(target, firer)), 50, 10) + if(isshadowdemon(firer)) + firer.throw_at(get_step(target, get_dir(target, firer)), 50, 10, callback = CALLBACK(firer, TYPE_PROC_REF(/mob/living/simple_animal/demon/shadow, unblock_shadow_crawl))) + else + firer.throw_at(get_step(target, get_dir(target, firer)), 50, 10) + else + unblock_shadowdemon_crawl() if(!.) return else @@ -224,6 +251,16 @@ L.apply_damage(40, BRUTE, BODY_ZONE_CHEST) L.throw_at(get_step(firer, get_dir(firer, target)), 50, 10) +/obj/item/projectile/magic/shadow_hand/Destroy() + if(!hit) + unblock_shadowdemon_crawl() + return ..() + +/obj/item/projectile/magic/shadow_hand/proc/unblock_shadowdemon_crawl() + var/mob/living/simple_animal/demon/shadow/current_demon = firer + if(istype(current_demon)) + current_demon.unblock_shadow_crawl() + /obj/effect/ebeam/floor plane = FLOOR_PLANE