Aimed Fireball Spells! (#19030)

* Fireball Spell Changes

- Changes the fireball spell to be click-to-fire.
- Converted Devil and Wand fireballs as well.
- Moved some code to the /proc_holder level to work across the /alien
and /spell branches.

* Tweaks and Fixes

- Infernal Fireball is now a projectile and has the right explosion
values.
- Removed non-projectile spell versions of fireball, as they are unused
- Fixed fireball not seeking adjacent targets.
- Fixed incorrect bolding slashes.

* Fix

Fixes the fireball sometimes missing.

* Fixes and tweak

- Uses TRUE/FALSE defines instead of 0 and 1 for boolean variables.
- Ranged abilities now remove themselves tries to use an ability in a
disabled state. (Such as being knocked out)
- Define for the click cooldown.
This commit is contained in:
GunHog
2016-07-05 09:06:01 +12:00
committed by oranges
parent c9cf322397
commit e2cfcb0bd1
16 changed files with 132 additions and 68 deletions
@@ -121,7 +121,7 @@
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/dumbfire/fireball)
wizmind.AddSpell(new /obj/effect/proc_holder/spell/fireball)
current_wizard = wizbody
@@ -11,7 +11,6 @@ Doesn't work on other aliens/AI.*/
panel = "Alien"
var/plasma_cost = 0
var/check_turf = 0
var/has_action = 1
var/datum/action/spell_action/alien/action = null
var/action_icon = 'icons/mob/actions.dmi'
@@ -191,31 +190,29 @@ Doesn't work on other aliens/AI.*/
name = "Spit Neurotoxin"
desc = "Spits neurotoxin at someone, paralyzing them for a short time."
action_icon_state = "alien_neurotoxin_0"
var/active = 0
active = FALSE
/obj/effect/proc_holder/alien/neurotoxin/fire(mob/living/carbon/user)
var/message
if(active)
user.ranged_ability = null
user << "<span class='notice'>You empty your neurotoxin gland.</span>"
active = 0
else if(user.ranged_ability && user.ranged_ability != src)
user << "<span class='warning'>You already have another aimed ability readied! Cancel it first."
return
message = "<span class='notice'>You empty your neurotoxin gland.</span>"
remove_ranged_ability(user, message)
else
user.ranged_ability = src
active = 1
user << "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
message = "<span class='notice'>You prepare your neurotoxin gland. <B>Left-click to fire at a target!</B></span>"
add_ranged_ability(user, message)
user.client.click_intercept = user.ranged_ability
/obj/effect/proc_holder/alien/neurotoxin/update_icon()
action.button_icon_state = "alien_neurotoxin_[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/alien/neurotoxin/InterceptClickOn(mob/living/carbon/user, params, atom/target)
if(..())
return
var/p_cost = 50
if(!iscarbon(user) || user.lying || user.stat)
remove_ranged_ability(user)
return
user.next_click = world.time + 6
user.face_atom(target)
if(user.getPlasma() < p_cost)
user << "<span class='warning'>You need at least [p_cost] plasma to spit.</span>"
return
@@ -223,7 +220,7 @@ Doesn't work on other aliens/AI.*/
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return 0
return FALSE
user.visible_message("<span class='danger'>[user] spits neurotoxin!", "<span class='alertalien'>You spit neurotoxin.</span>")
var/obj/item/projectile/bullet/neurotoxin/A = new /obj/item/projectile/bullet/neurotoxin(user.loc)
@@ -233,7 +230,7 @@ Doesn't work on other aliens/AI.*/
user.newtonian_move(get_dir(U, T))
user.adjustPlasma(-p_cost)
return 1
return TRUE
/obj/effect/proc_holder/alien/neurotoxin/on_lose(mob/living/carbon/user)
if(user.ranged_ability == src)
@@ -308,7 +305,7 @@ Doesn't work on other aliens/AI.*/
/obj/effect/proc_holder/alien/sneak
name = "Sneak"
desc = "Blend into the shadows to stalk your prey."
var/active = 0
active = 0
action_icon_state = "alien_sneak"
@@ -29,7 +29,7 @@
loot = list(/obj/effect/mob_spawn/human/corpse/wizard,
/obj/item/weapon/staff)
var/obj/effect/proc_holder/spell/dumbfire/fireball/fireball = null
var/obj/effect/proc_holder/spell/fireball/fireball = null
var/obj/effect/proc_holder/spell/targeted/turf_teleport/blink/blink = null
var/obj/effect/proc_holder/spell/targeted/projectile/magic_missile/mm = null
@@ -38,7 +38,7 @@
/mob/living/simple_animal/hostile/wizard/New()
..()
fireball = new /obj/effect/proc_holder/spell/dumbfire/fireball
fireball = new /obj/effect/proc_holder/spell/fireball
fireball.clothes_req = 0
fireball.human_req = 0
fireball.player_lock = 0
@@ -62,7 +62,7 @@
if(target && next_cast < world.time)
if((get_dir(src,target) in list(SOUTH,EAST,WEST,NORTH)) && fireball.cast_check(0,src)) //Lined up for fireball
src.setDir(get_dir(src,target))
fireball.choose_targets(src)
fireball.perform(list(target), user = src)
next_cast = world.time + 10 //One spell per second
return .
if(mm.cast_check(0,src))
+1 -1
View File
@@ -251,7 +251,7 @@
/obj/item/weapon/paper/contract/infernal/magic/FulfillContract(mob/living/carbon/human/user = target.current)
if(!istype(user) || !user.mind)
return -1
user.mind.AddSpell(new /obj/effect/proc_holder/spell/dumbfire/fireball(null))
user.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball(null))
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe_turf/knock(null))
return ..()
+22 -3
View File
@@ -24,27 +24,46 @@
damage_type = BRUTE
nodamage = 0
//explosion values
var/exp_heavy = 0
var/exp_light = 2
var/exp_flash = 3
var/exp_fire = 2
/obj/item/projectile/magic/fireball/Range()
var/turf/T1 = get_step(src,turn(dir, -45))
var/turf/T2 = get_step(src,turn(dir, 45))
var/turf/T3 = get_step(src,dir)
var/mob/living/L = locate(/mob/living) in T1 //if there's a mob alive in our front right diagonal, we hit it.
if(L && L.stat != DEAD)
Bump(L) //Magic Bullet #teachthecontroversy
Bump(L,1) //Magic Bullet #teachthecontroversy
return
L = locate(/mob/living) in T2
if(L && L.stat != DEAD)
Bump(L)
Bump(L,1)
return
L = locate(/mob/living) in T3
if(L && L.stat != DEAD)
Bump(L,1)
return
..()
/obj/item/projectile/magic/fireball/on_hit(target)
. = ..()
var/turf/T = get_turf(target)
explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
explosion(T, -1, exp_heavy, exp_light, exp_flash, 0, flame_range = exp_fire)
if(ismob(target)) //multiple flavors of pain
var/mob/living/M = target
M.take_overall_damage(0,10) //between this 10 burn, the 10 brute, the explosion brute, and the onfire burn, your at about 65 damage if you stop drop and roll immediately
/obj/item/projectile/magic/fireball/infernal
name = "infernal fireball"
exp_heavy = -1
exp_light = -1
exp_flash = 4
exp_fire= 5
/obj/item/projectile/magic/resurrection
name = "bolt of resurrection"
icon_state = "ion"
+33 -3
View File
@@ -1,14 +1,44 @@
#define TARGET_CLOSEST 1
#define TARGET_RANDOM 2
/obj/effect/proc_holder
var/panel = "Debug"//What panel the proc holder needs to go on.
var/active = FALSE //Used by toggle based abilities.
var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now
/obj/effect/proc_holder/proc/InterceptClickOn(mob/user, params, atom/A)
return
/obj/effect/proc_holder/proc/InterceptClickOn(mob/living/user, params, atom/A)
if(user.ranged_ability && user.ranged_ability != src)
user << "<span class='warning'><b>[user.ranged_ability.name]</b> has been disabled."
user.ranged_ability.remove_ranged_ability(user)
return TRUE //TRUE for failed, FALSE for passed.
user.next_click = world.time + CLICK_CD_CLICK_ABILITY
user.face_atom(A)
return FALSE
/obj/effect/proc_holder/proc/add_ranged_ability(mob/living/user, var/msg)
if(!user || !user.client)
return
if(user.ranged_ability && user.ranged_ability != src)
user << "<span class='warning'><b>[user.ranged_ability.name]</b> has been replaced by <b>[name]</b>."
user.ranged_ability.remove_ranged_ability(user)
user.ranged_ability = src
user.client.click_intercept = user.ranged_ability
active = TRUE
if(msg)
user << msg
update_icon()
/obj/effect/proc_holder/proc/remove_ranged_ability(mob/living/user, var/msg)
if(!user || !user.client ||user.ranged_ability != src) //To avoid removing the wrong ability
return
user.ranged_ability = null
user.client.click_intercept = null
active = FALSE
if(msg)
user << msg
update_icon()
/obj/effect/proc_holder/spell
name = "Spell"
@@ -61,10 +91,10 @@ var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin
var/critfailchance = 0
var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
var/datum/action/spell_action/action = null
var/action_icon = 'icons/mob/actions.dmi'
var/action_icon_state = "spell_default"
var/action_background_icon_state = "bg_spell"
var/datum/action/spell_action/action
/obj/effect/proc_holder/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
+2 -10
View File
@@ -75,7 +75,7 @@
user << "<span class='notice'>[C] seems to not be sentient. You cannot summon a contract for them.</span>"
/obj/effect/proc_holder/spell/dumbfire/fireball/hellish
/obj/effect/proc_holder/spell/fireball/hellish
name = "Hellfire"
desc = "This spell launches hellfire at the target."
@@ -86,18 +86,10 @@
invocation_type = "shout"
range = 2
proj_icon_state = "fireball"
proj_name = "a fireball"
proj_type = /obj/effect/proc_holder/spell/turf/fireball/infernal
proj_lifespan = 200
proj_step_delay = 1
fireball_type = /obj/item/projectile/magic/fireball/infernal
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/turf/fireball/infernal/cast(turf/T,mob/user = usr)
explosion(T, -1, -1, 1, 4, 0, flame_range = 5)
/obj/effect/proc_holder/spell/targeted/infernal_jaunt
name = "Infernal Jaunt"
desc = "Use hellfire to phase out of existence."
+46 -21
View File
@@ -250,7 +250,7 @@
duration = 300
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/dumbfire/fireball
/obj/effect/proc_holder/spell/fireball
name = "Fireball"
desc = "This spell fires a fireball at a target and does not require wizard garb."
@@ -261,30 +261,55 @@
invocation_type = "shout"
range = 20
cooldown_min = 20 //10 deciseconds reduction per rank
proj_icon_state = "fireball"
proj_name = "a fireball"
proj_type = "/obj/effect/proc_holder/spell/turf/fireball"
proj_lifespan = 200
proj_step_delay = 1
action_icon_state = "fireball"
var/fireball_type = /obj/item/projectile/magic/fireball
action_icon_state = "fireball0"
sound = "sound/magic/Fireball.ogg"
/obj/effect/proc_holder/spell/turf/fireball/cast(turf/T,mob/user = usr)
explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
active = FALSE
/obj/effect/proc_holder/spell/targeted/inflict_handler/fireball
amt_dam_brute = 20
amt_dam_fire = 25
/obj/effect/proc_holder/spell/fireball/Click()
var/mob/living/user = usr
if(!istype(user) || !can_cast(user))
return
/obj/effect/proc_holder/spell/targeted/explosion/fireball
ex_severe = -1
ex_heavy = -1
ex_light = 2
ex_flash = 5
var/msg
if(active)
msg = "<span class='notice'>You extinguish your fireball...for now.</span>"
remove_ranged_ability(user, msg)
else
msg = "<span class='notice'>Your prepare to cast your fireball spell! <B>Left-click to cast at a target!</B></span>"
add_ranged_ability(user, msg)
/obj/effect/proc_holder/spell/fireball/update_icon()
action.button_icon_state = "fireball[active]"
action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/fireball/InterceptClickOn(mob/living/user, params, atom/target)
if(..())
return
if(!cast_check(0, user))
remove_ranged_ability(user)
return
var/list/targets = list(target)
perform(targets,user = user)
/obj/effect/proc_holder/spell/fireball/cast(list/targets, mob/living/user)
var/target = targets[1] //There is only ever one target for fireball
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
if(!isturf(U) || !isturf(T))
return 0
var/obj/item/projectile/magic/fireball/FB = new fireball_type(user.loc)
FB.current = get_turf(user)
FB.preparePixelProjectile(target, get_turf(target), user)
FB.fire()
user.newtonian_move(get_dir(U, T))
return 1
/obj/effect/proc_holder/spell/aoe_turf/repulse
name = "Repulse"
@@ -315,7 +340,7 @@
if(AM == user || AM.anchored) continue
// created sparkles will disappear on their own
PoolOrNew(sparkle_path, AM)
PoolOrNew(sparkle_path, AM)
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
distfromcaster = get_dist(user, AM)
if(distfromcaster == 0)