mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 03:57:13 +01:00
Reworked Spellcasting System v0.9
- Very flexible - you can edit some of the spell's vars on the fly, or hardcode variations of the core spells. - Everyone can access it - you could even have observers with spells. - Slightly better UI - no longer will the spell verbs blink in and out of your verb panel. 1.0 will convert the existing spell sources (ie wizard spellbook) to this system and convert the last two spells to it. git-svn-id: http://tgstation13.googlecode.com/svn/trunk@860 316c924e-a436-60f5-8080-3fe189b3f50e
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
var/list/spells = list(/obj/spell/blind,/obj/spell/blink,/obj/spell/disintegrate,/obj/spell/ethereal_jaunt,/obj/spell/fireball,/obj/spell/forcewall,/obj/spell/knock,/obj/spell/magic_missile,/obj/spell/mutate,/obj/spell/teleport) //needed for the badmin verb for now
|
||||
|
||||
/obj/spell
|
||||
name = "Spell"
|
||||
desc = "A wizard spell"
|
||||
|
||||
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/recharge = 100 //recharge time in deciseconds
|
||||
var/clothes_req = 1 //see if it requires clothes
|
||||
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/cast = 0 //the only way I could think of making it temporarily disable
|
||||
var/message = "derp herp" //whatever it says to the guy affected by it. not always needed
|
||||
|
||||
/obj/spell/proc/cast_check() //checks if the spell can be cast based on its settings, plus handles chanting and recharge
|
||||
if(!(src in usr.spell_list))
|
||||
usr << "\red You shouldn't have this spell! Something's wrong."
|
||||
return 0
|
||||
if(cast)
|
||||
usr << "[name] is still recharging."
|
||||
return 0
|
||||
if(usr.stat)
|
||||
usr << "Not when you're incapacitated."
|
||||
return 0
|
||||
if(clothes_req) //clothes check
|
||||
if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe))
|
||||
usr << "I don't feel strong enough without my robe."
|
||||
return 0
|
||||
if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal))
|
||||
usr << "I don't feel strong enough without my sandals."
|
||||
return 0
|
||||
if(!istype(usr:head, /obj/item/clothing/head/wizard))
|
||||
usr << "I don't feel strong enough without my hat."
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/obj/spell/proc/invocation() //spelling the spell out and setting it on recharge
|
||||
|
||||
src.cast = 1
|
||||
var/old_name = src.name
|
||||
src.name += " (cast)"
|
||||
spawn(recharge)
|
||||
src.cast = 0
|
||||
src.name = old_name
|
||||
|
||||
switch(invocation_type)
|
||||
if("shout")
|
||||
usr.say(invocation)
|
||||
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)
|
||||
@@ -0,0 +1,43 @@
|
||||
/obj/spell/blind
|
||||
name = "Blind"
|
||||
desc = "This spell temporarly blinds a single person and does not require wizard garb."
|
||||
|
||||
school = "transmutation"
|
||||
recharge = 300
|
||||
clothes_req = 0
|
||||
invocation = "STI KALY"
|
||||
invocation_type = "whisper"
|
||||
message = "\blue Your eyes cry out in pain!"
|
||||
var/blind_time = 300 //in deciseconds
|
||||
var/eye_blind = 10 //I have no idea what these two do
|
||||
var/eye_blurry = 20 //but eh, they're in the code
|
||||
//I would add the ability to choose different disabilities (do ho ho), but I have no idea which bit corresponds to which disability
|
||||
|
||||
/obj/spell/blind/Click()
|
||||
..()
|
||||
|
||||
if(!cast_check())
|
||||
return
|
||||
|
||||
var/mob/M = input("Choose whom to blind", "ABRAKADABRA") as mob in oview(usr,range)
|
||||
|
||||
invocation()
|
||||
|
||||
var/obj/overlay/B = new /obj/overlay( M.loc )
|
||||
B.icon_state = "blspell"
|
||||
B.icon = 'wizard.dmi'
|
||||
B.name = "spell"
|
||||
B.anchored = 1
|
||||
B.density = 0
|
||||
B.layer = 4
|
||||
M.canmove = 0
|
||||
spawn(5)
|
||||
del(B)
|
||||
M.canmove = 1
|
||||
M << text("[message]")
|
||||
M.disabilities |= 1
|
||||
spawn(blind_time)
|
||||
M.disabilities &= ~1
|
||||
M.eye_blind = eye_blind
|
||||
M.eye_blurry = eye_blurry
|
||||
return
|
||||
@@ -0,0 +1,50 @@
|
||||
/obj/spell/blink
|
||||
name = "Blink"
|
||||
desc = "This spell randomly teleports you a short distance."
|
||||
|
||||
school = "abjuration"
|
||||
recharge = 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
|
||||
|
||||
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
|
||||
@@ -0,0 +1 @@
|
||||
//gotta test the framework in its fullest first, since it messes with it
|
||||
@@ -0,0 +1 @@
|
||||
//not gonna happen until muskets makes his emp_act() proc. we have enough copies of that proc
|
||||
@@ -0,0 +1,47 @@
|
||||
/obj/spell/disintegrate
|
||||
name = "Disintegrate"
|
||||
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
|
||||
|
||||
school = "evocation"
|
||||
recharge = 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/M = input("Choose whom to [kill_type]", "ABRAKADABRA") as mob in oview(usr,range)
|
||||
|
||||
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")
|
||||
for(var/i=0,i<damage_amount,i++)
|
||||
sleep(0) //to avoid troubles with instantly applying lots of damage, it seems to be buggy
|
||||
switch(damage_type)
|
||||
if("brute")
|
||||
M.bruteloss++
|
||||
if("toxin")
|
||||
M.toxloss++
|
||||
if("oxygen")
|
||||
M.oxyloss++
|
||||
if("fire")
|
||||
M.fireloss++
|
||||
@@ -0,0 +1,97 @@
|
||||
/obj/spell/ethereal_jaunt
|
||||
name = "Ethereal Jaunt"
|
||||
desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
|
||||
|
||||
school = "transmutation"
|
||||
recharge = 300
|
||||
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
|
||||
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
|
||||
|
||||
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/dummy/spell_jaunt
|
||||
name = "water"
|
||||
icon = 'effects.dmi'
|
||||
icon_state = "nothing"
|
||||
var/canmove = 1
|
||||
density = 0
|
||||
anchored = 1
|
||||
|
||||
/obj/dummy/spell_jaunt/relaymove(var/mob/user, direction)
|
||||
if (!src.canmove) return
|
||||
switch(direction)
|
||||
if(NORTH)
|
||||
src.y++
|
||||
if(SOUTH)
|
||||
src.y--
|
||||
if(EAST)
|
||||
src.x++
|
||||
if(WEST)
|
||||
src.x--
|
||||
if(NORTHEAST)
|
||||
src.y++
|
||||
src.x++
|
||||
if(NORTHWEST)
|
||||
src.y++
|
||||
src.x--
|
||||
if(SOUTHEAST)
|
||||
src.y--
|
||||
src.x++
|
||||
if(SOUTHWEST)
|
||||
src.y--
|
||||
src.x--
|
||||
src.canmove = 0
|
||||
spawn(2) src.canmove = 1
|
||||
|
||||
/obj/dummy/spell_jaunt/ex_act(blah)
|
||||
return
|
||||
/obj/dummy/spell_jaunt/bullet_act(blah,blah)
|
||||
return
|
||||
@@ -0,0 +1,46 @@
|
||||
/obj/spell/fireball
|
||||
name = "Fireball"
|
||||
desc = "This spell fires a fireball at a target and does not require wizard garb."
|
||||
|
||||
school = "evocation"
|
||||
recharge = 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|obj|turf in oview(usr,range)
|
||||
|
||||
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))
|
||||
M:bruteloss += bruteloss
|
||||
M:fireloss += fireloss
|
||||
explosion(M.loc, radius_devastation, radius_heavy, radius_light, radius_flash)
|
||||
del(A)
|
||||
return
|
||||
sleep(1)
|
||||
del(A)
|
||||
return
|
||||
@@ -0,0 +1,30 @@
|
||||
/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"
|
||||
recharge = 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)
|
||||
del (forcefields)
|
||||
|
||||
return
|
||||
@@ -0,0 +1,23 @@
|
||||
/obj/spell/knock
|
||||
name = "Knock"
|
||||
desc = "This spell opens nearby doors and does not require wizard garb."
|
||||
|
||||
school = "transmutation"
|
||||
recharge = 100
|
||||
clothes_req = 0
|
||||
invocation = "AULIE OXIN FIERA"
|
||||
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.open()
|
||||
return
|
||||
@@ -0,0 +1,57 @@
|
||||
/obj/spell/magic_missile
|
||||
name = "Magic missile"
|
||||
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
|
||||
|
||||
school = "evocation"
|
||||
recharge = 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/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.fireloss += missile_damage
|
||||
del(A)
|
||||
return
|
||||
sleep(missile_step_delay)
|
||||
del(A)
|
||||
targets++
|
||||
@@ -0,0 +1,47 @@
|
||||
/obj/spell/mutate
|
||||
name = "Mutate"
|
||||
desc = "This spell causes you to turn into a hulk and gain telekinesis for a short while."
|
||||
|
||||
school = "transmutation"
|
||||
recharge = 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
|
||||
|
||||
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
|
||||
@@ -0,0 +1,61 @@
|
||||
/obj/spell/teleport
|
||||
name = "Teleport"
|
||||
desc = "This spell teleports you to a type of area of your selection."
|
||||
|
||||
school = "abjuration"
|
||||
recharge = 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/blink/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
|
||||
|
||||
invocation()
|
||||
|
||||
var/A
|
||||
|
||||
A = input("Area to jump to", "BOOYEA", A) in teleportlocs
|
||||
|
||||
var/area/thearea = teleportlocs[A]
|
||||
|
||||
usr.say("SCYAR NILA [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()
|
||||
Reference in New Issue
Block a user