From 11376c3c7bdfcca770e404e84e7327ee2b3c54cd Mon Sep 17 00:00:00 2001 From: AnturK Date: Sun, 12 May 2019 00:53:20 +0200 Subject: [PATCH] Dumbfire changes (#43843) * Dumbfire changes * Unifies dumbfire and projectile. * Also fixes this while i'm at it. --- .../mob/living/simple_animal/constructs.dm | 2 +- .../spells/spell_types/construct_spells.dm | 37 ++-- code/modules/spells/spell_types/dumbfire.dm | 114 ------------ code/modules/spells/spell_types/projectile.dm | 176 +++++++++++------- code/modules/spells/spell_types/wizard.dm | 31 ++- tgstation.dme | 1 - 6 files changed, 140 insertions(+), 221 deletions(-) delete mode 100644 code/modules/spells/spell_types/dumbfire.dm diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm index fd9a9ef2d0f..567b33af970 100644 --- a/code/modules/mob/living/simple_animal/constructs.dm +++ b/code/modules/mob/living/simple_animal/constructs.dm @@ -137,7 +137,7 @@ mob_size = MOB_SIZE_LARGE force_threshold = 10 construct_spells = list(/obj/effect/proc_holder/spell/targeted/forcewall/cult, - /obj/effect/proc_holder/spell/dumbfire/juggernaut) + /obj/effect/proc_holder/spell/targeted/projectile/dumbfire/juggernaut) runetype = /datum/action/innate/cult/create_rune/wall playstyle_string = "You are a Juggernaut. Though slow, your shell can withstand heavy punishment, \ create shield walls, rip apart enemies and walls alike, and even deflect energy weapons." diff --git a/code/modules/spells/spell_types/construct_spells.dm b/code/modules/spells/spell_types/construct_spells.dm index 697113c2b0d..bd24b00a743 100644 --- a/code/modules/spells/spell_types/construct_spells.dm +++ b/code/modules/spells/spell_types/construct_spells.dm @@ -146,11 +146,14 @@ clothes_req = FALSE invocation = "none" invocation_type = "none" - proj_lifespan = 10 max_targets = 6 action_icon_state = "magicm" action_background_icon_state = "bg_demon" + proj_type = /obj/item/projectile/magic/spell/magic_missile/lesser +/obj/item/projectile/magic/spell/magic_missile/lesser + color = "red" //Looks more culty this way + range = 10 /obj/effect/proc_holder/spell/targeted/smoke/disable name = "Paralysing Smoke" @@ -282,37 +285,37 @@ jaunt_out_type = /obj/effect/temp_visual/dir_setting/cult/phase/out -/obj/effect/proc_holder/spell/dumbfire/juggernaut +/obj/effect/proc_holder/spell/targeted/projectile/dumbfire/juggernaut name = "Gauntlet Echo" desc = "Channels energy into your gauntlet - firing its essence forward in a slow moving, yet devastating, attack." - proj_icon_state = "cultfist" - proj_name = "gauntlet echo" - proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut" //IMPORTANT use only subtypes of this - proj_lifespan = 15 - proj_step_delay = 7 + proj_type = /obj/item/projectile/magic/spell/juggernaut charge_max = 350 clothes_req = FALSE action_icon = 'icons/mob/actions/actions_cult.dmi' action_icon_state = "cultfist" action_background_icon_state = "bg_demon" sound = 'sound/weapons/resonator_blast.ogg' - proj_trigger_range = 0 - ignore_factions = list("cult") - check_holy = TRUE -/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut +/obj/item/projectile/magic/spell/juggernaut name = "Gauntlet Echo" + icon_state = "cultfist" alpha = 180 - amt_dam_brute = 30 - amt_knockdown = 50 - sound = 'sound/weapons/punch3.ogg' + damage = 30 + damage_type = BRUTE + knockdown = 50 + hitsound = 'sound/weapons/punch3.ogg' + trigger_range = 0 + check_holy = TRUE + ignored_factions = list("cult") + range = 15 + speed = 7 -/obj/effect/proc_holder/spell/targeted/inflict_handler/juggernaut/cast(list/targets,mob/user = usr) +/obj/item/projectile/magic/spell/juggernaut/on_hit(atom/target, blocked) + . = ..() var/turf/T = get_turf(src) playsound(T, 'sound/weapons/resonator_blast.ogg', 100, FALSE) new /obj/effect/temp_visual/cult/sac(T) for(var/obj/O in range(src,1)) if(O.density && !istype(O, /obj/structure/destructible/cult)) O.take_damage(90, BRUTE, "melee", 0) - new /obj/effect/temp_visual/cult/turf/floor - ..() + new /obj/effect/temp_visual/cult/turf/floor(get_turf(O)) diff --git a/code/modules/spells/spell_types/dumbfire.dm b/code/modules/spells/spell_types/dumbfire.dm deleted file mode 100644 index fc8c7dd7091..00000000000 --- a/code/modules/spells/spell_types/dumbfire.dm +++ /dev/null @@ -1,114 +0,0 @@ - -//NEEDS MAJOR CODE CLEANUP - -/obj/effect/proc_holder/spell/dumbfire - - var/projectile_type = "" - var/activate_on_collision = 1 - - var/proj_icon = 'icons/obj/projectiles.dmi' - var/proj_icon_state = "spell" - var/proj_name = "a spell projectile" - - var/proj_trail = 0 //if it leaves a trail - var/proj_trail_lifespan = 0 //deciseconds - var/proj_trail_icon = 'icons/obj/wizard.dmi' - var/proj_trail_icon_state = "trail" - - var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this - - var/proj_insubstantial = 0 //if it can pass through dense objects or not - var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target) - - var/proj_lifespan = 100 //in deciseconds * proj_step_delay - var/proj_step_delay = 1 //lower = faster - var/list/ignore_factions = list() //Faction types that will be ignored - - var/check_antimagic = TRUE - var/check_holy = FALSE - -/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr) - - var/turf/T = get_turf(user) - for(var/i = 1; i < range; i++) - var/turf/new_turf = get_step(T, user.dir) - if(new_turf.density) - break - T = new_turf - perform(list(T),user = user) - -/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr) - playMagSound() - for(var/turf/target in targets) - launch_at(target, user) - -/obj/effect/proc_holder/spell/dumbfire/proc/launch_at(turf/target, mob/user) - set waitfor = FALSE - var/obj/effect/proc_holder/spell/targeted/projectile - if(istext(proj_type)) - var/projectile_type = text2path(proj_type) - projectile = new projectile_type(user) - else if(istype(proj_type, /obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile - T.linked_spells += proj_type - else - projectile = new proj_type(user) - projectile.icon = proj_icon - projectile.icon_state = proj_icon_state - projectile.setDir(get_dir(projectile, target)) - projectile.name = proj_name - - var/current_loc = user.loc - - projectile.forceMove(current_loc) - - for(var/i = 0,i < proj_lifespan,i++) - if(!projectile) - break - - if(proj_insubstantial) - projectile.forceMove(get_step(projectile, projectile.dir)) - else - step(projectile, projectile.dir) - - if(projectile.loc == current_loc || i == proj_lifespan) - projectile.cast(current_loc,user=user) - break - - var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - user - if(L && L.stat != DEAD && L.anti_magic_check(check_antimagic, check_holy)) - if(!ignore_factions.len) - projectile.cast(L.loc,user=user) - break - else - var/faction_check = FALSE - for(var/faction in L.faction) - if(ignore_factions.Find(faction)) - faction_check = TRUE - break - if(!faction_check) - projectile.cast(L.loc,user=user) - break - - if(proj_trail && projectile) - proj_trail(projectile) - - current_loc = projectile.loc - var/matrix/M = new - M.Turn(dir2angle(projectile.dir)) - projectile.transform = M - - sleep(proj_step_delay) - - if(projectile) - qdel(projectile) - -/obj/effect/proc_holder/spell/dumbfire/proc/proj_trail(obj/effect/proc_holder/spell/targeted/projectile) - set waitfor = FALSE - if(projectile) - var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.density = FALSE - QDEL_IN(trail, proj_trail_lifespan) diff --git a/code/modules/spells/spell_types/projectile.dm b/code/modules/spells/spell_types/projectile.dm index 679acdbdcb2..72d8c8208fb 100644 --- a/code/modules/spells/spell_types/projectile.dm +++ b/code/modules/spells/spell_types/projectile.dm @@ -1,96 +1,130 @@ + +/obj/item/projectile/magic/spell + name = "custom spell projectile" + var/list/ignored_factions //Do not hit these + var/check_holy = FALSE + var/check_antimagic = FALSE + var/trigger_range = 0 //How far we do we need to be to hit + var/linger = FALSE //Can't hit anything but the intended target + + var/trail = FALSE //if it leaves a trail + var/trail_lifespan = 0 //deciseconds + var/trail_icon = 'icons/obj/wizard.dmi' + var/trail_icon_state = "trail" + +//todo unify this and magic/aoe under common path +/obj/item/projectile/magic/spell/Range() + if(trigger_range > 1) + for(var/mob/living/L in range(trigger_range, get_turf(src))) + if(can_hit_target(L, ignore_loc = TRUE)) + return Bump(L) + . = ..() + +/obj/item/projectile/magic/spell/Moved(atom/OldLoc, Dir) + . = ..() + if(trail) + create_trail() + +/obj/item/projectile/magic/spell/proc/create_trail() + if(!trajectory) + return + var/datum/point/vector/previous = trajectory.return_vector_after_increments(1,-1) + var/obj/effect/overlay/trail = new /obj/effect/overlay(previous.return_turf()) + trail.pixel_x = previous.return_px() + trail.pixel_y = previous.return_py() + trail.icon = trail_icon + trail.icon_state = trail_icon_state + //might be changed to temp overlay + trail.density = FALSE + trail.mouse_opacity = MOUSE_OPACITY_TRANSPARENT + QDEL_IN(trail, trail_lifespan) + +/obj/item/projectile/magic/spell/can_hit_target(atom/target, list/passthrough, direct_target = FALSE, ignore_loc = FALSE) + . = ..() + if(linger && target != original) + return FALSE + if(ismob(target) && !direct_target) //Unsure about the direct target, i guess it could always skip these. + var/mob/M = target + if(M.anti_magic_check(check_antimagic, check_holy)) + return FALSE + if(ignored_factions && ignored_factions.len && faction_check(M.faction,ignored_factions)) + return FALSE + + //NEEDS MAJOR CODE CLEANUP. /obj/effect/proc_holder/spell/targeted/projectile name = "Projectile" desc = "This spell summons projectiles which try to hit the targets." + + + var/proj_type = /obj/item/projectile/magic/spell //IMPORTANT use only subtypes of this + + + var/update_projectile = FALSE //So you want to admin abuse magic bullets ? This is for you + //Below only apply if update_projectile is true var/proj_icon = 'icons/obj/projectiles.dmi' var/proj_icon_state = "spell" var/proj_name = "a spell projectile" - var/proj_trail = FALSE //if it leaves a trail var/proj_trail_lifespan = 0 //deciseconds var/proj_trail_icon = 'icons/obj/wizard.dmi' var/proj_trail_icon_state = "trail" - - - var/proj_type = "/obj/effect/proc_holder/spell/targeted" //IMPORTANT use only subtypes of this - var/proj_lingering = FALSE //if it lingers or disappears upon hitting an obstacle var/proj_homing = TRUE //if it follows the target var/proj_insubstantial = FALSE //if it can pass through dense objects or not - var/proj_trigger_range = FALSE //the range from target at which the projectile triggers cast(target) - + var/proj_trigger_range = 0 //the range from target at which the projectile triggers cast(target) var/proj_lifespan = 15 //in deciseconds * proj_step_delay var/proj_step_delay = 1 //lower = faster + var/list/ignore_factions = list() //Faction types that will be ignored + var/check_antimagic = TRUE + var/check_holy = FALSE + +/obj/effect/proc_holder/spell/targeted/projectile/proc/fire_projectile(atom/target, mob/user) + var/obj/item/projectile/magic/spell/projectile = new proj_type() + + if(update_projectile) + //Generally these should already be set on the projectile, this is mostly here for varedited spells. + projectile.icon = proj_icon + projectile.icon_state = proj_icon_state + projectile.name = proj_name + if(proj_insubstantial) + projectile.movement_type |= UNSTOPPABLE + if(proj_homing) + projectile.homing = TRUE + projectile.homing_turn_speed = 360 //Perfect tracking + if(proj_lingering) + projectile.linger = TRUE + projectile.trigger_range = proj_trigger_range + projectile.ignored_factions = ignore_factions + projectile.range = proj_lifespan + projectile.speed = proj_step_delay + projectile.trail = proj_trail + projectile.trail_lifespan = proj_trail_lifespan + projectile.trail_icon = proj_trail_icon + projectile.trail_icon_state = proj_trail_icon_state + + projectile.preparePixelProjectile(target,user) + if(projectile.homing) + projectile.set_homing_target(target) + projectile.fire() /obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr) playMagSound() - for(var/mob/living/target in targets) - launch(target, user) + for(var/atom/target in targets) + fire_projectile(target, user) -/obj/effect/proc_holder/spell/targeted/projectile/proc/launch(mob/living/target, mob/user) - set waitfor = FALSE - var/obj/effect/proc_holder/spell/targeted/projectile - if(istext(proj_type)) - var/projectile_type = text2path(proj_type) - projectile = new projectile_type(user) - if(istype(proj_type, /obj/effect/proc_holder/spell)) - projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user) - var/obj/effect/proc_holder/spell/targeted/trigger/T = projectile - T.linked_spells += proj_type - projectile.icon = proj_icon - projectile.icon_state = proj_icon_state - projectile.setDir(get_dir(target,projectile)) - projectile.name = proj_name +//This one just pops one projectile in direction user is facing, irrelevant of max_targets etc +/obj/effect/proc_holder/spell/targeted/projectile/dumbfire + name = "Dumbfire projectile" - var/current_loc = user.loc - - projectile.forceMove(current_loc) - - for(var/i = 0,i < proj_lifespan,i++) - if(!projectile) +/obj/effect/proc_holder/spell/targeted/projectile/dumbfire/choose_targets(mob/user = usr) + var/turf/T = get_turf(user) + for(var/i = 1; i < range; i++) + var/turf/new_turf = get_step(T, user.dir) + if(new_turf.density) break - - if(proj_homing) - if(proj_insubstantial) - projectile.setDir(get_dir(projectile,target)) - projectile.forceMove(get_step_to(projectile,target)) - else - step_to(projectile,target) - else - if(proj_insubstantial) - projectile.forceMove(get_step(projectile,dir)) - else - step(projectile,dir) - - if(!projectile) // step and step_to sleeps so we'll have to check again. - break - - if(!target || (!proj_lingering && projectile.loc == current_loc)) //if it didn't move since last time - qdel(projectile) - break - - if(proj_trail && projectile) - spawntrail(projectile) - - if(projectile.loc in range(target.loc,proj_trigger_range)) - projectile.perform(list(target),user=user) - break - - current_loc = projectile.loc - - sleep(proj_step_delay) - - if(projectile) - qdel(projectile) - -/obj/effect/proc_holder/spell/targeted/projectile/proc/spawntrail(obj/effect/proc_holder/spell/targeted/projectile) - set waitfor = FALSE - if(projectile) - var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc) - trail.icon = proj_trail_icon - trail.icon_state = proj_trail_icon_state - trail.density = FALSE - QDEL_IN(trail, proj_trail_lifespan) + T = new_turf + perform(list(T),user = user) \ No newline at end of file diff --git a/code/modules/spells/spell_types/wizard.dm b/code/modules/spells/spell_types/wizard.dm index 2a67febb739..dc327474e5f 100644 --- a/code/modules/spells/spell_types/wizard.dm +++ b/code/modules/spells/spell_types/wizard.dm @@ -9,27 +9,24 @@ invocation_type = "shout" range = 7 cooldown_min = 60 //35 deciseconds reduction per rank - max_targets = 0 - - proj_icon_state = "magicm" - proj_name = "a magic missile" - proj_lingering = 1 - proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile" - - proj_lifespan = 20 - proj_step_delay = 5 - - proj_trail = TRUE - proj_trail_lifespan = 5 - proj_trail_icon_state = "magicmd" - + proj_type = /obj/item/projectile/magic/spell/magic_missile action_icon_state = "magicm" sound = 'sound/magic/magic_missile.ogg' -/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile - amt_knockdown = 60 - sound = 'sound/magic/mm_hit.ogg' +/obj/item/projectile/magic/spell/magic_missile + name = "a magic missile" + icon_state = "magicm" + range = 20 + speed = 5 + trigger_range = 0 + linger = TRUE + knockdown = 60 + hitsound = 'sound/magic/mm_hit.ogg' + + trail = TRUE + trail_lifespan = 5 + trail_icon_state = "magicmd" /obj/effect/proc_holder/spell/targeted/genetic/mutate name = "Mutate" diff --git a/tgstation.dme b/tgstation.dme index daa66d7150a..2eb6e9ee7e9 100755 --- a/tgstation.dme +++ b/tgstation.dme @@ -2643,7 +2643,6 @@ #include "code\modules\spells\spell_types\curse.dm" #include "code\modules\spells\spell_types\devil.dm" #include "code\modules\spells\spell_types\devil_boons.dm" -#include "code\modules\spells\spell_types\dumbfire.dm" #include "code\modules\spells\spell_types\emplosion.dm" #include "code\modules\spells\spell_types\ethereal_jaunt.dm" #include "code\modules\spells\spell_types\explosion.dm"