Reworks the use of magnetism and lightning to make them actually work (#17235)

Co-authored-by: dearmochi <1496804+dearmochi@users.noreply.github.com>
This commit is contained in:
Farie82
2021-12-25 19:53:04 +01:00
committed by GitHub
co-authored by dearmochi
parent e33d20a844
commit 4daf5d1a1b
11 changed files with 231 additions and 223 deletions
-3
View File
@@ -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
-1
View File
@@ -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
+81
View File
@@ -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, "<span class='notice'>[stop_charging_text]</span>")
Reset(user)
start_recharge()
return TRUE
else
to_chat(user, "<span class='danger'>[stop_charging_fail_text]</span>")
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, "<span class='notice'>[start_charging_text]</span>")
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, "<span class='danger'>You lose control over the spell!</span>")
Reset(user)
spend_spell_cost(user)
start_recharge()
/obj/effect/proc_holder/spell/charge_up/after_cast(list/targets, mob/user)
..()
Reset(user)
+64
View File
@@ -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)
+36 -106
View File
@@ -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, "<span class='notice'>You start gathering the power.</span>")
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, "<span class='notice'>No target found in range.</span>")
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, "<span class='danger'>You lose control over the spell.</span>")
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
+41 -108
View File
@@ -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, "<span class='notice'>You start gathering the power.</span>")
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, "<span class='notice'>No target found in range.</span>")
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, "<span class='danger'>You lose control over the power.</span>")
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("<span class='warning'>[to_throw] gets thrown out of [thrower] [thrower.p_their()] hands!</span>",
"<span class='danger'>[to_throw] suddenly gets thrown out of your hands!</span>")
to_throw.throw_at(user, to_throw.throw_range, 4)
return TRUE