From c50ff7ce9ceaed383e7bc1b60fca831c3f880718 Mon Sep 17 00:00:00 2001 From: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> Date: Sat, 23 Nov 2024 08:50:39 -0500 Subject: [PATCH] Adds a new spellblade enchantment: Temporal. Also adds lightning knockdown back. (#27314) * cutting edge * remove the message admins lmao * eh name should just be temporal * undef * Apply suggestions from code review Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> * updates description, removes shock change as it happens on live now I guess --------- Signed-off-by: Qwertytoforty <52090703+Qwertytoforty@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> --- code/__DEFINES/status_effects.dm | 4 + code/datums/status_effects/debuffs.dm | 61 +++++++++++++++ code/game/gamemodes/wizard/spellbook.dm | 2 +- .../objects/items/weapons/melee/melee_misc.dm | 71 ++++++++++++++++-- icons/effects/spellblade.dmi | Bin 988 -> 1351 bytes 5 files changed, 131 insertions(+), 7 deletions(-) diff --git a/code/__DEFINES/status_effects.dm b/code/__DEFINES/status_effects.dm index c3f268824df..8bac4307c41 100644 --- a/code/__DEFINES/status_effects.dm +++ b/code/__DEFINES/status_effects.dm @@ -138,6 +138,10 @@ #define STATUS_EFFECT_C_FOAMED /datum/status_effect/c_foamed +#define STATUS_EFFECT_TEMPORAL_SLASH /datum/status_effect/temporal_slash + +#define STATUS_EFFECT_TEMPORAL_SLASH_FINISHER /datum/status_effect/temporal_slash_finisher + //#define STATUS_EFFECT_NECROPOLIS_CURSE /datum/status_effect/necropolis_curse //#define CURSE_BLINDING 1 //makes the edges of the target's screen obscured //#define CURSE_SPAWNING 2 //spawns creatures that attack the target only diff --git a/code/datums/status_effects/debuffs.dm b/code/datums/status_effects/debuffs.dm index 99e5dfbcb6a..858f9076582 100644 --- a/code/datums/status_effects/debuffs.dm +++ b/code/datums/status_effects/debuffs.dm @@ -1406,3 +1406,64 @@ duration = 5 SECONDS alert_type = null status_type = STATUS_EFFECT_REPLACE + +/// This is the threshold where the attack will stun on the last hit. Why? Because it is cool, that's why. +#define FINISHER_THRESHOLD 7 + +/datum/status_effect/temporal_slash + id = "temporal_slash" + duration = 3 SECONDS + status_type = STATUS_EFFECT_REFRESH + alert_type = null + /// How many times the user has been cut. Each cut adds a damage value below + var/cuts = 1 + /// How much damage the blade will do each slice + var/damage_per_cut = 20 + +/datum/status_effect/temporal_slash/on_creation(mob/living/new_owner, cut_damage = 20) + . = ..() + damage_per_cut = cut_damage + +/datum/status_effect/temporal_slash/refresh() + cuts++ + return ..() + +/datum/status_effect/temporal_slash/on_remove() + owner.apply_status_effect(STATUS_EFFECT_TEMPORAL_SLASH_FINISHER, cuts, damage_per_cut) //We apply this to a new status effect, to avoid refreshing while on_remove happens. + +/datum/status_effect/temporal_slash_finisher + id = "temporal_slash_finisher" + status_type = STATUS_EFFECT_UNIQUE + alert_type = null + tick_interval = 0.25 SECONDS + /// How many times the user has been cut. Each cut adds a damage value below + var/cuts = 1 + /// How much damage the blade will do each slice + var/damage_per_cut = 20 + /// Have we done enough damage to trigger the finisher? + var/finishing_cuts = FALSE + +/datum/status_effect/temporal_slash_finisher/on_creation(mob/living/new_owner, final_cuts = 1, cut_damage = 20) + . = ..() + cuts = final_cuts + damage_per_cut = cut_damage + if(ismegafauna(owner)) + damage_per_cut *= 4 //This will deal 40 damage bonus per cut on megafauna as a miner, and 80 as a wizard. To kill a megafauna, you need to hit it 48 times. You don't get the buffs of a crusher though. Also you already killed bubblegum, so, you know. + if(cuts >= FINISHER_THRESHOLD) + finishing_cuts = TRUE + new /obj/effect/temp_visual/temporal_slash(get_turf(owner), owner) + +/datum/status_effect/temporal_slash_finisher/tick() + . = ..() + owner.visible_message("[owner] gets slashed by a cut through spacetime!", "You get slashed by a cut through spacetime!") + playsound(owner, 'sound/weapons/rapierhit.ogg', 50, TRUE) + owner.apply_damage(damage_per_cut, BRUTE, pick(BODY_ZONE_CHEST, BODY_ZONE_HEAD, BODY_ZONE_L_ARM, BODY_ZONE_L_LEG, BODY_ZONE_R_ARM, BODY_ZONE_R_LEG), 0, TRUE, null, FALSE) + cuts-- + if(cuts <= 0) + if(finishing_cuts) + owner.Weaken(7 SECONDS) + qdel(src) + else + new /obj/effect/temp_visual/temporal_slash(get_turf(owner), owner) + +#undef FINISHER_THRESHOLD diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index 671a32e3b46..4df54ff12ee 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -520,7 +520,7 @@ /datum/spellbook_entry/item/spell_blade name = "Spellblade" - desc = "A magical sword that can be enchanted by using it in hand to have a unique on-hit effect. Lighting: arcs electricity between nearby targets, stunning and damaging them. Fire: creates a massive ball of fire on hit, and makes the wielder immune to fire. Bluespace: allows you to strike people from a range, teleporting you to them. Forceshield: on hit, makes you stun immune for 3 seconds and reduces damage by half." + desc = "A magical sword that can be enchanted by using it in hand to have a unique on-hit effect. Lighting: arcs electricity between nearby targets, stunning and damaging them. Fire: creates a massive ball of fire on hit, and makes the wielder immune to fire. Bluespace: allows you to strike people from a range, teleporting you to them. Forceshield: on hit, makes you stun immune for 3 seconds and reduces damage by half. Spacetime: will slice faster but weaker and will curse the target, slashing them a few seconds after they have not been swinged at for each hit" item_path = /obj/item/melee/spellblade category = "Weapons and Armors" diff --git a/code/game/objects/items/weapons/melee/melee_misc.dm b/code/game/objects/items/weapons/melee/melee_misc.dm index c3296817ff9..c051715815d 100644 --- a/code/game/objects/items/weapons/melee/melee_misc.dm +++ b/code/game/objects/items/weapons/melee/melee_misc.dm @@ -335,11 +335,13 @@ var/static/list/options = list("Lightning" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "chain_lightning"),/// todo add icons for these "Fire" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "fire"), "Bluespace" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "blink"), - "Forcewall" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "shield"),) + "Forcewall" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "shield"), + "Temporal Slash" = image(icon = 'icons/effects/spellblade.dmi', icon_state = "spacetime"),) var/static/list/options_to_type = list("Lightning" = /datum/enchantment/lightning, "Fire" = /datum/enchantment/fire, "Bluespace" = /datum/enchantment/bluespace, - "Forcewall" = /datum/enchantment/forcewall,) + "Forcewall" = /datum/enchantment/forcewall, + "Temporal Slash" = /datum/enchantment/time_slash,) var/choice = show_radial_menu(user, src, options) if(!choice) @@ -349,6 +351,7 @@ /obj/item/melee/spellblade/proc/add_enchantment(new_enchant, mob/living/user, intentional = TRUE) var/datum/enchantment/E = new new_enchant enchant = E + E.on_apply_to_blade(src) E.on_gain(src, user) E.power *= power if(intentional) @@ -378,6 +381,8 @@ var/cooldown = -1 /// If the spellblade has traits, has it applied them? var/applied_traits = FALSE + /// A modifier that can be appled to the cooldown after the enchantment has been initialized. Used by the forcewall spellblade + var/cooldown_multiplier = 1 /datum/enchantment/proc/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S) if(world.time < cooldown) @@ -388,7 +393,7 @@ return FALSE if(!ranged && !proximity) return FALSE - cooldown = world.time + initial(cooldown) + cooldown = world.time + (initial(cooldown) * cooldown_multiplier) return TRUE /datum/enchantment/proc/on_gain(obj/item/melee/spellblade, mob/living/user) @@ -397,9 +402,12 @@ /datum/enchantment/proc/toggle_traits(obj/item/I, mob/living/user) return +/datum/enchantment/proc/on_apply_to_blade(obj/item/melee/spellblade) + return + /datum/enchantment/lightning name = "lightning" - desc = "this blade conducts arcane energy to arc between its victims. It also makes the user immune to shocks." + desc = "this blade conducts arcane energy to arc between its victims. It also makes the user immune to shocks" // the damage of the first lighting arc. power = 20 cooldown = 3 SECONDS @@ -473,6 +481,11 @@ name = "forcewall" desc = "this blade will partially shield you against attacks and stuns for a short duration after striking a foe" cooldown = 4 SECONDS + // multiplier for how much the cooldown is reduced by. A miner spellblade can only buff every 4 seconds, making it more vunerable, the wizard one is much more consistant. + power = 2 + +/datum/enchantment/forcewall/on_apply_to_blade(obj/item/melee/spellblade) + cooldown_multiplier /= power /datum/enchantment/forcewall/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S) . = ..() @@ -482,7 +495,7 @@ /datum/enchantment/bluespace name = "bluespace" - desc = "this the fabric of space, transporting its wielder over medium distances to strike foes" + desc = "this blade will cut through the fabric of space, transporting its wielder over medium distances to strike foes" cooldown = 2.5 SECONDS ranged = TRUE // the number of deciseconds of stun applied by the teleport strike @@ -511,6 +524,51 @@ S.melee_attack_chain(user, target) target.Weaken(power) +/datum/enchantment/time_slash + name = "temporal" + desc = "this blade will slice faster but weaker, and will curse the target, slashing them a few seconds after they have not been swinged at for each hit" + power = 15 // This should come out to 40 damage per hit. However, delayed. + +/datum/enchantment/time_slash/on_apply_to_blade(obj/item/melee/spellblade) + spellblade.force /= 2 + +/datum/enchantment/time_slash/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S) + user.changeNext_move(CLICK_CD_MELEE * 0.5) + . = ..() + if(!.) + return + target.apply_status_effect(STATUS_EFFECT_TEMPORAL_SLASH, power) + +/obj/effect/temp_visual/temporal_slash + name = "temporal slash" + desc = "A cut through spacetime" + icon = 'icons/obj/projectiles.dmi' + icon_state = "arcane_barrage" + layer = FLY_LAYER + plane = GRAVITY_PULSE_PLANE + appearance_flags = PIXEL_SCALE|LONG_GLIDE + duration = 0.5 SECONDS + mouse_opacity = MOUSE_OPACITY_TRANSPARENT // Let us not have this visual block clicks + /// Who we are orbiting + var/target + /// A funky color matrix to recolor the slash to + var/list/funky_color_matrix = list(0.4,0,0,0, 0,1.1,0,0, 0,0,1.65,0, -0.3,0.15,0,1, 0,0,0,0) + +/obj/effect/temp_visual/temporal_slash/Initialize(mapload, new_target) + . = ..() + target = new_target + INVOKE_ASYNC(src, TYPE_PROC_REF(/atom/movable, orbit), target, 0, FALSE, 0, 0, FALSE, TRUE) + var/matrix/M = matrix() + M.Scale(1, 2) + M.Turn(rand(0, 360)) + transform = M + addtimer(CALLBACK(src, PROC_REF(animate_slash)), 0.25 SECONDS) + +/obj/effect/temp_visual/temporal_slash/proc/animate_slash() + plane = -1 + color = funky_color_matrix + animate(src, alpha = 0, time = duration, easing = EASE_OUT) + /obj/item/melee/spellblade/random power = 0.5 @@ -519,6 +577,7 @@ var/list/options = list(/datum/enchantment/lightning, /datum/enchantment/fire, /datum/enchantment/forcewall, - /datum/enchantment/bluespace,) + /datum/enchantment/bluespace, + /datum/enchantment/time_slash,) var/datum/enchantment/E = pick(options) add_enchantment(E, intentional = FALSE) diff --git a/icons/effects/spellblade.dmi b/icons/effects/spellblade.dmi index 63dd6d6c33327477d8e5055ea2d300c74e2b19b9..7e1e860e3e27df0c222222c6fd8f2bdd49db30e4 100644 GIT binary patch delta 1244 zcmV<21S9+02geG3iBL{Q4GJ0x0000DNk~Le0001B0000$2m=5B0MhD$JOBUyZ%|BB zMZmzo-)T$y(tnU00K~-n|NsAmsP(%p5Fa^l%UU9{v;XMm_~?L3|Hy;?@x@*n3doB} z86#^eO_WYAS1KhcMvbn(z`(iT|5F54kPUJ3HI)C1u26U`domw8{Jh6?P$`IDE1`x( zS1c5|qhl8nCLNNg*8l(j0d!JMQvg8b*k%9#0Fsd8EiwcVX1%H@RPy?fr&ska;Af%wM9v}XV;D-f{Kks?k2a6esmBmnSa#SVhh1QbV`^xf19 z*a*CQjqm`7!dUafLV2yv1y=rOo33C_`G0l}IWp!6C9l_CC9FRg1i}|6L0P?@1TnD2 zpbbW$x|T1?s;a=DBq>Wh1EUL0m+$6)2!wDHv%1nROQ>?G<*JgykDwq6aZ;;DhZR?V z>V216nh~)ZhCavg?~W$ zH~QU$Ft1-Y2zAqTwWw8yrt2E`@B^sNd%w74dC;#>zoDRE>q+=f=8*o)PNAWNH;uZZ zTOe#m;NJIEMw~$nnjqh{T{jE_#1J^yLl-^gWwo z0+jwdfdoH`rV>*urXXy6P4G%!6@NwwP1lH4{1cyF6rV6`f$9ga5DSl*8UZ5^z9B$= z+yLOXPenEXq)&ja?{7?CWP%?6m8r;g?gkq$GC}EY03e~~UBunC06>Yy5eck6VwtS*$OQ1S=zq2Z*sY8N zbDLrU8@8$5MRo=P0gFZ(sQWw!v%V%QkJCmh93MQ73guC+V&zb65jGrla|v`23_#1L z|DdYcDt(^}lpzlaV}b)uQ#?@NiO{ues~$LB7EO;#3j2{+E5dIcnd0N8+q&t1(00Z{ z-}|-V)oV+K>hM4Ymq5SseI=<7`@eYY|LVB^%dgnw_5DApcx3Yd&RQ=30000;M1&h>@** ze+8E^Wd&D17qFKAb7?+0yD{q70000^P)t-sz`(%&|NsB-#pvkxx#9o((trQRgT%!A zv$Ow&sP*W8OUR2#-)T!mjjqdDB2ajHyDktbO_WYASCAb5A31Se8wwdCYcd}@DkUlx z6DD%dQ7!-g00DGTPE!Ct=GbNc00O82!zAe+eps8-DM# z)@&0^UIfA#63o!VijEzCrLN=wm=-7i{t^)WZyRjc^5+25fKW(Gr1JDbq@Y}TB?2PT zU#Xz#8^Qy(m7lKaTSCz))fT(>899)77zh#-9o>jOFEkXzut}hb{)$t`1;qGc+{h^b z9T>;4Ll-idNB}}~-N<75e<`3PVT{`rim;Wo55v%=&Jcte5CacG@kjvHh+PejRst`e z;*kO@Q|Oiq(C${2V26JTV5c-u?f_t5(XJHy00?0eu|EP(HM_+Q?Ev%GiJxxs9`N{c z=8|^wV4g?OO#Y)1P5^=s|4|dq0Tlp8W4z1&Q%E1AQ$p~I4v+F>Kn-IMD#!qY7N7|k z03;2dJZy2F5Qvix=@c;k-07*qoM6N<$ Eg4FSa>;M1&