diff --git a/baystation12.dme b/baystation12.dme
index 510ef39501..7f3090e405 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -1633,11 +1633,12 @@
#include "code\modules\spells\targeted\flesh_to_stone.dm"
#include "code\modules\spells\targeted\genetic.dm"
#include "code\modules\spells\targeted\harvest.dm"
-#include "code\modules\spells\targeted\horsemask.dm"
#include "code\modules\spells\targeted\mind_transfer.dm"
#include "code\modules\spells\targeted\shift.dm"
#include "code\modules\spells\targeted\subjugate.dm"
#include "code\modules\spells\targeted\targeted.dm"
+#include "code\modules\spells\targeted\equip\equip.dm"
+#include "code\modules\spells\targeted\equip\horsemask.dm"
#include "code\modules\spells\targeted\projectile\dumbfire.dm"
#include "code\modules\spells\targeted\projectile\fireball.dm"
#include "code\modules\spells\targeted\projectile\magic_missile.dm"
diff --git a/code/_onclick/hud/spell_screen_objects.dm b/code/_onclick/hud/spell_screen_objects.dm
index ed208a588d..08c11e8680 100644
--- a/code/_onclick/hud/spell_screen_objects.dm
+++ b/code/_onclick/hud/spell_screen_objects.dm
@@ -12,6 +12,18 @@
var/mob/spell_holder
+/obj/screen/movable/spell_master/Destroy()
+ ..()
+ for(var/obj/screen/spell/spells in spell_objects)
+ spells.spellmaster = null
+ spell_objects = null
+ if(spell_holder)
+ spell_holder.spell_masters -= src
+
+/obj/screen/movable/spell_master/ResetVars()
+ ..("spell_objects")
+ spell_objects = list()
+
/obj/screen/movable/spell_master/MouseDrop()
if(showing)
return
@@ -57,16 +69,23 @@
/obj/screen/movable/spell_master/proc/add_spell(var/spell/spell)
if(!spell) return
- for(var/obj/screen/spell/spellscreen in spell_objects)
- if(spellscreen.spell == spell)
+ if(spell.connected_button) //we have one already, for some reason
+ if(spell.connected_button in spell_objects)
+ return
+ else
+ spell_objects.Add(spell.connected_button)
+ toggle_open(2)
return
if(spell.spell_flags & NO_BUTTON) //no button to add if we don't get one
return
- var/obj/screen/spell/newscreen = new
-
+ var/obj/screen/spell/newscreen = PoolOrNew(/obj/screen/spell)
+ newscreen.spellmaster = src
newscreen.spell = spell
+
+ spell.connected_button = newscreen
+
if(!spell.override_base) //if it's not set, we do basic checks
if(spell.spell_flags & CONSTRUCT_CHECK)
newscreen.spell_base = "const" //construct spells
@@ -80,16 +99,13 @@
toggle_open(2) //forces the icons to refresh on screen
/obj/screen/movable/spell_master/proc/remove_spell(var/spell/spell)
- for(var/obj/screen/spell/s_object in spell_objects)
- if(s_object.spell == spell)
- spell_objects.Remove(s_object)
- qdel(s_object)
- break
+ qdel(spell.connected_button)
+
+ spell.connected_button = null
if(spell_objects.len)
toggle_open(showing + 1)
else
- spell_holder.spell_masters.Remove(src)
qdel(src)
/obj/screen/movable/spell_master/proc/silence_spells(var/amount)
@@ -125,9 +141,18 @@
var/spell/spell = null
var/handle_icon_updates = 0
+ var/obj/screen/movable/spell_master/spellmaster
var/icon/last_charged_icon
+/obj/screen/spell/Destroy()
+ ..()
+ if(spellmaster)
+ spellmaster.spell_objects -= src
+ if(spellmaster && !spellmaster.spell_objects.len)
+ qdel(spellmaster)
+ spellmaster = null
+
/obj/screen/spell/proc/update_charge(var/forced_update = 0)
if(!spell)
qdel(src)
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index 6c601c419e..14f67295d8 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -601,31 +601,35 @@
/mob/Stat()
..()
+ . = (client && client.inactivity < 1200)
- if(client && client.holder)
- if(statpanel("Status"))
- statpanel("Status","Location:","([x], [y], [z])")
- statpanel("Status","CPU:","[world.cpu]")
- statpanel("Status","Instances:","[world.contents.len]")
- if(statpanel("Status") && processScheduler && processScheduler.getIsRunning())
- for(var/datum/controller/process/P in processScheduler.processes)
- statpanel("Status",P.getStatName(), P.getTickTime())
- else
- statpanel("Status","processScheduler is not running.")
+ if(.)
+ if(client.holder)
+ if(statpanel("Status"))
+ statpanel("Status","Location:","([x], [y], [z])")
+ statpanel("Status","CPU:","[world.cpu]")
+ statpanel("Status","Instances:","[world.contents.len]")
+ if(statpanel("Status") && processScheduler && processScheduler.getIsRunning())
+ for(var/datum/controller/process/P in processScheduler.processes)
+ statpanel("Status",P.getStatName(), P.getTickTime())
+ else
+ statpanel("Status","processScheduler is not running.")
- if(listed_turf && client)
- if(!TurfAdjacent(listed_turf))
- listed_turf = null
- else
- statpanel(listed_turf.name, null, listed_turf)
- for(var/atom/A in listed_turf)
- if(!A.mouse_opacity)
- continue
- if(A.invisibility > see_invisible)
- continue
- if(is_type_in_list(A, shouldnt_see))
- continue
- statpanel(listed_turf.name, null, A)
+ if(listed_turf && client)
+ if(!TurfAdjacent(listed_turf))
+ listed_turf = null
+ else
+ statpanel(listed_turf.name, null, listed_turf)
+ for(var/atom/A in listed_turf)
+ if(!A.mouse_opacity)
+ continue
+ if(A.invisibility > see_invisible)
+ continue
+ if(is_type_in_list(A, shouldnt_see))
+ continue
+ statpanel(listed_turf.name, null, A)
+
+ sleep(4) //Prevent updating the stat panel for the next .4 seconds, prevents clientside latency from updates
// facing verbs
/mob/proc/canface()
@@ -1026,4 +1030,4 @@ mob/proc/yank_out_object()
/mob/proc/throw_mode_on()
src.in_throw_mode = 1
if(src.throw_icon)
- src.throw_icon.icon_state = "act_throw_on"
\ No newline at end of file
+ src.throw_icon.icon_state = "act_throw_on"
diff --git a/code/modules/spells/aoe_turf/aoe_turf.dm b/code/modules/spells/aoe_turf/aoe_turf.dm
index 9a70eb18c6..3265761077 100644
--- a/code/modules/spells/aoe_turf/aoe_turf.dm
+++ b/code/modules/spells/aoe_turf/aoe_turf.dm
@@ -1,25 +1,25 @@
-/*
-Aoe turf spells target a ring of tiles around the user
-This ring has an outer radius (range) and an inner radius (inner_radius)
-Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm
-*/
-
-/spell/aoe_turf //affects all turfs in view or range (depends)
- spell_flags = IGNOREDENSE
- var/inner_radius = -1 //for all your ring spell needs
-
-/spell/aoe_turf/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- for(var/turf/target in view_or_range(range,user,selection_type))
- if(!(target in view_or_range(inner_radius,user,selection_type)))
- if(target.density && (spell_flags & IGNOREDENSE))
- continue
- if(istype(target, /turf/space) && (spell_flags & IGNORESPACE))
- continue
- targets += target
-
- if(!targets.len) //doesn't waste the spell
- return
-
+/*
+Aoe turf spells target a ring of tiles around the user
+This ring has an outer radius (range) and an inner radius (inner_radius)
+Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm
+*/
+
+/spell/aoe_turf //affects all turfs in view or range (depends)
+ spell_flags = IGNOREDENSE
+ var/inner_radius = -1 //for all your ring spell needs
+
+/spell/aoe_turf/choose_targets(mob/user = usr)
+ var/list/targets = list()
+
+ for(var/turf/target in view_or_range(range, holder, selection_type))
+ if(!(target in view_or_range(inner_radius, holder, selection_type)))
+ if(target.density && (spell_flags & IGNOREDENSE))
+ continue
+ if(istype(target, /turf/space) && (spell_flags & IGNORESPACE))
+ continue
+ targets += target
+
+ if(!targets.len) //doesn't waste the spell
+ return
+
return targets
\ No newline at end of file
diff --git a/code/modules/spells/spell_code.dm b/code/modules/spells/spell_code.dm
index ba631391b4..2015fde1e0 100644
--- a/code/modules/spells/spell_code.dm
+++ b/code/modules/spells/spell_code.dm
@@ -1,9 +1,9 @@
var/list/spells = typesof(/spell) //needed for the badmin verb for now
/spell
- name = "Spell"
- desc = "A spell"
- parent_type = /atom/movable
+ var/name = "Spell"
+ var/desc = "A spell"
+ parent_type = /datum
var/panel = "Spells"//What panel the proc holder needs to go on.
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?
@@ -25,8 +25,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
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/atom/movable/holder //where the spell is. Normally the user, can be a projectile
-
+ var/atom/movable/holder //where the spell is. Normally the user, can be an item
var/duration = 0 //how long the spell lasts
var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values
@@ -53,6 +52,8 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
var/hud_state = "" //name of the icon used in generating the spell hud object
var/override_base = ""
+ var/obj/screen/connected_button
+
///////////////////////
///SETUP AND PROCESS///
///////////////////////
@@ -69,11 +70,6 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
sleep(1)
return
-/spell/Click()
- ..()
-
- perform(usr)
-
/////////////////
/////CASTING/////
/////////////////
@@ -182,18 +178,18 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
- if(!(src in user.spell_list))
+ if(!(src in user.spell_list) && holder == user)
user << "You shouldn't have this spell! Something's wrong."
return 0
if(silenced > 0)
return
- var/turf/Turf = get_turf(user)
- if(!Turf)
- user << "You cannot cast spells in null space!"
-
- if(spell_flags & Z2NOCAST && (Turf.z in config.admin_levels)) //Certain spells are not allowed on the centcomm zlevel
+ var/turf/user_turf = get_turf(user)
+ if(!user_turf)
+ user << "You cannot cast spells in null space!"
+
+ if(spell_flags & Z2NOCAST && (user_turf.z in config.admin_levels)) //Certain spells are not allowed on the centcomm zlevel
return 0
if(spell_flags & CONSTRUCT_CHECK)
@@ -201,7 +197,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
if(findNullRod(T))
return 0
- if(istype(user, /mob/living/simple_animal))
+ if(istype(user, /mob/living/simple_animal) && holder == user)
var/mob/living/simple_animal/SA = user
if(SA.purge)
SA << "The nullrod's power interferes with your own!"
@@ -210,7 +206,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone
return 0
- if(!(spell_flags & GHOSTCAST))
+ if(!(spell_flags & GHOSTCAST) && holder == user)
if(user.stat && !(spell_flags & STATALLOWED))
usr << "Not when you're incapacitated."
return 0
@@ -221,7 +217,7 @@ var/list/spells = typesof(/spell) //needed for the badmin verb for now
return 0
var/spell/noclothes/spell = locate() in user.spell_list
- if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)))//clothes check
+ if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)) && holder == user)//clothes check
if(!user.wearing_wiz_garb())
return 0
diff --git a/code/modules/spells/spellbook.dm b/code/modules/spells/spellbook.dm
index 7823a7b602..6ddaf6331a 100644
--- a/code/modules/spells/spellbook.dm
+++ b/code/modules/spells/spellbook.dm
@@ -211,7 +211,7 @@
temp = "You have learned knock."
if("horseman")
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
- H.add_spell(new/spell/targeted/horsemask)
+ H.add_spell(new/spell/targeted/equip_item/horsemask)
temp = "You have learned curse of the horseman."
if("fleshtostone")
feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
@@ -424,7 +424,7 @@
user.Weaken(20)
/obj/item/weapon/spellbook/oneuse/horsemask
- spell = /spell/targeted/horsemask
+ spell = /spell/targeted/equip_item/horsemask
spellname = "horses"
icon_state ="bookhorses"
desc = "This book is more horse than your mind has room for."
diff --git a/code/modules/spells/spells.dm b/code/modules/spells/spells.dm
index d20eea00dc..2e7ee7b815 100644
--- a/code/modules/spells/spells.dm
+++ b/code/modules/spells/spells.dm
@@ -4,17 +4,26 @@
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
spell_master.update_spells(0, src)
-/mob/Stat()
+/mob/Login()
..()
- if(spell_list && spell_list.len && statpanel("Spells"))
+ if(spell_masters)
+ for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
+ spell_master.toggle_open(1)
+ client.screen -= spell_master
+
+/mob/Stat()
+ . = ..()
+ if(. && spell_list && spell_list.len)
for(var/spell/S in spell_list)
+ if((!S.connected_button) || !statpanel(S.panel))
+ continue //Not showing the noclothes spell
switch(S.charge_type)
if(Sp_RECHARGE)
- statpanel("Spells","[S.charge_counter/10.0]/[S.charge_max/10]",S)
+ statpanel(S.panel,"[S.charge_counter/10.0]/[S.charge_max/10]",S.connected_button)
if(Sp_CHARGES)
- statpanel("Spells","[S.charge_counter]/[S.charge_max]",S)
+ statpanel(S.panel,"[S.charge_counter]/[S.charge_max]",S.connected_button)
if(Sp_HOLDVAR)
- statpanel("Spells","[S.holder_var_type] [S.holder_var_amount]",S)
+ statpanel(S.panel,"[S.holder_var_type] [S.holder_var_amount]",S.connected_button)
/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready", var/master_type = /obj/screen/movable/spell_master)
if(!spell_masters)
diff --git a/code/modules/spells/targeted/equip/equip.dm b/code/modules/spells/targeted/equip/equip.dm
new file mode 100644
index 0000000000..735daf78e8
--- /dev/null
+++ b/code/modules/spells/targeted/equip/equip.dm
@@ -0,0 +1,40 @@
+//You can set duration to 0 to have the items last forever
+
+/spell/targeted/equip_item
+ name = "equipment spell"
+
+ var/list/equipped_summons = list() //assoc list of text ids and paths to spawn
+
+ var/list/summoned_items = list() //list of items we summoned and will dispose when the spell runs out
+
+ var/delete_old = 1 //if the item previously in the slot is deleted - otherwise, it's dropped
+
+/spell/targeted/equip_item/cast(list/targets, mob/user = usr)
+ ..()
+ for(var/mob/living/L in targets)
+ for(var/slot_id in equipped_summons)
+ var/to_create = equipped_summons[slot_id]
+ slot_id = text2num(slot_id) //because the index is text, we access this instead
+ var/obj/item/new_item = summon_item(to_create)
+ var/obj/item/old_item = L.get_equipped_item(slot_id)
+ L.equip_to_slot(new_item, slot_id)
+ if(old_item)
+ L.remove_from_mob(old_item)
+ if(delete_old)
+ qdel(old_item)
+ else
+ old_item.loc = L.loc
+
+ if(duration)
+ summoned_items += new_item //we store it in a list to remove later
+
+ if(duration)
+ spawn(duration)
+ for(var/obj/item/to_remove in summoned_items)
+ if(istype(to_remove.loc, /mob))
+ var/mob/M = to_remove.loc
+ M.remove_from_mob(to_remove)
+ qdel(to_remove)
+
+/spell/targeted/equip_item/proc/summon_item(var/newtype)
+ return new newtype
diff --git a/code/modules/spells/targeted/horsemask.dm b/code/modules/spells/targeted/equip/horsemask.dm
similarity index 66%
rename from code/modules/spells/targeted/horsemask.dm
rename to code/modules/spells/targeted/equip/horsemask.dm
index dad2032b72..b5fbcf4fbb 100644
--- a/code/modules/spells/targeted/horsemask.dm
+++ b/code/modules/spells/targeted/equip/horsemask.dm
@@ -1,35 +1,38 @@
-/spell/targeted/horsemask
- name = "Curse of the Horseman"
- desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
- school = "transmutation"
- charge_type = Sp_RECHARGE
- charge_max = 150
- charge_counter = 0
- spell_flags = 0
- invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
- invocation_type = SpI_SHOUT
- range = 7
- max_targets = 1
- cooldown_min = 30 //30 deciseconds reduction per rank
- selection_type = "range"
-
- compatible_mobs = list(/mob/living/carbon/human)
-
- hud_state = "wiz_horse"
-
-/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
- ..()
- for(var/mob/living/target in targets)
- var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
- magichead.canremove = 0 //curses!
- magichead.flags_inv = null //so you can still see their face
- magichead.voicechange = 1 //NEEEEIIGHH
- target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \
- "Your face burns up, and shortly after the fire you realise you have the face of a horse!")
- var/obj/old_mask = target.wear_mask
- if(old_mask)
- target.drop_from_inventory(old_mask)
- qdel(old_mask) //get rid of this shit
- target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
-
- flick("e_flash", target.flash)
\ No newline at end of file
+/spell/targeted/equip_item/horsemask
+ name = "Curse of the Horseman"
+ desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
+ school = "transmutation"
+ charge_type = Sp_RECHARGE
+ charge_max = 150
+ charge_counter = 0
+ spell_flags = 0
+ invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
+ invocation_type = SpI_SHOUT
+ range = 7
+ max_targets = 1
+ cooldown_min = 30 //30 deciseconds reduction per rank
+ selection_type = "range"
+
+ compatible_mobs = list(/mob/living/carbon/human)
+
+ hud_state = "wiz_horse"
+
+/spell/targeted/equip_item/horsemask/New()
+ ..()
+ equipped_summons = list("[slot_wear_mask]" = /obj/item/clothing/mask/horsehead)
+
+/spell/targeted/equip_item/horsemask/cast(list/targets, mob/user = usr)
+ ..()
+ for(var/mob/living/target in targets)
+ target.visible_message( "[target]'s face lights up in fire, and after the event a horse's head takes its place!", \
+ "Your face burns up, and shortly after the fire you realise you have the face of a horse!")
+ flick("e_flash", target.flash)
+
+/spell/targeted/equip_item/horsemask/summon_item(var/new_type)
+ var/obj/item/new_item = new new_type
+ if(istype(new_item, /obj/item/clothing/mask/horsehead))
+ var/obj/item/clothing/mask/horsehead/magichead = new_item
+ magichead.canremove = 0 //curses!
+ magichead.flags_inv = null //so you can still see their face
+ magichead.voicechange = 1 //NEEEEIIGHH
+ return new_item
diff --git a/code/modules/spells/targeted/genetic.dm b/code/modules/spells/targeted/genetic.dm
index 028cdafba0..045fbc7d41 100644
--- a/code/modules/spells/targeted/genetic.dm
+++ b/code/modules/spells/targeted/genetic.dm
@@ -57,7 +57,7 @@ code\game\dna\genes\goon_powers.dm
spell_flags = Z2NOCAST | NEEDSCLOTHES | INCLUDEUSER
invocation = "BIRUZ BENNAR"
invocation_type = SpI_SHOUT
- message = "\blue You feel strong! You feel a pressure building behind your eyes!"
+ message = "You feel strong! You feel a pressure building behind your eyes!"
range = 0
max_targets = 1
diff --git a/code/modules/spells/targeted/mind_transfer.dm b/code/modules/spells/targeted/mind_transfer.dm
index 2e1860da35..a3668a53d1 100644
--- a/code/modules/spells/targeted/mind_transfer.dm
+++ b/code/modules/spells/targeted/mind_transfer.dm
@@ -51,7 +51,10 @@
ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob.
caster.mind.transfer_to(victim)
- victim.spell_list = caster.spell_list//Now they are inside the victim's body.
+ victim.spell_list = list() //clear those out
+ for(var/spell/S in caster.spell_list)
+ victim.add_spell(S) //Now they are inside the victim's body - this also generates the HUD
+ caster.spell_list = list() //clean that out as well
if(victim.mind.special_verbs.len)//To add all the special verbs for the original caster.
for(var/V in caster.mind.special_verbs)//Not too important but could come into play.
@@ -59,7 +62,9 @@
ghost.mind.transfer_to(caster)
caster.key = ghost.key //have to transfer the key since the mind was not active
- caster.spell_list = ghost.spell_list
+ for(var/spell/S in ghost.spell_list)
+ caster.add_spell(S)
+ ghost.spell_list = list()
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
for(var/V in caster.mind.special_verbs)
@@ -71,4 +76,4 @@
//After a certain amount of time the victim gets a message about being in a different body.
spawn(msg_wait)
- caster << "\red You feel woozy and lightheaded. Your body doesn't seem like your own."
+ caster << "You feel woozy and lightheaded. Your body doesn't seem like your own."
diff --git a/code/modules/spells/targeted/targeted.dm b/code/modules/spells/targeted/targeted.dm
index 96bbab9905..498d363408 100644
--- a/code/modules/spells/targeted/targeted.dm
+++ b/code/modules/spells/targeted/targeted.dm
@@ -1,145 +1,145 @@
-/*
-Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
-Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
-*/
-
-
-/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, 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/amt_weakened = 0
- var/amt_paralysis = 0
- var/amt_stunned = 0
-
- var/amt_dizziness = 0
- var/amt_confused = 0
- var/amt_stuttering = 0
-
- //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/amt_eye_blind = 0
- var/amt_eye_blurry = 0
-
- var/list/compatible_mobs = list()
-
-
-/spell/targeted/choose_targets(mob/user = usr)
- var/list/targets = list()
-
- if(max_targets == 0) //unlimited
- if(range == -2)
- targets = living_mob_list
- else
- for(var/mob/living/target in view_or_range(range, user, selection_type))
- targets += target
-
- else if(max_targets == 1) //single target can be picked
- if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
- targets += user
- else
- var/list/possible_targets = list()
- var/list/starting_targets
- if(range == -2)
- starting_targets = living_mob_list
- else
- starting_targets = view_or_range(range, user, selection_type)
-
- for(var/mob/living/M in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && M == user)
- continue
- if(compatible_mobs && compatible_mobs.len)
- if(!is_type_in_list(M, compatible_mobs)) continue
- if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
- continue
- possible_targets += M
-
- if(possible_targets.len)
- if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details
- var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
- if(temp_target)
- targets += temp_target
- else
- targets += pick(possible_targets)
- //Adds a safety check post-input to make sure those targets are actually in range.
-
-
- else
- var/list/possible_targets = list()
- var/list/starting_targets
-
- if(range == -2)
- starting_targets = living_mob_list
- else
- starting_targets = view_or_range(range, user, selection_type)
-
- for(var/mob/living/target in starting_targets)
- if(!(spell_flags & INCLUDEUSER) && target == user)
- continue
- if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
- continue
- possible_targets += target
-
- if(spell_flags & SELECTABLE)
- for(var/i = 1; i<=max_targets, i++)
- if(!possible_targets.len)
- break
- var/mob/M = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
- if(!M)
- break
- if(range != -2)
- if(!(M in view_or_range(range, user, selection_type)))
- continue
- targets += M
- possible_targets -= M
- else
- 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(!(spell_flags & INCLUDEUSER) && (user in targets))
- targets -= user
-
- if(compatible_mobs && compatible_mobs.len)
- for(var/mob/living/target in targets) //filters out all the non-compatible mobs
- if(!is_type_in_list(target, compatible_mobs))
- targets -= target
-
- return targets
-
-/spell/targeted/cast(var/list/targets, mob/user)
- for(var/mob/living/target in targets)
- if(range >= 0)
- if(!(target in view_or_range(range, user, selection_type))) //filter at time of casting
- targets -= target
- continue
- apply_spell_damage(target)
-
-/spell/targeted/proc/apply_spell_damage(mob/living/target)
- target.adjustBruteLoss(amt_dam_brute)
- target.adjustFireLoss(amt_dam_fire)
- target.adjustToxLoss(amt_dam_tox)
- target.adjustOxyLoss(amt_dam_oxy)
- //disabling
- target.Weaken(amt_weakened)
- target.Paralyse(amt_paralysis)
- target.Stun(amt_stunned)
- if(amt_weakened || amt_paralysis || amt_stunned)
- if(target.buckled)
- target.buckled = null
- target.eye_blind += amt_eye_blind
- target.eye_blurry += amt_eye_blurry
- target.dizziness += amt_dizziness
- target.confused += amt_confused
+/*
+Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
+Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
+*/
+
+
+/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, 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/amt_weakened = 0
+ var/amt_paralysis = 0
+ var/amt_stunned = 0
+
+ var/amt_dizziness = 0
+ var/amt_confused = 0
+ var/amt_stuttering = 0
+
+ //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/amt_eye_blind = 0
+ var/amt_eye_blurry = 0
+
+ var/list/compatible_mobs = list()
+
+
+/spell/targeted/choose_targets(mob/user = usr)
+ var/list/targets = list()
+
+ if(max_targets == 0) //unlimited
+ if(range == -2)
+ targets = living_mob_list
+ else
+ for(var/mob/living/target in view_or_range(range, holder, selection_type))
+ targets += target
+
+ else if(max_targets == 1) //single target can be picked
+ if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
+ targets += user
+ else
+ var/list/possible_targets = list()
+ var/list/starting_targets
+ if(range == -2)
+ starting_targets = living_mob_list
+ else
+ starting_targets = view_or_range(range, holder, selection_type)
+
+ for(var/mob/living/M in starting_targets)
+ if(!(spell_flags & INCLUDEUSER) && M == user)
+ continue
+ if(compatible_mobs && compatible_mobs.len)
+ if(!is_type_in_list(M, compatible_mobs)) continue
+ if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
+ continue
+ possible_targets += M
+
+ if(possible_targets.len)
+ if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details
+ var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
+ if(temp_target)
+ targets += temp_target
+ else
+ targets += pick(possible_targets)
+ //Adds a safety check post-input to make sure those targets are actually in range.
+
+
+ else
+ var/list/possible_targets = list()
+ var/list/starting_targets
+
+ if(range == -2)
+ starting_targets = living_mob_list
+ else
+ starting_targets = view_or_range(range, holder, selection_type)
+
+ for(var/mob/living/target in starting_targets)
+ if(!(spell_flags & INCLUDEUSER) && target == user)
+ continue
+ if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
+ continue
+ possible_targets += target
+
+ if(spell_flags & SELECTABLE)
+ for(var/i = 1; i<=max_targets, i++)
+ if(!possible_targets.len)
+ break
+ var/mob/M = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
+ if(!M)
+ break
+ if(range != -2)
+ if(!(M in view_or_range(range, holder, selection_type)))
+ continue
+ targets += M
+ possible_targets -= M
+ else
+ 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(!(spell_flags & INCLUDEUSER) && (user in targets))
+ targets -= user
+
+ if(compatible_mobs && compatible_mobs.len)
+ for(var/mob/living/target in targets) //filters out all the non-compatible mobs
+ if(!is_type_in_list(target, compatible_mobs))
+ targets -= target
+
+ return targets
+
+/spell/targeted/cast(var/list/targets, mob/user)
+ for(var/mob/living/target in targets)
+ if(range >= 0)
+ if(!(target in view_or_range(range, holder, selection_type))) //filter at time of casting
+ targets -= target
+ continue
+ apply_spell_damage(target)
+
+/spell/targeted/proc/apply_spell_damage(mob/living/target)
+ target.adjustBruteLoss(amt_dam_brute)
+ target.adjustFireLoss(amt_dam_fire)
+ target.adjustToxLoss(amt_dam_tox)
+ target.adjustOxyLoss(amt_dam_oxy)
+ //disabling
+ target.Weaken(amt_weakened)
+ target.Paralyse(amt_paralysis)
+ target.Stun(amt_stunned)
+ if(amt_weakened || amt_paralysis || amt_stunned)
+ if(target.buckled)
+ target.buckled = null
+ target.eye_blind += amt_eye_blind
+ target.eye_blurry += amt_eye_blurry
+ target.dizziness += amt_dizziness
+ target.confused += amt_confused
target.stuttering += amt_stuttering
\ No newline at end of file