mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-07-19 02:54:41 +01:00
Spellblade rework (#17693)
* fire lighting and shielding * blink + lavaland loot * file move and projectile removal * get out of MY WALLS * review * sprites * forgot this * sprite update * Apply suggestions from code review Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com> * some TM changes Co-authored-by: S34N <12197162+S34NW@users.noreply.github.com>
This commit is contained in:
@@ -32,6 +32,8 @@
|
||||
|
||||
//#define STATUS_EFFECT_WISH_GRANTERS_GIFT /datum/status_effect/wish_granters_gift //If you're currently resurrecting with the Wish Granter
|
||||
|
||||
#define STATUS_EFFECT_FORCESHIELD /datum/status_effect/force_shield
|
||||
|
||||
#define STATUS_EFFECT_BLOODDRUNK /datum/status_effect/blooddrunk //Stun immunity and greatly reduced damage taken
|
||||
|
||||
|
||||
|
||||
@@ -188,6 +188,36 @@
|
||||
/datum/status_effect/blood_rush/on_remove()
|
||||
REMOVE_TRAIT(owner, TRAIT_GOTTAGOFAST, VAMPIRE_TRAIT)
|
||||
|
||||
/datum/status_effect/force_shield
|
||||
id = "forceshield"
|
||||
duration = 4 SECONDS
|
||||
tick_interval = 0
|
||||
var/mutable_appearance/shield
|
||||
|
||||
/datum/status_effect/force_shield/on_apply()
|
||||
. = ..()
|
||||
if(!. || !ishuman(owner))
|
||||
return
|
||||
var/mutable_appearance/MA = mutable_appearance('icons/effects/effects.dmi', "shield-old", ABOVE_MOB_LAYER)
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.add_overlay(MA)
|
||||
shield = MA
|
||||
H.add_stun_absorption("[id]", INFINITY, 1)
|
||||
H.physiology.stamina_mod *= 0.1
|
||||
H.physiology.brute_mod *= 0.5
|
||||
H.physiology.burn_mod *= 0.5
|
||||
|
||||
/datum/status_effect/force_shield/on_remove()
|
||||
. = ..()
|
||||
var/mob/living/carbon/human/H = owner
|
||||
H.cut_overlay(shield)
|
||||
if(islist(owner.stun_absorption) && owner.stun_absorption["[id]"])
|
||||
owner.stun_absorption -= "[id]"
|
||||
H.physiology.stamina_mod /= 0.1
|
||||
H.physiology.brute_mod /= 0.5
|
||||
H.physiology.burn_mod /= 0.5
|
||||
|
||||
|
||||
/datum/status_effect/exercised
|
||||
id = "Exercised"
|
||||
duration = 1200
|
||||
|
||||
@@ -499,10 +499,10 @@
|
||||
log_name = "SI"
|
||||
category = "Weapons and Armors"
|
||||
|
||||
/datum/spellbook_entry/item/spell_blade //Yes spellblade is technicaly a staff, but you can melee with it and it is not called a staff so I am putting it here
|
||||
/datum/spellbook_entry/item/spell_blade
|
||||
name = "Spellblade"
|
||||
desc = "A magical sword that is quite good at slashing people, but is even better at shooting magical projectiles that can potentialy delimb at range."
|
||||
item_path = /obj/item/gun/magic/staff/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."
|
||||
item_path = /obj/item/melee/spellblade
|
||||
log_name = "SB"
|
||||
category = "Weapons and Armors"
|
||||
|
||||
|
||||
@@ -106,3 +106,201 @@
|
||||
bug.death(TRUE)
|
||||
if(!QDELETED(M))
|
||||
qdel(M)
|
||||
|
||||
/obj/item/melee/spellblade
|
||||
name = "spellblade"
|
||||
desc = "An enchanted blade with a series of runes along the side."
|
||||
icon = 'icons/obj/guns/magic.dmi'
|
||||
icon_state = "spellblade"
|
||||
item_state = "spellblade"
|
||||
hitsound = 'sound/weapons/rapierhit.ogg'
|
||||
w_class = WEIGHT_CLASS_BULKY
|
||||
force = 25
|
||||
armour_penetration = 50
|
||||
block_chance = 50
|
||||
///enchantment holder, gives it unique on hit effects.
|
||||
var/datum/enchantment/enchant = null
|
||||
///the cooldown and power of enchantments are multiplied by this var when its applied
|
||||
var/power = 1
|
||||
|
||||
/obj/item/melee/spellblade/Destroy()
|
||||
QDEL_NULL(enchant)
|
||||
return ..()
|
||||
|
||||
/obj/item/melee/spellblade/afterattack(atom/target, mob/user, proximity, params)
|
||||
. = ..()
|
||||
enchant?.on_hit(target, user, proximity, src)
|
||||
|
||||
/obj/item/melee/spellblade/attack_self(mob/user)
|
||||
if(enchant)
|
||||
return
|
||||
|
||||
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"),)
|
||||
var/static/list/options_to_type = list("Lightning" = /datum/enchantment/lightning,
|
||||
"Fire" = /datum/enchantment/fire,
|
||||
"Bluespace" = /datum/enchantment/bluespace,
|
||||
"Forcewall" = /datum/enchantment/forcewall,)
|
||||
|
||||
var/choice = show_radial_menu(user, src, options)
|
||||
if(!choice)
|
||||
return
|
||||
add_enchantment(options_to_type[choice], user)
|
||||
|
||||
/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_gain(src, user)
|
||||
E.power *= power
|
||||
if(intentional)
|
||||
SSblackbox.record_feedback("nested tally", "spellblade_enchants", 1, list("[E.name]"))
|
||||
|
||||
/obj/item/melee/spellblade/examine(mob/user)
|
||||
. = ..()
|
||||
if(enchant && (iswizard(user) || iscultist(user))) // only wizards and cultists understand runes
|
||||
. += "The runes along the side read; [enchant.desc]."
|
||||
|
||||
|
||||
/obj/item/melee/spellblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
final_block_chance = 0
|
||||
return ..()
|
||||
|
||||
/datum/enchantment
|
||||
/// used for blackbox logging
|
||||
var/name = "You shouldn't be seeing this, file an issue report."
|
||||
/// used for wizards/cultists examining the runes on the blade
|
||||
var/desc = "Someone messed up, file an issue report."
|
||||
/// used for damage values
|
||||
var/power = 1
|
||||
/// whether the enchant procs despite not being in proximity
|
||||
var/ranged = FALSE
|
||||
/// stores the world.time after which it can be used again, the `initial(cooldown)` is the cooldown between activations.
|
||||
var/cooldown = -1
|
||||
|
||||
/datum/enchantment/proc/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S)
|
||||
if(world.time < cooldown)
|
||||
return FALSE
|
||||
if(!istype(target))
|
||||
return FALSE
|
||||
if(target.stat == DEAD)
|
||||
return FALSE
|
||||
if(!ranged && !proximity)
|
||||
return FALSE
|
||||
cooldown = world.time + initial(cooldown)
|
||||
return TRUE
|
||||
|
||||
/datum/enchantment/proc/on_gain(obj/item/melee/spellblade, mob/living/user)
|
||||
|
||||
/datum/enchantment/lightning
|
||||
name = "lightning"
|
||||
desc = "this blade conducts arcane energy to arc between its victims"
|
||||
// the damage of the first lighting arc.
|
||||
power = 20
|
||||
cooldown = 3 SECONDS
|
||||
|
||||
/datum/enchantment/lightning/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S)
|
||||
. = ..()
|
||||
if(.)
|
||||
zap(target, user, list(user), power)
|
||||
|
||||
|
||||
/datum/enchantment/lightning/proc/zap(mob/living/target, mob/living/source, protected_mobs, voltage)
|
||||
source.Beam(target, "lightning[rand(1,12)]", 'icons/effects/effects.dmi', time = 2 SECONDS, maxdistance = 7, beam_type = /obj/effect/ebeam/chain)
|
||||
if(!target.electrocute_act(voltage, flags = SHOCK_TESLA)) // if it fails to shock someone, break the chain
|
||||
return
|
||||
protected_mobs += target
|
||||
addtimer(CALLBACK(src, .proc/arc, target, voltage, protected_mobs), 2.5 SECONDS)
|
||||
|
||||
/datum/enchantment/lightning/proc/arc(mob/living/source, voltage, protected_mobs)
|
||||
voltage = voltage - 4
|
||||
if(voltage <= 0)
|
||||
return
|
||||
|
||||
for(var/mob/living/L in oview(7, get_turf(source)))
|
||||
if(L in protected_mobs)
|
||||
continue
|
||||
zap(L, source, protected_mobs, voltage)
|
||||
break
|
||||
|
||||
/datum/enchantment/fire
|
||||
name = "fire"
|
||||
desc = "this blade ignites on striking a foe, releasing a ball of fire. It also makes the wielder immune to fire"
|
||||
cooldown = 8 SECONDS
|
||||
var/applied_traits = FALSE
|
||||
|
||||
/datum/enchantment/fire/on_gain(obj/item/melee/spellblade/S, mob/living/user)
|
||||
..()
|
||||
RegisterSignal(S, list(COMSIG_ITEM_PICKUP, COMSIG_ITEM_DROPPED), .proc/toggle_traits)
|
||||
if(user)
|
||||
toggle_traits(S, user)
|
||||
|
||||
/datum/enchantment/fire/proc/toggle_traits(obj/item/I, mob/living/user)
|
||||
var/enchant_ID = UID(src) // so it only removes the traits applied by this specific enchant.
|
||||
if(applied_traits)
|
||||
REMOVE_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
|
||||
REMOVE_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
|
||||
applied_traits = FALSE
|
||||
else
|
||||
ADD_TRAIT(user, TRAIT_RESISTHEAT, "[enchant_ID]")
|
||||
ADD_TRAIT(user, TRAIT_NOFIRE, "[enchant_ID]")
|
||||
applied_traits = TRUE
|
||||
|
||||
/datum/enchantment/fire/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S)
|
||||
. = ..()
|
||||
if(.)
|
||||
fireflash_s(target, 4, 8000 * power, 500)
|
||||
|
||||
/datum/enchantment/forcewall
|
||||
name = "forcewall"
|
||||
desc = "this blade will partially shield you against attacks and stuns for a short duration after striking a foe"
|
||||
cooldown = 4 SECONDS
|
||||
|
||||
/datum/enchantment/forcewall/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
user.apply_status_effect(STATUS_EFFECT_FORCESHIELD)
|
||||
|
||||
/datum/enchantment/bluespace
|
||||
name = "bluespace"
|
||||
desc = "this 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
|
||||
power = 5
|
||||
|
||||
/datum/enchantment/bluespace/on_hit(mob/living/target, mob/living/user, proximity, obj/item/melee/spellblade/S)
|
||||
if(proximity) // don't put it on cooldown if adjacent
|
||||
return
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
var/turf/user_turf = get_turf(user)
|
||||
if(!(target in view(7, user_turf))) // no camera shenangians
|
||||
return
|
||||
var/list/turfs = list()
|
||||
for(var/turf/T in orange(1, get_turf(target)))
|
||||
if(is_blocked_turf(T, TRUE))
|
||||
continue
|
||||
turfs += T
|
||||
|
||||
var/target_turf = pick(turfs)
|
||||
user_turf.Beam(target_turf, "warp_beam", time = 0.3 SECONDS)
|
||||
user.forceMove(target_turf)
|
||||
S.melee_attack_chain(user, target)
|
||||
target.Weaken(power)
|
||||
|
||||
/obj/item/melee/spellblade/random
|
||||
power = 0.5
|
||||
|
||||
/obj/item/melee/spellblade/random/Initialize(mapload)
|
||||
. = ..()
|
||||
var/list/options = list(/datum/enchantment/lightning,
|
||||
/datum/enchantment/fire,
|
||||
/datum/enchantment/forcewall,
|
||||
/datum/enchantment/bluespace,)
|
||||
var/datum/enchantment/E = pick(options)
|
||||
add_enchantment(E, intentional = FALSE)
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
resistance_flags = FIRE_PROOF | LAVA_PROOF
|
||||
slowdown = 0
|
||||
armor = list(MELEE = 70, BULLET = 40, LASER = 10, ENERGY = 10, BOMB = 50, BIO = 100, RAD = 100, FIRE = 100, ACID = 100)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe)
|
||||
allowed = list(/obj/item/flashlight, /obj/item/tank/internals, /obj/item/resonator, /obj/item/mining_scanner, /obj/item/t_scanner/adv_mining_scanner, /obj/item/gun/energy/kinetic_accelerator, /obj/item/pickaxe, /obj/item/melee/spellblade)
|
||||
|
||||
/obj/item/clothing/suit/space/hostile_environment/New()
|
||||
..()
|
||||
|
||||
@@ -343,7 +343,7 @@
|
||||
/obj/item/his_grace,
|
||||
/obj/item/gun/projectile/automatic/l6_saw,
|
||||
/obj/item/gun/magic/staff/chaos,
|
||||
/obj/item/gun/magic/staff/spellblade,
|
||||
/obj/item/melee/spellblade,
|
||||
/obj/item/gun/magic/wand/death,
|
||||
/obj/item/gun/magic/wand/fireball,
|
||||
/obj/item/stack/telecrystal/twenty,
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
/obj/structure/closet/crate/necropolis/bubblegum/populate_contents()
|
||||
new /obj/item/clothing/suit/space/hostile_environment(src)
|
||||
new /obj/item/clothing/head/helmet/space/hostile_environment(src)
|
||||
new /obj/item/gun/magic/staff/spellblade(src)
|
||||
new /obj/item/melee/spellblade/random(src)
|
||||
|
||||
/obj/structure/closet/crate/necropolis/bubblegum/crusher
|
||||
name = "bloody bubblegum chest"
|
||||
|
||||
@@ -163,7 +163,7 @@
|
||||
|
||||
/obj/machinery/anomalous_crystal/emitter/New()
|
||||
..()
|
||||
generated_projectile = pick(/obj/item/projectile/magic/fireball/infernal,/obj/item/projectile/magic/spellblade,
|
||||
generated_projectile = pick(/obj/item/projectile/magic/fireball/infernal,
|
||||
/obj/item/projectile/bullet/meteorshot, /obj/item/projectile/beam/xray, /obj/item/projectile/colossus)
|
||||
|
||||
/obj/machinery/anomalous_crystal/emitter/ActivationReaction(mob/user, method)
|
||||
|
||||
@@ -21,7 +21,7 @@ If at half health it will start to charge from all sides with clones.
|
||||
|
||||
When Bubblegum dies, it leaves behind a chest that contains:
|
||||
1. A H.E.C.K. mining suit
|
||||
2. A spellblade that can slice off limbs at range
|
||||
2. A spellblade that can have a range of magical enchantments
|
||||
|
||||
Difficulty: Hard
|
||||
|
||||
|
||||
@@ -32,9 +32,6 @@
|
||||
/obj/item/ammo_casing/magic/chaos
|
||||
projectile_type = /obj/item/projectile/magic
|
||||
|
||||
/obj/item/ammo_casing/magic/spellblade
|
||||
projectile_type = /obj/item/projectile/magic/spellblade
|
||||
|
||||
/obj/item/ammo_casing/magic/slipping
|
||||
projectile_type = /obj/item/projectile/magic/slipping
|
||||
|
||||
|
||||
@@ -72,22 +72,3 @@
|
||||
icon_state = "focus"
|
||||
item_state = "focus"
|
||||
ammo_type = /obj/item/ammo_casing/magic/forcebolt
|
||||
|
||||
/obj/item/gun/magic/staff/spellblade
|
||||
name = "spellblade"
|
||||
desc = "A deadly combination of laziness and bloodlust, this blade allows the user to dismember their enemies without all the hard work of actually swinging the sword."
|
||||
fire_sound = 'sound/magic/fireball.ogg'
|
||||
ammo_type = /obj/item/ammo_casing/magic/spellblade
|
||||
icon_state = "spellblade"
|
||||
item_state = "spellblade"
|
||||
hitsound = 'sound/weapons/rapierhit.ogg'
|
||||
force = 20
|
||||
armour_penetration = 75
|
||||
block_chance = 50
|
||||
sharp = 1
|
||||
max_charges = 4
|
||||
|
||||
/obj/item/gun/magic/staff/spellblade/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK)
|
||||
if(attack_type == PROJECTILE_ATTACK)
|
||||
final_block_chance = 0
|
||||
return ..()
|
||||
|
||||
@@ -322,16 +322,6 @@
|
||||
var/mob/living/simple_animal/hostile/mimic/copy/C = change
|
||||
C.ChangeOwner(firer)
|
||||
|
||||
/obj/item/projectile/magic/spellblade
|
||||
name = "blade energy"
|
||||
icon_state = "lavastaff"
|
||||
damage = 15
|
||||
damage_type = BURN
|
||||
flag = "magic"
|
||||
sharp = TRUE
|
||||
dismemberment = 50
|
||||
nodamage = 0
|
||||
|
||||
/obj/item/projectile/magic/slipping
|
||||
name = "magical banana"
|
||||
icon = 'icons/obj/hydroponics/harvest.dmi'
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.0 KiB |
Reference in New Issue
Block a user