From b7db69b6f8aee5f36af940b6a6babb1a765aa6f9 Mon Sep 17 00:00:00 2001 From: uporotiy Date: Sun, 17 Apr 2011 18:49:46 +0000 Subject: [PATCH] Object spell system v1.1 Completely revamped the classes, it's even more streamlined now. Got a few bugs and tweaks (namely, blind doesn't work, fireball got buffed up as compensation for not dealing additional damage to the target), but it's okay, since nobody uses those anyway. Fixed the bug with emagged borg laws. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@1465 316c924e-a436-60f5-8080-3fe189b3f50e --- code/datums/spell.dm | 216 ++++++++++++++++-- code/datums/spells/area_teleport.dm | 63 +++++ code/datums/spells/blink.dm | 53 ----- code/datums/spells/conjure.dm | 39 ++-- code/datums/spells/disable_tech.dm | 20 -- code/datums/spells/disintegrate.dm | 72 ------ code/datums/spells/emplosion.dm | 13 ++ code/datums/spells/ethereal_jaunt.dm | 88 +++---- code/datums/spells/explosion.dm | 15 ++ code/datums/spells/fireball.dm | 48 ---- code/datums/spells/forcewall.dm | 32 --- code/datums/spells/genetic.dm | 34 +++ code/datums/spells/inflict_handler.dm | 44 ++++ code/datums/spells/knock.dm | 21 +- code/datums/spells/magic_missile.dm | 57 ----- code/datums/spells/mind_transfer.dm | 23 +- code/datums/spells/mutate.dm | 50 ---- code/datums/spells/projectile.dm | 75 ++++++ code/datums/spells/smoke.dm | 23 -- code/datums/spells/teleport.dm | 64 ------ code/datums/spells/turf_teleport.dm | 34 +++ code/datums/spells/wizard.dm | 183 +++++++++++++++ code/game/gamemodes/wizard/wizard.dm | 28 +-- .../modules/mob/living/silicon/robot/robot.dm | 2 +- icons/obj/projectiles.dmi | Bin 3155 -> 6618 bytes tgstation.dme | 17 +- 26 files changed, 761 insertions(+), 553 deletions(-) create mode 100644 code/datums/spells/area_teleport.dm delete mode 100644 code/datums/spells/blink.dm delete mode 100644 code/datums/spells/disable_tech.dm delete mode 100644 code/datums/spells/disintegrate.dm create mode 100644 code/datums/spells/emplosion.dm create mode 100644 code/datums/spells/explosion.dm delete mode 100644 code/datums/spells/fireball.dm delete mode 100644 code/datums/spells/forcewall.dm create mode 100644 code/datums/spells/genetic.dm create mode 100644 code/datums/spells/inflict_handler.dm delete mode 100644 code/datums/spells/magic_missile.dm delete mode 100644 code/datums/spells/mutate.dm create mode 100644 code/datums/spells/projectile.dm delete mode 100644 code/datums/spells/smoke.dm delete mode 100644 code/datums/spells/teleport.dm create mode 100644 code/datums/spells/turf_teleport.dm create mode 100644 code/datums/spells/wizard.dm diff --git a/code/datums/spell.dm b/code/datums/spell.dm index 23f1001de6..f89d81b499 100644 --- a/code/datums/spell.dm +++ b/code/datums/spell.dm @@ -1,19 +1,32 @@ -var/list/spells = list(/obj/spell/blind,/obj/spell/blink,/obj/spell/conjure,/obj/spell/disable_tech,/obj/spell/disintegrate,/obj/spell/ethereal_jaunt,/obj/spell/fireball,/obj/spell/forcewall,/obj/spell/knock,/obj/spell/magic_missile,/obj/spell/mind_transfer,/obj/spell/mutate,/obj/spell/smoke,/obj/spell/teleport) //needed for the badmin verb for now +var/list/spells = typesof(/obj/spell) //needed for the badmin verb for now /obj/spell name = "Spell" desc = "A wizard spell" + density = 0 + opacity = 0 var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit? var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions var/charge_max = 100 //recharge time in deciseconds if charge_type = "recharge" or starting charges if charge_type = "charges" var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = "recharge" or -- each cast if charge_type = "charges" var/clothes_req = 1 //see if it requires clothes - var/stat_allowed = 0 //see if it requires being conscious + var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell var/invocation_type = "none" //can be none, whisper and shout - var/range = 7 //the range of the spell - var/message = "derp herp" //whatever it says to the guy affected by it. not always needed + var/range = 7 //the range of the spell; outer radius for aoe spells + var/message = "" //whatever it says to the guy affected by it + var/selection_type = "view" //can be "range" or "view" + + var/overlay = 0 + var/overlay_icon = 'wizard.dmi' + var/overlay_icon_state = "spell" + var/overlay_lifespan = 0 + + var/sparks_spread = 0 + var/sparks_amt = 0 //cropped at 10 + var/smoke_spread = 0 //1 - harmless, 2 - harmful + var/smoke_amt = 0 //cropped at 10 /obj/spell/proc/cast_check() //checks if the spell can be cast based on its settings @@ -23,7 +36,7 @@ var/list/spells = list(/obj/spell/blind,/obj/spell/blink,/obj/spell/conjure,/obj switch(charge_type) if("recharge") - if(charge_counter != charge_max) + if(charge_counter < charge_max) usr << "[name] is still recharging." return 0 if("charges") @@ -46,6 +59,12 @@ var/list/spells = list(/obj/spell/blind,/obj/spell/blink,/obj/spell/conjure,/obj usr << "I don't feel strong enough without my hat." return 0 + switch(charge_type) + if("recharge") + charge_counter = 0 //doesn't start recharging until the targets selecting ends + if("charges") + charge_counter-- //returns the charge if the targets selecting fails + return 1 /obj/spell/proc/invocation() //spelling the spell out and setting it on recharge/reducing charges amount @@ -60,18 +79,181 @@ var/list/spells = list(/obj/spell/blind,/obj/spell/blink,/obj/spell/conjure,/obj if("whisper") usr.whisper(invocation) - switch(charge_type) - if("recharge") - charge_counter = 0 - - spawn(0) - while(charge_counter < charge_max) - sleep(1) - charge_counter++ - if("charges") - charge_counter-- - /obj/spell/New() ..() - charge_counter = charge_max \ No newline at end of file + charge_counter = charge_max + +/obj/spell/Click() + ..() + + if(!cast_check()) + return + + choose_targets() + +/obj/spell/proc/choose_targets() //depends on subtype - /targeted or /aoe_turf + return + +/obj/spell/proc/start_recharge() + while(charge_counter < charge_max) + sleep(1) + charge_counter++ + +/obj/spell/proc/perform(list/targets) + before_cast(targets) + invocation() + spawn(0) + if(charge_type == "recharge") + start_recharge() + cast(targets) + after_cast(targets) + +/obj/spell/proc/before_cast(list/targets) + if(overlay) + for(var/atom/target in targets) + var/location + if(istype(target,/mob)) + location = target.loc + else if(istype(target,/turf)) + location = target + var/obj/overlay/spell = new /obj/overlay(location) + spell.icon = overlay_icon + spell.icon_state = overlay_icon_state + spell.anchored = 1 + spell.density = 0 + spawn(overlay_lifespan) + del(spell) + +/obj/spell/proc/after_cast(list/targets) + for(var/atom/target in targets) + var/location + if(istype(target,/mob)) + location = target.loc + else if(istype(target,/turf)) + location = target + if(istype(target,/mob) && message) + target << text("[message]") + if(sparks_spread) + var/datum/effects/system/spark_spread/sparks = new /datum/effects/system/spark_spread() + sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is + sparks.start() + if(smoke_spread) + if(smoke_spread == 1) + var/datum/effects/system/harmless_smoke_spread/smoke = new /datum/effects/system/harmless_smoke_spread() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + else if(smoke_spread == 2) + var/datum/effects/system/bad_smoke_spread/smoke = new /datum/effects/system/bad_smoke_spread() + smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is + smoke.start() + +/obj/spell/proc/cast(list/targets) + return + +/obj/spell/proc/revert_cast() //resets recharge or readds a charge + switch(charge_type) + if("recharge") + charge_counter = charge_max + if("charges") + charge_counter++ + + return + + +/obj/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob + var/max_targets = 1 //leave 0 for unlimited targets in range, 1 for one selectable target in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range + var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast + var/include_usr = 0 //if it includes usr in the target list + +/obj/spell/aoe_turf //affects all turfs in view or range (depends) + var/inner_radius = -1 //for all your ring spell needs + +/obj/spell/targeted/choose_targets() + var/list/targets = list() + + switch(selection_type) + if("range") + switch(max_targets) + if(0) + for(var/mob/target in range(usr,range)) + targets += target + if(1) + if(range < 0) + targets += usr + else + var/possible_targets = range(usr,range) + if(!include_usr && usr in possible_targets) + possible_targets -= usr + targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets + else + var/list/possible_targets = list() + for(var/mob/target in range(usr,range)) + possible_targets += target + for(var/i=1,i<=max_targets,i++) + if(!possible_targets.len) + break + if(target_ignore_prev) + var/target = pick(possible_targets) + possible_targets -= target + targets += target + else + targets += pick(possible_targets) + if("view") + switch(max_targets) + if(0) + for(var/mob/target in view(usr,range)) + targets += target + if(1) + if(range < 0) + targets += usr + else + var/possible_targets = view(usr,range) + if(!include_usr && usr in possible_targets) + possible_targets -= usr + targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets + else + var/list/possible_targets = list() + for(var/mob/target in view(usr,range)) + possible_targets += target + for(var/i=1,i<=max_targets,i++) + if(!possible_targets.len) + break + if(target_ignore_prev) + var/target = pick(possible_targets) + possible_targets -= target + targets += target + else + targets += pick(possible_targets) + + if(!include_usr && (usr in targets)) + targets -= usr + + if(!targets.len) //doesn't waste the spell + revert_cast() + return + + perform(targets) + + return + +/obj/spell/aoe_turf/choose_targets() + var/list/targets = list() + + switch(selection_type) + if("range") + for(var/turf/target in range(usr,range)) + if(!(target in range(usr,inner_radius))) + targets += target + if("view") + for(var/turf/target in view(usr,range)) + if(!(target in view(usr,inner_radius))) + targets += target + + if(!targets.len) //doesn't waste the spell + revert_cast() + return + + perform(targets) + + return \ No newline at end of file diff --git a/code/datums/spells/area_teleport.dm b/code/datums/spells/area_teleport.dm new file mode 100644 index 0000000000..eb87980df0 --- /dev/null +++ b/code/datums/spells/area_teleport.dm @@ -0,0 +1,63 @@ +/obj/spell/targeted/area_teleport + name = "Area teleport" + desc = "This spell teleports you to a type of area of your selection." + + var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list + var/invocation_area = 1 //if the invocation appends the selected area + +/obj/spell/targeted/area_teleport/perform(list/targets) + var/thearea = before_cast(targets) + if(!thearea) + revert_cast() + return + invocation(thearea) + spawn(0) + if(charge_type == "recharge") + start_recharge() + cast(targets,thearea) + after_cast(targets) + +/obj/spell/targeted/area_teleport/before_cast(list/targets) + var/A = null + + if(!randomise_selection) + A = input("Area to teleport to", "Teleport", A) in teleportlocs + else + A = pick(teleportlocs) + + var/area/thearea = teleportlocs[A] + + return thearea + +/obj/spell/targeted/area_teleport/cast(list/targets,area/thearea) + for(var/mob/target in targets) + var/list/L = list() + for(var/turf/T in get_area_turfs(thearea.type)) + if(!T.density) + var/clear = 1 + for(var/obj/O in T) + if(O.density) + clear = 0 + break + if(clear) + L+=T + + target.loc = pick(L) + + return + +/obj/spell/targeted/area_teleport/invocation(area/chosenarea = null) + if(!invocation_area || !chosenarea) + ..() + else + switch(invocation_type) + if("shout") + usr.say("[invocation] [uppertext(chosenarea.name)]") + if(usr.gender=="male") + playsound(usr.loc, pick('vs_chant_conj_hm.wav','vs_chant_conj_lm.wav','vs_chant_ench_hm.wav','vs_chant_ench_lm.wav','vs_chant_evoc_hm.wav','vs_chant_evoc_lm.wav','vs_chant_illu_hm.wav','vs_chant_illu_lm.wav','vs_chant_necr_hm.wav','vs_chant_necr_lm.wav'), 100, 1) + else + playsound(usr.loc, pick('vs_chant_conj_hf.wav','vs_chant_conj_lf.wav','vs_chant_ench_hf.wav','vs_chant_ench_lf.wav','vs_chant_evoc_hf.wav','vs_chant_evoc_lf.wav','vs_chant_illu_hf.wav','vs_chant_illu_lf.wav','vs_chant_necr_hf.wav','vs_chant_necr_lf.wav'), 100, 1) + if("whisper") + usr.whisper("[invocation] [uppertext(chosenarea.name)]") + + return \ No newline at end of file diff --git a/code/datums/spells/blink.dm b/code/datums/spells/blink.dm deleted file mode 100644 index b588422acf..0000000000 --- a/code/datums/spells/blink.dm +++ /dev/null @@ -1,53 +0,0 @@ -/obj/spell/blink - name = "Blink" - desc = "This spell randomly teleports you a short distance." - - school = "abjuration" - charge_max = 20 - clothes_req = 1 - invocation = "none" - invocation_type = "none" - range = -1 //can affect only the user by default, but with var editing can be a teleport other spell - var/outer_teleport_radius = 6 //the radius of the area in which it picks turfs to teleport to - var/inner_teleport_radius = 0 //so with var fuckery you can have it teleport in a ring, not in a circle - var/smoke_spread = 1 //if set to 0, no smoke spreads when teleporting - -/obj/spell/blink/Click() - ..() - - if(!cast_check()) - return - - var/mob/M - - if(range>=0) - M = input("Choose whom to blink", "ABRAKADABRA") as mob in view(usr,range) - else - M = usr - - if(!M) - return - - invocation() - - var/list/turfs = new/list() - for(var/turf/T in orange(M,outer_teleport_radius)) - if(T in orange(M,inner_teleport_radius)) continue - if(istype(T,/turf/space)) continue - if(T.density) continue - if(T.x>world.maxx-outer_teleport_radius || T.xworld.maxy-outer_teleport_radius || T.y0) - M.take_overall_damage(abs(damage_amount),abs(damage_amount)) - M.toxloss+=abs(damage_amount) - M.oxyloss+=abs(damage_amount) - else - M.heal_overall_damage(abs(damage_amount),abs(damage_amount)) - M.toxloss+=abs(damage_amount) - M.oxyloss+=abs(damage_amount) -/* - for(var/i=0,i0) - M.bruteloss++ - else - M.bruteloss-- - if("toxin") - if(damage_amount>0) - M.toxloss++ - else - M.toxloss-- - if("oxygen") - if(damage_amount>0) - M.oxyloss++ - else - M.oxyloss-- - if("fire") - if(damage_amount>0) - M.fireloss++ - else - M.fireloss-- -*/ \ No newline at end of file diff --git a/code/datums/spells/emplosion.dm b/code/datums/spells/emplosion.dm new file mode 100644 index 0000000000..1d358865ca --- /dev/null +++ b/code/datums/spells/emplosion.dm @@ -0,0 +1,13 @@ +/obj/spell/targeted/emplosion + name = "Emplosion" + desc = "This spell emplodes an area." + + var/emp_heavy = 2 + var/emp_light = 3 + +/obj/spell/targeted/emplosion/cast(list/targets) + + for(var/mob/target in targets) + empulse(target.loc, emp_heavy, emp_light) + + return \ No newline at end of file diff --git a/code/datums/spells/ethereal_jaunt.dm b/code/datums/spells/ethereal_jaunt.dm index b442bf17e5..25c8c92159 100644 --- a/code/datums/spells/ethereal_jaunt.dm +++ b/code/datums/spells/ethereal_jaunt.dm @@ -1,4 +1,4 @@ -/obj/spell/ethereal_jaunt +/obj/spell/targeted/ethereal_jaunt name = "Ethereal Jaunt" desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls." @@ -7,58 +7,44 @@ clothes_req = 1 invocation = "none" invocation_type = "none" - range = -1 //can affect only the user by default, but with var editing can be an invis other spell + range = -1 + include_usr = 1 + var/jaunt_duration = 50 //in deciseconds -/obj/spell/ethereal_jaunt/Click() - ..() - - if(!cast_check()) - return - - var/mob/M - - if(range>=0) - M = input("Choose whom to jaunt", "ABRAKADABRA") as mob in view(usr,range) - else - M = usr - - if(!M) - return - - invocation() - - spawn(0) - var/mobloc = get_turf(M.loc) - var/obj/dummy/spell_jaunt/holder = new /obj/dummy/spell_jaunt( mobloc ) - var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc ) - animation.name = "water" - animation.density = 0 - animation.anchored = 1 - animation.icon = 'mob.dmi' - animation.icon_state = "liquify" - animation.layer = 5 - animation.master = holder - flick("liquify",animation) - M.loc = holder - M.client.eye = holder - var/datum/effects/system/steam_spread/steam = new /datum/effects/system/steam_spread() - steam.set_up(10, 0, mobloc) - steam.start() - sleep(jaunt_duration) - mobloc = get_turf(M.loc) - animation.loc = mobloc - steam.location = mobloc - steam.start() - M.canmove = 0 - sleep(20) - flick("reappear",animation) - sleep(5) - M.loc = mobloc - M.canmove = 1 - M.client.eye = M - del(animation) - del(holder) +/obj/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded + for(var/mob/target in targets) + spawn(0) + var/mobloc = get_turf(target.loc) + var/obj/dummy/spell_jaunt/holder = new /obj/dummy/spell_jaunt( mobloc ) + var/atom/movable/overlay/animation = new /atom/movable/overlay( mobloc ) + animation.name = "water" + animation.density = 0 + animation.anchored = 1 + animation.icon = 'mob.dmi' + animation.icon_state = "liquify" + animation.layer = 5 + animation.master = holder + flick("liquify",animation) + target.loc = holder + target.client.eye = holder + var/datum/effects/system/steam_spread/steam = new /datum/effects/system/steam_spread() + steam.set_up(10, 0, mobloc) + steam.start() + sleep(jaunt_duration) + mobloc = get_turf(target.loc) + animation.loc = mobloc + steam.location = mobloc + steam.start() + target.canmove = 0 + sleep(20) + flick("reappear",animation) + sleep(5) + target.loc = mobloc + target.canmove = 1 + target.client.eye = target + del(animation) + del(holder) /obj/dummy/spell_jaunt name = "water" diff --git a/code/datums/spells/explosion.dm b/code/datums/spells/explosion.dm new file mode 100644 index 0000000000..96e02e6899 --- /dev/null +++ b/code/datums/spells/explosion.dm @@ -0,0 +1,15 @@ +/obj/spell/targeted/explosion + name = "Explosion" + desc = "This spell explodes an area." + + var/ex_severe = 1 + var/ex_heavy = 2 + var/ex_light = 3 + var/ex_flash = 4 + +/obj/spell/targeted/explosion/cast(list/targets) + + for(var/mob/target in targets) + explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash) + + return \ No newline at end of file diff --git a/code/datums/spells/fireball.dm b/code/datums/spells/fireball.dm deleted file mode 100644 index 832c7ea99c..0000000000 --- a/code/datums/spells/fireball.dm +++ /dev/null @@ -1,48 +0,0 @@ -/obj/spell/fireball - name = "Fireball" - desc = "This spell fires a fireball at a target and does not require wizard garb." - - school = "evocation" - charge_max = 200 - clothes_req = 0 - invocation = "ONI SOMA" - invocation_type = "shout" - var/radius_devastation = -1 - var/radius_heavy = -1 - var/radius_light = 2 - var/radius_flash = 2 - var/bruteloss = 20 // apparently fireball deals damage in addition to the explosion - var/fireloss = 25 // huh - var/lifetime = 200 // in deciseconds - -/obj/spell/fireball/Click() - ..() - - if(!cast_check()) - return - - var/mob/M = input("Choose whom to fireball", "ABRAKADABRA") as mob in oview(usr,range) - - if(!M) - return - - invocation() - - var/obj/overlay/A = new /obj/overlay( usr.loc ) - A.icon_state = "fireball" - A.icon = 'wizard.dmi' - A.name = "a fireball" - A.anchored = 0 - A.density = 0 - var/i - for(i=0, i 0) + if(amt_dam_fire > 0) + target.take_overall_damage(amt_dam_brute,amt_dam_fire) + else if (amt_dam_fire < 0) + target.take_overall_damage(amt_dam_brute,0) + target.heal_overall_damage(0,amt_dam_fire) + else if(amt_dam_brute < 0) + if(amt_dam_fire > 0) + target.take_overall_damage(0,amt_dam_fire) + target.heal_overall_damage(amt_dam_brute,0) + else if (amt_dam_fire < 0) + target.heal_overall_damage(amt_dam_brute,amt_dam_fire) + target.toxloss += amt_dam_tox + target.oxyloss += amt_dam_oxy + //disabling + target.weakened += amt_weaken + target.paralysis += amt_paralysis \ No newline at end of file diff --git a/code/datums/spells/knock.dm b/code/datums/spells/knock.dm index 499ad94892..dafa286f91 100644 --- a/code/datums/spells/knock.dm +++ b/code/datums/spells/knock.dm @@ -1,4 +1,4 @@ -/obj/spell/knock +/obj/spell/aoe_turf/knock name = "Knock" desc = "This spell opens nearby doors and does not require wizard garb." @@ -9,16 +9,11 @@ invocation_type = "whisper" range = 3 -/obj/spell/knock/Click() - ..() - - if(!cast_check()) - return - - invocation() - - for(var/obj/machinery/door/G in oview(usr,range)) - spawn(1) - G:locked = 0 - G.open() +/obj/spell/aoe_turf/knock/cast(list/targets) + for(var/turf/T in targets) + for(var/obj/machinery/door/door in T.contents) + spawn(1) + if(istype(door,/obj/machinery/door/airlock)) + door:locked = 0 + door.open() return \ No newline at end of file diff --git a/code/datums/spells/magic_missile.dm b/code/datums/spells/magic_missile.dm deleted file mode 100644 index 28d455efe8..0000000000 --- a/code/datums/spells/magic_missile.dm +++ /dev/null @@ -1,57 +0,0 @@ -/obj/spell/magic_missile - name = "Magic Missile" - desc = "This spell fires several, slow moving, magic projectiles at nearby targets." - - school = "evocation" - charge_max = 100 - clothes_req = 1 - invocation = "FORTI GY AMA" - invocation_type = "shout" - range = 7 - var/max_targets = 0 //max targets for the spell. set to 0 for no limit - var/missile_lifespan = 20 //in deciseconds * missile_step_delay - var/missile_step_delay = 5 //lower = faster missile - var/missile_weaken_amt = 5 //the amount by which the missile weakens the target it hits - var/missile_damage = 10 //the amount of fireloss each missile deals - -/obj/spell/magic_missile/Click() - ..() - - if(!cast_check()) - return - - invocation() - - var/targets = 0 - for (var/mob/living/M as mob in oview(usr,range)) - if(max_targets) - if(targets >= max_targets) - break - spawn(0) - var/obj/overlay/A = new /obj/overlay( usr.loc ) - A.icon_state = "magicm" - A.icon = 'wizard.dmi' - A.name = "a magic missile" - A.anchored = 0 - A.density = 0 - A.layer = 4 - var/i - for(i=0, i 1) + usr << "Too many minds! You're not a hive damnit!" + return + + var/mob/target = targets[1] if(!target.client || !target.mind) usr << "They appear to be brain-dead." @@ -41,8 +44,6 @@ usr << "You didn't study necromancy back at the Space Wizard Federation academy." return - invocation() - var/mob/victim = target //mostly copypastaed, I have little idea how this works var/mob/caster = usr //losing spells @@ -51,14 +52,14 @@ for(var/i=1,i<=spell_loss_amount,i++) var/spell_loss_chance = base_spell_loss_chance var/list/checked_spells = usr.spell_list - checked_spells -= src //MT can't be lost + checked_spells -= src //MT can't be lost //doesn't work for(var/j=1,j<=checked_spells.len,j++) if(prob(spell_loss_chance)) if(checked_spells.len) usr.spell_list -= pick(checked_spells) spawn(msg_wait) - caster << "The mind transfer has robbed you of a spell." + victim << "The mind transfer has robbed you of a spell." break else spell_loss_chance += spell_loss_chance_modifier @@ -96,6 +97,6 @@ victim.paralysis += paralysis_amount_victim spawn(msg_wait) - victim << "Your body doesn't feel like itself." + caster << "Your body doesn't feel like itself." del(temp_ghost) \ No newline at end of file diff --git a/code/datums/spells/mutate.dm b/code/datums/spells/mutate.dm deleted file mode 100644 index 42c7ad7886..0000000000 --- a/code/datums/spells/mutate.dm +++ /dev/null @@ -1,50 +0,0 @@ -/obj/spell/mutate - name = "Mutate" - desc = "This spell causes you to turn into a hulk and gain telekinesis for a short while." - - school = "transmutation" - charge_max = 400 - clothes_req = 1 - invocation = "BIRUZ BENNAR" - invocation_type = "shout" - message = "\blue You feel strong! Your mind expands!" - range = -1 //can affect only the user by default, but with var editing can be a mutate other spell - var/mutate_duration = 300 //in deciseconds - var/list/mutation_types = list("hulk","tk") //right now understands only "hulk", "tk", "cold resist", "xray" and "clown" - -/obj/spell/mutate/Click() - ..() - - if(!cast_check()) - return - - var/mob/M - - if(range>=0) - M = input("Choose whom to mutate", "ABRAKADABRA") as mob in view(usr,range) - else - M = usr - - if(!M) - return - - invocation() - - M << text("[message]") - var/mutation = 0 - for(var/MT in mutation_types) - switch(MT) - if("tk") - mutation |= 1 - if("cold resist") - mutation |= 2 - if("xray") - mutation |= 4 - if("hulk") - mutation |= 8 - if("clown") - mutation |= 16 - M.mutations |= mutation - spawn (mutate_duration) - M.mutations &= ~mutation - return \ No newline at end of file diff --git a/code/datums/spells/projectile.dm b/code/datums/spells/projectile.dm new file mode 100644 index 0000000000..2a869b734b --- /dev/null +++ b/code/datums/spells/projectile.dm @@ -0,0 +1,75 @@ +/obj/spell/targeted/projectile + name = "Projectile" + desc = "This spell summons projectiles which try to hit the targets." + + var/proj_icon = '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 = 'wizard.dmi' + var/proj_trail_icon_state = "trail" + + var/proj_type = "/obj/spell/targeted" //IMPORTANT use only subtypes of this + + var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle + var/proj_homing = 1 //if it follows the target + 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 = 15 //in deciseconds * proj_step_delay + var/proj_step_delay = 1 //lower = faster + +/obj/spell/targeted/projectile/cast(list/targets) + + for(var/mob/target in targets) + spawn(0) + var/projectile_type = text2path(proj_type) + var/obj/spell/targeted/projectile = new projectile_type(usr) + projectile.icon = proj_icon + projectile.icon_state = proj_icon_state + projectile.dir = get_dir(target,projectile) + projectile.name = proj_name + + var/current_loc = usr.loc + + for(var/i = 0,i < proj_lifespan,i++) + if(!projectile) + break + + if(proj_homing) + if(proj_insubstantial) + projectile.loc = get_step_to(projectile,target) + else + step_to(projectile,target) + else + if(proj_insubstantial) + projectile.loc = get_step(projectile,dir) + else + step(projectile,dir) + + if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time + del(projectile) + break + + if(proj_trail && projectile) + spawn(0) + if(projectile) + var/obj/overlay/trail = new /obj/overlay(projectile.loc) + trail.icon = proj_trail_icon + trail.icon_state = proj_trail_icon_state + trail.density = 0 + spawn(proj_trail_lifespan) + del(trail) + + if(projectile.loc in range(target.loc,proj_trigger_range)) + projectile.perform(list(target)) + break + + current_loc = projectile.loc + + sleep(proj_step_delay) + + if(projectile) + del(projectile) \ No newline at end of file diff --git a/code/datums/spells/smoke.dm b/code/datums/spells/smoke.dm deleted file mode 100644 index 8227eea8a3..0000000000 --- a/code/datums/spells/smoke.dm +++ /dev/null @@ -1,23 +0,0 @@ -/obj/spell/smoke - name = "Smoke" - desc = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb." - - school = "conjuration" - charge_max = 120 - clothes_req = 0 - invocation = "none" - invocation_type = "none" - range = -1 //originates from the user and I don't give a shit atm - var/smoke_amount = 10 //above 10 gets reduced to 10 anyway by the set_up proc - -/obj/spell/smoke/Click() - ..() - - if(!cast_check()) - return - - invocation() - - var/datum/effects/system/bad_smoke_spread/smoke = new /datum/effects/system/bad_smoke_spread() - smoke.set_up(smoke_amount, 0, usr.loc) - smoke.start() \ No newline at end of file diff --git a/code/datums/spells/teleport.dm b/code/datums/spells/teleport.dm deleted file mode 100644 index e60bbfab39..0000000000 --- a/code/datums/spells/teleport.dm +++ /dev/null @@ -1,64 +0,0 @@ -/obj/spell/teleport - name = "Teleport" - desc = "This spell teleports you to a type of area of your selection." - - school = "abjuration" - charge_max = 600 - clothes_req = 1 - invocation = "SCYAR NILA" - invocation_type = "none" //hardcoded into the spell due to its specifics - range = -1 //can affect only the user by default, but with var editing can be a teleport other spell - var/smoke_spread = 1 //if set to 0, no smoke spreads when teleporting - -/obj/spell/teleport/Click() - ..() - - if(!cast_check()) - return - - var/mob/M - - if(range>=0) - M = input("Choose whom to teleport", "ABRAKADABRA") as mob in view(usr,range) - else - M = usr - - if(!M) - return - - invocation() - - var/A - - A = input("Area to jump to", "BOOYEA", A) in teleportlocs - - var/area/thearea = teleportlocs[A] - - usr.say("[invocation] [uppertext(A)]") - if(usr.gender=="male") - playsound(usr.loc, pick('vs_chant_conj_hm.wav','vs_chant_conj_lm.wav','vs_chant_ench_hm.wav','vs_chant_ench_lm.wav','vs_chant_evoc_hm.wav','vs_chant_evoc_lm.wav','vs_chant_illu_hm.wav','vs_chant_illu_lm.wav','vs_chant_necr_hm.wav','vs_chant_necr_lm.wav'), 100, 1) - else - playsound(usr.loc, pick('vs_chant_conj_hf.wav','vs_chant_conj_lf.wav','vs_chant_ench_hf.wav','vs_chant_ench_lf.wav','vs_chant_evoc_hf.wav','vs_chant_evoc_lf.wav','vs_chant_illu_hf.wav','vs_chant_illu_lf.wav','vs_chant_necr_hf.wav','vs_chant_necr_lf.wav'), 100, 1) - - var/datum/effects/system/harmless_smoke_spread/smoke = new /datum/effects/system/harmless_smoke_spread() - - if(smoke_spread) - smoke.set_up(5, 0, usr.loc) - smoke.attach(usr) - smoke.start() - - var/list/L = list() - for(var/turf/T in get_area_turfs(thearea.type)) - if(!T.density) - var/clear = 1 - for(var/obj/O in T) - if(O.density) - clear = 0 - break - if(clear) - L+=T - - M.loc = pick(L) - - if(smoke_spread) - smoke.start() \ No newline at end of file diff --git a/code/datums/spells/turf_teleport.dm b/code/datums/spells/turf_teleport.dm new file mode 100644 index 0000000000..49d3d6a595 --- /dev/null +++ b/code/datums/spells/turf_teleport.dm @@ -0,0 +1,34 @@ +/obj/spell/targeted/turf_teleport + name = "Turf Teleport" + desc = "This spell teleports the target to the turf in range." + + var/inner_tele_radius = 1 + var/outer_tele_radius = 2 + + var/include_space = 0 //whether it includes space tiles in possible teleport locations + var/include_dense = 0 //whether it includes dense tiles in possible teleport locations + +/obj/spell/targeted/turf_teleport/cast(list/targets) + for(var/mob/target in targets) + var/list/turfs = new/list() + for(var/turf/T in range(target,outer_tele_radius)) + if(T in range(target,inner_tele_radius)) continue + if(istype(T,/turf/space) && !include_space) continue + if(T.density && !include_dense) continue + if(T.x>world.maxx-outer_tele_radius || T.xworld.maxy-outer_tele_radius || T.y: [user.name]([user.key]) emagged [src.name]([src.key])") - set_zeroth_law("Only [usr] is a syndicate operative.") + set_zeroth_law("Only [user.name] and people he designates as being such are syndicate agents.") src << "\red ALERT: Foreign software detected." sleep(5) src << "\red Initiating diagnostics..." diff --git a/icons/obj/projectiles.dmi b/icons/obj/projectiles.dmi index 3857a271881d857573e6872ef0c9c71e5a87b614..d8cd49aab9938c716c0c2f8d59899edc24b039fa 100644 GIT binary patch literal 6618 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 TSDgB@2GG4}q+PCM_xxV~ZqtM$ literal 3155 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 diff --git a/tgstation.dme b/tgstation.dme index d42aa0902f..21af7e5ff3 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -201,20 +201,19 @@ #include "code\datums\diseases\xeno_transformation.dm" #include "code\datums\helper_datums\construction_datum.dm" #include "code\datums\helper_datums\global_iterator.dm" +#include "code\datums\spells\area_teleport.dm" #include "code\datums\spells\blind.dm" -#include "code\datums\spells\blink.dm" #include "code\datums\spells\conjure.dm" -#include "code\datums\spells\disable_tech.dm" -#include "code\datums\spells\disintegrate.dm" +#include "code\datums\spells\emplosion.dm" #include "code\datums\spells\ethereal_jaunt.dm" -#include "code\datums\spells\fireball.dm" -#include "code\datums\spells\forcewall.dm" +#include "code\datums\spells\explosion.dm" +#include "code\datums\spells\genetic.dm" +#include "code\datums\spells\inflict_handler.dm" #include "code\datums\spells\knock.dm" -#include "code\datums\spells\magic_missile.dm" #include "code\datums\spells\mind_transfer.dm" -#include "code\datums\spells\mutate.dm" -#include "code\datums\spells\smoke.dm" -#include "code\datums\spells\teleport.dm" +#include "code\datums\spells\projectile.dm" +#include "code\datums\spells\turf_teleport.dm" +#include "code\datums\spells\wizard.dm" #include "code\defines\atom.dm" #include "code\defines\client.dm" #include "code\defines\global.dm"