diff --git a/code/__HELPERS/mobs.dm b/code/__HELPERS/mobs.dm index c92415d6a4a..b3f80f85d50 100644 --- a/code/__HELPERS/mobs.dm +++ b/code/__HELPERS/mobs.dm @@ -333,7 +333,7 @@ msg_admin_attack("[key_name_admin(user)] vs [target_info]: [what_done]", loglevel) -/proc/do_mob(mob/user, mob/target, time = 30, uninterruptible = 0, progress = 1, list/extra_checks = list()) +/proc/do_mob(mob/user, mob/target, time = 30, progress = 1, list/extra_checks = list(), only_use_extra_checks = FALSE) if(!user || !target) return 0 var/user_loc = user.loc @@ -359,7 +359,9 @@ if(!user || !target) . = 0 break - if(uninterruptible) + if(only_use_extra_checks) + if(check_for_true_callbacks(extra_checks)) + break continue if(drifting && !user.inertia_dir) diff --git a/code/datums/action.dm b/code/datums/action.dm index 4ba27fb037d..42913514406 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -529,9 +529,6 @@ return FALSE var/obj/effect/proc_holder/spell/spell = target - if(spell.special_availability_check) - return TRUE - if(owner) return spell.can_cast(owner) return FALSE diff --git a/code/datums/spell.dm b/code/datums/spell.dm index f4733f64349..88d26db75b7 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -124,7 +124,6 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) var/action_icon = 'icons/mob/actions/actions.dmi' var/action_icon_state = "spell_default" var/action_background_icon_state = "bg_spell" - var/special_availability_check = 0//Whether the spell needs to bypass the action button's IsAvailable() var/sound = null //The sound the spell makes when it is cast var/gain_desc = null diff --git a/code/datums/spells/charge_up.dm b/code/datums/spells/charge_up.dm new file mode 100644 index 00000000000..24eba2c7d1a --- /dev/null +++ b/code/datums/spells/charge_up.dm @@ -0,0 +1,81 @@ +/** + * A click-based spell template which starts charging up once you click the action button/verb. Click again on something to activate the actual spell + */ + +/obj/effect/proc_holder/spell/charge_up + var/start_time = 0 + /// The overlay used to show that you are charging. Create this in the New of the spell + var/image/charge_up_overlay + /// How long you can charge for + var/max_charge_time + /// The sound charging up your power will make. Be sure to include a channel when creating the sound + var/sound/charge_sound + /// The text shown when you start charging + var/start_charging_text + /// The text shown when you successfully stop charging + var/stop_charging_text + /// The text shown when you are over the charge limit and thus can't stop. + var/stop_charging_fail_text + +/obj/effect/proc_holder/spell/charge_up/create_new_targeting() + var/datum/spell_targeting/click/T = new() + T.allowed_type = /mob/living + T.try_auto_target = FALSE + return T + +/obj/effect/proc_holder/spell/charge_up/Click() + if(cast_check(TRUE, FALSE, usr)) + if(!start_time) + INVOKE_ASYNC(src, .proc/StartChargeup, usr) + else + if(!try_stop_buildup(usr)) + return // Don't remove the click intercept + + return ..() + +/obj/effect/proc_holder/spell/charge_up/proc/try_stop_buildup(mob/user) + var/energy_perc = get_energy_charge() / max_charge_time + if(energy_perc < 0.5) + charge_counter = (1 - energy_perc) * charge_max // Give them some charge back + to_chat(user, "[stop_charging_text]") + Reset(user) + start_recharge() + return TRUE + else + to_chat(user, "[stop_charging_fail_text]") + return FALSE + +/obj/effect/proc_holder/spell/charge_up/proc/get_energy_charge() + return min(world.time - start_time, max_charge_time) + +/obj/effect/proc_holder/spell/charge_up/proc/StartChargeup(mob/user) + to_chat(user, "[start_charging_text]") + user.add_overlay(charge_up_overlay) + playsound(user, charge_sound, 50, FALSE, channel = charge_sound.channel) + start_time = world.time + if(do_mob(user, user, max_charge_time, extra_checks = list(CALLBACK(src, .proc/stopped_casting)), only_use_extra_checks = TRUE)) + if(start_time) + Discharge(user) + +/obj/effect/proc_holder/spell/charge_up/proc/stopped_casting() + return start_time == 0 + +/obj/effect/proc_holder/spell/charge_up/proc/Reset(mob/user) + start_time = 0 + user.cut_overlay(charge_up_overlay) + remove_ranged_ability(user) + playsound(user, null, 50, FALSE, channel = charge_sound.channel) + +/obj/effect/proc_holder/spell/charge_up/revert_cast(mob/user) + Reset(user) + ..() + +/obj/effect/proc_holder/spell/charge_up/proc/Discharge(mob/user) + to_chat(user, "You lose control over the spell!") + Reset(user) + spend_spell_cost(user) + start_recharge() + +/obj/effect/proc_holder/spell/charge_up/after_cast(list/targets, mob/user) + ..() + Reset(user) diff --git a/code/datums/spells/charge_up_bounce.dm b/code/datums/spells/charge_up_bounce.dm new file mode 100644 index 00000000000..b0cb94679e4 --- /dev/null +++ b/code/datums/spells/charge_up_bounce.dm @@ -0,0 +1,64 @@ +/** + * A spell template that adds bounces to the charge_up spell template. The spell will bounce between targets once released. + * Don't override cast and instead override apply_bounce_effect and the other procs + */ +/obj/effect/proc_holder/spell/charge_up/bounce + var/bounce_hit_sound + +/obj/effect/proc_holder/spell/charge_up/bounce/cast(list/targets, mob/user = usr) + var/mob/living/target = targets[1] + + bounce(user, target, get_bounce_energy(), get_bounce_amount(), user) + +/** + * How much energy should each bounce have? + */ +/obj/effect/proc_holder/spell/charge_up/bounce/proc/get_bounce_energy() + return + +/** + * How much bounces should there be in total? + */ +/obj/effect/proc_holder/spell/charge_up/bounce/proc/get_bounce_amount() + return + +/** + * Called when a bounce travels from one mob to another + * + * Arguments: + * * origin - Where the bounce came from + * * target - The mob that got hit + */ +/obj/effect/proc_holder/spell/charge_up/bounce/proc/create_beam(mob/origin, mob/target) + return + +/** + * The proc called when a bounce hits a target. Override this to add an effect + * The user itself is never hit + * + * Arguments: + * * origin - Where the bounce came from + * * target - The mob that got hit + * * energy - How much energy the bounce has + * * user - The caster of the spell + */ +/obj/effect/proc_holder/spell/charge_up/bounce/proc/apply_bounce_effect(mob/origin, mob/target, energy, mob/user) + return + +/obj/effect/proc_holder/spell/charge_up/bounce/proc/bounce(mob/origin, mob/target, energy, bounces, mob/user) + SHOULD_CALL_PARENT(TRUE) + create_beam(origin, target) + apply_bounce_effect(origin, target, energy, user) + add_attack_logs(user, target, "Bounce spell '[src]' bounced on") + playsound(get_turf(target), bounce_hit_sound, 50, 1, -1) + + if(bounces >= 1) + var/list/possible_targets = list() + for(var/mob/living/M in view(targeting.range, target)) + if(user == M || target == M && los_check(target, M)) + continue + possible_targets += M + if(!length(possible_targets)) + return + var/mob/living/next = pick(possible_targets) + bounce(target, next, energy, bounces - 1, user) diff --git a/code/datums/spells/lightning.dm b/code/datums/spells/lightning.dm index 08ad49803d4..2a3ad9eb93c 100644 --- a/code/datums/spells/lightning.dm +++ b/code/datums/spells/lightning.dm @@ -1,119 +1,49 @@ -/obj/effect/proc_holder/spell/lightning +/obj/effect/proc_holder/spell/charge_up/bounce/lightning name = "Lightning Bolt" - desc = "Throws a lightning bolt at the nearby enemy. Classic." + desc = "Throws a lightning bolt at your enemies. Classic. When clicked will start to charge in power. Then click on a mob to send the bolt before it overloads with power." charge_type = "recharge" - charge_max = 300 - clothes_req = 1 + charge_max = 30 SECONDS + clothes_req = TRUE invocation = "UN'LTD P'WAH!" invocation_type = "shout" - cooldown_min = 30 - special_availability_check = 1 - var/start_time = 0 - var/ready = 0 - var/image/halo = null + cooldown_min = 3 SECONDS action_icon_state = "lightning" - var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea. + charge_sound = new /sound('sound/magic/lightning_chargeup.ogg', channel = 7) + max_charge_time = 10 SECONDS + stop_charging_text = "You stop charging the lightning around you." + stop_charging_fail_text = "The lightning around you is too strong to stop now!" + start_charging_text = "You start gathering lightning around you." + bounce_hit_sound = 'sound/magic/lightningshock.ogg' var/damaging = TRUE -/obj/effect/proc_holder/spell/lightning/create_new_targeting() - var/datum/spell_targeting/targeted/T = new() - T.allowed_type = /mob/living - T.random_target = TRUE - return T - -/obj/effect/proc_holder/spell/lightning/lightnian - clothes_req = 0 - invocation_type = "none" - damaging = 0 - -/obj/effect/proc_holder/spell/lightning/Click() - if(!ready && start_time == 0) - if(cast_check(TRUE, FALSE, usr)) - StartChargeup() - else - if(ready && cast_check(TRUE, FALSE, usr)) - choose_targets() - return 1 - -/obj/effect/proc_holder/spell/lightning/proc/StartChargeup(mob/user = usr) - ready = 1 - to_chat(user, "You start gathering the power.") - Snd = new/sound('sound/magic/lightning_chargeup.ogg', channel = 7) - halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER) - user.overlays.Add(halo) - playsound(get_turf(user), Snd, 50, 0) - start_time = world.time - if(do_mob(user, user, 100, uninterruptible=1)) - if(ready) - Discharge() - -/obj/effect/proc_holder/spell/lightning/proc/Reset(mob/user = usr) - ready = 0 - start_time = 0 - if(halo) - user.overlays.Remove(halo) - -/obj/effect/proc_holder/spell/lightning/revert_cast(mob/user = usr) - to_chat(user, "No target found in range.") - Reset(user) +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/New() ..() + charge_up_overlay = image(icon = 'icons/effects/effects.dmi', icon_state = "electricity", layer = EFFECTS_LAYER) -/obj/effect/proc_holder/spell/lightning/proc/Discharge(mob/user = usr) - var/mob/living/M = user - to_chat(M, "You lose control over the spell.") - Reset(user) - start_recharge() +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/lightnian + clothes_req = FALSE + invocation_type = "none" + damaging = FALSE - -/obj/effect/proc_holder/spell/lightning/cast(list/targets, mob/user = usr) - ready = 0 - var/mob/living/target = targets[1] - Snd = sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck? - playsound(get_turf(user), Snd, 50, 0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way. - - playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1) - user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5) - - var/energy = min(world.time - start_time,100) +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/get_bounce_energy() if(damaging) - Bolt(user,target,max(15,energy/2),5,user) //5 bounces for energy/2 burn - else - var/bounces = round(energy/20) - Bolt(user,target,0,bounces,user) - Reset(user) + return max(15, get_energy_charge() / 2) + return 0 -/obj/effect/proc_holder/spell/lightning/proc/Bolt(mob/origin, mob/living/target, bolt_energy, bounces, mob/user = usr) - origin.Beam(target,icon_state="lightning[rand(1,12)]", icon='icons/effects/effects.dmi', time=5) - var/mob/living/current = target - if(bounces < 1) - if(damaging) - current.electrocute_act(bolt_energy, "Lightning Bolt", flags = SHOCK_NOGLOVES) - else - current.AdjustJitter(1000) //High numbers for violent convulsions - current.do_jitter_animation(current.jitteriness) - current.AdjustStuttering(2) - current.Slowed(3) - spawn(20) - current.AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less - playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1) +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/get_bounce_amount() + if(damaging) + return 5 + return round(get_energy_charge() / 20) + +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/create_beam(mob/origin, mob/target) + origin.Beam(target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5) + +/obj/effect/proc_holder/spell/charge_up/bounce/lightning/apply_bounce_effect(mob/origin, mob/living/target, energy, mob/user) + if(damaging) + target.electrocute_act(energy, "Lightning Bolt", flags = SHOCK_NOGLOVES) else - if(damaging) - current.electrocute_act(bolt_energy, "Lightning Bolt", flags = SHOCK_NOGLOVES) - else - current.AdjustJitter(1000) //High numbers for violent convulsions - current.do_jitter_animation(current.jitteriness) - current.AdjustStuttering(2) - current.Slowed(3) - spawn(20) - current.AdjustJitter(-1000, bound_lower = 10) //Still jittery, but vastly less - playsound(get_turf(current), 'sound/magic/lightningshock.ogg', 50, 1, -1) - var/list/possible_targets = new - for(var/mob/living/M in view_or_range(targeting.range, target, "view")) - if(user == M || target == M && los_check(current,M)) // || origin == M ? Not sure double shockings is good or not - continue - possible_targets += M - if(!possible_targets.len) - return - var/mob/living/next = pick(possible_targets) - if(next) - Bolt(current,next,bolt_energy,bounces-1,user) // 5 max bounces + target.AdjustJitter(1000) //High numbers for violent convulsions + target.do_jitter_animation(target.jitteriness) + target.AdjustStuttering(2) + target.Slowed(3) + addtimer(CALLBACK(target, /mob/.proc/AdjustJitter, -1000, 10), 2 SECONDS) //Still jittery, but vastly less diff --git a/code/datums/spells/magnet.dm b/code/datums/spells/magnet.dm index 21bf77d35b3..ea296eb5979 100644 --- a/code/datums/spells/magnet.dm +++ b/code/datums/spells/magnet.dm @@ -1,124 +1,57 @@ -// Disclaimer. This ain't working. Probably never worked -/obj/effect/proc_holder/spell/magnet +/obj/effect/proc_holder/spell/charge_up/bounce/magnet name = "Magnetic Pull" desc = "Pulls metalic objects from enemies hands with the power of MAGNETS." charge_type = "recharge" - charge_max = 300 - clothes_req = 0 + action_icon_state = "magnet" + charge_max = 30 SECONDS + clothes_req = FALSE invocation = "UN'LTD P'WAH!" invocation_type = "none" - cooldown_min = 30 - var/energy = 0 - var/ready = 0 - var/start_time = 0 - var/image/halo = null - var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea. - action_icon_state = "tech" + cooldown_min = 3 SECONDS + charge_sound = new /sound('sound/magic/lightning_chargeup.ogg', channel = 7) + max_charge_time = 10 SECONDS + stop_charging_text = "You stop charging the magnetism around you." + stop_charging_fail_text = "The magnetism around you is too strong to stop now!" + start_charging_text = "You start gathering magnetism around you." + bounce_hit_sound = 'sound/machines/defib_zap.ogg' -/obj/effect/proc_holder/spell/magnet/create_new_targeting() - var/datum/spell_targeting/targeted/T = new() - T.random_target = TRUE - T.allowed_type = /mob/living - return T - -/obj/effect/proc_holder/spell/magnet/Click() - if(!ready && start_time == 0) - if(cast_check(TRUE, FALSE, usr)) - StartChargeup() - else - if(ready && cast_check(TRUE, FALSE, usr)) - choose_targets(usr) - return 1 - -/obj/effect/proc_holder/spell/magnet/proc/StartChargeup(mob/user = usr) - ready = 1 - to_chat(user, "You start gathering the power.") - Snd = new/sound('sound/magic/lightning_chargeup.ogg', channel = 7) - halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER) - user.overlays.Add(halo) - playsound(get_turf(user), Snd, 50, 0) - start_time = world.time - if(do_mob(user, user, 100, uninterruptible=1)) - if(ready) - Discharge() - -/obj/effect/proc_holder/spell/magnet/proc/Reset(mob/user = usr) - ready = 0 - energy = 0 - start_time = 0 - if(halo) - user.overlays.Remove(halo) - -/obj/effect/proc_holder/spell/magnet/revert_cast(mob/user = usr) - to_chat(user, "No target found in range.") - Reset(user) +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/New() ..() + charge_up_overlay = image(icon = 'icons/effects/effects.dmi', icon_state = "electricity", layer = EFFECTS_LAYER) -/obj/effect/proc_holder/spell/magnet/proc/Discharge(mob/user = usr) - var/mob/living/M = user - to_chat(M, "You lose control over the power.") - Reset(user) - start_recharge() +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/get_bounce_energy() + return get_energy_charge() +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/get_bounce_amount() + if(get_energy_charge() >= 75) + return 5 + return 0 -/obj/effect/proc_holder/spell/magnet/cast(list/targets, mob/user = usr) - ready = 0 - var/mob/living/target = targets[1] - Snd = sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck? - playsound(get_turf(user), Snd, 50, 0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way. - - user.Beam(target,icon_state="lightning",icon='icons/effects/effects.dmi',time=5) +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/create_beam(mob/origin, mob/target) + origin.Beam(target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5) +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/apply_bounce_effect(mob/origin, mob/target, energy, mob/user) + var/list/items_to_throw = list() switch(energy) if(0 to 25) if(prob(50)) - for(var/obj/item/I in target.l_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) + if(target.l_hand) + items_to_throw += target.l_hand else - for(var/obj/item/I in target.r_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - playsound(get_turf(target), 'sound/machines/defib_zap.ogg', 50, 1, -1) - if(25 to 75) - for(var/obj/item/I in target.l_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - for(var/obj/item/I in target.r_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - playsound(get_turf(target), 'sound/machines/defib_zap.ogg', 50, 1, -1) - if(75 to 100) - //CHAIN magnet - Bolt(user,target,energy,5,user) - Reset(user) + if(target.r_hand) + items_to_throw += target.r_hand + if(25 to INFINITY) + if(target.r_hand) + items_to_throw += target.r_hand + if(target.l_hand) + items_to_throw += target.l_hand + for(var/I in items_to_throw) + try_throw_object(user, target, I) -/obj/effect/proc_holder/spell/magnet/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces, mob/user = usr) - origin.Beam(target, icon_state="lightning", icon='icons/effects/effects.dmi', time=5) - var/mob/living/carbon/current = target - if(bounces < 1) - for(var/obj/item/I in target.l_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - for(var/obj/item/I in target.r_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1) - else - for(var/obj/item/I in target.l_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - for(var/obj/item/I in target.r_hand) - if(I.flags & CONDUCT) - I.throw_at(user, I.throw_range, 4, target) - playsound(get_turf(current), 'sound/machines/defib_zap.ogg', 50, 1, -1) - var/list/possible_targets = new - for(var/mob/living/M in view_or_range(targeting.range, target, "view")) - if(user == M || target == M && los_check(current,M)) // || origin == M ? Not sure double shockings is good or not - continue - possible_targets += M - if(!possible_targets.len) - return - var/mob/living/next = pick(possible_targets) - if(next) - Bolt(current,next,bolt_energy,bounces-1,user) // 5 max bounces +/obj/effect/proc_holder/spell/charge_up/bounce/magnet/proc/try_throw_object(mob/user, mob/thrower, obj/item/to_throw) + if(!(to_throw.flags & CONDUCT) || !thrower.unEquip(to_throw, silent = TRUE)) + return FALSE + thrower.visible_message("[to_throw] gets thrown out of [thrower] [thrower.p_their()] hands!", + "[to_throw] suddenly gets thrown out of your hands!") + to_throw.throw_at(user, to_throw.throw_range, 4) + return TRUE diff --git a/code/game/gamemodes/wizard/spellbook.dm b/code/game/gamemodes/wizard/spellbook.dm index c6ebf4a3d35..5c85e5128fa 100644 --- a/code/game/gamemodes/wizard/spellbook.dm +++ b/code/game/gamemodes/wizard/spellbook.dm @@ -107,7 +107,7 @@ /datum/spellbook_entry/lightningbolt name = "Lightning Bolt" - spell_type = /obj/effect/proc_holder/spell/lightning + spell_type = /obj/effect/proc_holder/spell/charge_up/bounce/lightning log_name = "LB" category = "Offensive" cost = 1 diff --git a/code/modules/mob/living/carbon/superheroes.dm b/code/modules/mob/living/carbon/superheroes.dm index 220844a84d9..bf1f4e56b3b 100644 --- a/code/modules/mob/living/carbon/superheroes.dm +++ b/code/modules/mob/living/carbon/superheroes.dm @@ -107,7 +107,7 @@ desc = "You are LightnIan, the lord of lightning! A freak electrical accident while working in the station's kennel \ has given you mastery over lightning and a peculiar desire to sniff butts. Although you are a recent addition to the \ station's hero roster, you intend to leave your mark." - default_spells = list(/obj/effect/proc_holder/spell/lightning/lightnian) + default_spells = list(/obj/effect/proc_holder/spell/charge_up/bounce/lightning/lightnian) /datum/superheroes/lightnian/equip(mob/living/carbon/human/H) ..() @@ -126,7 +126,7 @@ desc = "You were a roboticist, once. Now you are Electro-Negmatic, a name this station will learn to fear. You designed \ your costume to resemble E-N, your faithful dog that some callous RD destroyed because it was sparking up the plasma. You \ intend to take your revenge and make them all pay thanks to your magnetic powers." - default_spells = list(/obj/effect/proc_holder/spell/magnet) + default_spells = list(/obj/effect/proc_holder/spell/charge_up/bounce/magnet) /datum/superheroes/electro/equip(mob/living/carbon/human/H) ..() diff --git a/icons/mob/actions/actions.dmi b/icons/mob/actions/actions.dmi index 19fc60a03c4..8cb31fd5135 100644 Binary files a/icons/mob/actions/actions.dmi and b/icons/mob/actions/actions.dmi differ diff --git a/paradise.dme b/paradise.dme index e1149a50c41..b54d8813b0e 100644 --- a/paradise.dme +++ b/paradise.dme @@ -434,6 +434,8 @@ #include "code\datums\spells\bloodcrawl.dm" #include "code\datums\spells\chaplain.dm" #include "code\datums\spells\charge.dm" +#include "code\datums\spells\charge_up.dm" +#include "code\datums\spells\charge_up_bounce.dm" #include "code\datums\spells\cluwne.dm" #include "code\datums\spells\conjure.dm" #include "code\datums\spells\conjure_item.dm"