initial commit - cross reference with 5th port - obviously has compile errors
This commit is contained in:
@@ -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>"
|
||||
@@ -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"
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
@@ -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!")
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
..()
|
||||
Reference in New Issue
Block a user