initial commit - cross reference with 5th port - obviously has compile errors

This commit is contained in:
LetterJay
2016-07-03 02:17:19 -05:00
commit 35a1723e98
4355 changed files with 2221257 additions and 0 deletions
+436
View File
@@ -0,0 +1,436 @@
#define TARGET_CLOSEST 1
#define TARGET_RANDOM 2
/obj/effect/proc_holder
var/panel = "Debug"//What panel the proc holder needs to go on.
var/list/spells = typesof(/obj/effect/proc_holder/spell) //needed for the badmin verb for now
/obj/effect/proc_holder/proc/InterceptClickOn(mob/user, params, atom/A)
return
/obj/effect/proc_holder/spell
name = "Spell"
desc = "A wizard spell"
panel = "Spells"
var/sound = null //The sound the spell makes when it is cast
anchored = 1 // Crap like fireball projectiles are proc_holders, this is needed so fireballs don't get blown back into your face via atmos etc.
pass_flags = PASSTABLE
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; can also be based on the holder's vars now, use "holder_var" for that
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/still_recharging_msg = "<span class='notice'>The spell is still recharging.</span>"
var/holder_var_type = "bruteloss" //only used if charge_type equals to "holder_var"
var/holder_var_amount = 20 //same. The amount adjusted with the mob's var when the spell is used
var/clothes_req = 1 //see if it requires clothes
var/cult_req = 0 //SPECIAL SNOWFLAKE clothes required for cult only spells
var/human_req = 0 //spell can only be cast by humans
var/nonabstract_req = 0 //spell can only be cast by mobs that are physical entities
var/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
var/phase_allowed = 0 // If true, the spell can be cast while phased, eg. blood crawling, ethereal jaunting
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
var/invocation_emote_self = null
var/invocation_type = "none" //can be none, whisper, emote and shout
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/spell_level = 0 //if a spell can be taken multiple times, this raises
var/level_max = 4 //The max possible level_max is 4
var/cooldown_min = 0 //This defines what spell quickened four times has as a cooldown. Make sure to set this for every spell
var/player_lock = 1 //If it can be used by simple mobs
var/overlay = 0
var/overlay_icon = 'icons/obj/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
var/critfailchance = 0
var/centcom_cancast = 1 //Whether or not the spell should be allowed on z2
var/datum/action/spell_action/action = null
var/action_icon = 'icons/mob/actions.dmi'
var/action_icon_state = "spell_default"
var/action_background_icon_state = "bg_spell"
/obj/effect/proc_holder/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(player_lock)
if(!user.mind || !(src in user.mind.spell_list) && !(src in user.mob_spell_list))
user << "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>"
return 0
else
if(!(src in user.mob_spell_list))
return 0
var/turf/T = get_turf(user)
if(T.z == ZLEVEL_CENTCOM && (!centcom_cancast || ticker.mode.name == "ragin' mages")) //Certain spells are not allowed on the centcom zlevel
user << "<span class='notice'>You can't cast this spell here.</span>"
return 0
if(!skipcharge)
switch(charge_type)
if("recharge")
if(charge_counter < charge_max)
user << still_recharging_msg
return 0
if("charges")
if(!charge_counter)
user << "<span class='notice'>[name] has no charges left.</span>"
return 0
if(user.stat && !stat_allowed)
user << "<span class='notice'>Not when you're incapacitated.</span>"
return 0
if(!phase_allowed && istype(user.loc, /obj/effect/dummy))
user << "<span class='notice'>[name] cannot be cast unless you are completely manifested in the material plane.</span>"
return 0
if(ishuman(user))
var/mob/living/carbon/human/H = user
if((invocation_type == "whisper" || invocation_type == "shout") && H.is_muzzled())
user << "<span class='notice'>You can't get the words out!</span>"
return 0
if(clothes_req) //clothes check
if(!istype(H.wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/wizard))
H << "<span class='notice'>I don't feel strong enough without my robe.</span>"
return 0
if(!istype(H.shoes, /obj/item/clothing/shoes/sandal))
H << "<span class='notice'>I don't feel strong enough without my sandals.</span>"
return 0
if(!istype(H.head, /obj/item/clothing/head/wizard) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/wizard))
H << "<span class='notice'>I don't feel strong enough without my hat.</span>"
return 0
if(cult_req) //CULT_REQ CLOTHES CHECK
if(!istype(H.wear_suit, /obj/item/clothing/suit/magusred) && !istype(H.wear_suit, /obj/item/clothing/suit/space/hardsuit/cult))
H << "<span class='notice'>I don't feel strong enough without my armor.</span>"
return 0
if(!istype(H.head, /obj/item/clothing/head/magus) && !istype(H.head, /obj/item/clothing/head/helmet/space/hardsuit/cult))
H << "<span class='notice'>I don't feel strong enough without my helmet.</span>"
return 0
else
if(clothes_req || human_req)
user << "<span class='notice'>This spell can only be cast by humans!</span>"
return 0
if(nonabstract_req && (isbrain(user) || ispAI(user)))
user << "<span class='notice'>This spell can only be cast by physical beings!</span>"
return 0
if(!skipcharge)
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
if("holdervar")
adjust_var(user, holder_var_type, holder_var_amount)
return 1
/obj/effect/proc_holder/spell/proc/invocation(mob/user = usr) //spelling the spell out and setting it on recharge/reducing charges amount
switch(invocation_type)
if("shout")
if(prob(50))//Auto-mute? Fuck that noise
user.say(invocation)
else
user.say(replacetext(invocation," ","`"))
if("whisper")
if(prob(50))
user.whisper(invocation)
else
user.whisper(replacetext(invocation," ","`"))
if("emote")
user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm
/obj/effect/proc_holder/spell/proc/playMagSound()
playsound(get_turf(usr), sound,50,1)
/obj/effect/proc_holder/spell/New()
..()
action = new(src)
still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
charge_counter = charge_max
/obj/effect/proc_holder/spell/Destroy()
qdel(action)
return ..()
/obj/effect/proc_holder/spell/Click()
if(cast_check())
choose_targets()
return 1
/obj/effect/proc_holder/spell/proc/choose_targets(mob/user = usr) //depends on subtype - /targeted or /aoe_turf
return
/obj/effect/proc_holder/spell/proc/start_recharge()
if(action)
action.UpdateButtonIcon()
while(charge_counter < charge_max && !qdeleted(src))
sleep(1)
charge_counter++
if(action)
action.UpdateButtonIcon()
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1, mob/user = usr) //if recharge is started is important for the trigger spells
before_cast(targets)
invocation(user)
if(user && user.ckey)
user.attack_log += text("\[[time_stamp()]\] <span class='danger'>[user.real_name] ([user.ckey]) cast the spell [name].</span>")
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
if(sound)
playMagSound()
if(prob(critfailchance))
critfail(targets)
else
cast(targets,user=user)
after_cast(targets)
/obj/effect/proc_holder/spell/proc/before_cast(list/targets)
if(overlay)
for(var/atom/target in targets)
var/location
if(istype(target,/mob/living))
location = target.loc
else if(istype(target,/turf))
location = target
var/obj/effect/overlay/spell = new /obj/effect/overlay(location)
spell.icon = overlay_icon
spell.icon_state = overlay_icon_state
spell.anchored = 1
spell.density = 0
QDEL_IN(spell, overlay_lifespan)
/obj/effect/proc_holder/spell/proc/after_cast(list/targets)
for(var/atom/target in targets)
var/location
if(istype(target,/mob/living))
location = target.loc
else if(istype(target,/turf))
location = target
if(istype(target,/mob/living) && message)
target << text("[message]")
if(sparks_spread)
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is
sparks.start()
if(smoke_spread)
if(smoke_spread == 1)
var/datum/effect_system/smoke_spread/smoke = new
smoke.set_up(smoke_amt, location)
smoke.start()
else if(smoke_spread == 2)
var/datum/effect_system/smoke_spread/bad/smoke = new
smoke.set_up(smoke_amt, location)
smoke.start()
else if(smoke_spread == 3)
var/datum/effect_system/smoke_spread/sleeping/smoke = new
smoke.set_up(smoke_amt, location)
smoke.start()
/obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr)
return
/obj/effect/proc_holder/spell/proc/critfail(list/targets)
return
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
switch(charge_type)
if("recharge")
charge_counter = charge_max
if("charges")
charge_counter++
if("holdervar")
adjust_var(user, holder_var_type, -holder_var_amount)
/obj/effect/proc_holder/spell/proc/adjust_var(mob/living/target = usr, type, amount) //handles the adjustment of the var when the spell is used. has some hardcoded types
switch(type)
if("bruteloss")
target.adjustBruteLoss(amount)
if("fireloss")
target.adjustFireLoss(amount)
if("toxloss")
target.adjustToxLoss(amount)
if("oxyloss")
target.adjustOxyLoss(amount)
if("stunned")
target.AdjustStunned(amount)
if("weakened")
target.AdjustWeakened(amount)
if("paralysis")
target.AdjustParalysis(amount)
else
target.vars[type] += amount //I bear no responsibility for the runtimes that'll happen if you try to adjust non-numeric or even non-existant vars
/obj/effect/proc_holder/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_user = 0 //if it includes usr in the target list
var/random_target = 0 // chooses random viable target instead of asking the caster
var/random_target_priority = TARGET_CLOSEST // if random_target is enabled how it will pick the target
/obj/effect/proc_holder/spell/aoe_turf //affects all turfs in view or range (depends)
var/inner_radius = -1 //for all your ring spell needs
/obj/effect/proc_holder/spell/targeted/choose_targets(mob/user = usr)
var/list/targets = list()
switch(max_targets)
if(0) //unlimited
for(var/mob/living/target in view_or_range(range, user, selection_type))
targets += target
if(1) //single target can be picked
if(range < 0)
targets += user
else
var/possible_targets = list()
for(var/mob/living/M in view_or_range(range, user, selection_type))
if(!include_user && user == M)
continue
possible_targets += M
//targets += input("Choose the target for the spell.", "Targeting") as mob in possible_targets
//Adds a safety check post-input to make sure those targets are actually in range.
var/mob/M
if(!random_target)
M = input("Choose the target for the spell.", "Targeting") as null|mob in possible_targets
else
switch(random_target_priority)
if(TARGET_RANDOM)
M = pick(possible_targets)
if(TARGET_CLOSEST)
for(var/mob/living/L in possible_targets)
if(M)
if(get_dist(user,L) < get_dist(user,M))
if(los_check(user,L))
M = L
else
if(los_check(user,L))
M = L
if(M in view_or_range(range, user, selection_type)) targets += M
else
var/list/possible_targets = list()
for(var/mob/living/target in view_or_range(range, user, selection_type))
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_user && (user in targets))
targets -= user
if(!targets.len) //doesn't waste the spell
revert_cast(user)
return
perform(targets,user=user)
/obj/effect/proc_holder/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)))
targets += target
if(!targets.len) //doesn't waste the spell
revert_cast()
return
perform(targets,user=user)
/obj/effect/proc_holder/spell/proc/can_be_cast_by(mob/caster)
if((human_req || clothes_req) && !ishuman(caster))
return 0
return 1
/obj/effect/proc_holder/spell/targeted/proc/los_check(mob/A,mob/B)
//Checks for obstacles from A to B
var/obj/dummy = new(A.loc)
dummy.pass_flags |= PASSTABLE
for(var/turf/turf in getline(A,B))
for(var/atom/movable/AM in turf)
if(!AM.CanPass(dummy,turf,1))
qdel(dummy)
return 0
qdel(dummy)
return 1
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr)
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
return 0
switch(charge_type)
if("recharge")
if(charge_counter < charge_max)
return 0
if("charges")
if(!charge_counter)
return 0
if(user.stat && !stat_allowed)
return 0
if(!ishuman(user))
if(clothes_req || human_req)
return 0
if(nonabstract_req && (isbrain(user) || ispAI(user)))
return 0
return 1
/obj/effect/proc_holder/spell/self //Targets only the caster. Good for buffs and heals, but probably not wise for fireballs (although they usually fireball themselves anyway, honke)
range = -1 //Duh
/obj/effect/proc_holder/spell/self/choose_targets(mob/user = usr)
if(!user)
revert_cast()
return
perform(null,user=user)
/obj/effect/proc_holder/spell/self/basic_heal //This spell exists mainly for debugging purposes, and also to show how casting works
name = "Lesser Heal"
desc = "Heals a small amount of brute and burn damage."
human_req = 1
clothes_req = 0
charge_max = 100
cooldown_min = 50
invocation = "Victus sano!"
invocation_type = "whisper"
school = "restoration"
sound = 'sound/magic/Staff_Healing.ogg'
/obj/effect/proc_holder/spell/self/basic_heal/cast(mob/living/carbon/human/user) //Note the lack of "list/targets" here. Instead, use a "user" var depending on mob requirements.
//Also, notice the lack of a "for()" statement that looks through the targets. This is, again, because the spell can only have a single target.
user.visible_message("<span class='warning'>A wreath of gentle light passes over [user]!</span>", "<span class='notice'>You wreath yourself in healing light!</span>")
user.adjustBruteLoss(-10)
user.adjustFireLoss(-10)
@@ -0,0 +1,89 @@
/obj/effect/proc_holder/spell/targeted/area_teleport
name = "Area teleport"
desc = "This spell teleports you to a type of area of your selection."
nonabstract_req = 1
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
var/sound1 = "sound/weapons/ZapBang.ogg"
var/sound2 = "sound/weapons/ZapBang.ogg"
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1,mob/living/user = usr)
var/thearea = before_cast(targets)
if(!thearea || !cast_check(1))
revert_cast()
return
invocation(thearea,user)
spawn(0)
if(charge_type == "recharge" && recharge)
start_recharge()
cast(targets,thearea,user)
after_cast(targets)
/obj/effect/proc_holder/spell/targeted/area_teleport/before_cast(list/targets)
var/A = null
if(!randomise_selection)
A = input("Area to teleport to", "Teleport", A) as null|anything in teleportlocs
else
A = pick(teleportlocs)
if(!A)
return
var/area/thearea = teleportlocs[A]
return thearea
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea,mob/user = usr)
playsound(get_turf(user), sound1, 50,1)
for(var/mob/living/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
if(!L.len)
usr <<"The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry."
return
if(target && target.buckled)
target.buckled.unbuckle_mob(target, force=1)
var/list/tempL = L
var/attempt = null
var/success = 0
while(tempL.len)
attempt = pick(tempL)
target.Move(attempt)
if(get_turf(target) == attempt)
success = 1
break
else
tempL.Remove(attempt)
if(!success)
target.loc = pick(L)
playsound(get_turf(user), sound2, 50,1)
return
/obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null,mob/user = usr)
if(!invocation_area || !chosenarea)
..()
else
switch(invocation_type)
if("shout")
user.say("[invocation] [uppertext(chosenarea.name)]")
if(user.gender==MALE)
playsound(user.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
else
playsound(user.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
if("whisper")
user.whisper("[invocation] [uppertext(chosenarea.name)]")
return
@@ -0,0 +1,50 @@
/obj/effect/proc_holder/spell/targeted/barnyardcurse
name = "Curse of the Barnyard"
desc = "This spell dooms the fate of any unlucky soul to the speech and facial attributes of a barnyard animal"
school = "transmutation"
charge_type = "recharge"
charge_max = 150
charge_counter = 0
clothes_req = 0
stat_allowed = 0
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
invocation_type = "shout"
range = 7
cooldown_min = 30
selection_type = "range"
var/list/compatible_mobs = list(/mob/living/carbon/human,/mob/living/carbon/monkey)
action_icon_state = "barn"
/obj/effect/proc_holder/spell/targeted/barnyardcurse/cast(list/targets, mob/user = usr)
if(!targets.len)
user << "<span class='notice'>No target found in range.</span>"
return
var/mob/living/carbon/target = targets[1]
if(!(target.type in compatible_mobs))
user << "<span class='notice'>You are unable to curse [target]'s head!</span>"
return
if(!(target in oview(range)))
user << "<span class='notice'>They are too far away!</span>"
return
var/list/masks = list(/obj/item/clothing/mask/spig, /obj/item/clothing/mask/cowmask, /obj/item/clothing/mask/horsehead)
var/list/mSounds = list("sound/magic/PigHead_curse.ogg", "sound/magic/CowHead_Curse.ogg", "sound/magic/HorseHead_curse.ogg")
var/randM = rand(1,3)
var/choice = masks[randM]
var/obj/item/clothing/mask/magichead = new choice
magichead.flags |=NODROP
magichead.flags_inv = null
target.visible_message("<span class='danger'>[target]'s face lights up in fire, and after the event a barnyard animal's head takes it's place!</span>", \
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a barnyard animal!</span>")
if(!target.unEquip(target.wear_mask))
qdel(target.wear_mask)
target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
playsound(get_turf(target), mSounds[randM], 50, 1)
target.flash_eyes()
@@ -0,0 +1,35 @@
/obj/effect/proc_holder/spell/bloodcrawl
name = "Blood Crawl"
desc = "Use pools of blood to phase out of existence."
charge_max = 0
clothes_req = 0
//If you couldn't cast this while phased, you'd have a problem
phase_allowed = 1
selection_type = "range"
range = 1
cooldown_min = 0
overlay = null
action_icon_state = "bloodcrawl"
action_background_icon_state = "bg_demon"
var/phased = 0
/obj/effect/proc_holder/spell/bloodcrawl/choose_targets(mob/user = usr)
for(var/obj/effect/decal/cleanable/target in range(range, get_turf(user)))
if(target.can_bloodcrawl_in())
perform(target)
return
revert_cast()
user << "<span class='warning'>There must be a nearby source of blood!</span>"
/obj/effect/proc_holder/spell/bloodcrawl/perform(obj/effect/decal/cleanable/target, recharge = 1, mob/living/user = usr)
if(istype(user))
if(phased)
if(user.phasein(target))
phased = 0
else
if(user.phaseout(target))
phased = 1
start_recharge()
return
revert_cast()
user << "<span class='warning'>You are unable to blood crawl!</span>"
+93
View File
@@ -0,0 +1,93 @@
/obj/effect/proc_holder/spell/targeted/charge
name = "Charge"
desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user."
school = "transmutation"
charge_max = 600
clothes_req = 0
invocation = "DIRI CEL"
invocation_type = "whisper"
range = -1
cooldown_min = 400 //50 deciseconds reduction per rank
include_user = 1
/obj/effect/proc_holder/spell/targeted/charge/cast(list/targets,mob/user = usr)
for(var/mob/living/L in targets)
var/list/hand_items = list(L.get_active_hand(),L.get_inactive_hand())
var/charged_item = null
var/burnt_out = 0
if(L.pulling && (istype(L.pulling, /mob/living)))
var/mob/living/M = L.pulling
if(M.mob_spell_list.len != 0 || (M.mind && M.mind.spell_list.len != 0))
for(var/obj/effect/proc_holder/spell/S in M.mob_spell_list)
S.charge_counter = S.charge_max
if(M.mind)
for(var/obj/effect/proc_holder/spell/S in M.mind.spell_list)
S.charge_counter = S.charge_max
M <<"<span class='notice'>you feel raw magic flowing through you, it feels good!</span>"
else
M <<"<span class='notice'>you feel very strange for a moment, but then it passes.</span>"
burnt_out = 1
charged_item = M
break
for(var/obj/item in hand_items)
if(istype(item, /obj/item/weapon/spellbook))
if(istype(item, /obj/item/weapon/spellbook/oneuse))
var/obj/item/weapon/spellbook/oneuse/I = item
if(prob(80))
L.visible_message("<span class='warning'>[I] catches fire!</span>")
qdel(I)
else
I.used = 0
charged_item = I
break
else
L << "<span class='caution'>Glowing red letters appear on the front cover...</span>"
L << "<span class='warning'>[pick("NICE TRY BUT NO!","CLEVER BUT NOT CLEVER ENOUGH!", "SUCH FLAGRANT CHEESING IS WHY WE ACCEPTED YOUR APPLICATION!", "CUTE!", "YOU DIDN'T THINK IT'D BE THAT EASY, DID YOU?")]</span>"
burnt_out = 1
else if(istype(item, /obj/item/weapon/gun/magic))
var/obj/item/weapon/gun/magic/I = item
if(prob(80) && !I.can_charge)
I.max_charges--
if(I.max_charges <= 0)
I.max_charges = 0
burnt_out = 1
I.charges = I.max_charges
if(istype(item,/obj/item/weapon/gun/magic/wand) && I.max_charges != 0)
var/obj/item/weapon/gun/magic/W = item
W.icon_state = initial(W.icon_state)
charged_item = I
break
else if(istype(item, /obj/item/weapon/stock_parts/cell/))
var/obj/item/weapon/stock_parts/cell/C = item
if(prob(80))
C.maxcharge -= 200
if(C.maxcharge <= 1) //Div by 0 protection
C.maxcharge = 1
burnt_out = 1
C.charge = C.maxcharge
charged_item = C
break
else if(item.contents)
var/obj/I = null
for(I in item.contents)
if(istype(I, /obj/item/weapon/stock_parts/cell/))
var/obj/item/weapon/stock_parts/cell/C = I
if(prob(80))
C.maxcharge -= 200
if(C.maxcharge <= 1) //Div by 0 protection
C.maxcharge = 1
burnt_out = 1
C.charge = C.maxcharge
item.update_icon()
charged_item = item
break
if(!charged_item)
L << "<span class='notice'>you feel magical power surging to your hands, but the feeling rapidly fades...</span>"
else if(burnt_out)
L << "<span class='caution'>[charged_item] doesn't seem to be reacting to the spell...</span>"
else
playsound(get_turf(L), "sound/magic/Charge.ogg", 50, 1)
L << "<span class='notice'>[charged_item] suddenly feels very warm!</span>"
@@ -0,0 +1,52 @@
/obj/effect/proc_holder/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
//should be text, like list("/mob/living/simple_animal/bot/ed209")
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
var/list/newVars = list() //vars of the summoned objects will be replaced with those where they meet
//should have format of list("emagged" = 1,"name" = "Wizard's Justicebot"), for example
var/cast_sound = 'sound/items/welder.ogg'
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets,mob/user = usr)
playsound(get_turf(user), cast_sound, 50,1)
for(var/turf/T in targets)
if(T.density && !summon_ignore_density)
targets -= T
for(var/i=0,i<summon_amt,i++)
if(!targets.len)
break
var/summoned_object_type = pick(summon_type)
var/spawn_place = pick(targets)
if(summon_ignore_prev_spawn_points)
targets -= spawn_place
if(ispath(summoned_object_type,/turf))
var/turf/O = spawn_place
var/N = summoned_object_type
O.ChangeTurf(N)
else
var/atom/summoned_object = new summoned_object_type(spawn_place)
for(var/varName in newVars)
if(varName in summoned_object.vars)
summoned_object.vars[varName] = newVars[varName]
if(summon_lifespan)
QDEL_IN(summoned_object, summon_lifespan)
/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes - Also a lot of fun
name = "Dispense Wizard Justice"
desc = "This spell dispenses wizard justice."
summon_type = list(/mob/living/simple_animal/bot/ed209)
summon_amt = 10
range = 3
newVars = list("emagged" = 2, "remote_disabled" = 1,"shoot_sound" = 'sound/weapons/laser.ogg',"projectile" = /obj/item/projectile/beam/laser, "declare_arrests" = 0,"name" = "Wizard's Justicebot")
@@ -0,0 +1,156 @@
//////////////////////////////Construct Spells/////////////////////////
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser
charge_max = 1800
action_icon_state = "artificer"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser/cult
cult_req = 1
charge_max = 2500
/obj/effect/proc_holder/spell/aoe_turf/conjure/floor
name = "Summon Cult Floor"
desc = "This spell constructs a cult floor"
school = "conjuration"
charge_max = 20
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
summon_type = list(/turf/open/floor/engine/cult)
action_icon_state = "floorconstruct"
action_background_icon_state = "bg_cult"
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall
name = "Summon Cult Wall"
desc = "This spell constructs a cult wall"
school = "conjuration"
charge_max = 100
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
action_icon_state = "lesserconstruct"
action_background_icon_state = "bg_cult"
summon_type = list(/turf/closed/wall/mineral/cult/artificer) //we don't want artificer-based runed metal farms
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall/reinforced
name = "Greater Construction"
desc = "This spell constructs a reinforced metal wall"
school = "conjuration"
charge_max = 300
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
summon_type = list(/turf/closed/wall/r_wall)
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone
name = "Summon Soulstone"
desc = "This spell reaches into Nar-Sie's realm, summoning one of the legendary fragments across time and space"
school = "conjuration"
charge_max = 3000
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
action_icon_state = "summonsoulstone"
action_background_icon_state = "bg_demon"
summon_type = list(/obj/item/device/soulstone)
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/cult
cult_req = 1
charge_max = 4000
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/noncult
summon_type = list(/obj/item/device/soulstone/anybody)
/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall
name = "Shield"
desc = "This spell creates a temporary forcefield to shield yourself and allies from incoming fire"
school = "transmutation"
charge_max = 300
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
summon_type = list(/obj/effect/forcefield/cult)
summon_lifespan = 200
action_icon_state = "cultforcewall"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift
name = "Phase Shift"
desc = "This spell allows you to pass through walls"
school = "transmutation"
charge_max = 200
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = -1
include_user = 1
jaunt_duration = 50 //in deciseconds
centcom_cancast = 0 //Stop people from getting to centcom
action_icon_state = "phaseshift"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(atom/movable/overlay/animation, mob/living/target)
animation.icon_state = "phase_shift"
animation.setDir(target.dir)
flick("phase_shift",animation)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(atom/movable/overlay/animation, mob/living/target)
animation.icon_state = "phase_shift2"
animation.setDir(target.dir)
flick("phase_shift2",animation)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
/obj/effect/proc_holder/spell/targeted/projectile/magic_missile/lesser
name = "Lesser Magic Missile"
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
school = "evocation"
charge_max = 400
clothes_req = 0
invocation = "none"
invocation_type = "none"
proj_lifespan = 10
max_targets = 6
action_icon_state = "magicm"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/targeted/smoke/disable
name = "Paralysing Smoke"
desc = "This spell spawns a cloud of paralysing smoke."
school = "conjuration"
charge_max = 200
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = -1
include_user = 1
cooldown_min = 20 //25 deciseconds reduction per rank
smoke_spread = 3
smoke_amt = 4
action_icon_state = "parasmoke"
action_background_icon_state = "bg_cult"
+218
View File
@@ -0,0 +1,218 @@
/obj/effect/proc_holder/spell/targeted/summon_pitchfork
name = "Summon Pitchfork"
desc = "A devil's weapon of choice. Use this to summon/unsummon your pitchfork."
invocation_type = "none"
include_user = 1
range = -1
clothes_req = 0
var/obj/item/weapon/twohanded/pitchfork/demonic/pitchfork
var/pitchfork_type = /obj/item/weapon/twohanded/pitchfork/demonic/
school = "conjuration"
charge_max = 150
cooldown_min = 10
action_icon_state = "pitchfork"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/targeted/summon_pitchfork/cast(list/targets, mob/user = usr)
if (pitchfork)
qdel(pitchfork)
else
for(var/mob/living/carbon/C in targets)
if(C.drop_item())
pitchfork = new pitchfork_type
C.put_in_hands(pitchfork)
/obj/effect/proc_holder/spell/targeted/summon_pitchfork/Del()
if(pitchfork)
qdel(pitchfork)
/obj/effect/proc_holder/spell/targeted/summon_pitchfork/greater
pitchfork_type = /obj/item/weapon/twohanded/pitchfork/demonic/greater
/obj/effect/proc_holder/spell/targeted/summon_pitchfork/ascended
pitchfork_type = /obj/item/weapon/twohanded/pitchfork/demonic/ascended
/obj/effect/proc_holder/spell/targeted/summon_contract
name = "Summon infernal contract"
desc = "Skip making a contract by hand, just do it by magic."
invocation_type = "whisper"
invocation = "Just sign on the dotted line."
include_user = 0
range = 5
clothes_req = 0
school = "conjuration"
charge_max = 150
cooldown_min = 10
action_icon_state = "spell_default"
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/targeted/summon_contract/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/C in targets)
if(C.mind && user.mind)
if(C.stat == DEAD)
if(user.drop_item())
var/obj/item/weapon/paper/contract/infernal/revive/contract = new(user.loc, C.mind, user.mind)
user.put_in_hands(contract)
else
var/obj/item/weapon/paper/contract/infernal/contract // = new(user.loc, C.mind, contractType, user.mind)
var/contractTypeName = input(user, "What type of contract?") in list ("Power", "Wealth", "Prestige", "Magic", "Knowledge")
switch(contractTypeName)
if("Power")
contract = new /obj/item/weapon/paper/contract/infernal/power(C.loc, C.mind, user.mind)
if("Wealth")
contract = new /obj/item/weapon/paper/contract/infernal/wealth(C.loc, C.mind, user.mind)
if("Prestige")
contract = new /obj/item/weapon/paper/contract/infernal/prestige(C.loc, C.mind, user.mind)
if("Magic")
contract = new /obj/item/weapon/paper/contract/infernal/magic(C.loc, C.mind, user.mind)
if("Knowledge")
contract = new /obj/item/weapon/paper/contract/infernal/knowledge(C.loc, C.mind, user.mind)
C.put_in_hands(contract)
else
user << "<span class='notice'>[C] seems to not be sentient. You cannot summon a contract for them.</span>"
/obj/effect/proc_holder/spell/dumbfire/fireball/hellish
name = "Hellfire"
desc = "This spell launches hellfire at the target."
school = "evocation"
charge_max = 80
clothes_req = 0
invocation = "Your very soul will catch fire!"
invocation_type = "shout"
range = 2
proj_icon_state = "fireball"
proj_name = "a fireball"
proj_type = /obj/effect/proc_holder/spell/turf/fireball/infernal
proj_lifespan = 200
proj_step_delay = 1
action_background_icon_state = "bg_demon"
/obj/effect/proc_holder/spell/turf/fireball/infernal/cast(turf/T,mob/user = usr)
explosion(T, -1, -1, 1, 4, 0, flame_range = 5)
/obj/effect/proc_holder/spell/targeted/infernal_jaunt
name = "Infernal Jaunt"
desc = "Use hellfire to phase out of existence."
charge_max = 10
clothes_req = 0
selection_type = "range"
range = -1
cooldown_min = 0
overlay = null
include_user = 1
action_icon_state = "jaunt"
action_background_icon_state = "bg_demon"
phase_allowed = 1
/obj/effect/proc_holder/spell/targeted/infernal_jaunt/cast(list/targets, mob/living/user = usr)
if(istype(user))
if(istype(user.loc, /obj/effect/dummy/slaughter/))
var/continuing = 0
for(var/mob/living/C in orange(2, get_turf(user.loc)))
if (C.mind && C.mind.soulOwner == C.mind)
continuing = 1
break
if(continuing)
addtimer(user,"infernalphasein",150,TRUE)
else
user << "<span class='warning'>You can only re-appear near a potential signer."
revert_cast()
return ..()
else
user.notransform = 1
user.fakefire()
addtimer(user, "infernalphaseout",150,TRUE,get_turf(user))
start_recharge()
return
revert_cast()
/mob/living/proc/infernalphaseout(var/turf/mobloc)
if(get_turf(src) != mobloc)
src << "<span class='warning'>You must remain still while exiting."
return
dust_animation()
spawn_dust()
src.visible_message("<span class='warning'>[src] disappears in a flashfire!</span>")
playsound(get_turf(src), 'sound/magic/enter_blood.ogg', 100, 1, -1)
var/obj/effect/dummy/slaughter/holder = PoolOrNew(/obj/effect/dummy/slaughter,mobloc)
src.ExtinguishMob()
if(buckled)
buckled.unbuckle_mob(src,force=1)
if(has_buckled_mobs())
unbuckle_all_mobs(force=1)
if(pulledby)
pulledby.stop_pulling()
if(pulling)
stop_pulling()
src.loc = holder
src.holder = holder
src.notransform = 0
fakefireextinguish()
/mob/living/proc/infernalphasein()
if(src.notransform)
src << "<span class='warning'>You're too busy to jaunt in.</span>"
return 0
fakefire()
src.loc = get_turf(src)
src.client.eye = src
src.visible_message("<span class='warning'><B>[src] appears in a firey blaze!</B>")
playsound(get_turf(src), 'sound/magic/exit_blood.ogg', 100, 1, -1)
addtimer(src, "fakefireextinguish" ,15,TRUE,get_turf(src))
/mob/living/proc/fakefire()
return
/mob/living/carbon/fakefire(var/fire_icon = "Generic_mob_burning")
overlays_standing[FIRE_LAYER] = image("icon"='icons/mob/OnFire.dmi', "icon_state"= fire_icon, "layer"=-FIRE_LAYER)
apply_overlay(FIRE_LAYER)
/mob/living/proc/fakefireextinguish()
return
/mob/living/carbon/fakefireextinguish()
remove_overlay(FIRE_LAYER)
/obj/effect/proc_holder/spell/targeted/sintouch
name = "Sin Touch"
desc = "Subtly encourage someone to sin."
charge_max = 1800
clothes_req = 0
selection_type = "range"
range = 2
cooldown_min = 0
overlay = null
include_user = 0
action_icon_state = "sintouch"
action_background_icon_state = "bg_demon"
phase_allowed = 0
random_target = 1
random_target_priority = TARGET_RANDOM
max_targets = 3
invocation = "TASTE SIN AND INDULGE!!"
invocation_type = "shout"
/obj/effect/proc_holder/spell/targeted/sintouch/ascended
name = "Greater sin touch"
charge_max = 100
range = 7
max_targets = 10
/obj/effect/proc_holder/spell/targeted/sintouch/cast(list/targets, mob/living/user = usr)
for(var/mob/living/carbon/human/H in targets)
if(!H.mind)
continue
for(var/datum/objective/sintouched/A in H.mind.objectives)
continue
H.influenceSin()
H.Weaken(2)
H.Stun(2)
@@ -0,0 +1,44 @@
/obj/effect/proc_holder/spell/targeted/summon_wealth
name = "Summon wealth"
desc = "The reward for selling your soul."
invocation_type = "none"
include_user = 1
range = -1
clothes_req = 0
school = "conjuration"
charge_max = 100
cooldown_min = 10
action_icon_state = "moneybag"
/obj/effect/proc_holder/spell/targeted/summon_wealth/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/C in targets)
if(user.drop_item())
var/obj/item = pick(
new /obj/item/weapon/coin/gold(user.loc),
new /obj/item/weapon/coin/diamond(user.loc),
new /obj/item/weapon/coin/silver(user.loc),
new /obj/item/clothing/tie/medal/gold(user.loc),
new /obj/item/stack/sheet/mineral/gold(user.loc),
new /obj/item/stack/sheet/mineral/silver(user.loc),
new /obj/item/stack/sheet/mineral/diamond(user.loc),
new /obj/item/stack/spacecash/c1000(user.loc))
C.put_in_hands(item)
/obj/effect/proc_holder/spell/targeted/view_range
name = "Distant vision"
desc = "The reward for selling your soul."
invocation_type = "none"
include_user = 1
range = -1
clothes_req = 0
charge_max = 50
cooldown_min = 10
action_icon_state = "camera_jump"
var/ranges = list(7,8,9,10/*,11,12*/)
/obj/effect/proc_holder/spell/targeted/view_range/cast(list/targets, mob/user = usr)
for(var/mob/C in targets)
if(!C.client)
continue
C.client.view = input("Select view range:", "Range", 4) in ranges
@@ -0,0 +1,90 @@
/obj/effect/proc_holder/spell/dumbfire
var/projectile_type = ""
var/activate_on_collision = 1
var/proj_icon = 'icons/obj/projectiles.dmi'
var/proj_icon_state = "spell"
var/proj_name = "a spell projectile"
var/proj_trail = 0 //if it leaves a trail
var/proj_trail_lifespan = 0 //deciseconds
var/proj_trail_icon = 'icons/obj/wizard.dmi'
var/proj_trail_icon_state = "trail"
var/proj_type = "/obj/effect/proc_holder/spell" //IMPORTANT use only subtypes of this
var/proj_insubstantial = 0 //if it can pass through dense objects or not
var/proj_trigger_range = 1 //the range from target at which the projectile triggers cast(target)
var/proj_lifespan = 100 //in deciseconds * proj_step_delay
var/proj_step_delay = 1 //lower = faster
/obj/effect/proc_holder/spell/dumbfire/choose_targets(mob/user = usr)
var/turf/T = get_turf(user)
for(var/i = 1; i < range; i++)
var/turf/new_turf = get_step(T, user.dir)
if(new_turf.density)
break
T = new_turf
perform(list(T),user = user)
/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr)
playMagSound()
for(var/turf/target in targets)
spawn(0)
var/obj/effect/proc_holder/spell/targeted/projectile
if(istext(proj_type))
var/projectile_type = text2path(proj_type)
projectile = new projectile_type(user)
else if(istype(proj_type,/obj/effect/proc_holder/spell))
projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
projectile:linked_spells += proj_type
else
projectile = new proj_type(user)
projectile.icon = proj_icon
projectile.icon_state = proj_icon_state
projectile.setDir(get_dir(projectile, target))
projectile.name = proj_name
var/current_loc = user.loc
projectile.loc = current_loc
for(var/i = 0,i < proj_lifespan,i++)
if(!projectile)
break
if(proj_insubstantial)
projectile.loc = get_step(projectile, projectile.dir)
else
step(projectile, projectile.dir)
if(projectile.loc == current_loc || i == proj_lifespan)
projectile.cast(current_loc,user=user)
break
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - user
if(L && L.stat != DEAD)
projectile.cast(L.loc,user=user)
break
if(proj_trail && projectile)
spawn(0)
if(projectile)
var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc)
trail.icon = proj_trail_icon
trail.icon_state = proj_trail_icon_state
trail.density = 0
QDEL_IN(trail, proj_trail_lifespan)
current_loc = projectile.loc
var/matrix/M = new
M.Turn(dir2angle(projectile.dir))
projectile.transform = M
sleep(proj_step_delay)
if(projectile)
qdel(projectile)
@@ -0,0 +1,16 @@
/obj/effect/proc_holder/spell/targeted/emplosion
name = "Emplosion"
desc = "This spell emplodes an area."
var/emp_heavy = 2
var/emp_light = 3
action_icon_state = "emp"
sound = "sound/weapons/ZapBang.ogg"
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets,mob/user = usr)
playsound(get_turf(user), sound, 50,1)
for(var/mob/living/target in targets)
empulse(target.loc, emp_heavy, emp_light)
return
@@ -0,0 +1,116 @@
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt
name = "Ethereal Jaunt"
desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
school = "transmutation"
charge_max = 300
clothes_req = 1
invocation = "none"
invocation_type = "none"
range = -1
cooldown_min = 100 //50 deciseconds reduction per rank
include_user = 1
centcom_cancast = 0 //Prevent people from getting to centcom
nonabstract_req = 1
var/jaunt_duration = 50 //in deciseconds
action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets,mob/user = usr) //magnets, so mostly hardcoded
playsound(get_turf(user), 'sound/magic/Ethereal_Enter.ogg', 50, 1, -1)
for(var/mob/living/target in targets)
target.notransform = 1 //protects the mob from being transformed (replaced) midjaunt and getting stuck in bluespace
spawn(0)
var/turf/mobloc = get_turf(target.loc)
var/obj/effect/dummy/spell_jaunt/holder = new /obj/effect/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 = 'icons/mob/mob.dmi'
animation.layer = FLY_LAYER
animation.master = holder
target.ExtinguishMob()
if(target.buckled)
target.buckled.unbuckle_mob(target,force=1)
if(target.pulledby)
target.pulledby.stop_pulling()
target.stop_pulling()
if(target.has_buckled_mobs())
target.unbuckle_all_mobs(force=1)
jaunt_disappear(animation, target)
target.loc = holder
target.reset_perspective(holder)
target.notransform=0 //mob is safely inside holder now, no need for protection.
jaunt_steam(mobloc)
sleep(jaunt_duration)
if(target.loc != holder) //mob warped out of the warp
qdel(holder)
return
mobloc = get_turf(target.loc)
animation.loc = mobloc
jaunt_steam(mobloc)
target.canmove = 0
holder.reappearing = 1
playsound(get_turf(user), 'sound/magic/Ethereal_Exit.ogg', 50, 1, -1)
sleep(20)
if(!qdeleted(target))
jaunt_reappear(animation, target)
sleep(5)
qdel(animation)
qdel(holder)
if(!qdeleted(target))
if(mobloc.density)
for(var/direction in list(1,2,4,8,5,6,9,10))
var/turf/T = get_step(mobloc, direction)
if(T)
if(target.Move(T))
break
target.canmove = 1
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(atom/movable/overlay/animation, mob/living/target)
animation.icon_state = "liquify"
flick("liquify",animation)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(atom/movable/overlay/animation, mob/living/target)
flick("reappear",animation)
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/proc/jaunt_steam(mobloc)
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
steam.set_up(10, 0, mobloc)
steam.start()
/obj/effect/dummy/spell_jaunt
name = "water"
icon = 'icons/effects/effects.dmi'
icon_state = "nothing"
var/canmove = 1
var/reappearing = 0
density = 0
anchored = 1
invisibility = 60
burn_state = LAVA_PROOF
/obj/effect/dummy/spell_jaunt/Destroy()
// Eject contents if deleted somehow
for(var/atom/movable/AM in src)
AM.forceMove(get_turf(src))
return ..()
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
if (!src.canmove || reappearing || !direction) return
var/turf/newLoc = get_step(src,direction)
if(!(newLoc.flags & NOJAUNT))
loc = newLoc
else
user << "<span class='warning'>Some strange aura is blocking the way!</span>"
src.canmove = 0
spawn(2) src.canmove = 1
/obj/effect/dummy/spell_jaunt/ex_act(blah)
return
/obj/effect/dummy/spell_jaunt/bullet_act(blah)
return
@@ -0,0 +1,15 @@
/obj/effect/proc_holder/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/effect/proc_holder/spell/targeted/explosion/cast(list/targets,mob/user = usr)
for(var/mob/living/target in targets)
explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
return
@@ -0,0 +1,30 @@
/obj/effect/proc_holder/spell/targeted/genetic
name = "Genetic"
desc = "This spell inflicts a set of mutations and disabilities upon the target."
var/disabilities = 0 //bits
var/list/mutations = list() //mutation strings
var/duration = 100 //deciseconds
/*
Disabilities
1st bit - ?
2nd bit - ?
3rd bit - ?
4th bit - ?
5th bit - ?
6th bit - ?
*/
/obj/effect/proc_holder/spell/targeted/genetic/cast(list/targets,mob/user = usr)
playMagSound()
for(var/mob/living/carbon/target in targets)
if(!target.dna)
continue
for(var/A in mutations)
target.dna.add_mutation(A)
target.disabilities |= disabilities
spawn(duration)
if(target && !qdeleted(target))
for(var/A in mutations)
target.dna.remove_mutation(A)
target.disabilities &= ~disabilities
@@ -0,0 +1,76 @@
/obj/item/weapon/melee/touch_attack
name = "\improper outstretched hand"
desc = "High Five?"
var/catchphrase = "High Five!"
var/on_use_sound = null
var/obj/effect/proc_holder/spell/targeted/touch/attached_spell
icon = 'icons/obj/weapons.dmi'
icon_state = "syndballoon"
item_state = null
flags = ABSTRACT | NODROP
w_class = 5
force = 0
throwforce = 0
throw_range = 0
throw_speed = 0
/obj/item/weapon/melee/touch_attack/New(var/spell)
attached_spell = spell
..()
/obj/item/weapon/melee/touch_attack/attack(mob/target, mob/living/carbon/user)
if(!iscarbon(user)) //Look ma, no hands
return
if(user.lying || user.handcuffed)
user << "<span class='warning'>You can't reach out!</span>"
return
..()
/obj/item/weapon/melee/touch_attack/afterattack(atom/target, mob/user, proximity)
user.say(catchphrase)
playsound(get_turf(user), on_use_sound,50,1)
if(attached_spell)
attached_spell.attached_hand = null
qdel(src)
/obj/item/weapon/melee/touch_attack/dropped()
if(attached_spell)
attached_spell.attached_hand = null
qdel(src)
/obj/item/weapon/melee/touch_attack/disintegrate
name = "\improper disintegrating touch"
desc = "This hand of mine glows with an awesome power!"
catchphrase = "EI NATH!!"
on_use_sound = "sound/magic/Disintegrate.ogg"
icon_state = "disintegrate"
item_state = "disintegrate"
/obj/item/weapon/melee/touch_attack/disintegrate/afterattack(atom/target, mob/living/carbon/user, proximity)
if(!proximity || target == user || !ismob(target) || !iscarbon(user) || user.lying || user.handcuffed) //exploding after touching yourself would be bad
return
var/mob/M = target
var/datum/effect_system/spark_spread/sparks = new
sparks.set_up(4, 0, M.loc) //no idea what the 0 is
sparks.start()
M.gib()
..()
/obj/item/weapon/melee/touch_attack/fleshtostone
name = "\improper petrifying touch"
desc = "That's the bottom line, because flesh to stone said so!"
catchphrase = "STAUN EI!!"
on_use_sound = "sound/magic/FleshToStone.ogg"
icon_state = "fleshtostone"
item_state = "fleshtostone"
/obj/item/weapon/melee/touch_attack/fleshtostone/afterattack(atom/target, mob/living/carbon/user, proximity)
if(!proximity || target == user || !isliving(target) || !iscarbon(user) || user.lying || user.handcuffed) //getting hard after touching yourself would also be bad
return
if(user.lying || user.handcuffed)
user << "<span class='warning'>You can't reach out!</span>"
return
var/mob/living/M = target
M.Stun(2)
M.petrify()
..()
@@ -0,0 +1,22 @@
/obj/effect/proc_holder/spell/targeted/infinite_guns
name = "Lesser Summon Guns"
desc = "Why reload when you have infinite guns? Summons an unending stream of bolt action rifles. Requires both hands free to use."
invocation_type = "none"
include_user = 1
range = -1
school = "conjuration"
charge_max = 750
clothes_req = 1
cooldown_min = 10 //Gun wizard
action_icon_state = "bolt_action"
/obj/effect/proc_holder/spell/targeted/infinite_guns/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/C in targets)
C.drop_item()
C.swap_hand()
C.drop_item()
var/obj/item/weapon/gun/projectile/shotgun/boltaction/enchanted/GUN = new
C.put_in_hands(GUN)
@@ -0,0 +1,48 @@
/obj/effect/proc_holder/spell/targeted/inflict_handler
name = "Inflict Handler"
desc = "This spell blinds and/or destroys/damages/heals and/or weakens/stuns the target."
var/amt_weakened = 0
var/amt_paralysis = 0
var/amt_stunned = 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/destroys = "none" //can be "none", "gib" or "disintegrate"
var/summon_type = null //this will put an obj at the target's location
/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets,mob/user = usr)
for(var/mob/living/target in targets)
playsound(target,sound, 50,1)
switch(destroys)
if("gib")
target.gib()
if("disintegrate")
target.dust()
if(!target)
continue
//damage/healing
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)
target.blind_eyes(amt_eye_blind)
target.blur_eyes(amt_eye_blurry)
//summoning
if(summon_type)
new summon_type(target.loc, target)
+31
View File
@@ -0,0 +1,31 @@
/obj/effect/proc_holder/spell/aoe_turf/knock
name = "Knock"
desc = "This spell opens nearby doors and does not require wizard garb."
school = "transmutation"
charge_max = 100
clothes_req = 0
invocation = "AULIE OXIN FIERA"
invocation_type = "whisper"
range = 3
cooldown_min = 20 //20 deciseconds reduction per rank
action_icon_state = "knock"
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets,mob/user = usr)
user << sound("sound/magic/Knock.ogg")
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
addtimer(src, "open_door", 0, FALSE, door)
for(var/obj/structure/closet/C in T.contents)
addtimer(src, "open_closet", 0, FALSE, C)
/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_door(var/obj/machinery/door/door)
if(istype(door, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/A = door
A.locked = FALSE
door.open()
/obj/effect/proc_holder/spell/aoe_turf/knock/proc/open_closet(var/obj/structure/closet/C)
C.locked = FALSE
C.open()
+137
View File
@@ -0,0 +1,137 @@
/obj/effect/proc_holder/spell/targeted/lichdom
name = "Bind Soul"
desc = "A dark necromantic pact that can forever bind your soul to an \
item of your choosing. So long as both your body and the item remain \
intact and on the same plane you can revive from death, though the time \
between reincarnations grows steadily with use, along with the weakness \
that the new skeleton body will experience upon 'birth'. Note that \
becoming a lich destroys all internal organs except the brain."
school = "necromancy"
charge_max = 10
clothes_req = 0
centcom_cancast = 0
invocation = "NECREM IMORTIUM!"
invocation_type = "shout"
range = -1
level_max = 0 //cannot be improved
cooldown_min = 10
include_user = 1
var/obj/marked_item
var/mob/living/current_body
var/resurrections = 0
var/existence_stops_round_end = 0
action_icon_state = "skeleton"
/obj/effect/proc_holder/spell/targeted/lichdom/New()
if(initial(ticker.mode.round_ends_with_antag_death))
existence_stops_round_end = 1
ticker.mode.round_ends_with_antag_death = 0
..()
/obj/effect/proc_holder/spell/targeted/lichdom/Destroy()
for(var/datum/mind/M in ticker.mode.wizards) //Make sure no other bones are about
for(var/obj/effect/proc_holder/spell/S in M.spell_list)
if(istype(S,/obj/effect/proc_holder/spell/targeted/lichdom) && S != src)
return ..()
if(existence_stops_round_end)
ticker.mode.round_ends_with_antag_death = 1
..()
/obj/effect/proc_holder/spell/targeted/lichdom/cast(list/targets,mob/user = usr)
for(var/mob/M in targets)
var/list/hand_items = list()
if(iscarbon(M))
hand_items = list(M.get_active_hand(),M.get_inactive_hand())
if(marked_item && !stat_allowed) //sanity, shouldn't happen without badminry
marked_item = null
return
if(stat_allowed) //Death is not my end!
if(M.stat == CONSCIOUS && iscarbon(M))
M << "<span class='notice'>You aren't dead enough to revive!</span>" //Usually a good problem to have
charge_counter = charge_max
return
if(!marked_item || qdeleted(marked_item)) //Wait nevermind
M << "<span class='warning'>Your phylactery is gone!</span>"
return
var/turf/user_turf = get_turf(M)
var/turf/item_turf = get_turf(marked_item)
if(user_turf.z != item_turf.z)
M << "<span class='warning'>Your phylactery is out of range!</span>"
return
if(isobserver(M))
var/mob/dead/observer/O = M
O.reenter_corpse()
var/mob/living/carbon/human/lich = new /mob/living/carbon/human(item_turf)
lich.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(lich), slot_shoes)
lich.equip_to_slot_or_del(new /obj/item/clothing/under/color/black(lich), slot_w_uniform)
lich.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(lich), slot_wear_suit)
lich.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(lich), slot_head)
lich.real_name = M.mind.name
M.mind.transfer_to(lich)
lich.hardset_dna(null,null,lich.real_name,null,/datum/species/skeleton)
lich << "<span class='warning'>Your bones clatter and shutter as they're pulled back into this world!</span>"
charge_max += 600
var/mob/old_body = current_body
var/turf/body_turf = get_turf(old_body)
current_body = lich
lich.Weaken(10+10*resurrections)
++resurrections
if(old_body && old_body.loc)
if(iscarbon(old_body))
var/mob/living/carbon/C = old_body
for(var/obj/item/W in C)
C.unEquip(W)
for(var/obj/item/organ/I in C.internal_organs)
I.Remove(C)
I.forceMove(body_turf)
var/wheres_wizdo = dir2text(get_dir(body_turf, item_turf))
if(wheres_wizdo)
old_body.visible_message("<span class='warning'>Suddenly [old_body.name]'s corpse falls to pieces! You see a strange energy rise from the remains, and speed off towards the [wheres_wizdo]!</span>")
body_turf.Beam(item_turf,icon_state="lichbeam",icon='icons/effects/effects.dmi',time=10+10*resurrections,maxdistance=INFINITY)
old_body.dust()
if(!marked_item) //linking item to the spell
message = "<span class='warning'>"
for(var/obj/item in hand_items)
if(ABSTRACT in item.flags || NODROP in item.flags)
continue
marked_item = item
M << "<span class='warning'>You begin to focus your very being into the [item.name]...</span>"
break
if(!marked_item)
M << "<span class='caution'>You must hold an item you wish to make your phylactery...</span>"
return
if(!do_after(M, 50, needhand=FALSE, target=marked_item))
M << "<span class='warning'>Your soul snaps back to your body as you stop ensouling [marked_item.name]!</span>"
marked_item = null
return
name = "RISE!"
desc = "Rise from the dead! You will reform at the location of your phylactery and your old body will crumble away."
charge_max = 1800 //3 minute cooldown, if you rise in sight of someone and killed again, you're probably screwed.
charge_counter = 1800
stat_allowed = 1
marked_item.name = "Ensouled [marked_item.name]"
marked_item.desc = "A terrible aura surrounds this item, its very existence is offensive to life itself..."
marked_item.color = "#003300"
M << "<span class='userdanger'>With a hideous feeling of emptiness you watch in horrified fascination as skin sloughs off bone! Blood boils, nerves disintegrate, eyes boil in their sockets! As your organs crumble to dust in your fleshless chest you come to terms with your choice. You're a lich!</span>"
M.set_species(/datum/species/skeleton)
current_body = M.mind.current
if(ishuman(M))
var/mob/living/carbon/human/H = M
H.unEquip(H.wear_suit)
H.unEquip(H.head)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), slot_wear_suit)
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), slot_head)
@@ -0,0 +1,81 @@
/obj/effect/proc_holder/spell/targeted/lightning
name = "Lightning Bolt"
desc = "Charges up and throws a lightning bolt at nearby enemies. Classic."
charge_type = "recharge"
charge_max = 300
clothes_req = 1
invocation = "UN'LTD P'WAH!"
invocation_type = "shout"
range = 7
cooldown_min = 30
selection_type = "view"
random_target = 1
var/ready = 0
var/image/halo = null
var/sound/Snd // so far only way i can think of to stop a sound, thank MSO for the idea.
action_icon_state = "lightning"
/obj/effect/proc_holder/spell/targeted/lightning/Click()
if(!ready && cast_check())
StartChargeup()
return 1
/obj/effect/proc_holder/spell/targeted/lightning/proc/StartChargeup(mob/user = usr)
ready = 1
user << "<span class='notice'>You start gathering the power.</span>"
Snd = new/sound('sound/magic/lightning_chargeup.ogg',channel = 7)
halo = image("icon"='icons/effects/effects.dmi',"icon_state" ="electricity","layer" = EFFECTS_LAYER)
user.overlays.Add(halo)
playsound(get_turf(user), Snd, 50, 0)
if(do_mob(user,user,100,1))
if(ready && cast_check(skipcharge=1))
choose_targets()
else
Reset(user)
/obj/effect/proc_holder/spell/targeted/lightning/proc/Reset(mob/user = usr)
ready = 0
if(halo)
user.overlays.Remove(halo)
/obj/effect/proc_holder/spell/targeted/lightning/revert_cast(mob/user = usr)
user << "<span class='notice'>No target found in range.</span>"
Reset(user)
..()
/obj/effect/proc_holder/spell/targeted/lightning/cast(list/targets, mob/user = usr)
ready = 0
var/mob/living/carbon/target = targets[1]
Snd=sound(null, repeat = 0, wait = 1, channel = Snd.channel) //byond, why you suck?
playsound(get_turf(user),Snd,50,0)// Sorry MrPerson, but the other ways just didn't do it the way i needed to work, this is the only way.
if(get_dist(user,target)>range)
user << "<span class='notice'>They are too far away!</span>"
Reset(user)
return
playsound(get_turf(user), 'sound/magic/lightningbolt.ogg', 50, 1)
user.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
Bolt(user,target,30,5,user)
Reset(user)
/obj/effect/proc_holder/spell/targeted/lightning/proc/Bolt(mob/origin,mob/target,bolt_energy,bounces,mob/user = usr)
origin.Beam(target,icon_state="lightning[rand(1,12)]",icon='icons/effects/effects.dmi',time=5)
var/mob/living/carbon/current = target
if(bounces < 1)
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
else
current.electrocute_act(bolt_energy,"Lightning Bolt",safety=1)
playsound(get_turf(current), 'sound/magic/LightningShock.ogg', 50, 1, -1)
var/list/possible_targets = new
for(var/mob/living/M in view_or_range(range,target,"view"))
if(user == M || target == M && los_check(current,M)) // || origin == M ? Not sure double shockings is good or not
continue
possible_targets += M
if(!possible_targets.len)
return
var/mob/living/next = pick(possible_targets)
if(next)
Bolt(current,next,max((bolt_energy-5),5),bounces-1,user)
+62
View File
@@ -0,0 +1,62 @@
/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall
name = "Invisible wall"
desc = "The mime's performance transmutates into physical reality."
school = "mime"
panel = "Mime"
summon_type = list(/obj/effect/forcefield/mime)
invocation_type = "emote"
invocation_emote_self = "<span class='notice'>You form a wall in front of yourself.</span>"
summon_lifespan = 300
charge_max = 300
clothes_req = 0
range = 0
cast_sound = null
human_req = 1
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/aoe_turf/conjure/mime_wall/Click()
if(usr && usr.mind)
if(!usr.mind.miming)
usr << "<span class='notice'>You must dedicate yourself to silence first.</span>"
return
invocation = "<B>[usr.real_name]</B> looks as if a wall is in front of them."
else
invocation_type ="none"
..()
/obj/effect/proc_holder/spell/targeted/mime/speak
name = "Speech"
desc = "Make or break a vow of silence."
school = "mime"
panel = "Mime"
clothes_req = 0
human_req = 1
charge_max = 3000
range = -1
include_user = 1
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/targeted/mime/speak/Click()
if(!usr)
return
if(!ishuman(usr))
return
var/mob/living/carbon/human/H = usr
if(H.mind.miming)
still_recharging_msg = "<span class='warning'>You can't break your vow of silence that fast!</span>"
else
still_recharging_msg = "<span class='warning'>You'll have to wait before you can give your vow of silence again!</span>"
..()
/obj/effect/proc_holder/spell/targeted/mime/speak/cast(list/targets,mob/user = usr)
for(var/mob/living/carbon/human/H in targets)
H.mind.miming=!H.mind.miming
if(H.mind.miming)
H << "<span class='notice'>You make a vow of silence.</span>"
else
H << "<span class='notice'>You break your vow of silence.</span>"
@@ -0,0 +1,91 @@
/obj/effect/proc_holder/spell/targeted/mind_transfer
name = "Mind Transfer"
desc = "This spell allows the user to switch bodies with a target."
school = "transmutation"
charge_max = 600
clothes_req = 0
invocation = "GIN'YU CAPAN"
invocation_type = "whisper"
range = 1
cooldown_min = 200 //100 deciseconds reduction per rank
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
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
action_icon_state = "mindswap"
/*
Urist: I don't feel like figuring out how you store object spells so I'm leaving this for you to do.
Make sure spells that are removed from spell_list are actually removed and deleted when mind transfering.
Also, you never added distance checking after target is selected. I've went ahead and did that.
*/
/obj/effect/proc_holder/spell/targeted/mind_transfer/cast(list/targets, mob/user = usr, distanceoverride)
if(!targets.len)
user << "<span class='warning'>No mind found!</span>"
return
if(targets.len > 1)
user << "<span class='warning'>Too many minds! You're not a hive damnit!</span>"//Whaa...aat?
return
var/mob/living/target = targets[1]
if(!(target in oview(range)) && !distanceoverride)//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
user << "<span class='warning'>They are too far away!</span>"
return
if(istype(target, /mob/living/simple_animal/hostile/megafauna))
user << "<span class='warning'>This creature is too powerful to control!</span>"
return
if(target.stat == DEAD)
user << "<span class='warning'>You don't particularly want to be dead!</span>"
return
if(!target.key || !target.mind)
user << "<span class='warning'>They appear to be catatonic! Not even magic can affect their vacant mind.</span>"
return
if(user.suiciding)
user << "<span class='warning'>You're killing yourself! You can't concentrate enough to do this!</span>"
return
if((target.mind.special_role in protected_roles) || cmptext(copytext(target.key,1,2),"@"))
user << "<span class='warning'>Their mind is resisting your spell!</span>"
return
var/mob/living/victim = target//The target of the spell whos body will be transferred to.
var/mob/caster = user//The wizard/whomever doing the body transferring.
//MIND TRANSFER BEGIN
if(caster.mind.special_verbs.len)//If the caster had any special verbs, remove them from the mob verb list.
for(var/V in caster.mind.special_verbs)//Since the caster is using an object spell system, this is mostly moot.
caster.verbs -= V//But a safety nontheless.
if(victim.mind.special_verbs.len)//Now remove all of the victim's verbs.
for(var/V in victim.mind.special_verbs)
victim.verbs -= V
var/mob/dead/observer/ghost = victim.ghostize(0)
caster.mind.transfer_to(victim)
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.
caster.verbs += V
ghost.mind.transfer_to(caster)
if(ghost.key)
caster.key = ghost.key //have to transfer the key since the mind was not active
qdel(ghost)
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
for(var/V in caster.mind.special_verbs)
caster.verbs += V
//MIND TRANSFER END
//Here we paralyze both mobs and knock them out for a time.
caster.Paralyse(paralysis_amount_caster)
victim.Paralyse(paralysis_amount_victim)
caster << sound('sound/magic/MandSwap.ogg')
victim << sound('sound/magic/MandSwap.ogg')// only the caster and victim hear the sounds, that way no one knows for sure if the swap happened
@@ -0,0 +1,86 @@
/obj/effect/proc_holder/spell/targeted/projectile
name = "Projectile"
desc = "This spell summons projectiles which try to hit the targets."
var/proj_icon = 'icons/obj/projectiles.dmi'
var/proj_icon_state = "spell"
var/proj_name = "a spell projectile"
var/proj_trail = 0 //if it leaves a trail
var/proj_trail_lifespan = 0 //deciseconds
var/proj_trail_icon = 'icons/obj/wizard.dmi'
var/proj_trail_icon_state = "trail"
var/proj_type = "/obj/effect/proc_holder/spell/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 = 0 //the range from target at which the projectile triggers cast(target)
var/proj_lifespan = 15 //in deciseconds * proj_step_delay
var/proj_step_delay = 1 //lower = faster
/obj/effect/proc_holder/spell/targeted/projectile/cast(list/targets, mob/user = usr)
playMagSound()
for(var/mob/living/target in targets)
spawn(0)
var/obj/effect/proc_holder/spell/targeted/projectile
if(istext(proj_type))
var/projectile_type = text2path(proj_type)
projectile = new projectile_type(user)
if(istype(proj_type,/obj/effect/proc_holder/spell))
projectile = new /obj/effect/proc_holder/spell/targeted/trigger(user)
projectile:linked_spells += proj_type
projectile.icon = proj_icon
projectile.icon_state = proj_icon_state
projectile.setDir(get_dir(target,projectile))
projectile.name = proj_name
var/current_loc = user.loc
projectile.loc = current_loc
for(var/i = 0,i < proj_lifespan,i++)
if(!projectile)
break
if(proj_homing)
if(proj_insubstantial)
projectile.setDir(get_dir(projectile,target))
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(!projectile) // step and step_to sleeps so we'll have to check again.
break
if(!target || (!proj_lingering && projectile.loc == current_loc)) //if it didn't move since last time
qdel(projectile)
break
if(proj_trail && projectile)
spawn(0)
if(projectile)
var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc)
trail.icon = proj_trail_icon
trail.icon_state = proj_trail_icon_state
trail.density = 0
QDEL_IN(trail, proj_trail_lifespan)
if(projectile.loc in range(target.loc,proj_trigger_range))
projectile.perform(list(target),user=user)
break
current_loc = projectile.loc
sleep(proj_step_delay)
if(projectile)
qdel(projectile)
@@ -0,0 +1,205 @@
//In this file: Summon Magic/Summon Guns/Summon Events
/proc/rightandwrong(summon_type, mob/user, survivor_probability) //0 = Summon Guns, 1 = Summon Magic
var/list/gunslist = list("taser","gravgun","egun","laser","revolver","detective","c20r","nuclear","deagle","gyrojet","pulse","suppressed","cannon","doublebarrel","shotgun","combatshotgun","bulldog","mateba","sabr","crossbow","saw","car","boltaction","speargun","arg","uzi","alienpistol","dragnet","turret","pulsecarbine","decloner","mindflayer","hyperkinetic","advplasmacutter","wormhole","wt550","bulldog","grenadelauncher","goldenrevolver","sniper","medibeam","scatterbeam")
var/list/magiclist = list("fireball","smoke","blind","mindswap","forcewall","knock","horsemask","charge", "summonitem", "wandnothing", "wanddeath", "wandresurrection", "wandpolymorph", "wandteleport", "wanddoor", "wandfireball", "staffchange", "staffhealing", "armor", "scrying","staffdoor","voodoo", "special")
var/list/magicspeciallist = list("staffchange","staffanimation", "wandbelt", "contract", "staffchaos", "necromantic")
if(user) //in this case either someone holding a spellbook or a badmin
user << "<B>You summoned [summon_type ? "magic" : "guns"]!</B>"
message_admins("[key_name_admin(user, 1)] summoned [summon_type ? "magic" : "guns"]!")
log_game("[key_name(user)] summoned [summon_type ? "magic" : "guns"]!")
for(var/mob/living/carbon/human/H in player_list)
if(H.stat == 2 || !(H.client)) continue
if(H.mind)
if(H.mind.special_role == "Wizard" || H.mind.special_role == "apprentice" || H.mind.special_role == "survivalist") continue
if(prob(survivor_probability) && !(H.mind in ticker.mode.traitors))
ticker.mode.traitors += H.mind
var/datum/objective/summon_guns/guns = new
guns.owner = H.mind
H.mind.objectives += guns
H.mind.special_role = "survivalist"
var/datum/objective/survive/survive = new
survive.owner = H.mind
H.mind.objectives += survive
H.attack_log += "\[[time_stamp()]\] <font color='red'>Was made into a survivalist, and trusts no one!</font>"
H << "<B>You are the survivalist! Your own safety matters above all else, and the only way to ensure your safety is to stockpile weapons! Grab as many guns as possible, by any means necessary. Kill anyone who gets in your way.</B>"
var/obj_count = 1
for(var/datum/objective/OBJ in H.mind.objectives)
H << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"
obj_count++
var/randomizeguns = pick(gunslist)
var/randomizemagic = pick(magiclist)
var/randomizemagicspecial = pick(magicspeciallist)
if(!summon_type)
var/obj/item/weapon/gun/G
switch (randomizeguns)
if("taser")
G = new /obj/item/weapon/gun/energy/gun/advtaser(get_turf(H))
if("egun")
G = new /obj/item/weapon/gun/energy/gun(get_turf(H))
if("laser")
G = new /obj/item/weapon/gun/energy/laser(get_turf(H))
if("revolver")
G = new /obj/item/weapon/gun/projectile/revolver(get_turf(H))
if("detective")
G = new /obj/item/weapon/gun/projectile/revolver/detective(get_turf(H))
if("deagle")
G = new /obj/item/weapon/gun/projectile/automatic/pistol/deagle/camo(get_turf(H))
if("gyrojet")
G = new /obj/item/weapon/gun/projectile/automatic/gyropistol(get_turf(H))
if("pulse")
G = new /obj/item/weapon/gun/energy/pulse(get_turf(H))
if("suppressed")
G = new /obj/item/weapon/gun/projectile/automatic/pistol(get_turf(H))
new /obj/item/weapon/suppressor(get_turf(H))
if("doublebarrel")
G = new /obj/item/weapon/gun/projectile/revolver/doublebarrel(get_turf(H))
if("shotgun")
G = new /obj/item/weapon/gun/projectile/shotgun(get_turf(H))
if("combatshotgun")
G = new /obj/item/weapon/gun/projectile/shotgun/automatic/combat(get_turf(H))
if("arg")
G = new /obj/item/weapon/gun/projectile/automatic/ar(get_turf(H))
if("mateba")
G = new /obj/item/weapon/gun/projectile/revolver/mateba(get_turf(H))
if("boltaction")
G = new /obj/item/weapon/gun/projectile/shotgun/boltaction(get_turf(H))
if("speargun")
G = new /obj/item/weapon/gun/projectile/automatic/speargun(get_turf(H))
if("uzi")
G = new /obj/item/weapon/gun/projectile/automatic/mini_uzi(get_turf(H))
if("cannon")
G = new /obj/item/weapon/gun/energy/lasercannon(get_turf(H))
if("crossbow")
G = new /obj/item/weapon/gun/energy/kinetic_accelerator/crossbow/large(get_turf(H))
if("nuclear")
G = new /obj/item/weapon/gun/energy/gun/nuclear(get_turf(H))
if("sabr")
G = new /obj/item/weapon/gun/projectile/automatic/proto(get_turf(H))
if("bulldog")
G = new /obj/item/weapon/gun/projectile/automatic/shotgun/bulldog(get_turf(H))
if("c20r")
G = new /obj/item/weapon/gun/projectile/automatic/c20r(get_turf(H))
if("saw")
G = new /obj/item/weapon/gun/projectile/automatic/l6_saw(get_turf(H))
if("car")
G = new /obj/item/weapon/gun/projectile/automatic/m90(get_turf(H))
if("alienpistol")
G = new /obj/item/weapon/gun/energy/alien(get_turf(H))
if("dragnet")
G = new /obj/item/weapon/gun/energy/gun/dragnet(get_turf(H))
if("turret")
G = new /obj/item/weapon/gun/energy/gun/turret(get_turf(H))
if("pulsecarbine")
G = new /obj/item/weapon/gun/energy/pulse/carbine(get_turf(H))
if("decloner")
G = new /obj/item/weapon/gun/energy/decloner(get_turf(H))
if("mindflayer")
G = new /obj/item/weapon/gun/energy/mindflayer(get_turf(H))
if("hyperkinetic")
G = new /obj/item/weapon/gun/energy/kinetic_accelerator/hyper(get_turf(H))
if("advplasmacutter")
G = new /obj/item/weapon/gun/energy/plasmacutter/adv(get_turf(H))
if("wormhole")
G = new /obj/item/weapon/gun/energy/wormhole_projector(get_turf(H))
if("wt550")
G = new /obj/item/weapon/gun/projectile/automatic/wt550(get_turf(H))
if("bulldog")
G = new /obj/item/weapon/gun/projectile/automatic/shotgun(get_turf(H))
if("grenadelauncher")
G = new /obj/item/weapon/gun/projectile/revolver/grenadelauncher(get_turf(H))
if("goldenrevolver")
G = new /obj/item/weapon/gun/projectile/revolver/golden(get_turf(H))
if("sniper")
G = new /obj/item/weapon/gun/projectile/automatic/sniper_rifle(get_turf(H))
if("medibeam")
G = new /obj/item/weapon/gun/medbeam(get_turf(H))
if("scatterbeam")
G = new /obj/item/weapon/gun/energy/laser/scatter(get_turf(H))
if("gravgun")
G = new /obj/item/weapon/gun/energy/gravity_gun(get_turf(H))
G.unlock()
playsound(get_turf(H),'sound/magic/Summon_guns.ogg', 50, 1)
else
switch (randomizemagic)
if("fireball")
new /obj/item/weapon/spellbook/oneuse/fireball(get_turf(H))
if("smoke")
new /obj/item/weapon/spellbook/oneuse/smoke(get_turf(H))
if("blind")
new /obj/item/weapon/spellbook/oneuse/blind(get_turf(H))
if("mindswap")
new /obj/item/weapon/spellbook/oneuse/mindswap(get_turf(H))
if("forcewall")
new /obj/item/weapon/spellbook/oneuse/forcewall(get_turf(H))
if("knock")
new /obj/item/weapon/spellbook/oneuse/knock(get_turf(H))
if("horsemask")
new /obj/item/weapon/spellbook/oneuse/barnyard(get_turf(H))
if("charge")
new /obj/item/weapon/spellbook/oneuse/charge(get_turf(H))
if("summonitem")
new /obj/item/weapon/spellbook/oneuse/summonitem(get_turf(H))
if("wandnothing")
new /obj/item/weapon/gun/magic/wand(get_turf(H))
if("wanddeath")
new /obj/item/weapon/gun/magic/wand/death(get_turf(H))
if("wandresurrection")
new /obj/item/weapon/gun/magic/wand/resurrection(get_turf(H))
if("wandpolymorph")
new /obj/item/weapon/gun/magic/wand/polymorph(get_turf(H))
if("wandteleport")
new /obj/item/weapon/gun/magic/wand/teleport(get_turf(H))
if("wanddoor")
new /obj/item/weapon/gun/magic/wand/door(get_turf(H))
if("wandfireball")
new /obj/item/weapon/gun/magic/wand/fireball(get_turf(H))
if("staffhealing")
new /obj/item/weapon/gun/magic/staff/healing(get_turf(H))
if("staffdoor")
new /obj/item/weapon/gun/magic/staff/door(get_turf(H))
if("armor")
new /obj/item/clothing/suit/space/hardsuit/wizard(get_turf(H))
if("scrying")
new /obj/item/weapon/scrying(get_turf(H))
if (!(H.dna.check_mutation(XRAY)))
H.dna.add_mutation(XRAY)
H << "<span class='notice'>The walls suddenly disappear.</span>"
if("voodoo")
new /obj/item/voodoo(get_turf(H))
if("special")
magiclist -= "special" //only one super OP item per summoning max
switch (randomizemagicspecial)
if("staffchange")
new /obj/item/weapon/gun/magic/staff/change(get_turf(H))
if("staffanimation")
new /obj/item/weapon/gun/magic/staff/animate(get_turf(H))
if("wandbelt")
new /obj/item/weapon/storage/belt/wands/full(get_turf(H))
if("contract")
new /obj/item/weapon/antag_spawner/contract(get_turf(H))
if("staffchaos")
new /obj/item/weapon/gun/magic/staff/chaos(get_turf(H))
if("necromantic")
new /obj/item/device/necromantic_stone(get_turf(H))
H << "<span class='notice'>You suddenly feel lucky.</span>"
playsound(get_turf(H),'sound/magic/Summon_Magic.ogg', 50, 1)
/proc/summonevents()
if(!SSevent.wizardmode)
SSevent.frequency_lower = 600 //1 minute lower bound
SSevent.frequency_upper = 3000 //5 minutes upper bound
SSevent.toggleWizardmode()
SSevent.reschedule()
else //Speed it up
SSevent.frequency_upper -= 600 //The upper bound falls a minute each time, making the AVERAGE time between events lessen
if(SSevent.frequency_upper < SSevent.frequency_lower) //Sanity
SSevent.frequency_upper = SSevent.frequency_lower
SSevent.reschedule()
message_admins("Summon Events intensifies, events will now occur every [SSevent.frequency_lower / 600] to [SSevent.frequency_upper / 600] minutes.")
log_game("Summon Events was increased!")
+15
View File
@@ -0,0 +1,15 @@
//Santa spells!
/obj/effect/proc_holder/spell/aoe_turf/conjure/presents
name = "Conjure Presents!"
desc = "This spell lets you reach into S-space and retrieve presents! Yay!"
school = "santa"
charge_max = 600
clothes_req = 0
invocation = "HO HO HO"
invocation_type = "shout"
range = 3
cooldown_min = 50
summon_type = list("/obj/item/weapon/a_gift")
summon_lifespan = 0
summon_amt = 5
@@ -0,0 +1,73 @@
/obj/effect/proc_holder/spell/targeted/shapeshift
name = "Shapechange"
desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed."
clothes_req = 0
human_req = 0
charge_max = 200
cooldown_min = 50
range = -1
include_user = 1
invocation = "RAC'WA NO!"
invocation_type = "shout"
action_icon_state = "shapeshift"
var/shapeshift_type
var/list/current_shapes = list()
var/list/current_casters = list()
var/list/possible_shapes = list(/mob/living/simple_animal/mouse,\
/mob/living/simple_animal/pet/dog/corgi,\
/mob/living/simple_animal/hostile/carp/ranged/chaos,\
/mob/living/simple_animal/bot/ed209,\
/mob/living/simple_animal/hostile/construct/armored)
/obj/effect/proc_holder/spell/targeted/shapeshift/cast(list/targets,mob/user = usr)
for(var/mob/living/M in targets)
if(!shapeshift_type)
var/list/animal_list = list()
for(var/path in possible_shapes)
var/mob/living/simple_animal/A = path
animal_list[initial(A.name)] = path
shapeshift_type = input(M, "Choose Your Animal Form!", "It's Morphing Time!", null) as anything in animal_list
if(!shapeshift_type) //If you aren't gonna decide I am!
shapeshift_type = pick(animal_list)
shapeshift_type = animal_list[shapeshift_type]
if(M in current_shapes)
Restore(M)
else
Shapeshift(M)
/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Shapeshift(mob/living/caster)
for(var/mob/living/M in caster)
if(M.status_flags & GODMODE)
caster << "<span class='warning'>You're already shapeshifted!</span>"
return
var/mob/living/shape = new shapeshift_type(caster.loc)
caster.loc = shape
caster.status_flags |= GODMODE
current_shapes |= shape
current_casters |= caster
clothes_req = 0
human_req = 0
caster.mind.transfer_to(shape)
/obj/effect/proc_holder/spell/targeted/shapeshift/proc/Restore(mob/living/shape)
var/mob/living/caster
for(var/mob/living/M in shape)
if(M in current_casters)
caster = M
break
if(!caster)
return
caster.loc = shape.loc
caster.status_flags &= ~GODMODE
clothes_req = initial(clothes_req)
human_req = initial(human_req)
current_casters.Remove(caster)
current_shapes.Remove(shape)
shape.mind.transfer_to(caster)
qdel(shape) //Gib it maybe ?
@@ -0,0 +1,108 @@
/obj/effect/proc_holder/spell/spacetime_dist
name = "Spacetime Distortion"
desc = "Entangle the strings of spacetime to deny easy movement around you. The strings vibrate..."
charge_max = 300
var/duration = 150
range = 7
var/list/effects
var/ready = TRUE
centcom_cancast = FALSE
sound = "sound/effects/magic.ogg"
/obj/effect/proc_holder/spell/spacetime_dist/can_cast(mob/user = usr)
if(ready)
return ..()
return FALSE
/obj/effect/proc_holder/spell/spacetime_dist/choose_targets(mob/user = usr)
var/list/turfs = spiral_range_turfs(range, user)
if(!turfs.len)
revert_cast()
return
ready = FALSE
var/list/turf_steps = list()
var/length = round(turfs.len * 0.5)
for(var/i in 1 to length)
turf_steps[pick_n_take(turfs)] = pick_n_take(turfs)
if(turfs.len > 0)
var/turf/loner = pick(turfs)
turf_steps[loner] = pick(Z_TURFS(user.z))
perform(turf_steps,user=user)
/obj/effect/proc_holder/spell/spacetime_dist/after_cast(list/targets)
addtimer(src, "clean_turfs", duration)
/obj/effect/proc_holder/spell/spacetime_dist/cast(list/targets, mob/user = usr)
effects = list()
for(var/V in targets)
var/turf/T0 = V
var/turf/T1 = targets[V]
var/obj/effect/cross_action/spacetime_dist/STD0 = new /obj/effect/cross_action/spacetime_dist(T0)
var/obj/effect/cross_action/spacetime_dist/STD1 = new /obj/effect/cross_action/spacetime_dist(T1)
STD0.linked_dist = STD1
STD1.linked_dist = STD0
effects += STD0
effects += STD1
/obj/effect/proc_holder/spell/spacetime_dist/proc/clean_turfs()
for(var/effect in effects)
qdel(effect)
effects.Cut()
effects = null
ready = TRUE
/obj/effect/cross_action
name = "cross me"
desc = "for crossing"
anchored = 1
/obj/effect/cross_action/spacetime_dist
name = "spacetime distortion"
desc = "A distortion in spacetime. You can hear faint music..."
icon_state = "wave1"
color = "#8A2BE2"
var/obj/effect/cross_action/spacetime_dist/linked_dist
var/busy = FALSE
var/sound
var/walks_left = 50 //prevents the game from hanging in extreme cases (such as minigun fire)
/obj/effect/cross_action/spacetime_dist/New()
..()
sound = "sound/guitar/[safepick(guitar_notes)]"
/obj/effect/cross_action/spacetime_dist/proc/walk_link(atom/movable/AM)
if(linked_dist && walks_left > 0)
flick("purplesparkles", src)
linked_dist.get_walker(AM)
walks_left--
/obj/effect/cross_action/spacetime_dist/proc/get_walker(atom/movable/AM)
busy = TRUE
if(linked_dist)
flick("purplesparkles", src)
AM.forceMove(get_turf(src))
playsound(get_turf(src),sound,70,0)
busy = FALSE
/obj/effect/cross_action/spacetime_dist/Crossed(atom/movable/AM)
if(!busy)
walk_link(AM)
/obj/effect/cross_action/spacetime_dist/attackby(obj/item/W, mob/user, params)
if(user.unEquip(W))
walk_link(W)
else
walk_link(user)
/obj/effect/cross_action/spacetime_dist/attack_hand(mob/user)
walk_link(user)
/obj/effect/cross_action/spacetime_dist/attack_paw(mob/user)
walk_link(user)
/obj/effect/cross_action/spacetime_dist/Destroy()
busy = TRUE
linked_dist = null
return ..()
@@ -0,0 +1,116 @@
/obj/effect/proc_holder/spell/targeted/summonitem
name = "Instant Summons"
desc = "This spell can be used to recall a previously marked item to your hand from anywhere in the universe."
school = "transmutation"
charge_max = 100
clothes_req = 0
invocation = "GAR YOK"
invocation_type = "whisper"
range = -1
level_max = 0 //cannot be improved
cooldown_min = 100
include_user = 1
var/obj/marked_item
action_icon_state = "summons"
/obj/effect/proc_holder/spell/targeted/summonitem/cast(list/targets,mob/user = usr)
for(var/mob/living/L in targets)
var/list/hand_items = list(L.get_active_hand(),L.get_inactive_hand())
var/butterfingers = 0
var/message
if(!marked_item) //linking item to the spell
message = "<span class='notice'>"
for(var/obj/item in hand_items)
if(ABSTRACT in item.flags)
continue
if(NODROP in item.flags)
message += "Though it feels redundant, "
marked_item = item
message += "You mark [item] for recall.</span>"
name = "Recall [item]"
break
if(!marked_item)
if(hand_items)
message = "<span class='caution'>You aren't holding anything that can be marked for recall.</span>"
else
message = "<span class='notice'>You must hold the desired item in your hands to mark it for recall.</span>"
else if(marked_item && marked_item in hand_items) //unlinking item to the spell
message = "<span class='notice'>You remove the mark on [marked_item] to use elsewhere.</span>"
name = "Instant Summons"
marked_item = null
else if(marked_item && qdeleted(marked_item)) //the item was destroyed at some point
message = "<span class='warning'>You sense your marked item has been destroyed!</span>"
name = "Instant Summons"
marked_item = null
else //Getting previously marked item
var/obj/item_to_retrive = marked_item
var/infinite_recursion = 0 //I don't want to know how someone could put something inside itself but these are wizards so let's be safe
if(!item_to_retrive.loc)
if(isorgan(item_to_retrive)) // Organs are usually stored in nullspace
var/obj/item/organ/organ = item_to_retrive
if(organ.owner)
// If this code ever runs I will be happy
add_logs(L, organ.owner, "magically removed [organ.name] from", addition="INTENT: [uppertext(L.a_intent)]")
organ.Remove(organ.owner)
else
while(!isturf(item_to_retrive.loc) && infinite_recursion < 10) //if it's in something you get the whole thing.
if(ismob(item_to_retrive.loc)) //If its on someone, properly drop it
var/mob/M = item_to_retrive.loc
if(issilicon(M)) //Items in silicons warp the whole silicon
M.loc.visible_message("<span class='warning'>[M] suddenly disappears!</span>")
M.loc = L.loc
M.loc.visible_message("<span class='caution'>[M] suddenly appears!</span>")
item_to_retrive = null
break
M.unEquip(item_to_retrive)
if(iscarbon(M)) //Edge case housekeeping
var/mob/living/carbon/C = M
if(C.stomach_contents && item_to_retrive in C.stomach_contents)
C.stomach_contents -= item_to_retrive
else
if(istype(item_to_retrive.loc,/obj/machinery/portable_atmospherics/)) //Edge cases for moved machinery
var/obj/machinery/portable_atmospherics/P = item_to_retrive.loc
P.disconnect()
P.update_icon()
item_to_retrive = item_to_retrive.loc
infinite_recursion += 1
if(!item_to_retrive)
return
if(item_to_retrive.loc)
item_to_retrive.loc.visible_message("<span class='warning'>The [item_to_retrive.name] suddenly disappears!</span>")
if(L.hand) //left active hand
if(!L.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
if(!L.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
butterfingers = 1
else //right active hand
if(!L.equip_to_slot_if_possible(item_to_retrive, slot_r_hand, 0, 1, 1))
if(!L.equip_to_slot_if_possible(item_to_retrive, slot_l_hand, 0, 1, 1))
butterfingers = 1
if(butterfingers)
item_to_retrive.loc = L.loc
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears!</span>")
playsound(get_turf(L),"sound/magic/SummonItems_generic.ogg",50,1)
else
item_to_retrive.loc.visible_message("<span class='caution'>The [item_to_retrive.name] suddenly appears in [L]'s hand!</span>")
playsound(get_turf(L),"sound/magic/SummonItems_generic.ogg",50,1)
if(message)
L << message
@@ -0,0 +1,70 @@
/obj/effect/proc_holder/spell/targeted/touch/
var/hand_path = "/obj/item/weapon/melee/touch_attack"
var/obj/item/weapon/melee/touch_attack/attached_hand = null
invocation_type = "none" //you scream on connecting, not summoning
include_user = 1
range = -1
/obj/effect/proc_holder/spell/targeted/touch/Click(mob/user = usr)
if(attached_hand)
qdel(attached_hand)
charge_counter = charge_max
attached_hand = null
user << "<span class='notice'>You draw the power out of your hand.</span>"
return 0
..()
/obj/effect/proc_holder/spell/targeted/touch/cast(list/targets,mob/user = usr)
for(var/mob/living/carbon/C in targets)
if(!attached_hand)
if(!ChargeHand(C))
return 0
while(attached_hand) //hibernate untill the spell is actually used
charge_counter = 0
sleep(1)
/obj/effect/proc_holder/spell/targeted/touch/proc/ChargeHand(mob/living/carbon/user)
var/hand_handled = 1
attached_hand = new hand_path(src)
if(user.hand) //left active hand
if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1))
if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1))
hand_handled = 0
else //right active hand
if(!user.equip_to_slot_if_possible(attached_hand, slot_r_hand, 0, 1, 1))
if(!user.equip_to_slot_if_possible(attached_hand, slot_l_hand, 0, 1, 1))
hand_handled = 0
if(!hand_handled)
qdel(attached_hand)
charge_counter = charge_max
attached_hand = null
user << "<span class='warning'>Your hands are full!</span>"
return 0
user << "<span class='notice'>You channel the power of the spell to your hand.</span>"
return 1
/obj/effect/proc_holder/spell/targeted/touch/disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
hand_path = "/obj/item/weapon/melee/touch_attack/disintegrate"
school = "evocation"
charge_max = 600
clothes_req = 1
cooldown_min = 200 //100 deciseconds reduction per rank
action_icon_state = "gib"
/obj/effect/proc_holder/spell/targeted/touch/flesh_to_stone
name = "Flesh to Stone"
desc = "This spell charges your hand with the power to turn victims into inert statues for a long period of time."
hand_path = "/obj/item/weapon/melee/touch_attack/fleshtostone"
school = "transmutation"
charge_max = 600
clothes_req = 1
cooldown_min = 200 //100 deciseconds reduction per rank
action_icon_state = "statue"
sound = "sound/magic/FleshToStone.ogg"
@@ -0,0 +1,30 @@
/obj/effect/proc_holder/spell/targeted/trigger
name = "Trigger"
desc = "This spell triggers another spell or a few."
var/list/linked_spells = list() //those are just referenced by the trigger spell and are unaffected by it directly
var/list/starting_spells = list() //those are added on New() to contents from default spells and are deleted when the trigger spell is deleted to prevent memory leaks
/obj/effect/proc_holder/spell/targeted/trigger/New()
..()
for(var/spell in starting_spells)
var/spell_to_add = text2path(spell)
new spell_to_add(src) //should result in adding to contents, needs testing
/obj/effect/proc_holder/spell/targeted/trigger/Destroy()
for(var/spell in contents)
qdel(spell)
linked_spells = null
starting_spells = null
return ..()
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets,mob/user = usr)
playMagSound()
for(var/mob/living/target in targets)
for(var/obj/effect/proc_holder/spell/spell in contents)
spell.perform(list(target),0)
for(var/obj/effect/proc_holder/spell/spell in linked_spells)
spell.perform(list(target),0)
return
@@ -0,0 +1,46 @@
/obj/effect/proc_holder/spell/targeted/turf_teleport
name = "Turf Teleport"
desc = "This spell teleports the target to the turf in range."
nonabstract_req = 1
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
var/sound1 = "sound/weapons/ZapBang.ogg"
var/sound2 = "sound/weapons/ZapBang.ogg"
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets,mob/user = usr)
playsound(get_turf(user), sound1, 50,1)
for(var/mob/living/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/open/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
if(!target.Move(picked))
if(target.buckled)
target.buckled.unbuckle_mob(target,force=1)
if(target.has_buckled_mobs())
target.unbuckle_all_mobs(force=1)
target.loc = picked
playsound(get_turf(user), sound2, 50,1)
+352
View File
@@ -0,0 +1,352 @@
/obj/effect/proc_holder/spell/targeted/projectile/magic_missile
name = "Magic Missile"
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
school = "evocation"
charge_max = 200
clothes_req = 1
invocation = "FORTI GY AMA"
invocation_type = "shout"
range = 7
cooldown_min = 60 //35 deciseconds reduction per rank
max_targets = 0
proj_icon_state = "magicm"
proj_name = "a magic missile"
proj_lingering = 1
proj_type = "/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile"
proj_lifespan = 20
proj_step_delay = 5
proj_trail = 1
proj_trail_lifespan = 5
proj_trail_icon_state = "magicmd"
action_icon_state = "magicm"
sound = "sound/magic/MAGIC_MISSILE.ogg"
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
amt_weakened = 3
sound = "sound/magic/MM_Hit.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/mutate
name = "Mutate"
desc = "This spell causes you to turn into a hulk and gain laser vision for a short while."
school = "transmutation"
charge_max = 400
clothes_req = 1
invocation = "BIRUZ BENNAR"
invocation_type = "shout"
range = -1
include_user = 1
centcom_cancast = 0
mutations = list(LASEREYES, HULK)
duration = 300
cooldown_min = 300 //25 deciseconds reduction per rank
action_icon_state = "mutate"
sound = "sound/magic/Mutate.ogg"
/obj/effect/proc_holder/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_user = 1
cooldown_min = 20 //25 deciseconds reduction per rank
smoke_spread = 2
smoke_amt = 4
action_icon_state = "smoke"
/obj/effect/proc_holder/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_user = 1
cooldown_min = 200 //50 deciseconds reduction per rank
emp_heavy = 6
emp_light = 10
sound = "sound/magic/Disable_Tech.ogg"
/obj/effect/proc_holder/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_user = 1
cooldown_min = 5 //4 deciseconds reduction per rank
smoke_spread = 1
smoke_amt = 0
inner_tele_radius = 0
outer_tele_radius = 6
centcom_cancast = 0 //prevent people from getting to centcom
action_icon_state = "blink"
sound1="sound/magic/blink.ogg"
sound2="sound/magic/blink.ogg"
/obj/effect/proc_holder/spell/targeted/turf_teleport/blink/cult
name = "quickstep"
charge_max = 100
clothes_req = 0
cult_req = 1
/obj/effect/proc_holder/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_user = 1
cooldown_min = 200 //100 deciseconds reduction per rank
smoke_spread = 1
smoke_amt = 2
sound1="sound/magic/Teleport_diss.ogg"
sound2="sound/magic/Teleport_app.ogg"
/obj/effect/proc_holder/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
cooldown_min = 50 //12 deciseconds reduction per rank
summon_type = list("/obj/effect/forcefield")
summon_lifespan = 300
action_icon_state = "shield"
cast_sound = "sound/magic/ForceWall.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/timestop
name = "Stop Time"
desc = "This spell stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen."
charge_max = 500
clothes_req = 1
invocation = "TOKI WO TOMARE"
invocation_type = "shout"
range = 0
cooldown_min = 100
summon_amt = 1
action_icon_state = "time"
summon_type = list(/obj/effect/timestop/wizard)
/obj/effect/proc_holder/spell/aoe_turf/conjure/carp
name = "Summon Carp"
desc = "This spell conjures a simple carp."
school = "conjuration"
charge_max = 1200
clothes_req = 1
invocation = "NOUK FHUNMM SACP RISSKA"
invocation_type = "shout"
range = 1
summon_type = list(/mob/living/simple_animal/hostile/carp)
cast_sound = "sound/magic/Summon_Karp.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct
name = "Artificer"
desc = "This spell conjures a construct which may be controlled by Shades"
school = "conjuration"
charge_max = 600
clothes_req = 0
invocation = "none"
invocation_type = "none"
range = 0
summon_type = list(/obj/structure/constructshell)
action_icon_state = "artificer"
cast_sound = "sound/magic/SummonItems_generic.ogg"
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature
name = "Summon Creature Swarm"
desc = "This spell tears the fabric of reality, allowing horrific daemons to spill forth"
school = "conjuration"
charge_max = 1200
clothes_req = 0
invocation = "IA IA"
invocation_type = "shout"
summon_amt = 10
range = 3
summon_type = list(/mob/living/simple_animal/hostile/creature)
cast_sound = "sound/magic/SummonItems_generic.ogg"
/obj/effect/proc_holder/spell/targeted/trigger/blind
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 = "<span class='notice'>Your eyes cry out in pain!</span>"
cooldown_min = 50 //12 deciseconds reduction per rank
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind")
action_icon_state = "blind"
/obj/effect/proc_holder/spell/aoe_turf/conjure/creature/cult
name = "Summon Creatures (DANGEROUS)"
cult_req = 1
charge_max = 5000
summon_amt = 2
/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
amt_eye_blind = 10
amt_eye_blurry = 20
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/targeted/genetic/blind
mutations = list(BLINDMUT)
duration = 300
sound="sound/magic/Blind.ogg"
/obj/effect/proc_holder/spell/dumbfire/fireball
name = "Fireball"
desc = "This spell fires a fireball at a target and does not require wizard garb."
school = "evocation"
charge_max = 60
clothes_req = 0
invocation = "ONI SOMA"
invocation_type = "shout"
range = 20
cooldown_min = 20 //10 deciseconds reduction per rank
proj_icon_state = "fireball"
proj_name = "a fireball"
proj_type = "/obj/effect/proc_holder/spell/turf/fireball"
proj_lifespan = 200
proj_step_delay = 1
action_icon_state = "fireball"
sound = "sound/magic/Fireball.ogg"
/obj/effect/proc_holder/spell/turf/fireball/cast(turf/T,mob/user = usr)
explosion(T, -1, 0, 2, 3, 0, flame_range = 2)
/obj/effect/proc_holder/spell/targeted/inflict_handler/fireball
amt_dam_brute = 20
amt_dam_fire = 25
/obj/effect/proc_holder/spell/targeted/explosion/fireball
ex_severe = -1
ex_heavy = -1
ex_light = 2
ex_flash = 5
/obj/effect/proc_holder/spell/aoe_turf/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
charge_max = 400
clothes_req = 1
invocation = "GITTAH WEIGH"
invocation_type = "shout"
range = 5
cooldown_min = 150
selection_type = "view"
sound = 'sound/magic/Repulse.ogg'
var/maxthrow = 5
var/sparkle_path = /obj/effect/overlay/temp/sparkle
action_icon_state = "repulse"
/obj/effect/proc_holder/spell/aoe_turf/repulse/cast(list/targets,mob/user = usr)
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
playMagSound()
for(var/turf/T in targets) //Done this way so things don't get thrown all around hilariously.
for(var/atom/movable/AM in T)
thrownatoms += AM
for(var/atom/movable/AM in thrownatoms)
if(AM == user || AM.anchored) continue
// created sparkles will disappear on their own
PoolOrNew(sparkle_path, AM)
throwtarget = get_edge_target_turf(user, get_dir(user, get_step_away(AM, user)))
distfromcaster = get_dist(user, AM)
if(distfromcaster == 0)
if(istype(AM, /mob/living))
var/mob/living/M = AM
M.Weaken(5)
M.adjustBruteLoss(5)
M << "<span class='userdanger'>You're slammed into the floor by [user]!</span>"
else
if(istype(AM, /mob/living))
var/mob/living/M = AM
M.Weaken(2)
M << "<span class='userdanger'>You're thrown back by [user]!</span>"
AM.throw_at_fast(throwtarget, ((Clamp((maxthrow - (Clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1,user)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno //i fixed conflicts only to find out that this is in the WIZARD file instead of the xeno file?!
name = "Tail Sweep"
desc = "Throw back attackers with a sweep of your tail."
sound = 'sound/magic/Tail_swing.ogg'
charge_max = 150
clothes_req = 0
range = 2
cooldown_min = 150
invocation_type = "none"
sparkle_path = /obj/effect/overlay/temp/sparkle/tailsweep
action_icon_state = "tailsweep"
action_background_icon_state = "bg_alien"
/obj/effect/proc_holder/spell/aoe_turf/repulse/xeno/cast(list/targets,mob/user = usr)
if(istype(user, /mob/living/carbon))
var/mob/living/carbon/C = user
playsound(C.loc, 'sound/voice/hiss5.ogg', 80, 1, 1)
C.spin(6,1)
..()