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
This commit is contained in:
uporotiy
2011-04-17 18:49:46 +00:00
parent ffc69056f8
commit b7db69b6f8
26 changed files with 761 additions and 553 deletions

View File

@@ -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
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

View File

@@ -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

View File

@@ -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.x<outer_teleport_radius) continue //putting them at the edge is dumb
if(T.y>world.maxy-outer_teleport_radius || T.y<outer_teleport_radius) continue
turfs += T
if(!turfs.len)
var/list/turfs_to_pick_from = list()
for(var/turf/T in orange(M,outer_teleport_radius))
if(!(T in orange(M,inner_teleport_radius)))
turfs_to_pick_from += T
turfs += pick(/turf in turfs_to_pick_from)
if(smoke_spread)
var/datum/effects/system/harmless_smoke_spread/smoke = new /datum/effects/system/harmless_smoke_spread()
smoke.set_up(10, 0, M.loc)
smoke.start()
var/turf/picked = pick(turfs)
if(!isturf(picked)) return
M.loc = picked

View File

@@ -1,3 +1,14 @@
/obj/spell/aoe_turf/conjure
name = "Conjure"
desc = "This spell conjures objs of the specified types in range."
var/list/summon_type = list() //determines what exactly will be summoned
var/summon_lifespan = 0 // 0=permanent, any other time in deciseconds
var/summon_amt = 1 //amount of objects summoned
var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places
var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point
/*
/obj/spell/conjure
name = "Summon Bigger Carp"
desc = "This spell conjures an elite carp."
@@ -13,31 +24,23 @@
var/summon_amt = 1 //amount of objects summoned
var/summon_ignore_density = 0 //if set to 1, adds dense tiles to possible spawn places
var/summon_ignore_prev_spawn_points = 0 //if set to 1, each new object is summoned on a new spawn point
*/
/obj/spell/aoe_turf/conjure/cast(list/targets)
/obj/spell/conjure/Click()
..()
if(!cast_check())
return
invocation()
var/list/possible_spawn_points = list()
for(var/turf/T in oview(usr,range))
if(!T.density || summon_ignore_density)
possible_spawn_points += T
for(var/turf/T in targets)
if(T.density && !summon_ignore_density)
targets -= T
for(var/i=0,i<summon_amt,i++)
if(!possible_spawn_points.len)
if(!targets.len)
break
var/summoned_object_type = text2path(pick(summon_type))
var/spawn_place = pick(possible_spawn_points)
var/spawn_place = pick(targets)
if(summon_ignore_prev_spawn_points)
possible_spawn_points -= spawn_place
targets -= spawn_place
var/summoned_object = new summoned_object_type(spawn_place)
if(summon_duration)
spawn(summon_duration)
if(summon_lifespan)
spawn(summon_lifespan)
if(summoned_object)
del(summoned_object)

View File

@@ -1,20 +0,0 @@
/obj/spell/disable_tech
name = "Disable Tech"
desc = "This spell disables all weapons, cameras and most other technology in range."
charge_max = 400
clothes_req = 1
invocation = "NEC CANTIO"
invocation_type = "shout"
var/emp_heavy_radius = 5
var/emp_light_radius = 7
/obj/spell/disable_tech/Click()
..()
if(!cast_check())
return
invocation()
empulse(usr.loc, src.emp_heavy_radius, src.emp_light_radius)
return

View File

@@ -1,72 +0,0 @@
/obj/spell/disintegrate
name = "Disintegrate"
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
school = "evocation"
charge_max = 600
clothes_req = 1
invocation = "EI NATH"
invocation_type = "shout"
range = 1
var/sparks_spread = 1 //if set to 0, no sparks spread when disintegrating
var/kill_type = "disintegrate" //"disintegrate" leaves a pile of ash and bones (remains), "gib" gibs, "kill" adds damage_amount of damage_type
var/damage_amount = 2000 //only used if kill_type = "damage"
var/damage_type = "brute" //can be "brute", "fire", "toxin" or "oxygen"
/obj/spell/disintegrate/Click()
..()
if(!cast_check())
return
var/mob/living/M = input("Choose whom to [kill_type]", "ABRAKADABRA") as mob in oview(usr,range)
if(!istype(M))
return
invocation()
if(sparks_spread)
var/datum/effects/system/spark_spread/s = new /datum/effects/system/spark_spread
s.set_up(4, 1, M)
s.start()
switch(kill_type)
if("disintegrate")
M.dust()
if("gib")
M.gib()
if("kill")
if (damage_amount>0)
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,i<abs(damage_amount),i++)
sleep(0) //to avoid troubles with instantly applying lots of damage, it seems to be buggy
switch(damage_type)
if("brute")
if(damage_amount>0)
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--
*/

View File

@@ -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

View File

@@ -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"

View File

@@ -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

View File

@@ -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<lifetime, i++)
step_to(A,M,0)
if(get_dist(A,M) <= 1)
if(istype(M,/mob/living))
M:take_organ_damage(bruteloss,fireloss)
explosion(M.loc, radius_devastation, radius_heavy, radius_light, radius_flash)
del(A)
return
sleep(1)
del(A)
return

View File

@@ -1,32 +0,0 @@
/obj/spell/forcewall
name = "Forcewall"
desc = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
school = "transmutation"
charge_max = 100
clothes_req = 0
invocation = "TARCOL MINTI ZHERI"
invocation_type = "whisper"
range = 0 //default creates only a 1x1 forcewall in the user's tile
var/wall_lifespan = 300 //in deciseconds
var/wall_visibility = 1 //if 0, the created wall(s) is(are) invisible
/obj/spell/forcewall/Click()
..()
if(!cast_check())
return
invocation()
var/list/forcefields = list()
for(var/turf/T in range(usr,range))
forcefields += new /obj/forcefield(T)
spawn (wall_lifespan)
for(var/obj/forcefield/F in forcefields)
del(F)
del(forcefields)
return

View File

@@ -0,0 +1,34 @@
/obj/spell/targeted/genetic
name = "Genetic"
desc = "This spell inflicts a set of mutations and disabilities upon the target."
var/disabilities = 0 //bits
var/mutations = 0 //bits
var/duration = 100 //deciseconds
/*
Disabilities
1st bit - ?
2nd bit - ?
3rd bit - ?
4th bit - ?
5th bit - ?
6th bit - ?
Mutations
1st bit - portals
2nd bit - cold resist
3rd bit - xray
4th bit - hulk
5th bit - clown
6th bit - fat
*/
/obj/spell/targeted/genetic/cast(list/targets)
for(var/mob/target in targets)
target.mutations |= mutations
target.disabilities |= disabilities
spawn(duration)
target.mutations &= ~mutations
target.disabilities &= ~disabilities
return

View File

@@ -0,0 +1,44 @@
/obj/spell/targeted/inflict_handler
name = "Inflict Handler"
desc = "This spell destroys/damages/heals and/or weakens/stuns the target."
var/amt_weaken = 0
var/amt_paralysis = 0 //stun
//set to negatives for healing
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
var/amt_dam_tox = 0
var/destroys = "none" //can be "none", "gib" or "disintegrate"
/obj/spell/targeted/inflict_handler/cast(list/targets)
for(var/mob/living/target in targets)
switch(destroys)
if("gib")
target.gib()
if("disintegrate")
target.dust()
if(!target)
continue
//damage
if(amt_dam_brute > 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

View File

@@ -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

View File

@@ -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<missile_lifespan, i++)
var/obj/overlay/B = new /obj/overlay( A.loc )
B.icon_state = "magicmd"
B.icon = 'wizard.dmi'
B.name = "trail"
B.anchored = 1
B.density = 0
B.layer = 3
spawn(5)
del(B)
step_to(A,M,0)
if (get_dist(A,M) == 0)
M.weakened += missile_weaken_amt
M.take_organ_damage(0, missile_damage)
del(A)
return
sleep(missile_step_delay)
del(A)
targets++

View File

@@ -1,4 +1,4 @@
/obj/spell/mind_transfer
/obj/spell/targeted/mind_transfer
name = "Mind Transfer"
desc = "This spell allows the user to switch bodies with a target."
@@ -17,13 +17,16 @@
var/paralysis_amount_caster = 20 //how much the caster is paralysed for after the spell
var/paralysis_amount_victim = 20 //how much the victim is paralysed for after the spell
/obj/spell/mind_transfer/Click()
..()
if(!cast_check())
/obj/spell/targeted/mind_transfer/cast(list/targets) //magnets, so mostly hardcoded
if(!targets.len)
usr << "No mind found"
return
var/mob/target = input("Choose whom to transfer your mind to", "ABRAKADABRA") as mob in oview(usr,range)
if(targets.len > 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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -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()

View File

@@ -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.x<outer_tele_radius) continue //putting them at the edge is dumb
if(T.y>world.maxy-outer_tele_radius || T.y<outer_tele_radius) continue
turfs += T
if(!turfs.len)
var/list/turfs_to_pick_from = list()
for(var/turf/T in orange(target,outer_tele_radius))
if(!(T in orange(target,inner_tele_radius)))
turfs_to_pick_from += T
turfs += pick(/turf in turfs_to_pick_from)
var/turf/picked = pick(turfs)
if(!picked || !isturf(picked))
return
target.loc = picked

View File

@@ -0,0 +1,183 @@
/obj/spell/targeted/projectile/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"
proj_icon_state = "fireball"
proj_name = "a fireball"
proj_lingering = 1
proj_type = "/obj/spell/targeted/explosion/fireball"
/obj/spell/targeted/explosion/fireball
ex_severe = -1
ex_heavy = -1
ex_light = 3
ex_flash = 5
/obj/spell/targeted/projectile/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
max_targets = 0
proj_icon_state = "magicm"
proj_name = "a magic missile"
proj_lingering = 1
proj_type = "/obj/spell/targeted/inflict_handler/magic_missile"
proj_lifespan = 20
proj_step_delay = 5
proj_trail = 1
proj_trail_lifespan = 5
proj_trail_icon_state = "magicmd"
/obj/spell/targeted/inflict_handler/magic_missile
amt_weaken = 5
amt_dam_fire = 10
/obj/spell/targeted/genetic/blind //doesn't work properly
name = "Blind"
desc = "This spell temporarily blinds a single person and does not require wizard garb."
school = "transmutation"
charge_max = 300
clothes_req = 0
invocation = "STI KALY"
invocation_type = "whisper"
message = "\blue Your eyes cry out in pain!"
disabilities = 1
duration = 300
/obj/spell/targeted/genetic/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
include_usr = 1
mutations = 9
duration = 300
/obj/spell/targeted/inflict_handler/disintegrate
name = "Disintegrate"
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
school = "evocation"
charge_max = 600
clothes_req = 1
invocation = "EI NATH"
invocation_type = "shout"
range = 1
destroys = "disintegrate"
sparks_spread = 1
sparks_amt = 4
/obj/spell/targeted/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
include_usr = 1
smoke_spread = 2
smoke_amt = 10
/obj/spell/targeted/emplosion/disable_tech
name = "Disable Tech"
desc = "This spell disables all weapons, cameras and most other technology in range."
charge_max = 400
clothes_req = 1
invocation = "NEC CANTIO"
invocation_type = "shout"
range = -1
include_usr = 1
emp_heavy = 5
emp_light = 7
/obj/spell/targeted/turf_teleport/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
include_usr = 1
smoke_spread = 1
smoke_amt = 10
inner_tele_radius = 0
outer_tele_radius = 6
/obj/spell/targeted/area_teleport/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 = "shout"
range = -1
include_usr = 1
smoke_spread = 1
smoke_amt = 5
/obj/spell/aoe_turf/conjure/forcewall
name = "Forcewall"
desc = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
school = "transmutation"
charge_max = 100
clothes_req = 0
invocation = "TARCOL MINTI ZHERI"
invocation_type = "whisper"
range = 0
summon_type = list("/obj/forcefield")
summon_lifespan = 300
/obj/spell/aoe_turf/conjure/carp
name = "Summon Bigger Carp"
desc = "This spell conjures an elite carp."
school = "conjuration"
charge_max = 1200
clothes_req = 1
invocation = "NOUK FHUNMM SACP RISSKA"
invocation_type = "shout"
range = 1
summon_type = list("/obj/livestock/spesscarp/elite")

View File

@@ -175,7 +175,7 @@
wizard_mob.verbs += /client/proc/jaunt
wizard_mob.mind.special_verbs += /client/proc/jaunt
else
wizard_mob.spell_list += new /obj/spell/ethereal_jaunt(usr)
wizard_mob.spell_list += new /obj/spell/targeted/ethereal_jaunt(usr)
//So zards properly get their items when they are admin-made.
del(wizard_mob.wear_suit)
@@ -394,43 +394,43 @@
if(!already_knows)
switch(href_list["spell_choice"])
if ("1")
usr.spell_list += new /obj/spell/magic_missile(usr)
usr.spell_list += new /obj/spell/targeted/projectile/magic_missile(usr)
src.temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage."
if ("2")
usr.spell_list += new /obj/spell/fireball(usr)
usr.spell_list += new /obj/spell/targeted/projectile/fireball(usr)
src.temp = "This spell fires a fireball at a target and does not require wizard garb. Be careful not to fire it at people that are standing next to you."
if ("3")
usr.spell_list += new /obj/spell/disintegrate(usr)
usr.spell_list += new /obj/spell/targeted/inflict_handler/disintegrate(usr)
src.temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown."
if ("4")
usr.spell_list += new /obj/spell/disable_tech(usr)
usr.spell_list += new /obj/spell/targeted/emplosion/disable_tech(usr)
src.temp = "This spell disables all weapons, cameras and most other technology in range."
if ("5")
usr.spell_list += new /obj/spell/smoke(usr)
usr.spell_list += new /obj/spell/targeted/smoke(usr)
src.temp = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb."
if ("6")
usr.spell_list += new /obj/spell/blind(usr)
usr.spell_list += new /obj/spell/targeted/genetic/blind(usr)
src.temp = "This spell temporarly blinds a single person and does not require wizard garb."
if ("7")
usr.spell_list += new /obj/spell/mind_transfer(usr)
usr.spell_list += new /obj/spell/targeted/mind_transfer(usr)
src.temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process."
if ("8")
usr.spell_list += new /obj/spell/forcewall(usr)
usr.spell_list += new /obj/spell/aoe_turf/conjure/forcewall(usr)
src.temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
if ("9")
usr.spell_list += new /obj/spell/blink(usr)
usr.spell_list += new /obj/spell/targeted/turf_teleport/blink(usr)
src.temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience."
if ("10")
usr.spell_list += new /obj/spell/teleport(usr)
usr.spell_list += new /obj/spell/targeted/area_teleport/teleport(usr)
src.temp = "This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable."
if ("11")
usr.spell_list += new /obj/spell/mutate(usr)
usr.spell_list += new /obj/spell/targeted/genetic/mutate(usr)
src.temp = "This spell causes you to turn into a hulk and gain telekinesis for a short while."
if ("12")
usr.spell_list += new /obj/spell/ethereal_jaunt(usr)
usr.spell_list += new /obj/spell/targeted/ethereal_jaunt(usr)
src.temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
if ("13")
usr.spell_list += new /obj/spell/knock(usr)
usr.spell_list += new /obj/spell/aoe_turf/knock(usr)
src.temp = "This spell opens nearby doors and does not require wizard garb."
if (href_list["spell_choice"] == "14")
var/area/wizard_station/A = locate()

View File

@@ -476,7 +476,7 @@
src.laws = new /datum/ai_laws/syndicate_override
var/time = time2text(world.realtime,"hh:mm:ss")
lawchanges.Add("[time] <B>:</B> [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..."