mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 18:22:39 +00:00
Ports /vg/'s spell system for the sake of cult porting.
Does offer a much more pleasant basis to work with in the future, if someone wishes to add more spell-like abilities.
This commit is contained in:
25
code/modules/spells/aoe_turf/aoe_turf.dm
Normal file
25
code/modules/spells/aoe_turf/aoe_turf.dm
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
Aoe turf spells target a ring of tiles around the user
|
||||
This ring has an outer radius (range) and an inner radius (inner_radius)
|
||||
Aoe turf spells have two useful flags: IGNOREDENSE and IGNORESPACE. These are explained in setup.dm
|
||||
*/
|
||||
|
||||
/spell/aoe_turf //affects all turfs in view or range (depends)
|
||||
spell_flags = IGNOREDENSE
|
||||
var/inner_radius = -1 //for all your ring spell needs
|
||||
|
||||
/spell/aoe_turf/choose_targets(mob/user = usr)
|
||||
var/list/targets = list()
|
||||
|
||||
for(var/turf/target in view_or_range(range,user,selection_type))
|
||||
if(!(target in view_or_range(inner_radius,user,selection_type)))
|
||||
if(target.density && (spell_flags & IGNOREDENSE))
|
||||
continue
|
||||
if(istype(target, /turf/space) && (spell_flags & IGNORESPACE))
|
||||
continue
|
||||
targets += target
|
||||
|
||||
if(!targets.len) //doesn't waste the spell
|
||||
return
|
||||
|
||||
return targets
|
||||
34
code/modules/spells/aoe_turf/blink.dm
Normal file
34
code/modules/spells/aoe_turf/blink.dm
Normal file
@@ -0,0 +1,34 @@
|
||||
/spell/aoe_turf/blink
|
||||
name = "Blink"
|
||||
desc = "This spell randomly teleports you a short distance."
|
||||
|
||||
school = "abjuration"
|
||||
charge_max = 20
|
||||
spell_flags = Z2NOCAST | IGNOREDENSE | IGNORESPACE
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 7
|
||||
inner_radius = 1
|
||||
cooldown_min = 5 //4 deciseconds reduction per rank
|
||||
hud_state = "wiz_blink"
|
||||
|
||||
/spell/aoe_turf/blink/cast(var/list/targets, mob/user)
|
||||
if(!targets.len)
|
||||
return
|
||||
|
||||
var/turf/T = pick(targets)
|
||||
var/turf/starting = get_turf(user)
|
||||
if(T)
|
||||
if(user.buckled)
|
||||
user.buckled = null
|
||||
user.forceMove(T)
|
||||
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(3, 0, starting)
|
||||
smoke.start()
|
||||
|
||||
smoke = new()
|
||||
smoke.set_up(3, 0, T)
|
||||
smoke.start()
|
||||
|
||||
return
|
||||
69
code/modules/spells/aoe_turf/charge.dm
Normal file
69
code/modules/spells/aoe_turf/charge.dm
Normal file
@@ -0,0 +1,69 @@
|
||||
/spell/aoe_turf/charge
|
||||
name = "Charge"
|
||||
desc = "This spell can be used to charge up spent magical artifacts, among other things."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
spell_flags = 0
|
||||
invocation = "DIRI CEL"
|
||||
invocation_type = SpI_WHISPER
|
||||
range = 0
|
||||
cooldown_min = 400 //50 deciseconds reduction per rank
|
||||
|
||||
hud_state = "wiz_charge"
|
||||
|
||||
/spell/aoe_turf/charge/cast(var/list/targets, mob/user)
|
||||
for(var/turf/T in targets)
|
||||
depth_cast(T)
|
||||
|
||||
/spell/aoe_turf/charge/proc/depth_cast(var/list/targets)
|
||||
for(var/atom/A in targets)
|
||||
if(A.contents.len)
|
||||
depth_cast(A.contents)
|
||||
cast_charge(A)
|
||||
|
||||
/spell/aoe_turf/charge/proc/mob_charge(var/mob/living/M)
|
||||
if(M.spell_list.len != 0)
|
||||
for(var/spell/S in M.spell_list)
|
||||
if(!istype(S, /spell/aoe_turf/charge))
|
||||
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>"
|
||||
return M
|
||||
|
||||
/spell/aoe_turf/charge/proc/cast_charge(var/atom/target)
|
||||
var/atom/charged_item
|
||||
|
||||
if(istype(target, /mob/living))
|
||||
charged_item = mob_charge(target)
|
||||
|
||||
if(istype(target, /obj/item/weapon/grab))
|
||||
var/obj/item/weapon/grab/G = target
|
||||
if(G.affecting)
|
||||
var/mob/M = G.affecting
|
||||
charged_item = mob_charge(M)
|
||||
|
||||
if(istype(target, /obj/item/weapon/spellbook/oneuse))
|
||||
var/obj/item/weapon/spellbook/oneuse/I = target
|
||||
if(prob(50))
|
||||
I.visible_message("<span class='warning'>[I] catches fire!</span>")
|
||||
del(I)
|
||||
else
|
||||
I.used = 0
|
||||
charged_item = I
|
||||
|
||||
if(istype(target, /obj/item/weapon/cell/))
|
||||
var/obj/item/weapon/cell/C = target
|
||||
if(prob(80))
|
||||
C.maxcharge -= 200
|
||||
if(C.maxcharge <= 1) //Div by 0 protection
|
||||
C.maxcharge = 1
|
||||
C.charge = C.maxcharge
|
||||
charged_item = C
|
||||
|
||||
if(!charged_item)
|
||||
return 0
|
||||
else
|
||||
charged_item.visible_message("<span class='notice'>[charged_item] suddenly sparks with energy!</span>")
|
||||
return 1
|
||||
74
code/modules/spells/aoe_turf/conjure/conjure.dm
Normal file
74
code/modules/spells/aoe_turf/conjure/conjure.dm
Normal file
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
Conjure spells spawn things (mobs, objs, turfs) in their summon_type
|
||||
How they spawn stuff is decided by behaviour vars, which are explained below
|
||||
*/
|
||||
|
||||
/spell/aoe_turf/conjure
|
||||
name = "Conjure"
|
||||
desc = "This spell conjures objs of the specified types in range."
|
||||
|
||||
school = "conjuration" //funny, that
|
||||
|
||||
var/list/summon_type = list() //determines what exactly will be summoned
|
||||
//should be text, like list("/obj/machinery/bot/ed209")
|
||||
|
||||
range = 0 //default values: only spawn on the player tile
|
||||
selection_type = "view"
|
||||
|
||||
duration = 0 // 0=permanent, any other time in deciseconds - how long the summoned objects last for
|
||||
var/summon_amt = 1 //amount of objects summoned
|
||||
var/summon_exclusive = 0 //spawn one of everything, instead of random things
|
||||
|
||||
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
|
||||
|
||||
cast_sound = 'sound/items/welder.ogg'
|
||||
|
||||
/spell/aoe_turf/conjure/cast(list/targets, mob/user)
|
||||
playsound(get_turf(user), cast_sound, 50, 1)
|
||||
|
||||
for(var/i=1,i <= summon_amt,i++)
|
||||
if(!targets.len)
|
||||
break
|
||||
var/summoned_object_type
|
||||
if(summon_exclusive)
|
||||
if(!summon_type.len)
|
||||
break
|
||||
summoned_object_type = summon_type[1]
|
||||
summon_type -= summoned_object_type
|
||||
else
|
||||
summoned_object_type = pick(summon_type)
|
||||
var/turf/spawn_place = pick(targets)
|
||||
if(spell_flags & IGNOREPREV)
|
||||
targets -= spawn_place
|
||||
|
||||
var/atom/summoned_object
|
||||
if(ispath(summoned_object_type,/turf))
|
||||
if(istype(get_turf(user),/turf/simulated/shuttle) || istype(spawn_place, /turf/simulated/shuttle))
|
||||
user << "<span class='warning>You can't build things on shuttles!</span>"
|
||||
continue
|
||||
spawn_place.ChangeTurf(summoned_object_type)
|
||||
summoned_object = spawn_place
|
||||
else
|
||||
summoned_object = new summoned_object_type(spawn_place)
|
||||
var/atom/movable/overlay/animation = new /atom/movable/overlay(spawn_place)
|
||||
animation.name = "conjure"
|
||||
animation.density = 0
|
||||
animation.anchored = 1
|
||||
animation.icon = 'icons/effects/effects.dmi'
|
||||
animation.layer = 3
|
||||
animation.master = summoned_object
|
||||
|
||||
for(var/varName in newVars)
|
||||
if(varName in summoned_object.vars)
|
||||
summoned_object.vars[varName] = newVars[varName]
|
||||
|
||||
if(duration)
|
||||
spawn(duration)
|
||||
if(summoned_object && !istype(summoned_object, /turf))
|
||||
qdel(summoned_object)
|
||||
conjure_animation(animation, spawn_place)
|
||||
return
|
||||
|
||||
/spell/aoe_turf/conjure/proc/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
|
||||
del(animation)
|
||||
137
code/modules/spells/aoe_turf/conjure/construct.dm
Normal file
137
code/modules/spells/aoe_turf/conjure/construct.dm
Normal file
@@ -0,0 +1,137 @@
|
||||
//////////////////////////////Construct Spells/////////////////////////
|
||||
|
||||
/spell/aoe_turf/conjure/construct
|
||||
name = "Artificer"
|
||||
desc = "This spell conjures a construct which may be controlled by Shades"
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 600
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/constructshell)
|
||||
|
||||
hud_state = "artificer"
|
||||
|
||||
/spell/aoe_turf/conjure/construct/lesser
|
||||
charge_max = 1800
|
||||
summon_type = list(/obj/structure/constructshell/cult)
|
||||
hud_state = "const_shell"
|
||||
override_base = "const"
|
||||
|
||||
/spell/aoe_turf/conjure/floor
|
||||
name = "Floor Construction"
|
||||
desc = "This spell constructs a cult floor"
|
||||
|
||||
charge_max = 20
|
||||
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
summon_type = list(/turf/simulated/floor/engine/cult)
|
||||
|
||||
hud_state = "const_floor"
|
||||
|
||||
/spell/aoe_turf/conjure/floor/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
|
||||
animation.icon_state = "cultfloor"
|
||||
flick("cultfloor",animation)
|
||||
spawn(10)
|
||||
del(animation)
|
||||
|
||||
/spell/aoe_turf/conjure/wall
|
||||
name = "Lesser Construction"
|
||||
desc = "This spell constructs a cult wall"
|
||||
|
||||
charge_max = 100
|
||||
spell_flags = Z2NOCAST | CONSTRUCT_CHECK
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
summon_type = list(/turf/simulated/wall/cult)
|
||||
|
||||
hud_state = "const_wall"
|
||||
|
||||
/spell/aoe_turf/conjure/wall/conjure_animation(var/atom/movable/overlay/animation, var/turf/target)
|
||||
animation.icon_state = "cultwall"
|
||||
flick("cultwall",animation)
|
||||
spawn(10)
|
||||
del(animation)
|
||||
|
||||
/spell/aoe_turf/conjure/wall/reinforced
|
||||
name = "Greater Construction"
|
||||
desc = "This spell constructs a reinforced metal wall"
|
||||
|
||||
charge_max = 300
|
||||
spell_flags = Z2NOCAST
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
cast_delay = 50
|
||||
|
||||
summon_type = list(/turf/simulated/wall/r_wall)
|
||||
|
||||
/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"
|
||||
|
||||
charge_max = 3000
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/item/device/soulstone)
|
||||
|
||||
hud_state = "const_stone"
|
||||
override_base = "const"
|
||||
|
||||
/spell/aoe_turf/conjure/pylon
|
||||
name = "Red Pylon"
|
||||
desc = "This spell conjures a fragile crystal from Nar-Sie's realm. Makes for a convenient light source."
|
||||
|
||||
charge_max = 200
|
||||
spell_flags = CONSTRUCT_CHECK
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
|
||||
summon_type = list(/obj/structure/cult/pylon)
|
||||
|
||||
hud_state = "const_pylon"
|
||||
|
||||
/spell/aoe_turf/conjure/pylon/cast(list/targets)
|
||||
..()
|
||||
var/turf/spawn_place = pick(targets)
|
||||
for(var/obj/structure/cult/pylon/P in spawn_place.contents)
|
||||
if(P.isbroken)
|
||||
P.repair(usr)
|
||||
continue
|
||||
return
|
||||
|
||||
/spell/aoe_turf/conjure/forcewall/lesser
|
||||
name = "Shield"
|
||||
desc = "Allows you to pull up a shield to protect yourself and allies from incoming threats"
|
||||
|
||||
charge_max = 300
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
summon_type = list(/obj/effect/forcefield/cult)
|
||||
duration = 200
|
||||
|
||||
hud_state = "const_juggwall"
|
||||
|
||||
//Code for the Juggernaut construct's forcefield, that seemed like a good place to put it.
|
||||
/obj/effect/forcefield/cult
|
||||
desc = "That eerie looking obstacle seems to have been pulled from another dimension through sheer force"
|
||||
name = "Juggerwall"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "m_shield_cult"
|
||||
l_color = "#B40000"
|
||||
luminosity = 2
|
||||
|
||||
/obj/effect/forcefield/cult/cultify()
|
||||
return
|
||||
52
code/modules/spells/aoe_turf/conjure/forcewall.dm
Normal file
52
code/modules/spells/aoe_turf/conjure/forcewall.dm
Normal file
@@ -0,0 +1,52 @@
|
||||
/spell/aoe_turf/conjure/forcewall
|
||||
name = "Forcewall"
|
||||
desc = "Create a wall of pure energy at your location."
|
||||
summon_type = list(/obj/effect/forcefield)
|
||||
duration = 300
|
||||
charge_max = 100
|
||||
spell_flags = 0
|
||||
range = 0
|
||||
cast_sound = null
|
||||
|
||||
hud_state = "wiz_shield"
|
||||
|
||||
/spell/aoe_turf/conjure/forcewall/mime
|
||||
name = "Invisible wall"
|
||||
desc = "Create an invisible wall on your location."
|
||||
school = "mime"
|
||||
panel = "Mime"
|
||||
summon_type = list(/obj/effect/forcefield/mime)
|
||||
invocation_type = SpI_EMOTE
|
||||
invocation = "mimes placing their hands on a flat surfacing, and pushing against it."
|
||||
charge_max = 300
|
||||
cast_sound = null
|
||||
|
||||
override_base = "grey"
|
||||
hud_state = "mime_wall"
|
||||
|
||||
/obj/effect/forcefield
|
||||
desc = "A space wizard's magic wall."
|
||||
name = "FORCEWALL"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "m_shield"
|
||||
anchored = 1.0
|
||||
opacity = 0
|
||||
density = 1
|
||||
unacidable = 1
|
||||
|
||||
/obj/effect/forcefield/bullet_act(var/obj/item/projectile/Proj, var/def_zone)
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(T)
|
||||
for(var/mob/M in T)
|
||||
Proj.on_hit(M,M.bullet_act(Proj, def_zone))
|
||||
return
|
||||
|
||||
/obj/effect/forcefield/mime
|
||||
icon_state = "empty"
|
||||
name = "invisible wall"
|
||||
desc = "You have a bad feeling about this."
|
||||
|
||||
/obj/effect/forcefield/cultify()
|
||||
new /obj/effect/forcefield/cult(get_turf(src))
|
||||
qdel(src)
|
||||
return
|
||||
23
code/modules/spells/aoe_turf/disable_tech.dm
Normal file
23
code/modules/spells/aoe_turf/disable_tech.dm
Normal file
@@ -0,0 +1,23 @@
|
||||
/spell/aoe_turf/disable_tech
|
||||
name = "Disable Tech"
|
||||
desc = "This spell disables all weapons, cameras and most other technology in range."
|
||||
charge_max = 400
|
||||
spell_flags = NEEDSCLOTHES
|
||||
invocation = "NEC CANTIO"
|
||||
invocation_type = SpI_SHOUT
|
||||
selection_type = "range"
|
||||
range = 0
|
||||
inner_radius = -1
|
||||
|
||||
cooldown_min = 200 //50 deciseconds reduction per rank
|
||||
|
||||
var/emp_heavy = 6
|
||||
var/emp_light = 10
|
||||
|
||||
hud_state = "wiz_tech"
|
||||
|
||||
/spell/aoe_turf/disable_tech/cast(list/targets)
|
||||
|
||||
for(var/turf/target in targets)
|
||||
empulse(get_turf(target), emp_heavy, emp_light)
|
||||
return
|
||||
44
code/modules/spells/aoe_turf/knock.dm
Normal file
44
code/modules/spells/aoe_turf/knock.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
/spell/aoe_turf/knock
|
||||
name = "Knock"
|
||||
desc = "This spell opens nearby doors and does not require wizard garb."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 100
|
||||
spell_flags = 0
|
||||
invocation = "AULIE OXIN FIERA"
|
||||
invocation_type = SpI_WHISPER
|
||||
range = 3
|
||||
cooldown_min = 20 //20 deciseconds reduction per rank
|
||||
|
||||
hud_state = "wiz_knock"
|
||||
|
||||
/spell/aoe_turf/knock/cast(list/targets)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/door/door in T.contents)
|
||||
spawn(1)
|
||||
if(istype(door,/obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/AL = door //casting is important
|
||||
AL.locked = 0
|
||||
door.open()
|
||||
return
|
||||
|
||||
|
||||
//Construct version
|
||||
/spell/aoe_turf/knock/harvester
|
||||
name = "Disintegrate Doors"
|
||||
desc = "No door shall stop you."
|
||||
|
||||
spell_flags = CONSTRUCT_CHECK
|
||||
|
||||
charge_max = 100
|
||||
invocation = ""
|
||||
invocation_type = "silent"
|
||||
range = 5
|
||||
|
||||
hud_state = "const_knock"
|
||||
|
||||
/spell/aoe_turf/knock/harvester/cast(list/targets)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/door/door in T.contents)
|
||||
spawn door.cultify()
|
||||
return
|
||||
17
code/modules/spells/aoe_turf/smoke.dm
Normal file
17
code/modules/spells/aoe_turf/smoke.dm
Normal file
@@ -0,0 +1,17 @@
|
||||
/spell/aoe_turf/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
|
||||
spell_flags = 0
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = 1
|
||||
inner_radius = -1
|
||||
cooldown_min = 20 //25 deciseconds reduction per rank
|
||||
|
||||
smoke_spread = 2
|
||||
smoke_amt = 5
|
||||
|
||||
hud_state = "wiz_smoke"
|
||||
41
code/modules/spells/aoe_turf/summons.dm
Normal file
41
code/modules/spells/aoe_turf/summons.dm
Normal file
@@ -0,0 +1,41 @@
|
||||
/spell/aoe_turf/conjure/summonEdSwarm //test purposes
|
||||
name = "Dispense Wizard Justice"
|
||||
desc = "This spell dispenses wizard justice."
|
||||
|
||||
summon_type = list(/obj/machinery/bot/secbot/ed209)
|
||||
summon_amt = 10
|
||||
range = 3
|
||||
newVars = list("emagged" = 1,"name" = "Wizard's Justicebot")
|
||||
|
||||
hud_state = "wiz_ed"
|
||||
|
||||
/spell/aoe_turf/conjure/carp
|
||||
name = "Summon Carp"
|
||||
desc = "This spell conjures a simple carp."
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 1200
|
||||
spell_flags = NEEDSCLOTHES
|
||||
invocation = "NOUK FHUNMM SACP RISSKA"
|
||||
invocation_type = SpI_SHOUT
|
||||
range = 1
|
||||
|
||||
summon_type = list(/mob/living/simple_animal/hostile/carp)
|
||||
|
||||
hud_state = "wiz_carp"
|
||||
|
||||
/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
|
||||
spell_flags = 0
|
||||
invocation = "IA IA"
|
||||
invocation_type = SpI_SHOUT
|
||||
summon_amt = 10
|
||||
range = 3
|
||||
|
||||
summon_type = list(/mob/living/simple_animal/hostile/creature)
|
||||
|
||||
hud_state = "wiz_creature"
|
||||
@@ -1,82 +0,0 @@
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport
|
||||
name = "Area teleport"
|
||||
desc = "This spell teleports you to a type of area of your selection."
|
||||
|
||||
var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list
|
||||
var/invocation_area = 1 //if the invocation appends the selected area
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/perform(list/targets, recharge = 1)
|
||||
var/thearea = before_cast(targets)
|
||||
if(!thearea || !cast_check(1))
|
||||
revert_cast()
|
||||
return
|
||||
invocation(thearea)
|
||||
spawn(0)
|
||||
if(charge_type == "recharge" && recharge)
|
||||
start_recharge()
|
||||
cast(targets,thearea)
|
||||
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) in teleportlocs
|
||||
else
|
||||
A = pick(teleportlocs)
|
||||
|
||||
var/area/thearea = teleportlocs[A]
|
||||
|
||||
return thearea
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/cast(list/targets,area/thearea)
|
||||
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()
|
||||
|
||||
var/list/tempL = L
|
||||
var/attempt = null
|
||||
var/success = 0
|
||||
while(tempL.len)
|
||||
attempt = pick(tempL)
|
||||
success = target.Move(attempt)
|
||||
if(!success)
|
||||
tempL.Remove(attempt)
|
||||
else
|
||||
break
|
||||
|
||||
if(!success)
|
||||
target.loc = pick(L)
|
||||
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/area_teleport/invocation(area/chosenarea = null)
|
||||
if(!invocation_area || !chosenarea)
|
||||
..()
|
||||
else
|
||||
switch(invocation_type)
|
||||
if("shout")
|
||||
usr.say("[invocation] [uppertext(chosenarea.name)]")
|
||||
if(usr.gender==MALE)
|
||||
playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
|
||||
else
|
||||
playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
|
||||
if("whisper")
|
||||
usr.whisper("[invocation] [uppertext(chosenarea.name)]")
|
||||
|
||||
return
|
||||
19
code/modules/spells/artifacts.dm
Normal file
19
code/modules/spells/artifacts.dm
Normal file
@@ -0,0 +1,19 @@
|
||||
//////////////////////Scrying orb//////////////////////
|
||||
|
||||
/obj/item/weapon/scrying
|
||||
name = "scrying orb"
|
||||
desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means."
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "bluespace"
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
throwforce = 10
|
||||
damtype = BURN
|
||||
force = 10
|
||||
hitsound = 'sound/items/welder2.ogg'
|
||||
|
||||
/obj/item/weapon/scrying/attack_self(mob/user as mob)
|
||||
user << "<span class='info'>You can see... everything!</span>"
|
||||
visible_message("<span class='danger'>[usr] stares into [src], their eyes glazing over.</span>")
|
||||
announce_ghost_joinleave(user.ghostize(1), 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.")
|
||||
return
|
||||
@@ -1,87 +0,0 @@
|
||||
/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("/obj/machinery/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/delay = 1//Go Go Gadget Inheritance
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/cast(list/targets)
|
||||
|
||||
for(var/turf/T in targets)
|
||||
if(T.density && !summon_ignore_density)
|
||||
targets -= T
|
||||
playsound(src.loc, 'sound/items/welder.ogg', 50, 1)
|
||||
|
||||
if(do_after(usr,delay))
|
||||
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/turf/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)
|
||||
spawn(summon_lifespan)
|
||||
if(summoned_object)
|
||||
del(summoned_object)
|
||||
else
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
charge_counter = charge_max - 5//So you don't lose charge for a failed spell(Also prevents most over-fill)
|
||||
if("charges")
|
||||
charge_counter++//Ditto, just for different spell types
|
||||
|
||||
|
||||
return
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/summonEdSwarm //test purposes
|
||||
name = "Dispense Wizard Justice"
|
||||
desc = "This spell dispenses wizard justice."
|
||||
|
||||
summon_type = list(/obj/item/weapon/secbot_assembly/ed209_assembly)
|
||||
summon_amt = 10
|
||||
range = 3
|
||||
newVars = list("emagged" = 1,"name" = "Wizard's Justicebot")
|
||||
|
||||
|
||||
//This was previously left in the old wizard code, not being included.
|
||||
//Wasn't sure if I should transfer it here, or to code/datums/spells.dm
|
||||
//But I decided because it is a conjuration related object it would fit better here
|
||||
//Feel free to change this, I don't know.
|
||||
/obj/effect/forcefield
|
||||
desc = "A space wizard's magic wall."
|
||||
name = "FORCEWALL"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "m_shield"
|
||||
anchored = 1.0
|
||||
opacity = 0
|
||||
density = 1
|
||||
unacidable = 1
|
||||
|
||||
|
||||
bullet_act(var/obj/item/projectile/Proj, var/def_zone)
|
||||
var/turf/T = get_turf(src.loc)
|
||||
if(T)
|
||||
for(var/mob/M in T)
|
||||
Proj.on_hit(M,M.bullet_act(Proj, def_zone))
|
||||
return
|
||||
12
code/modules/spells/construct_spells.dm
Normal file
12
code/modules/spells/construct_spells.dm
Normal file
@@ -0,0 +1,12 @@
|
||||
//////////////////////////////Construct Spells/////////////////////////
|
||||
|
||||
proc/findNullRod(var/atom/target)
|
||||
if(istype(target,/obj/item/weapon/nullrod))
|
||||
var/turf/T = get_turf(target)
|
||||
T.turf_animation('icons/effects/96x96.dmi',"nullding",-32,-32,MOB_LAYER+1,'sound/piano/Ab7.ogg')
|
||||
return 1
|
||||
else if(target.contents)
|
||||
for(var/atom/A in target.contents)
|
||||
if(findNullRod(A))
|
||||
return 1
|
||||
return 0
|
||||
@@ -1,86 +0,0 @@
|
||||
/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(usr)
|
||||
for(var/i = 1; i < range; i++)
|
||||
var/turf/new_turf = get_step(T, usr.dir)
|
||||
if(new_turf.density)
|
||||
break
|
||||
T = new_turf
|
||||
perform(list(T))
|
||||
|
||||
/obj/effect/proc_holder/spell/dumbfire/cast(list/targets, mob/user = usr)
|
||||
|
||||
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)
|
||||
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.set_dir(get_dir(projectile, target))
|
||||
projectile.name = proj_name
|
||||
|
||||
var/current_loc = usr.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)
|
||||
break
|
||||
|
||||
var/mob/living/L = locate(/mob/living) in range(projectile, proj_trigger_range) - usr
|
||||
if(L)
|
||||
projectile.cast(L.loc)
|
||||
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
|
||||
spawn(proj_trail_lifespan)
|
||||
del(trail)
|
||||
|
||||
current_loc = projectile.loc
|
||||
|
||||
sleep(proj_step_delay)
|
||||
|
||||
if(projectile)
|
||||
del(projectile)
|
||||
@@ -1,13 +0,0 @@
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion
|
||||
name = "Emplosion"
|
||||
desc = "This spell emplodes an area."
|
||||
|
||||
var/emp_heavy = 2
|
||||
var/emp_light = 3
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/emplosion/cast(list/targets)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
empulse(target.loc, emp_heavy, emp_light)
|
||||
|
||||
return
|
||||
@@ -1,106 +0,0 @@
|
||||
/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
|
||||
include_user = 1
|
||||
centcomm_cancast = 0 //Prevent people from getting to centcomm
|
||||
|
||||
var phaseshift = 0
|
||||
var/jaunt_duration = 50 //in deciseconds
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
|
||||
for(var/mob/living/target in targets)
|
||||
spawn(0)
|
||||
|
||||
if(target.buckled)
|
||||
var/obj/structure/bed/buckled_to = target.buckled.
|
||||
buckled_to.unbuckle_mob()
|
||||
|
||||
var/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.icon_state = "liquify"
|
||||
animation.layer = 5
|
||||
animation.master = holder
|
||||
if(phaseshift == 1)
|
||||
animation.dir = target.dir
|
||||
flick("phase_shift",animation)
|
||||
target.loc = holder
|
||||
target.client.eye = holder
|
||||
sleep(jaunt_duration)
|
||||
mobloc = get_turf(target.loc)
|
||||
animation.loc = mobloc
|
||||
target.canmove = 0
|
||||
sleep(20)
|
||||
animation.dir = target.dir
|
||||
flick("phase_shift2",animation)
|
||||
sleep(5)
|
||||
if(!target.Move(mobloc))
|
||||
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
|
||||
target.client.eye = target
|
||||
del(animation)
|
||||
del(holder)
|
||||
else
|
||||
flick("liquify",animation)
|
||||
target.loc = holder
|
||||
target.client.eye = holder
|
||||
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread()
|
||||
steam.set_up(10, 0, mobloc)
|
||||
steam.start()
|
||||
sleep(jaunt_duration)
|
||||
mobloc = get_turf(target.loc)
|
||||
animation.loc = mobloc
|
||||
steam.location = mobloc
|
||||
steam.start()
|
||||
target.canmove = 0
|
||||
sleep(20)
|
||||
flick("reappear",animation)
|
||||
sleep(5)
|
||||
if(!target.Move(mobloc))
|
||||
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
|
||||
target.client.eye = target
|
||||
del(animation)
|
||||
del(holder)
|
||||
|
||||
/obj/effect/dummy/spell_jaunt
|
||||
name = "water"
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "nothing"
|
||||
var/canmove = 1
|
||||
density = 0
|
||||
anchored = 1
|
||||
|
||||
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
|
||||
if (!src.canmove) 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
|
||||
@@ -1,15 +0,0 @@
|
||||
/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)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
explosion(target.loc,ex_severe,ex_heavy,ex_light,ex_flash)
|
||||
|
||||
return
|
||||
85
code/modules/spells/general/area_teleport.dm
Normal file
85
code/modules/spells/general/area_teleport.dm
Normal file
@@ -0,0 +1,85 @@
|
||||
/spell/area_teleport
|
||||
name = "Teleport"
|
||||
desc = "This spell teleports you to a type of area of your selection."
|
||||
|
||||
school = "abjuration"
|
||||
charge_max = 600
|
||||
spell_flags = NEEDSCLOTHES
|
||||
invocation = "SCYAR NILA"
|
||||
invocation_type = SpI_SHOUT
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_amt = 5
|
||||
|
||||
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
|
||||
|
||||
cast_sound = 'sound/effects/teleport.ogg'
|
||||
|
||||
hud_state = "wiz_tele"
|
||||
|
||||
/spell/area_teleport/before_cast()
|
||||
return
|
||||
|
||||
/spell/area_teleport/choose_targets()
|
||||
var/A = null
|
||||
|
||||
if(!randomise_selection)
|
||||
A = input("Area to teleport to", "Teleport", A) in teleportlocs
|
||||
else
|
||||
A = pick(teleportlocs)
|
||||
|
||||
var/area/thearea = teleportlocs[A]
|
||||
|
||||
return list(thearea)
|
||||
|
||||
/spell/area_teleport/cast(area/thearea, mob/user)
|
||||
if(!istype(thearea))
|
||||
if(istype(thearea, /list))
|
||||
thearea = thearea[1]
|
||||
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)
|
||||
user <<"The spell matrix was unable to locate a suitable teleport destination for an unknown reason. Sorry."
|
||||
return
|
||||
|
||||
if(user && user.buckled)
|
||||
user.buckled = null
|
||||
|
||||
var/attempt = null
|
||||
var/success = 0
|
||||
while(L.len)
|
||||
attempt = pick(L)
|
||||
success = user.Move(attempt)
|
||||
if(!success)
|
||||
L.Remove(attempt)
|
||||
else
|
||||
break
|
||||
|
||||
if(!success)
|
||||
user.loc = pick(L)
|
||||
|
||||
return
|
||||
|
||||
/spell/area_teleport/after_cast()
|
||||
return
|
||||
|
||||
/spell/area_teleport/invocation(mob/user, area/chosenarea)
|
||||
if(!istype(chosenarea))
|
||||
return //can't have that, can we
|
||||
if(!invocation_area || !chosenarea)
|
||||
..()
|
||||
else
|
||||
invocation += "[uppertext(chosenarea.name)]"
|
||||
..()
|
||||
return
|
||||
175
code/modules/spells/general/rune_write.dm
Normal file
175
code/modules/spells/general/rune_write.dm
Normal file
@@ -0,0 +1,175 @@
|
||||
/spell/rune_write
|
||||
name = "Scribe a Rune"
|
||||
desc = "Let's you instantly manifest a working rune."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 100
|
||||
charge_type = Sp_RECHARGE
|
||||
invocation_type = SpI_NONE
|
||||
|
||||
spell_flags = CONSTRUCT_CHECK
|
||||
|
||||
hud_state = "const_rune"
|
||||
|
||||
smoke_amt = 1
|
||||
|
||||
/spell/rune_write/choose_targets(mob/user = usr)
|
||||
return list(user)
|
||||
|
||||
/spell/rune_write/cast(null, mob/user = usr)
|
||||
if(!cultwords["travel"])
|
||||
runerandom()
|
||||
var/list/runes = list("Teleport", "Teleport Other", "Spawn a Tome", "Change Construct Type", "Convert", "EMP", "Drain Blood", "See Invisible", "Resurrect", "Hide Runes", "Reveal Runes", "Astral Journey", "Manifest a Ghost", "Imbue Talisman", "Sacrifice", "Wall", "Free Cultist", "Summon Cultist", "Deafen", "Blind", "BloodBoil", "Communicate", "Stun")
|
||||
var/r = input(user, "Choose a rune to scribe", "Rune Scribing") in runes //not cancellable.
|
||||
var/obj/effect/rune/R = new /obj/effect/rune(user.loc)
|
||||
if(istype(user.loc,/turf))
|
||||
var/area/A = get_area(user)
|
||||
log_and_message_admins("created \an [r] rune at \the [A.name] - [user.loc.x]-[user.loc.y]-[user.loc.z].", user)
|
||||
switch(r)
|
||||
if("Teleport")
|
||||
if(cast_check(1))
|
||||
var/beacon
|
||||
if(user)
|
||||
beacon = input(user, "Select the last rune", "Rune Scribing") in rnwords
|
||||
R.word1=cultwords["travel"]
|
||||
R.word2=cultwords["self"]
|
||||
R.word3=beacon
|
||||
R.check_icon()
|
||||
if("Teleport Other")
|
||||
if(cast_check(1))
|
||||
var/beacon
|
||||
if(user)
|
||||
beacon = input(user, "Select the last rune", "Rune Scribing") in rnwords
|
||||
R.word1=cultwords["travel"]
|
||||
R.word2=cultwords["other"]
|
||||
R.word3=beacon
|
||||
R.check_icon()
|
||||
if("Spawn a Tome")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["see"]
|
||||
R.word2=cultwords["blood"]
|
||||
R.word3=cultwords["hell"]
|
||||
R.check_icon()
|
||||
if("Change Construct Type")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hell"]
|
||||
R.word2=cultwords["destroy"]
|
||||
R.word3=cultwords["other"]
|
||||
R.check_icon()
|
||||
if("Convert")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["join"]
|
||||
R.word2=cultwords["blood"]
|
||||
R.word3=cultwords["self"]
|
||||
R.check_icon()
|
||||
if("EMP")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["destroy"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["technology"]
|
||||
R.check_icon()
|
||||
if("Drain Blood")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["travel"]
|
||||
R.word2=cultwords["blood"]
|
||||
R.word3=cultwords["self"]
|
||||
R.check_icon()
|
||||
if("See Invisible")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["see"]
|
||||
R.word2=cultwords["hell"]
|
||||
R.word3=cultwords["join"]
|
||||
R.check_icon()
|
||||
if("Resurrect")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["blood"]
|
||||
R.word2=cultwords["join"]
|
||||
R.word3=cultwords["hell"]
|
||||
R.check_icon()
|
||||
if("Hide Runes")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hide"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["blood"]
|
||||
R.check_icon()
|
||||
if("Astral Journey")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hell"]
|
||||
R.word2=cultwords["travel"]
|
||||
R.word3=cultwords["self"]
|
||||
R.check_icon()
|
||||
if("Manifest a Ghost")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["blood"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["travel"]
|
||||
R.check_icon()
|
||||
if("Imbue Talisman")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hell"]
|
||||
R.word2=cultwords["technology"]
|
||||
R.word3=cultwords["join"]
|
||||
R.check_icon()
|
||||
if("Sacrifice")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hell"]
|
||||
R.word2=cultwords["blood"]
|
||||
R.word3=cultwords["join"]
|
||||
R.check_icon()
|
||||
if("Reveal Runes")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["blood"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["hide"]
|
||||
R.check_icon()
|
||||
if("Wall")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["destroy"]
|
||||
R.word2=cultwords["travel"]
|
||||
R.word3=cultwords["self"]
|
||||
R.check_icon()
|
||||
if("Freedom")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["travel"]
|
||||
R.word2=cultwords["technology"]
|
||||
R.word3=cultwords["other"]
|
||||
R.check_icon()
|
||||
if("Cultsummon")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["join"]
|
||||
R.word2=cultwords["other"]
|
||||
R.word3=cultwords["self"]
|
||||
R.check_icon()
|
||||
if("Deafen")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["hide"]
|
||||
R.word2=cultwords["other"]
|
||||
R.word3=cultwords["see"]
|
||||
R.check_icon()
|
||||
if("Blind")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["destroy"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["other"]
|
||||
R.check_icon()
|
||||
if("BloodBoil")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["destroy"]
|
||||
R.word2=cultwords["see"]
|
||||
R.word3=cultwords["blood"]
|
||||
R.check_icon()
|
||||
if("Communicate")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["self"]
|
||||
R.word2=cultwords["other"]
|
||||
R.word3=cultwords["technology"]
|
||||
R.check_icon()
|
||||
if("Stun")
|
||||
if(cast_check(1))
|
||||
R.word1=cultwords["join"]
|
||||
R.word2=cultwords["hide"]
|
||||
R.word3=cultwords["technology"]
|
||||
R.check_icon()
|
||||
else
|
||||
user << "<span class='warning'> You do not have enough space to write a proper rune.</span>"
|
||||
return
|
||||
@@ -1,31 +0,0 @@
|
||||
/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)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
for(var/x in mutations)
|
||||
target.mutations.Add(x)
|
||||
target.disabilities |= disabilities
|
||||
target.update_mutations() //update target's mutation overlays
|
||||
spawn(duration)
|
||||
for(var/x in mutations)
|
||||
target.mutations.Remove(x)
|
||||
target.disabilities &= ~disabilities
|
||||
target.update_mutations()
|
||||
|
||||
return
|
||||
@@ -1,50 +0,0 @@
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask
|
||||
name = "Curse of the Horseman"
|
||||
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
|
||||
school = "transmutation"
|
||||
charge_type = "recharge"
|
||||
charge_max = 150
|
||||
charge_counter = 0
|
||||
clothes_req = 0
|
||||
stat_allowed = 0
|
||||
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
|
||||
invocation_type = "shout"
|
||||
range = 7
|
||||
selection_type = "range"
|
||||
var/list/compatible_mobs = list(/mob/living/carbon/human)
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/horsemask/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'>It'd be stupid to curse [target] with a horse's head!</span>"
|
||||
return
|
||||
|
||||
if(!(target in oview(range)))//If they are not in overview after selection.
|
||||
user << "<span class='notice'>They are too far away!</span>"
|
||||
return
|
||||
|
||||
var/obj/item/clothing/mask/horsehead/magic/magichead = new /obj/item/clothing/mask/horsehead/magic
|
||||
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \
|
||||
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a horse!</span>")
|
||||
target.equip_to_slot(magichead, slot_wear_mask)
|
||||
|
||||
flick("e_flash", target.flash)
|
||||
|
||||
//item used by the horsehead spell
|
||||
/obj/item/clothing/mask/horsehead/magic
|
||||
//flags_inv = null //so you can still see their face... no. How can you recognize someone when their face is completely different?
|
||||
voicechange = 1 //NEEEEIIGHH
|
||||
|
||||
dropped(mob/user as mob)
|
||||
canremove = 1
|
||||
..()
|
||||
|
||||
equipped(var/mob/user, var/slot)
|
||||
if (slot == slot_wear_mask)
|
||||
canremove = 0 //curses!
|
||||
..()
|
||||
@@ -1,59 +0,0 @@
|
||||
/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"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/cast(list/targets)
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
switch(destroys)
|
||||
if("gib")
|
||||
target.gib()
|
||||
if("gib_brain")
|
||||
if(ishuman(target) || issmall(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(!C.has_brain()) // Their brain is already taken out
|
||||
var/obj/item/organ/brain/B = new(C.loc)
|
||||
B.transfer_identity(C)
|
||||
target.gib()
|
||||
if("disintegrate")
|
||||
target.dust()
|
||||
|
||||
if(!target)
|
||||
continue
|
||||
//damage
|
||||
if(amt_dam_brute > 0)
|
||||
if(amt_dam_fire >= 0)
|
||||
target.take_overall_damage(amt_dam_brute,amt_dam_fire)
|
||||
else if (amt_dam_fire < 0)
|
||||
target.take_overall_damage(amt_dam_brute,0)
|
||||
target.heal_overall_damage(0,amt_dam_fire)
|
||||
else if(amt_dam_brute < 0)
|
||||
if(amt_dam_fire > 0)
|
||||
target.take_overall_damage(0,amt_dam_fire)
|
||||
target.heal_overall_damage(amt_dam_brute,0)
|
||||
else if (amt_dam_fire <= 0)
|
||||
target.heal_overall_damage(amt_dam_brute,amt_dam_fire)
|
||||
target.adjustToxLoss(amt_dam_tox)
|
||||
target.oxyloss += amt_dam_oxy
|
||||
//disabling
|
||||
target.Weaken(amt_weakened)
|
||||
target.Paralyse(amt_paralysis)
|
||||
target.Stun(amt_stunned)
|
||||
|
||||
target.eye_blind += amt_eye_blind
|
||||
target.eye_blurry += amt_eye_blurry
|
||||
@@ -1,20 +0,0 @@
|
||||
/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
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/knock/cast(list/targets)
|
||||
for(var/turf/T in targets)
|
||||
for(var/obj/machinery/door/door in T.contents)
|
||||
spawn(1)
|
||||
if(istype(door,/obj/machinery/door/airlock))
|
||||
var/obj/machinery/door/airlock/A = door
|
||||
A.unlock(1) //forced because it's magic!
|
||||
door.open()
|
||||
return
|
||||
@@ -1,116 +0,0 @@
|
||||
/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
|
||||
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
|
||||
var/list/compatible_mobs = list(/mob/living/carbon/human) //which types of mobs are affected by the spell. NOTE: change at your own risk
|
||||
var/base_spell_loss_chance = 20 //base probability of the wizard losing a spell in the process
|
||||
var/spell_loss_chance_modifier = 7 //amount of probability of losing a spell added per spell (mind_transfer included)
|
||||
var/spell_loss_amount = 1 //the maximum amount of spells possible to lose during a single transfer
|
||||
var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a 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
|
||||
|
||||
/*
|
||||
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)
|
||||
if(!targets.len)
|
||||
user << "No mind found."
|
||||
return
|
||||
|
||||
if(targets.len > 1)
|
||||
user << "Too many minds! You're not a hive damnit!"//Whaa...aat?
|
||||
return
|
||||
|
||||
var/mob/living/target = targets[1]
|
||||
|
||||
if(!(target in oview(range)))//If they are not in overview after selection. Do note that !() is necessary for in to work because ! takes precedence over it.
|
||||
user << "They are too far away!"
|
||||
return
|
||||
|
||||
if(!(target.type in compatible_mobs))
|
||||
user << "Their mind isn't compatible with yours."
|
||||
return
|
||||
|
||||
if(target.stat == DEAD)
|
||||
user << "You didn't study necromancy back at the Space Wizard Federation academy."
|
||||
return
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
user << "They appear to be catatonic. Not even magic can affect their vacant mind."
|
||||
return
|
||||
|
||||
if(target.mind.special_role in protected_roles)
|
||||
user << "Their mind is resisting your spell."
|
||||
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.
|
||||
|
||||
//SPELL LOSS BEGIN
|
||||
admin_attack_log(caster, victim, "Used mind transfer", "Was the victim of mind transfer", "used mind transfer on")
|
||||
|
||||
//NOTE: The caster must ALWAYS keep mind transfer, even when other spells are lost.
|
||||
var/obj/effect/proc_holder/spell/targeted/mind_transfer/m_transfer = locate() in user.spell_list//Find mind transfer directly.
|
||||
var/list/checked_spells = user.spell_list
|
||||
checked_spells -= m_transfer //Remove Mind Transfer from the list.
|
||||
|
||||
if(caster.spell_list.len)//If they have any spells left over after mind transfer is taken out. If they don't, we don't need this.
|
||||
for(var/i=spell_loss_amount,(i>0&&checked_spells.len),i--)//While spell loss amount is greater than zero and checked_spells has spells in it, run this proc.
|
||||
for(var/j=checked_spells.len,(j>0&&checked_spells.len),j--)//While the spell list to check is greater than zero and has spells in it, run this proc.
|
||||
if(prob(base_spell_loss_chance))
|
||||
checked_spells -= pick(checked_spells)//Pick a random spell to remove.
|
||||
spawn(msg_wait)
|
||||
victim << "The mind transfer has robbed you of a spell."
|
||||
break//Spell lost. Break loop, going back to the previous for() statement.
|
||||
else//Or keep checking, adding spell chance modifier to increase chance of losing a spell.
|
||||
base_spell_loss_chance += spell_loss_chance_modifier
|
||||
|
||||
checked_spells += m_transfer//Add back Mind Transfer.
|
||||
user.spell_list = checked_spells//Set user spell list to whatever the new list is.
|
||||
//SPELL LOSS END
|
||||
|
||||
//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)
|
||||
ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob.
|
||||
|
||||
caster.mind.transfer_to(victim)
|
||||
victim.spell_list = caster.spell_list//Now they are inside the victim's body.
|
||||
|
||||
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)
|
||||
caster.key = ghost.key //have to transfer the key since the mind was not active
|
||||
caster.spell_list = ghost.spell_list
|
||||
|
||||
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
|
||||
for(var/V in caster.mind.special_verbs)
|
||||
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)
|
||||
|
||||
//After a certain amount of time the victim gets a message about being in a different body.
|
||||
spawn(msg_wait)
|
||||
caster << "\red You feel woozy and lightheaded. <b>Your body doesn't seem like your own.</b>"
|
||||
5
code/modules/spells/no_clothes.dm
Normal file
5
code/modules/spells/no_clothes.dm
Normal file
@@ -0,0 +1,5 @@
|
||||
/spell/noclothes
|
||||
name = "No Clothes"
|
||||
desc = "This is a placeholder for knowing if you dont need clothes for any spell."
|
||||
|
||||
spell_flags = NO_BUTTON
|
||||
@@ -1,83 +0,0 @@
|
||||
/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)
|
||||
|
||||
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.set_dir(get_dir(target,projectile))
|
||||
projectile.name = proj_name
|
||||
|
||||
var/current_loc = usr.loc
|
||||
|
||||
projectile.loc = current_loc
|
||||
|
||||
for(var/i = 0,i < proj_lifespan,i++)
|
||||
if(!projectile)
|
||||
break
|
||||
|
||||
if(proj_homing)
|
||||
if(proj_insubstantial)
|
||||
projectile.set_dir(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(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time
|
||||
del(projectile)
|
||||
break
|
||||
|
||||
if(proj_trail && projectile)
|
||||
spawn(0)
|
||||
if(projectile)
|
||||
var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc)
|
||||
trail.icon = proj_trail_icon
|
||||
trail.icon_state = proj_trail_icon_state
|
||||
trail.density = 0
|
||||
spawn(proj_trail_lifespan)
|
||||
del(trail)
|
||||
|
||||
if(projectile.loc in range(target.loc,proj_trigger_range))
|
||||
projectile.perform(list(target))
|
||||
break
|
||||
|
||||
current_loc = projectile.loc
|
||||
|
||||
sleep(proj_step_delay)
|
||||
|
||||
if(projectile)
|
||||
del(projectile)
|
||||
@@ -1,302 +0,0 @@
|
||||
/client/proc/give_spell(mob/T as mob in mob_list) // -- Urist
|
||||
set category = "Fun"
|
||||
set name = "Give Spell"
|
||||
set desc = "Gives a spell to a mob."
|
||||
var/list/spell_names = list()
|
||||
for(var/v in spells)
|
||||
// "/obj/effect/proc_holder/spell/" 30 symbols ~Intercross21
|
||||
spell_names.Add(copytext("[v]", 31, 0))
|
||||
var/S = input("Choose the spell to give to that guy", "ABRAKADABRA") as null|anything in spell_names
|
||||
if(!S) return
|
||||
var/path = text2path("/obj/effect/proc_holder/spell/[S]")
|
||||
T.spell_list += new path
|
||||
feedback_add_details("admin_verb","GS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
|
||||
log_admin("[key_name(usr)] gave [key_name(T)] the spell [S].")
|
||||
message_admins("\blue [key_name_admin(usr)] gave [key_name(T)] the spell [S].", 1)
|
||||
|
||||
/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/spell
|
||||
name = "Spell"
|
||||
desc = "A wizard spell"
|
||||
density = 0
|
||||
opacity = 0
|
||||
|
||||
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
|
||||
|
||||
var/charge_type = "recharge" //can be recharge or charges, see charge_max and charge_counter descriptions; 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/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/stat_allowed = 0 //see if it requires being conscious/alive, need to set to 1 for ghostpells
|
||||
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
|
||||
var/invocation_type = "none" //can be none, whisper and shout
|
||||
var/range = 7 //the range of the spell; outer radius for aoe spells
|
||||
var/message = "" //whatever it says to the guy affected by it
|
||||
var/selection_type = "view" //can be "range" or "view"
|
||||
|
||||
var/overlay = 0
|
||||
var/overlay_icon = '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/centcomm_cancast = 1 //Whether or not the spell should be allowed on z2
|
||||
|
||||
/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(!(src in usr.spell_list))
|
||||
usr << "\red You shouldn't have this spell! Something's wrong."
|
||||
return 0
|
||||
|
||||
if(usr.z == 2 && !centcomm_cancast) //Certain spells are not allowed on the centcomm zlevel
|
||||
return 0
|
||||
|
||||
if(!skipcharge)
|
||||
switch(charge_type)
|
||||
if("recharge")
|
||||
if(charge_counter < charge_max)
|
||||
usr << "[name] is still recharging."
|
||||
return 0
|
||||
if("charges")
|
||||
if(!charge_counter)
|
||||
usr << "[name] has no charges left."
|
||||
return 0
|
||||
|
||||
if(usr.stat && !stat_allowed)
|
||||
usr << "Not when you're incapacitated."
|
||||
return 0
|
||||
|
||||
if(ishuman(usr) || issmall(usr))
|
||||
if(istype(usr.wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
usr << "Mmmf mrrfff!"
|
||||
return 0
|
||||
|
||||
if(clothes_req) //clothes check
|
||||
if(!istype(usr, /mob/living/carbon/human))
|
||||
usr << "You aren't a human, Why are you trying to cast a human spell, silly non-human? Casting human spells is for humans."
|
||||
return 0
|
||||
if(!istype(usr:wear_suit, /obj/item/clothing/suit/wizrobe) && !istype(user:wear_suit, /obj/item/clothing/suit/space/void/wizard))
|
||||
usr << "I don't feel strong enough without my robe."
|
||||
return 0
|
||||
if(!istype(usr:shoes, /obj/item/clothing/shoes/sandal))
|
||||
usr << "I don't feel strong enough without my sandals."
|
||||
return 0
|
||||
if(!istype(usr:head, /obj/item/clothing/head/wizard) && !istype(user:head, /obj/item/clothing/head/helmet/space/void/wizard))
|
||||
usr << "I don't feel strong enough without my hat."
|
||||
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
|
||||
usr.say(invocation)
|
||||
else
|
||||
usr.say(replacetext(invocation," ","`"))
|
||||
if(usr.gender==MALE)
|
||||
playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
|
||||
else
|
||||
playsound(usr.loc, pick('sound/misc/null.ogg','sound/misc/null.ogg'), 100, 1)
|
||||
if("whisper")
|
||||
if(prob(50))
|
||||
usr.whisper(invocation)
|
||||
else
|
||||
usr.whisper(replacetext(invocation," ","`"))
|
||||
|
||||
/obj/effect/proc_holder/spell/New()
|
||||
..()
|
||||
|
||||
charge_counter = charge_max
|
||||
|
||||
/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()
|
||||
while(charge_counter < charge_max)
|
||||
sleep(1)
|
||||
charge_counter++
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = 1) //if recharge is started is important for the trigger spells
|
||||
before_cast(targets)
|
||||
invocation()
|
||||
spawn(0)
|
||||
if(charge_type == "recharge" && recharge)
|
||||
start_recharge()
|
||||
if(prob(critfailchance))
|
||||
critfail(targets)
|
||||
else
|
||||
cast(targets)
|
||||
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
|
||||
spawn(overlay_lifespan)
|
||||
del(spell)
|
||||
|
||||
/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/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is
|
||||
sparks.start()
|
||||
if(smoke_spread)
|
||||
if(smoke_spread == 1)
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
||||
smoke.start()
|
||||
else if(smoke_spread == 2)
|
||||
var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
|
||||
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
||||
smoke.start()
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast(list/targets)
|
||||
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)
|
||||
|
||||
return
|
||||
|
||||
/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
|
||||
return
|
||||
|
||||
/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
|
||||
|
||||
/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
|
||||
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)
|
||||
|
||||
return
|
||||
|
||||
/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)
|
||||
|
||||
return
|
||||
341
code/modules/spells/spell_code.dm
Normal file
341
code/modules/spells/spell_code.dm
Normal file
@@ -0,0 +1,341 @@
|
||||
var/list/spells = typesof(/spell) //needed for the badmin verb for now
|
||||
|
||||
/spell
|
||||
name = "Spell"
|
||||
desc = "A spell"
|
||||
parent_type = /atom/movable
|
||||
var/panel = "Spells"//What panel the proc holder needs to go on.
|
||||
|
||||
var/school = "evocation" //not relevant at now, but may be important later if there are changes to how spells work. the ones I used for now will probably be changed... maybe spell presets? lacking flexibility but with some other benefit?
|
||||
|
||||
var/charge_type = Sp_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 = Sp_RECHARGE or starting charges if charge_type = Sp_CHARGES
|
||||
var/charge_counter = 0 //can only cast spells if it equals recharge, ++ each decisecond if charge_type = Sp_RECHARGE or -- each cast if charge_type = Sp_CHARGES
|
||||
var/still_recharging_msg = "<span class='notice'>The spell is still recharging.</span>"
|
||||
|
||||
var/silenced = 0 //not a binary - the length of time we can't cast this for
|
||||
|
||||
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/spell_flags = NEEDSCLOTHES
|
||||
var/invocation = "HURP DURP" //what is uttered when the wizard casts the spell
|
||||
var/invocation_type = SpI_NONE //can be none, whisper, shout, and emote
|
||||
var/range = 7 //the range of the spell; outer radius for aoe spells
|
||||
var/message = "" //whatever it says to the guy affected by it
|
||||
var/selection_type = "view" //can be "range" or "view"
|
||||
var/atom/movable/holder //where the spell is. Normally the user, can be a projectile
|
||||
|
||||
var/duration = 0 //how long the spell lasts
|
||||
|
||||
var/list/spell_levels = list(Sp_SPEED = 0, Sp_POWER = 0) //the current spell levels - total spell levels can be obtained by just adding the two values
|
||||
var/list/level_max = list(Sp_TOTAL = 4, Sp_SPEED = 4, Sp_POWER = 0) //maximum possible levels in each category. Total does cover both.
|
||||
var/cooldown_reduc = 0 //If set, defines how much charge_max drops by every speed upgrade
|
||||
var/delay_reduc = 0
|
||||
var/cooldown_min = 0 //minimum possible cooldown for a charging spell
|
||||
|
||||
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/cast_delay = 1
|
||||
var/cast_sound = ""
|
||||
|
||||
var/hud_state = "" //name of the icon used in generating the spell hud object
|
||||
var/override_base = ""
|
||||
|
||||
///////////////////////
|
||||
///SETUP AND PROCESS///
|
||||
///////////////////////
|
||||
|
||||
/spell/New()
|
||||
..()
|
||||
|
||||
//still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
|
||||
charge_counter = charge_max
|
||||
|
||||
/spell/proc/process()
|
||||
spawn while(charge_counter < charge_max)
|
||||
charge_counter++
|
||||
sleep(1)
|
||||
return
|
||||
|
||||
/spell/Click()
|
||||
..()
|
||||
|
||||
perform(usr)
|
||||
|
||||
/////////////////
|
||||
/////CASTING/////
|
||||
/////////////////
|
||||
|
||||
/spell/proc/choose_targets(mob/user = usr) //depends on subtype - see targeted.dm, aoe_turf.dm, dumbfire.dm, or code in general folder
|
||||
return
|
||||
|
||||
/spell/proc/perform(mob/user = usr, skipcharge = 0) //if recharge is started is important for the trigger spells
|
||||
if(!holder)
|
||||
holder = user //just in case
|
||||
if(!cast_check(skipcharge, user))
|
||||
return
|
||||
if(cast_delay && !spell_do_after(user, cast_delay))
|
||||
return
|
||||
var/list/targets = choose_targets(user)
|
||||
if(targets && targets.len)
|
||||
invocation(user, targets)
|
||||
take_charge(user, skipcharge)
|
||||
|
||||
before_cast(targets) //applies any overlays and effects
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='red'>[user.real_name] ([user.ckey]) cast the spell [name].</font>")
|
||||
if(prob(critfailchance))
|
||||
critfail(targets, user)
|
||||
else
|
||||
cast(targets, user)
|
||||
after_cast(targets) //generates the sparks, smoke, target messages etc.
|
||||
|
||||
|
||||
/spell/proc/cast(list/targets, mob/user) //the actual meat of the spell
|
||||
return
|
||||
|
||||
/spell/proc/critfail(list/targets, mob/user) //the wizman has fucked up somehow
|
||||
return
|
||||
|
||||
/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
|
||||
return
|
||||
|
||||
///////////////////////////
|
||||
/////CASTING WRAPPERS//////
|
||||
///////////////////////////
|
||||
|
||||
/spell/proc/before_cast(list/targets)
|
||||
var/valid_targets[0]
|
||||
for(var/atom/target in targets)
|
||||
// Check range again (fixes long-range EI NATH)
|
||||
if(!(target in view_or_range(range,usr,selection_type)))
|
||||
continue
|
||||
|
||||
valid_targets += target
|
||||
|
||||
if(overlay)
|
||||
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
|
||||
spawn(overlay_lifespan)
|
||||
del(spell)
|
||||
return valid_targets
|
||||
|
||||
/spell/proc/after_cast(list/targets)
|
||||
for(var/atom/target in targets)
|
||||
var/location = get_turf(target)
|
||||
if(istype(target,/mob/living) && message)
|
||||
target << text("[message]")
|
||||
if(sparks_spread)
|
||||
var/datum/effect/effect/system/spark_spread/sparks = new /datum/effect/effect/system/spark_spread()
|
||||
sparks.set_up(sparks_amt, 0, location) //no idea what the 0 is
|
||||
sparks.start()
|
||||
if(smoke_spread)
|
||||
if(smoke_spread == 1)
|
||||
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
|
||||
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
||||
smoke.start()
|
||||
else if(smoke_spread == 2)
|
||||
var/datum/effect/effect/system/smoke_spread/bad/smoke = new /datum/effect/effect/system/smoke_spread/bad()
|
||||
smoke.set_up(smoke_amt, 0, location) //no idea what the 0 is
|
||||
smoke.start()
|
||||
|
||||
/////////////////////
|
||||
////CASTING TOOLS////
|
||||
/////////////////////
|
||||
/*Checkers, cost takers, message makers, etc*/
|
||||
|
||||
/spell/proc/cast_check(skipcharge = 0,mob/user = usr) //checks if the spell can be cast based on its settings; skipcharge is used when an additional cast_check is called inside the spell
|
||||
|
||||
if(!(src in user.spell_list))
|
||||
user << "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>"
|
||||
return 0
|
||||
|
||||
if(silenced > 0)
|
||||
return
|
||||
|
||||
if(user.z == 2 && spell_flags & Z2NOCAST) //Certain spells are not allowed on the centcomm zlevel
|
||||
return 0
|
||||
|
||||
if(spell_flags & CONSTRUCT_CHECK)
|
||||
for(var/turf/T in range(holder, 1))
|
||||
if(findNullRod(T))
|
||||
return 0
|
||||
|
||||
if(istype(user, /mob/living/simple_animal))
|
||||
var/mob/living/simple_animal/SA = user
|
||||
if(SA.purge)
|
||||
SA << "<span class='warning'>The nullrod's power interferes with your own!</span>"
|
||||
return 0
|
||||
|
||||
if(!src.check_charge(skipcharge, user)) //sees if we can cast based on charges alone
|
||||
return 0
|
||||
|
||||
if(!(spell_flags & GHOSTCAST))
|
||||
if(user.stat && !(spell_flags & STATALLOWED))
|
||||
usr << "Not when you're incapacitated."
|
||||
return 0
|
||||
|
||||
if(ishuman(user) && !(invocation_type in list(SpI_EMOTE, SpI_NONE)))
|
||||
if(istype(user.wear_mask, /obj/item/clothing/mask/muzzle))
|
||||
user << "Mmmf mrrfff!"
|
||||
return 0
|
||||
|
||||
var/spell/noclothes/spell = locate() in user.spell_list
|
||||
if((spell_flags & NEEDSCLOTHES) && !(spell && istype(spell)))//clothes check
|
||||
if(!user.wearing_wiz_garb())
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/spell/proc/check_charge(var/skipcharge, mob/user)
|
||||
if(!skipcharge)
|
||||
switch(charge_type)
|
||||
if(Sp_RECHARGE)
|
||||
if(charge_counter < charge_max)
|
||||
user << still_recharging_msg
|
||||
return 0
|
||||
if(Sp_CHARGES)
|
||||
if(!charge_counter)
|
||||
user << "<span class='notice'>[name] has no charges left.</span>"
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/spell/proc/take_charge(mob/user = user, var/skipcharge)
|
||||
if(!skipcharge)
|
||||
switch(charge_type)
|
||||
if(Sp_RECHARGE)
|
||||
charge_counter = 0 //doesn't start recharging until the targets selecting ends
|
||||
src.process()
|
||||
return 1
|
||||
if(Sp_CHARGES)
|
||||
charge_counter-- //returns the charge if the targets selecting fails
|
||||
return 1
|
||||
if(Sp_HOLDVAR)
|
||||
adjust_var(user, holder_var_type, holder_var_amount)
|
||||
return 1
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/spell/proc/invocation(mob/user = usr, var/list/targets) //spelling the spell out and setting it on recharge/reducing charges amount
|
||||
|
||||
switch(invocation_type)
|
||||
if(SpI_SHOUT)
|
||||
if(prob(50))//Auto-mute? Fuck that noise
|
||||
user.say(invocation)
|
||||
else
|
||||
user.say(replacetext(invocation," ","`"))
|
||||
if(SpI_WHISPER)
|
||||
if(prob(50))
|
||||
user.whisper(invocation)
|
||||
else
|
||||
user.whisper(replacetext(invocation," ","`"))
|
||||
if(SpI_EMOTE)
|
||||
user.emote("me", 1, invocation) //the 1 means it's for everyone in view, the me makes it an emote, and the invocation is written accordingly.
|
||||
|
||||
/////////////////////
|
||||
///UPGRADING PROCS///
|
||||
/////////////////////
|
||||
|
||||
/spell/proc/can_improve(var/upgrade_type)
|
||||
if(level_max[Sp_TOTAL] <= ( spell_levels[Sp_SPEED] + spell_levels[Sp_POWER] )) //too many levels, can't do it
|
||||
return 0
|
||||
|
||||
if(upgrade_type && upgrade_type in spell_levels && upgrade_type in level_max)
|
||||
if(spell_levels[upgrade_type] >= level_max[upgrade_type])
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/spell/proc/empower_spell()
|
||||
return
|
||||
|
||||
/spell/proc/quicken_spell()
|
||||
if(!can_improve(Sp_SPEED))
|
||||
return 0
|
||||
|
||||
spell_levels[Sp_SPEED]++
|
||||
|
||||
if(delay_reduc && cast_delay)
|
||||
cast_delay = max(0, cast_delay - delay_reduc)
|
||||
else if(cast_delay)
|
||||
cast_delay = round( max(0, initial(cast_delay) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) )
|
||||
|
||||
if(charge_type == Sp_RECHARGE)
|
||||
if(cooldown_reduc)
|
||||
charge_max = max(cooldown_min, charge_max - cooldown_reduc)
|
||||
else
|
||||
charge_max = round( max(cooldown_min, initial(charge_max) * ((level_max[Sp_SPEED] - spell_levels[Sp_SPEED]) / level_max[Sp_SPEED] ) ) ) //the fraction of the way you are to max speed levels is the fraction you lose
|
||||
if(charge_max < charge_counter)
|
||||
charge_counter = charge_max
|
||||
|
||||
var/temp = ""
|
||||
name = initial(name)
|
||||
switch(level_max[Sp_SPEED] - spell_levels[Sp_SPEED])
|
||||
if(3)
|
||||
temp = "You have improved [name] into Efficient [name]."
|
||||
name = "Efficient [name]"
|
||||
if(2)
|
||||
temp = "You have improved [name] into Quickened [name]."
|
||||
name = "Quickened [name]"
|
||||
if(1)
|
||||
temp = "You have improved [name] into Free [name]."
|
||||
name = "Free [name]"
|
||||
if(0)
|
||||
temp = "You have improved [name] into Instant [name]."
|
||||
name = "Instant [name]"
|
||||
|
||||
return temp
|
||||
|
||||
/spell/proc/spell_do_after(var/mob/user as mob, delay as num, var/numticks = 5)
|
||||
if(!user || isnull(user))
|
||||
return 0
|
||||
if(numticks == 0)
|
||||
return 1
|
||||
|
||||
var/delayfraction = round(delay/numticks)
|
||||
var/Location = user.loc
|
||||
var/originalstat = user.stat
|
||||
|
||||
for(var/i = 0, i<numticks, i++)
|
||||
sleep(delayfraction)
|
||||
|
||||
|
||||
if(!user || (!(spell_flags & (STATALLOWED|GHOSTCAST)) && user.stat != originalstat) || !(user.loc == Location))
|
||||
return 0
|
||||
return 1
|
||||
62
code/modules/spells/spell_projectile.dm
Normal file
62
code/modules/spells/spell_projectile.dm
Normal file
@@ -0,0 +1,62 @@
|
||||
/obj/item/projectile/spell_projectile
|
||||
name = "spell"
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
|
||||
nodamage = 1 //Most of the time, anyways
|
||||
|
||||
var/spell/targeted/projectile/carried
|
||||
|
||||
kill_count = 10 //set by the duration of the spell
|
||||
|
||||
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/list/trails = new()
|
||||
|
||||
/obj/item/projectile/spell_projectile/Destroy()
|
||||
..()
|
||||
for(var/trail in trails)
|
||||
qdel(trail)
|
||||
|
||||
/obj/item/projectile/spell_projectile/ex_act()
|
||||
return
|
||||
|
||||
/obj/item/projectile/spell_projectile/before_move()
|
||||
if(carried)
|
||||
var/list/targets = carried.choose_prox_targets(user = carried.holder, spell_holder = src)
|
||||
if(targets.len)
|
||||
src.prox_cast(targets)
|
||||
if(proj_trail && src && src.loc) //pretty trails
|
||||
var/obj/effect/overlay/trail = PoolOrNew(/obj/effect/overlay, src.loc)
|
||||
trails += trail
|
||||
trail.icon = proj_trail_icon
|
||||
trail.icon_state = proj_trail_icon_state
|
||||
trail.density = 0
|
||||
spawn(proj_trail_lifespan)
|
||||
trails -= trail
|
||||
qdel(trail)
|
||||
|
||||
/obj/item/projectile/spell_projectile/proc/prox_cast(var/list/targets)
|
||||
if(loc)
|
||||
carried.prox_cast(targets, src)
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
/obj/item/projectile/spell_projectile/Bump(var/atom/A)
|
||||
if(loc)
|
||||
prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src))
|
||||
return
|
||||
|
||||
/obj/item/projectile/spell_projectile/on_impact()
|
||||
if(loc)
|
||||
prox_cast(carried.choose_prox_targets(user = carried.holder, spell_holder = src))
|
||||
return
|
||||
|
||||
/obj/item/projectile/spell_projectile/seeking
|
||||
name = "seeking spell"
|
||||
|
||||
/obj/item/projectile/spell_projectile/seeking/process_step()
|
||||
..()
|
||||
if(original && !isnull(src.loc))
|
||||
current = original //update the target
|
||||
@@ -1,211 +1,454 @@
|
||||
// This is a bloody terrible place to put the spellbook, but it doesn't belong in the
|
||||
// roundmode code and the wizard's staff is in weapons.dm for some fucking reason. ~Z
|
||||
|
||||
/obj/item/weapon/spellbook
|
||||
name = "spell book"
|
||||
desc = "The legendary book of spells of the wizard."
|
||||
icon = 'icons/obj/library.dmi'
|
||||
icon_state ="book"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = 2.0
|
||||
var/uses = 5
|
||||
var/temp = null
|
||||
var/max_uses = 5
|
||||
var/op = 1
|
||||
|
||||
|
||||
/obj/item/weapon/spellbook/attack_self(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = "[temp]<BR><BR><A href='byond://?src=\ref[src];temp=1'>Clear</A>"
|
||||
else
|
||||
dat = "<B>The Book of Spells:</B><BR>"
|
||||
dat += "Spells left to memorize: [uses]<BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<B>Memorize which spell:</B><BR>"
|
||||
dat += "<I>The number after the spell name is the cooldown time.</I><BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=magicmissile'>Magic Missile</A> (15)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=fireball'>Fireball</A> (10)<BR>"
|
||||
//dat += "<A href='byond://?src=\ref[src];spell_choice=disintegrate'>Disintegrate</A> (60)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=disabletech'>Disable Technology</A> (40)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=smoke'>Smoke</A> (12)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=blind'>Blind</A> (30)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=mindswap'>Mind Transfer</A> (60)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=forcewall'>Forcewall</A> (10)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=blink'>Blink</A> (2)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=teleport'>Teleport</A> (60)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=mutate'>Mutate</A> (40)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=etherealjaunt'>Ethereal Jaunt</A> (30)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=knock'>Knock</A> (10)<BR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=horseman'>Curse of the Horseman</A> (15)<BR>"
|
||||
// if(op)
|
||||
// dat += "<A href='byond://?src=\ref[src];spell_choice=summonguns'>Summon Guns</A> (One time use, global spell)<BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<B>Artefacts:</B><BR>"
|
||||
dat += "Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.<BR>"
|
||||
dat += "It is recommended that only experienced wizards attempt to wield such artefacts.<BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=staffchange'>Staff of Change</A><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=mentalfocus'>Mental Focus</A><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=soulstone'>Six Soul Stone Shards and the spell Artificer</A><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=armor'>Mastercrafted Armor Set</A><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=staffanimation'>Staff of Animation</A><BR>"
|
||||
dat += "<HR>"
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=scrying'>Scrying Orb</A><BR>"
|
||||
dat += "<HR>"
|
||||
if(op)
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=rememorize'>Re-memorize Spells</A><BR>"
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
/obj/item/weapon/spellbook/Topic(href, href_list)
|
||||
..()
|
||||
var/mob/living/carbon/human/H = usr
|
||||
|
||||
if(H.stat || H.restrained())
|
||||
return
|
||||
if(!istype(H, /mob/living/carbon/human))
|
||||
return 1
|
||||
|
||||
if(loc == H || (in_range(src, H) && istype(loc, /turf)))
|
||||
H.set_machine(src)
|
||||
if(href_list["spell_choice"])
|
||||
if(href_list["spell_choice"] == "rememorize")
|
||||
var/area/wizard_station/A = locate()
|
||||
if(usr in A.contents)
|
||||
uses = max_uses
|
||||
H.spellremove(usr)
|
||||
temp = "All spells have been removed. You may now memorize a new set of spells."
|
||||
feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
else
|
||||
temp = "You may only re-memorize spells whilst located inside the wizard sanctuary."
|
||||
else if(uses >= 1 && max_uses >=1)
|
||||
uses--
|
||||
/*
|
||||
*/
|
||||
var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", summonguns = "Summon Guns", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation")
|
||||
var/already_knows = 0
|
||||
for(var/obj/effect/proc_holder/spell/aspell in H.spell_list)
|
||||
if(available_spells[href_list["spell_choice"]] == aspell.name)
|
||||
already_knows = 1
|
||||
temp = "You already know that spell."
|
||||
uses++
|
||||
break
|
||||
/*
|
||||
*/
|
||||
if(!already_knows)
|
||||
switch(href_list["spell_choice"])
|
||||
if("magicmissile")
|
||||
feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/projectile/magic_missile(H)
|
||||
temp = "This spell fires several, slow moving, magic projectiles at nearby targets. If a projectile hits a target, the target is stunned for some time."
|
||||
if("fireball")
|
||||
feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/dumbfire/fireball(H)
|
||||
temp = "This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you."
|
||||
if("disintegrate")
|
||||
feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate(H)
|
||||
temp = "This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown."
|
||||
if("disabletech")
|
||||
feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/emplosion/disable_tech(H)
|
||||
temp = "This spell releases an EMP from your person disabling most technology within range; computers, doors, prosthetics, etc."
|
||||
if("smoke")
|
||||
feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/smoke(H)
|
||||
temp = "This spell spawns a cloud of vision obscuring smoke at your location and does not require wizard garb."
|
||||
if("blind")
|
||||
feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/trigger/blind(H)
|
||||
temp = "This spell temporarly blinds a single person and does not require wizard garb."
|
||||
if("mindswap")
|
||||
feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/mind_transfer(H)
|
||||
temp = "This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process."
|
||||
if("forcewall")
|
||||
feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/forcewall(H)
|
||||
temp = "This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb."
|
||||
if("blink")
|
||||
feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/turf_teleport/blink(H)
|
||||
temp = "This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience."
|
||||
if("teleport")
|
||||
feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/area_teleport/teleport(H)
|
||||
temp = "This spell teleports you to an area of your selection, and creates a cloud of smoke around you upon arrival. Very useful if you are in danger.."
|
||||
if("mutate")
|
||||
feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/genetic/mutate(H)
|
||||
temp = "This spell causes you to turn into a hulk, gaining super strength and the ability to punch down walls! You also gain the ability to fire lasers from your eyes!"
|
||||
if("etherealjaunt")
|
||||
feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/ethereal_jaunt(H)
|
||||
temp = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
|
||||
if("knock")
|
||||
feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/knock(H)
|
||||
temp = "This spell opens nearby doors and does not require wizard garb."
|
||||
if("horseman")
|
||||
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/targeted/horsemask(H)
|
||||
temp = "This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require a wizard garb. Do note the curse will disintegrate the target's current mask if they are wearing one."
|
||||
if("summonguns")
|
||||
feedback_add_details("wizard_spell_learned","SG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
rightandwrong()
|
||||
max_uses--
|
||||
temp = "Nothing could possibly go wrong with arming a crew of lunatics just itching for an excuse to kill eachother. Just be careful not to get hit in the crossfire!"
|
||||
if("staffchange")
|
||||
feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff(get_turf(H))
|
||||
temp = "An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself"
|
||||
max_uses--
|
||||
if("mentalfocus")
|
||||
feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff/focus(get_turf(H))
|
||||
temp = "An artefact that channels the will of the user into destructive bolts of force."
|
||||
max_uses--
|
||||
if("soulstone")
|
||||
feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H))
|
||||
H.spell_list += new /obj/effect/proc_holder/spell/aoe_turf/conjure/construct(H)
|
||||
temp = "Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot."
|
||||
max_uses--
|
||||
if("armor")
|
||||
feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them.
|
||||
new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit
|
||||
new /obj/item/clothing/suit/space/void/wizard(get_turf(H))
|
||||
new /obj/item/clothing/head/helmet/space/void/wizard(get_turf(H))
|
||||
temp = "An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space."
|
||||
max_uses--
|
||||
if("staffanimation")
|
||||
feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff/animate(get_turf(H))
|
||||
temp = "An artefact that spits bolts of life-force which causes objects which are hit by it to animate and come to life! This magic doesn't affect machines."
|
||||
max_uses--
|
||||
if("scrying")
|
||||
feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/scrying(get_turf(H))
|
||||
if (!(XRAY in H.mutations))
|
||||
H.mutations.Add(XRAY)
|
||||
H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
|
||||
H.see_in_dark = 8
|
||||
H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
H << "<span class='info'>The walls suddenly disappear.</span>"
|
||||
temp = "You have purchased a scrying orb, and gained x-ray vision."
|
||||
max_uses--
|
||||
else
|
||||
if(href_list["temp"])
|
||||
temp = null
|
||||
attack_self(H)
|
||||
|
||||
return
|
||||
/obj/item/weapon/spellbook
|
||||
name = "spell book"
|
||||
desc = "The legendary book of spells of the wizard."
|
||||
icon = 'icons/obj/library.dmi'
|
||||
icon_state ="spellbook"
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = 1.0
|
||||
var/uses = 5
|
||||
var/temp = null
|
||||
var/max_uses = 5
|
||||
var/op = 1
|
||||
|
||||
/obj/item/weapon/spellbook/attack_self(mob/user = usr)
|
||||
if(!user)
|
||||
return
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if(temp)
|
||||
dat = "[temp]<BR><BR><A href='byond://?src=\ref[src];temp=1'>Clear</A>"
|
||||
else
|
||||
|
||||
// AUTOFIXED BY fix_string_idiocy.py
|
||||
dat = {"<B>The Book of Spells:</B><BR>
|
||||
Spells left to memorize: [uses]<BR>
|
||||
<HR>
|
||||
<B>Memorize which spell:</B><BR>
|
||||
<I>The number after the spell name is the cooldown time.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=magicmissile'>Magic Missile</A> (10)<BR>
|
||||
<I>This spell fires several, slow moving, magic projectiles at nearby targets. If they hit a target, it is paralyzed and takes minor damage.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=fireball'>Fireball</A> (10)<BR>
|
||||
<I>This spell fires a fireball in the direction you're facing and does not require wizard garb. Be careful not to fire it at people that are standing next to you.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=disintegrate'>Disintegrate</A> (60)<BR>
|
||||
<I>This spell instantly kills somebody adjacent to you with the vilest of magick. It has a long cooldown.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=disabletech'>Disable Technology</A> (60)<BR>
|
||||
<I>This spell disables all weapons, cameras and most other technology in range.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=smoke'>Smoke</A> (10)<BR>
|
||||
<I>This spell spawns a cloud of choking smoke at your location and does not require wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=blind'>Blind</A> (30)<BR>
|
||||
<I>This spell temporarly blinds a single person and does not require wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=subjugation'>Subjugation</A> (30)<BR>
|
||||
<I>This spell temporarily subjugates a target's mind and does not require wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=mindswap'>Mind Transfer</A> (60)<BR>
|
||||
<I>This spell allows the user to switch bodies with a target. Careful to not lose your memory in the process.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=forcewall'>Forcewall</A> (10)<BR>
|
||||
<I>This spell creates an unbreakable wall that lasts for 30 seconds and does not need wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=blink'>Blink</A> (2)<BR>
|
||||
<I>This spell randomly teleports you a short distance. Useful for evasion or getting into areas if you have patience.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=teleport'>Teleport</A> (60)<BR>
|
||||
<I>This spell teleports you to a type of area of your selection. Very useful if you are in danger, but has a decent cooldown, and is unpredictable.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=mutate'>Mutate</A> (60)<BR>
|
||||
<I>This spell causes you to turn into a hulk and gain telekinesis for a short while.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=etherealjaunt'>Ethereal Jaunt</A> (60)<BR>
|
||||
<I>This spell creates your ethereal form, temporarily making you invisible and able to pass through walls.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=knock'>Knock</A> (10)<BR>
|
||||
<I>This spell opens nearby doors and does not require wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=horseman'>Curse of the Horseman</A> (15)<BR>
|
||||
<I>This spell will curse a person to wear an unremovable horse mask (it has glue on the inside) and speak like a horse. It does not require wizard garb.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=fleshtostone'>Flesh to Stone</A> (60)<BR>
|
||||
<I>This spell will curse a person to immediately turn into an unmoving statue. The effect will eventually wear off if the statue is not destroyed.</I><BR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=noclothes'>Remove Clothes Requirement</A> <b>Warning: this takes away 2 spell choices.</b><BR>
|
||||
<HR>
|
||||
<B>Artefacts:</B><BR>
|
||||
Powerful items imbued with eldritch magics. Summoning one will count towards your maximum number of spells.<BR>
|
||||
It is recommended that only experienced wizards attempt to wield such artefacts.<BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=staffchange'>Staff of Change</A><BR>
|
||||
<I>An artefact that spits bolts of coruscating energy which cause the target's very form to reshape itself.</I><BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=mentalfocus'>Mental Focus</A><BR>
|
||||
<I>An artefact that channels the will of the user into destructive bolts of force.</I><BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=soulstone'>Six Soul Stone Shards and the spell Artificer</A><BR>
|
||||
<I>Soul Stone Shards are ancient tools capable of capturing and harnessing the spirits of the dead and dying. The spell Artificer allows you to create arcane machines for the captured souls to pilot.</I><BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=armor'>Mastercrafted Armor Set</A><BR>
|
||||
<I>An artefact suit of armor that allows you to cast spells while providing more protection against attacks and the void of space.</I><BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=staffanimation'>Staff of Animation</A><BR>
|
||||
<I>An arcane staff capable of shooting bolts of eldritch energy which cause inanimate objects to come to life. This magic doesn't affect machines.</I><BR>
|
||||
<HR>
|
||||
<A href='byond://?src=\ref[src];spell_choice=scrying'>Scrying Orb</A><BR>
|
||||
<I>An incandescent orb of crackling energy, using it will allow you to ghost while alive, allowing you to spy upon the station with ease. In addition, buying it will permanently grant you x-ray vision.</I><BR>
|
||||
<HR>"}
|
||||
// END AUTOFIX
|
||||
if(op)
|
||||
dat += "<A href='byond://?src=\ref[src];spell_choice=rememorize'>Re-memorize Spells</A><BR>"
|
||||
user << browse(dat, "window=radio")
|
||||
onclose(user, "radio")
|
||||
return
|
||||
|
||||
/obj/item/weapon/spellbook/Topic(href, href_list)
|
||||
..()
|
||||
var/mob/living/carbon/human/H = usr
|
||||
|
||||
if(H.stat || H.restrained())
|
||||
return
|
||||
if(!istype(H, /mob/living/carbon/human))
|
||||
return 1
|
||||
|
||||
if(H.mind.special_role == "apprentice")
|
||||
temp = "If you got caught sneaking a peak from your teacher's spellbook, you'd likely be expelled from the Wizard Academy. Better not."
|
||||
return
|
||||
|
||||
if(loc == H || (in_range(src, H) && istype(loc, /turf)))
|
||||
H.set_machine(src)
|
||||
if(href_list["spell_choice"])
|
||||
if(href_list["spell_choice"] == "rememorize")
|
||||
var/area/wizard_station/A = locate()
|
||||
if(usr in A.contents)
|
||||
uses = max_uses
|
||||
H.spellremove()
|
||||
temp = "All spells have been removed. You may now memorize a new set of spells."
|
||||
feedback_add_details("wizard_spell_learned","UM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
else
|
||||
temp = "You may only re-memorize spells whilst located inside the wizard sanctuary."
|
||||
else if(uses >= 1 && max_uses >=1)
|
||||
if(href_list["spell_choice"] == "noclothes")
|
||||
if(uses < 2)
|
||||
return
|
||||
uses--
|
||||
/*
|
||||
*/
|
||||
var/list/available_spells = list(magicmissile = "Magic Missile", fireball = "Fireball", disintegrate = "Disintegrate", disabletech = "Disable Tech", smoke = "Smoke", blind = "Blind", subjugation = "Subjugation", mindswap = "Mind Transfer", forcewall = "Forcewall", blink = "Blink", teleport = "Teleport", mutate = "Mutate", etherealjaunt = "Ethereal Jaunt", knock = "Knock", horseman = "Curse of the Horseman", staffchange = "Staff of Change", mentalfocus = "Mental Focus", soulstone = "Six Soul Stone Shards and the spell Artificer", armor = "Mastercrafted Armor Set", staffanimate = "Staff of Animation", noclothes = "No Clothes",fleshtostone = "Flesh to Stone")
|
||||
var/already_knows = 0
|
||||
for(var/spell/aspell in H.spell_list)
|
||||
if(available_spells[href_list["spell_choice"]] == initial(aspell.name))
|
||||
already_knows = 1
|
||||
if(!aspell.can_improve())
|
||||
temp = "This spell cannot be improved further."
|
||||
uses++
|
||||
break
|
||||
else
|
||||
if(aspell.can_improve("speed") && aspell.can_improve("power"))
|
||||
switch(alert(src, "Do you want to upgrade this spell's speed or power?", "Select Upgrade", "Speed", "Power", "Cancel"))
|
||||
if("Speed")
|
||||
temp = aspell.quicken_spell()
|
||||
if("Power")
|
||||
temp = aspell.empower_spell()
|
||||
else
|
||||
uses++
|
||||
break
|
||||
else if (aspell.can_improve("speed"))
|
||||
temp = aspell.quicken_spell()
|
||||
else if (aspell.can_improve("power"))
|
||||
temp = aspell.empower_spell()
|
||||
/*
|
||||
*/
|
||||
if(!already_knows)
|
||||
switch(href_list["spell_choice"])
|
||||
if("noclothes")
|
||||
feedback_add_details("wizard_spell_learned","NC")
|
||||
H.add_spell(new/spell/noclothes)
|
||||
temp = "This teaches you how to use your spells without your magical garb, truely you are the wizardest."
|
||||
uses--
|
||||
if("magicmissile")
|
||||
feedback_add_details("wizard_spell_learned","MM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/projectile/magic_missile)
|
||||
temp = "You have learned magic missile."
|
||||
if("fireball")
|
||||
feedback_add_details("wizard_spell_learned","FB") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/projectile/dumbfire/fireball)
|
||||
temp = "You have learned fireball."
|
||||
if("disintegrate")
|
||||
feedback_add_details("wizard_spell_learned","DG") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/disintegrate)
|
||||
temp = "You have learned disintegrate."
|
||||
if("disabletech")
|
||||
feedback_add_details("wizard_spell_learned","DT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/aoe_turf/disable_tech)
|
||||
temp = "You have learned disable technology."
|
||||
if("smoke")
|
||||
feedback_add_details("wizard_spell_learned","SM") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/aoe_turf/smoke)
|
||||
temp = "You have learned smoke."
|
||||
if("blind")
|
||||
feedback_add_details("wizard_spell_learned","BD") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/genetic/blind)
|
||||
temp = "You have learned blind."
|
||||
if("subjugation")
|
||||
feedback_add_details("wizard_spell_learned","SJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/subjugation)
|
||||
temp = "You have learned subjugate."
|
||||
if("mindswap")
|
||||
feedback_add_details("wizard_spell_learned","MT") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/mind_transfer)
|
||||
temp = "You have learned mindswap."
|
||||
if("forcewall")
|
||||
feedback_add_details("wizard_spell_learned","FW") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/aoe_turf/conjure/forcewall)
|
||||
temp = "You have learned forcewall."
|
||||
if("blink")
|
||||
feedback_add_details("wizard_spell_learned","BL") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/aoe_turf/blink)
|
||||
temp = "You have learned blink."
|
||||
if("teleport")
|
||||
feedback_add_details("wizard_spell_learned","TP") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/area_teleport)
|
||||
temp = "You have learned teleport."
|
||||
if("mutate")
|
||||
feedback_add_details("wizard_spell_learned","MU") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/genetic/mutate)
|
||||
temp = "You have learned mutate."
|
||||
if("etherealjaunt")
|
||||
feedback_add_details("wizard_spell_learned","EJ") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/ethereal_jaunt)
|
||||
temp = "You have learned ethereal jaunt."
|
||||
if("knock")
|
||||
feedback_add_details("wizard_spell_learned","KN") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/aoe_turf/knock)
|
||||
temp = "You have learned knock."
|
||||
if("horseman")
|
||||
feedback_add_details("wizard_spell_learned","HH") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/horsemask)
|
||||
temp = "You have learned curse of the horseman."
|
||||
if("fleshtostone")
|
||||
feedback_add_details("wizard_spell_learned","FS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
H.add_spell(new/spell/targeted/flesh_to_stone)
|
||||
temp = "You have learned flesh to stone."
|
||||
if("staffchange")
|
||||
feedback_add_details("wizard_spell_learned","ST") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff(get_turf(H))
|
||||
temp = "You have purchased a staff of change."
|
||||
max_uses--
|
||||
if("mentalfocus")
|
||||
feedback_add_details("wizard_spell_learned","MF") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff/focus(get_turf(H))
|
||||
temp = "An artefact that channels the will of the user into destructive bolts of force."
|
||||
max_uses--
|
||||
if("soulstone")
|
||||
feedback_add_details("wizard_spell_learned","SS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/storage/belt/soulstone/full(get_turf(H))
|
||||
H.add_spell(new/spell/aoe_turf/conjure/construct)
|
||||
temp = "You have purchased a belt full of soulstones and have learned the artificer spell."
|
||||
max_uses--
|
||||
if("armor")
|
||||
feedback_add_details("wizard_spell_learned","HS") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/clothing/shoes/sandal(get_turf(H)) //In case they've lost them.
|
||||
new /obj/item/clothing/gloves/purple(get_turf(H))//To complete the outfit
|
||||
new /obj/item/clothing/suit/space/void/wizard(get_turf(H))
|
||||
new /obj/item/clothing/head/helmet/space/void/wizard(get_turf(H))
|
||||
temp = "You have purchased a suit of wizard armor."
|
||||
max_uses--
|
||||
if("staffanimation")
|
||||
feedback_add_details("wizard_spell_learned","SA") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/gun/energy/staff/animate(get_turf(H))
|
||||
temp = "You have purchased a staff of animation."
|
||||
max_uses--
|
||||
if("scrying")
|
||||
feedback_add_details("wizard_spell_learned","SO") //please do not change the abbreviation to keep data processing consistent. Add a unique id to any new spells
|
||||
new /obj/item/weapon/scrying(get_turf(H))
|
||||
if (!(XRAY in H.mutations))
|
||||
H.mutations.Add(XRAY)
|
||||
H.sight |= (SEE_MOBS|SEE_OBJS|SEE_TURFS)
|
||||
H.see_in_dark = 8
|
||||
H.see_invisible = SEE_INVISIBLE_LEVEL_TWO
|
||||
H << "\blue The walls suddenly disappear."
|
||||
temp = "You have purchased a scrying orb, and gained x-ray vision."
|
||||
max_uses--
|
||||
else
|
||||
if(href_list["temp"])
|
||||
temp = null
|
||||
attack_self()
|
||||
|
||||
return
|
||||
|
||||
//Single Use Spellbooks//
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse
|
||||
var/spell = /spell/targeted/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic
|
||||
var/spellname = "sandbox"
|
||||
var/used = 0
|
||||
name = "spellbook of "
|
||||
uses = 1
|
||||
max_uses = 1
|
||||
desc = "This template spellbook was never meant for the eyes of man..."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/New()
|
||||
..()
|
||||
name += spellname
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/attack_self(mob/user as mob)
|
||||
var/spell/S = new spell(user)
|
||||
for(var/spell/knownspell in user.spell_list)
|
||||
if(knownspell.type == S.type)
|
||||
if(user.mind)
|
||||
if(user.mind.special_role == "apprentice" || user.mind.special_role == "Wizard")
|
||||
user <<"<span class='notice'>You're already far more versed in this spell than this flimsy how-to book can provide.</span>"
|
||||
else
|
||||
user <<"<span class='notice'>You've already read this one.</span>"
|
||||
return
|
||||
if(used)
|
||||
recoil(user)
|
||||
else
|
||||
user.add_spell(S)
|
||||
user <<"<span class='notice'>you rapidly read through the arcane book. Suddenly you realize you understand [spellname]!</span>"
|
||||
user.attack_log += text("\[[time_stamp()]\] <font color='orange'>[user.real_name] ([user.ckey]) learned the spell [spellname] ([S]).</font>")
|
||||
onlearned(user)
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/proc/recoil(mob/user as mob)
|
||||
user.visible_message("<span class='warning'>[src] glows in a black light!</span>")
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/proc/onlearned(mob/user as mob)
|
||||
used = 1
|
||||
user.visible_message("<span class='caution'>[src] glows dark for a second!</span>")
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/attackby()
|
||||
return
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/fireball
|
||||
spell = /spell/targeted/projectile/dumbfire/fireball
|
||||
spellname = "fireball"
|
||||
icon_state ="bookfireball"
|
||||
desc = "This book feels warm to the touch."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/fireball/recoil(mob/user as mob)
|
||||
..()
|
||||
explosion(user.loc, -1, 0, 2, 3, 0, flame_range = 2)
|
||||
qdel(src)
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/smoke
|
||||
spell = /spell/aoe_turf/smoke
|
||||
spellname = "smoke"
|
||||
icon_state ="booksmoke"
|
||||
desc = "This book is overflowing with the dank arts."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/smoke/recoil(mob/user as mob)
|
||||
..()
|
||||
user <<"<span class='caution'>Your stomach rumbles...</span>"
|
||||
if(user.nutrition)
|
||||
user.nutrition -= 200
|
||||
if(user.nutrition <= 0)
|
||||
user.nutrition = 0
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/blind
|
||||
spell = /spell/targeted/genetic/blind
|
||||
spellname = "blind"
|
||||
icon_state ="bookblind"
|
||||
desc = "This book looks blurry, no matter how you look at it."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/blind/recoil(mob/user as mob)
|
||||
..()
|
||||
user <<"<span class='warning'>You go blind!</span>"
|
||||
user.eye_blind = 10
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/mindswap
|
||||
spell = /spell/targeted/mind_transfer
|
||||
spellname = "mindswap"
|
||||
icon_state ="bookmindswap"
|
||||
desc = "This book's cover is pristine, though its pages look ragged and torn."
|
||||
var/mob/stored_swap = null //Used in used book recoils to store an identity for mindswaps
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/mindswap/onlearned()
|
||||
spellname = pick("fireball","smoke","blind","forcewall","knock","horses","charge")
|
||||
icon_state = "book[spellname]"
|
||||
name = "spellbook of [spellname]" //Note, desc doesn't change by design
|
||||
..()
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/mindswap/recoil(mob/user as mob)
|
||||
..()
|
||||
if(stored_swap in dead_mob_list)
|
||||
stored_swap = null
|
||||
if(!stored_swap)
|
||||
stored_swap = user
|
||||
user <<"<span class='warning'>For a moment you feel like you don't even know who you are anymore.</span>"
|
||||
return
|
||||
if(stored_swap == user)
|
||||
user <<"<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>"
|
||||
return
|
||||
|
||||
if(user.mind.special_verbs.len)
|
||||
for(var/V in user.mind.special_verbs)
|
||||
user.verbs -= V
|
||||
|
||||
if(stored_swap.mind.special_verbs.len)
|
||||
for(var/V in stored_swap.mind.special_verbs)
|
||||
stored_swap.verbs -= V
|
||||
|
||||
var/mob/dead/observer/ghost = stored_swap.ghostize(0)
|
||||
ghost.spell_list = stored_swap.spell_list
|
||||
|
||||
user.mind.transfer_to(stored_swap)
|
||||
stored_swap.spell_list = user.spell_list
|
||||
|
||||
if(stored_swap.mind.special_verbs.len)
|
||||
for(var/V in user.mind.special_verbs)
|
||||
user.verbs += V
|
||||
|
||||
ghost.mind.transfer_to(user)
|
||||
user.key = ghost.key
|
||||
user.spell_list = ghost.spell_list
|
||||
|
||||
if(user.mind.special_verbs.len)
|
||||
for(var/V in user.mind.special_verbs)
|
||||
user.verbs += V
|
||||
|
||||
stored_swap <<"<span class='warning'>You're suddenly somewhere else... and someone else?!</span>"
|
||||
user <<"<span class='warning'>Suddenly you're staring at [src] again... where are you, who are you?!</span>"
|
||||
stored_swap = null
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/forcewall
|
||||
spell = /spell/aoe_turf/conjure/forcewall
|
||||
spellname = "forcewall"
|
||||
icon_state ="bookforcewall"
|
||||
desc = "This book has a dedication to mimes everywhere inside the front cover."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/forcewall/recoil(mob/user as mob)
|
||||
..()
|
||||
user <<"<span class='warning'>You suddenly feel very solid!</span>"
|
||||
var/obj/structure/closet/statue/S = new /obj/structure/closet/statue(user.loc, user)
|
||||
S.timer = 30
|
||||
user.drop_item()
|
||||
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/knock
|
||||
spell = /spell/aoe_turf/knock
|
||||
spellname = "knock"
|
||||
icon_state ="bookknock"
|
||||
desc = "This book is hard to hold closed properly."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/knock/recoil(mob/user as mob)
|
||||
..()
|
||||
user <<"<span class='warning'>You're knocked down!</span>"
|
||||
user.Weaken(20)
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/horsemask
|
||||
spell = /spell/targeted/horsemask
|
||||
spellname = "horses"
|
||||
icon_state ="bookhorses"
|
||||
desc = "This book is more horse than your mind has room for."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/horsemask/recoil(mob/living/carbon/user as mob)
|
||||
if(istype(user, /mob/living/carbon/human))
|
||||
user <<"<font size='15' color='red'><b>HOR-SIE HAS RISEN</b></font>"
|
||||
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
|
||||
magichead.canremove = 0 //curses!
|
||||
magichead.flags_inv = null //so you can still see their face
|
||||
magichead.voicechange = 1 //NEEEEIIGHH
|
||||
user.drop_from_inventory(user.wear_mask)
|
||||
user.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
|
||||
qdel(src)
|
||||
else
|
||||
user <<"<span class='notice'>I say thee neigh</span>"
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/charge
|
||||
spell = /spell/aoe_turf/charge
|
||||
spellname = "charging"
|
||||
icon_state ="bookcharge"
|
||||
desc = "This book is made of 100% post-consumer wizard."
|
||||
|
||||
/obj/item/weapon/spellbook/oneuse/charge/recoil(mob/user as mob)
|
||||
..()
|
||||
user <<"<span class='warning'>[src] suddenly feels very warm!</span>"
|
||||
empulse(src, 1, 1)
|
||||
|
||||
64
code/modules/spells/spells.dm
Normal file
64
code/modules/spells/spells.dm
Normal file
@@ -0,0 +1,64 @@
|
||||
/mob/Life()
|
||||
..()
|
||||
if(spell_masters && spell_masters.len)
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
spell_master.update_spells(0, src)
|
||||
|
||||
/mob/Stat()
|
||||
..()
|
||||
if(spell_list && spell_list.len && statpanel("Spells"))
|
||||
for(var/spell/S in spell_list)
|
||||
switch(S.charge_type)
|
||||
if(Sp_RECHARGE)
|
||||
statpanel("Spells","[S.charge_counter/10.0]/[S.charge_max/10]",S)
|
||||
if(Sp_CHARGES)
|
||||
statpanel("Spells","[S.charge_counter]/[S.charge_max]",S)
|
||||
if(Sp_HOLDVAR)
|
||||
statpanel("Spells","[S.holder_var_type] [S.holder_var_amount]",S)
|
||||
|
||||
/mob/proc/add_spell(var/spell/spell_to_add, var/spell_base = "wiz_spell_ready", var/master_type = /obj/screen/movable/spell_master)
|
||||
if(!spell_masters)
|
||||
spell_masters = list()
|
||||
|
||||
if(spell_masters.len)
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
if(spell_master.type == master_type)
|
||||
spell_list.Add(spell_to_add)
|
||||
spell_master.add_spell(spell_to_add)
|
||||
return 1
|
||||
|
||||
var/obj/screen/movable/spell_master/new_spell_master = new master_type //we're here because either we didn't find our type, or we have no spell masters to attach to
|
||||
if(client)
|
||||
src.client.screen += new_spell_master
|
||||
new_spell_master.spell_holder = src
|
||||
new_spell_master.add_spell(spell_to_add)
|
||||
if(spell_base)
|
||||
new_spell_master.icon_state = spell_base
|
||||
spell_masters.Add(new_spell_master)
|
||||
spell_list.Add(spell_to_add)
|
||||
return 1
|
||||
|
||||
/mob/proc/remove_spell(var/spell/spell_to_remove)
|
||||
if(!spell_to_remove || !istype(spell_to_remove))
|
||||
return
|
||||
|
||||
if(!(spell_to_remove in spell_list))
|
||||
return
|
||||
|
||||
if(!spell_masters || !spell_masters.len)
|
||||
return
|
||||
|
||||
spell_list.Remove(spell_to_remove)
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
spell_master.remove_spell(spell_to_remove)
|
||||
return 1
|
||||
|
||||
/mob/proc/silence_spells(var/amount = 0)
|
||||
if(!(amount >= 0))
|
||||
return
|
||||
|
||||
if(!spell_masters || !spell_masters.len)
|
||||
return
|
||||
|
||||
for(var/obj/screen/movable/spell_master/spell_master in spell_masters)
|
||||
spell_master.silence_spells(amount)
|
||||
27
code/modules/spells/targeted/disintegrate.dm
Normal file
27
code/modules/spells/targeted/disintegrate.dm
Normal file
@@ -0,0 +1,27 @@
|
||||
/spell/targeted/disintegrate
|
||||
name = "Disintegrate"
|
||||
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 600
|
||||
spell_flags = NEEDSCLOTHES
|
||||
invocation = "EI NATH"
|
||||
invocation_type = SpI_SHOUT
|
||||
range = 1
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
|
||||
sparks_spread = 1
|
||||
sparks_amt = 4
|
||||
|
||||
hud_state = "wiz_disint"
|
||||
|
||||
/spell/targeted/disintegrate/cast(var/list/targets)
|
||||
..()
|
||||
for(var/mob/living/target in targets)
|
||||
if(ishuman(target))
|
||||
var/mob/living/carbon/C = target
|
||||
if(!C.has_brain()) // Their brain is already taken out
|
||||
var/obj/item/organ/brain/B = new(C.loc)
|
||||
B.transfer_identity(C)
|
||||
target.gib()
|
||||
return
|
||||
98
code/modules/spells/targeted/ethereal_jaunt.dm
Normal file
98
code/modules/spells/targeted/ethereal_jaunt.dm
Normal file
@@ -0,0 +1,98 @@
|
||||
/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
|
||||
spell_flags = Z2NOCAST | NEEDSCLOTHES | INCLUDEUSER
|
||||
invocation = "none"
|
||||
invocation_type = SpI_NONE
|
||||
range = -1
|
||||
max_targets = 1
|
||||
cooldown_min = 100 //50 deciseconds reduction per rank
|
||||
duration = 50 //in deciseconds
|
||||
|
||||
hud_state = "wiz_jaunt"
|
||||
|
||||
/spell/targeted/ethereal_jaunt/cast(list/targets) //magnets, so mostly hardcoded
|
||||
for(var/mob/living/target in targets)
|
||||
target.monkeyizing = 1 //protects the mob from being transformed (replaced) midjaunt and getting stuck in bluespace
|
||||
if(target.buckled) target.buckled = null
|
||||
spawn(0)
|
||||
var/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 = 5
|
||||
animation.master = holder
|
||||
target.ExtinguishMob()
|
||||
if(target.buckled)
|
||||
target.buckled = null
|
||||
jaunt_disappear(animation, target)
|
||||
target.loc = holder
|
||||
target.monkeyizing=0 //mob is safely inside holder now, no need for protection.
|
||||
jaunt_steam(mobloc)
|
||||
sleep(duration)
|
||||
mobloc = get_turf(target.loc)
|
||||
animation.loc = mobloc
|
||||
jaunt_steam(mobloc)
|
||||
target.canmove = 0
|
||||
holder.reappearing = 1
|
||||
sleep(20)
|
||||
jaunt_reappear(animation, target)
|
||||
sleep(5)
|
||||
if(!target.forceMove(mobloc))
|
||||
for(var/direction in list(1,2,4,8,5,6,9,10))
|
||||
var/turf/T = get_step(mobloc, direction)
|
||||
if(T)
|
||||
if(target.forceMove(T))
|
||||
break
|
||||
target.canmove = 1
|
||||
target.client.eye = target
|
||||
del(animation)
|
||||
del(holder)
|
||||
|
||||
/spell/targeted/ethereal_jaunt/proc/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
|
||||
animation.icon_state = "liquify"
|
||||
flick("liquify",animation)
|
||||
|
||||
/spell/targeted/ethereal_jaunt/proc/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
|
||||
flick("reappear",animation)
|
||||
|
||||
/spell/targeted/ethereal_jaunt/proc/jaunt_steam(var/mobloc)
|
||||
var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/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
|
||||
|
||||
/obj/effect/dummy/spell_jaunt/Destroy()
|
||||
// Eject contents if deleted somehow
|
||||
for(var/atom/movable/AM in src)
|
||||
AM.loc = get_turf(src)
|
||||
..()
|
||||
|
||||
/obj/effect/dummy/spell_jaunt/relaymove(var/mob/user, direction)
|
||||
if (!src.canmove || reappearing) 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
|
||||
21
code/modules/spells/targeted/flesh_to_stone.dm
Normal file
21
code/modules/spells/targeted/flesh_to_stone.dm
Normal file
@@ -0,0 +1,21 @@
|
||||
/spell/targeted/flesh_to_stone
|
||||
name = "Flesh to Stone"
|
||||
desc = "This spell turns a single person into an inert statue for a long period of time."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
spell_flags = NEEDSCLOTHES
|
||||
range = 3
|
||||
max_targets = 1
|
||||
invocation = "STAUN EI"
|
||||
invocation_type = SpI_SHOUT
|
||||
amt_stunned = 5//just exists to make sure the statue "catches" them
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
|
||||
hud_state = "wiz_statue"
|
||||
|
||||
/spell/targeted/flesh_to_stone/cast(var/list/targets, mob/user)
|
||||
..()
|
||||
for(var/mob/living/target in targets)
|
||||
new /obj/structure/closet/statue(target.loc, target) //makes the statue
|
||||
return
|
||||
68
code/modules/spells/targeted/genetic.dm
Normal file
68
code/modules/spells/targeted/genetic.dm
Normal file
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
Other mutation or disability spells can be found in
|
||||
code\game\dna\genes\vg_powers.dm //hulk is in this file
|
||||
code\game\dna\genes\goon_disabilities.dm
|
||||
code\game\dna\genes\goon_powers.dm
|
||||
*/
|
||||
/spell/targeted/genetic
|
||||
name = "Genetic modifier"
|
||||
desc = "This spell inflicts a set of mutations and disabilities upon the target."
|
||||
|
||||
var/disabilities = 0 //bits
|
||||
var/list/mutations = list() //mutation strings
|
||||
duration = 100 //deciseconds
|
||||
|
||||
|
||||
/spell/targeted/genetic/cast(list/targets)
|
||||
..()
|
||||
for(var/mob/living/target in targets)
|
||||
for(var/x in mutations)
|
||||
target.mutations.Add(x)
|
||||
target.disabilities |= disabilities
|
||||
target.update_mutations() //update target's mutation overlays
|
||||
spawn(duration)
|
||||
for(var/x in mutations)
|
||||
target.mutations.Remove(x)
|
||||
target.disabilities &= ~disabilities
|
||||
target.update_mutations()
|
||||
return
|
||||
|
||||
/spell/targeted/genetic/blind
|
||||
name = "Blind"
|
||||
disabilities = 1
|
||||
duration = 300
|
||||
|
||||
charge_max = 300
|
||||
|
||||
spell_flags = 0
|
||||
invocation = "STI KALY"
|
||||
invocation_type = SpI_WHISPER
|
||||
message = "<span class='danger'>Your eyes cry out in pain!</span>"
|
||||
cooldown_min = 50
|
||||
|
||||
range = 7
|
||||
max_targets = 0
|
||||
|
||||
amt_eye_blind = 10
|
||||
amt_eye_blurry = 20
|
||||
|
||||
hud_state = "wiz_blind"
|
||||
|
||||
/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
|
||||
spell_flags = Z2NOCAST | NEEDSCLOTHES | INCLUDEUSER
|
||||
invocation = "BIRUZ BENNAR"
|
||||
invocation_type = SpI_SHOUT
|
||||
message = "\blue You feel strong! You feel a pressure building behind your eyes!"
|
||||
range = 0
|
||||
max_targets = 1
|
||||
|
||||
mutations = list(LASER, HULK)
|
||||
duration = 300
|
||||
cooldown_min = 300 //25 deciseconds reduction per rank
|
||||
|
||||
hud_state = "wiz_hulk"
|
||||
36
code/modules/spells/targeted/harvest.dm
Normal file
36
code/modules/spells/targeted/harvest.dm
Normal file
@@ -0,0 +1,36 @@
|
||||
/spell/targeted/harvest
|
||||
name = "Harvest"
|
||||
desc = "Back to where I come from, and you're coming with me."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 200
|
||||
spell_flags = Z2NOCAST | CONSTRUCT_CHECK | INCLUDEUSER
|
||||
invocation = ""
|
||||
invocation_type = SpI_NONE
|
||||
range = 0
|
||||
max_targets = 0
|
||||
|
||||
overlay = 1
|
||||
overlay_icon = 'icons/effects/effects.dmi'
|
||||
overlay_icon_state = "rune_teleport"
|
||||
overlay_lifespan = 0
|
||||
|
||||
hud_state = "const_harvest"
|
||||
|
||||
/spell/targeted/harvest/cast(list/targets, mob/user)//because harvest is already a proc
|
||||
..()
|
||||
|
||||
var/destination = null
|
||||
for(var/obj/machinery/singularity/narsie/large/N in narsie_list)
|
||||
destination = N.loc
|
||||
break
|
||||
if(destination)
|
||||
var/prey = 0
|
||||
for(var/mob/living/M in targets)
|
||||
if(!findNullRod(M))
|
||||
M.forceMove(destination)
|
||||
if(M != user)
|
||||
prey = 1
|
||||
user << "<span class='sinister'>You warp back to Nar-Sie[prey ? " along with your prey":""].</span>"
|
||||
else
|
||||
user << "<span class='danger'>...something's wrong!</span>"//There shouldn't be an instance of Harvesters when Nar-Sie isn't in the world.
|
||||
35
code/modules/spells/targeted/horsemask.dm
Normal file
35
code/modules/spells/targeted/horsemask.dm
Normal file
@@ -0,0 +1,35 @@
|
||||
/spell/targeted/horsemask
|
||||
name = "Curse of the Horseman"
|
||||
desc = "This spell triggers a curse on a target, causing them to wield an unremovable horse head mask. They will speak like a horse! Any masks they are wearing will be disintegrated. This spell does not require robes."
|
||||
school = "transmutation"
|
||||
charge_type = Sp_RECHARGE
|
||||
charge_max = 150
|
||||
charge_counter = 0
|
||||
spell_flags = 0
|
||||
invocation = "KN'A FTAGHU, PUCK 'BTHNK!"
|
||||
invocation_type = SpI_SHOUT
|
||||
range = 7
|
||||
max_targets = 1
|
||||
cooldown_min = 30 //30 deciseconds reduction per rank
|
||||
selection_type = "range"
|
||||
|
||||
compatible_mobs = list(/mob/living/carbon/human)
|
||||
|
||||
hud_state = "wiz_horse"
|
||||
|
||||
/spell/targeted/horsemask/cast(list/targets, mob/user = usr)
|
||||
..()
|
||||
for(var/mob/living/target in targets)
|
||||
var/obj/item/clothing/mask/horsehead/magichead = new /obj/item/clothing/mask/horsehead
|
||||
magichead.canremove = 0 //curses!
|
||||
magichead.flags_inv = null //so you can still see their face
|
||||
magichead.voicechange = 1 //NEEEEIIGHH
|
||||
target.visible_message( "<span class='danger'>[target]'s face lights up in fire, and after the event a horse's head takes its place!</span>", \
|
||||
"<span class='danger'>Your face burns up, and shortly after the fire you realise you have the face of a horse!</span>")
|
||||
var/obj/old_mask = target.wear_mask
|
||||
if(old_mask)
|
||||
target.drop_from_inventory(old_mask)
|
||||
qdel(old_mask) //get rid of this shit
|
||||
target.equip_to_slot_if_possible(magichead, slot_wear_mask, 1, 1)
|
||||
|
||||
flick("e_flash", target.flash)
|
||||
73
code/modules/spells/targeted/mind_transfer.dm
Normal file
73
code/modules/spells/targeted/mind_transfer.dm
Normal file
@@ -0,0 +1,73 @@
|
||||
/spell/targeted/mind_transfer
|
||||
name = "Mind Transfer"
|
||||
desc = "This spell allows the user to switch bodies with a target."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 600
|
||||
spell_flags = 0
|
||||
invocation = "GIN'YU CAPAN"
|
||||
invocation_type = SpI_WHISPER
|
||||
max_targets = 1
|
||||
range = 1
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
compatible_mobs = list(/mob/living/carbon/human) //which types of mobs are affected by the spell. NOTE: change at your own risk
|
||||
|
||||
var/list/protected_roles = list("Wizard","Changeling","Cultist") //which roles are immune to the spell
|
||||
var/msg_wait = 500 //how long in deciseconds it waits before telling that body doesn't feel right or mind swap robbed of a spell
|
||||
amt_paralysis = 20 //how much the victim is paralysed for after the spell
|
||||
|
||||
hud_state = "wiz_mindswap"
|
||||
|
||||
/spell/targeted/mind_transfer/cast(list/targets, mob/user)
|
||||
..()
|
||||
|
||||
for(var/mob/living/target in targets)
|
||||
if(target.stat == DEAD)
|
||||
user << "You didn't study necromancy back at the Space Wizard Federation academy."
|
||||
continue
|
||||
|
||||
if(!target.key || !target.mind)
|
||||
user << "They appear to be catatonic. Not even magic can affect their vacant mind."
|
||||
continue
|
||||
|
||||
if(target.mind.special_role in protected_roles)
|
||||
user << "Their mind is resisting your spell."
|
||||
continue
|
||||
|
||||
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)
|
||||
ghost.spell_list = victim.spell_list//If they have spells, transfer them. Now we basically have a backup mob.
|
||||
|
||||
caster.mind.transfer_to(victim)
|
||||
victim.spell_list = caster.spell_list//Now they are inside the victim's body.
|
||||
|
||||
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)
|
||||
caster.key = ghost.key //have to transfer the key since the mind was not active
|
||||
caster.spell_list = ghost.spell_list
|
||||
|
||||
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
|
||||
for(var/V in caster.mind.special_verbs)
|
||||
caster.verbs += V
|
||||
//MIND TRANSFER END
|
||||
|
||||
//Target is handled in ..(), so we handle the caster here
|
||||
caster.Paralyse(amt_paralysis)
|
||||
|
||||
//After a certain amount of time the victim gets a message about being in a different body.
|
||||
spawn(msg_wait)
|
||||
caster << "\red You feel woozy and lightheaded. <b>Your body doesn't seem like your own.</b>"
|
||||
13
code/modules/spells/targeted/projectile/dumbfire.dm
Normal file
13
code/modules/spells/targeted/projectile/dumbfire.dm
Normal file
@@ -0,0 +1,13 @@
|
||||
/spell/targeted/projectile/dumbfire
|
||||
name = "dumbfire spell"
|
||||
|
||||
/spell/targeted/projectile/dumbfire/choose_targets(mob/user = usr)
|
||||
var/list/targets = list()
|
||||
|
||||
var/starting_dir = user.dir //where are we facing at the time of casting?
|
||||
var/turf/starting_turf = get_turf(user)
|
||||
var/current_turf = starting_turf
|
||||
for(var/i = 1; i <= src.range; i++)
|
||||
current_turf = get_step(current_turf, starting_dir)
|
||||
targets += current_turf
|
||||
return targets
|
||||
39
code/modules/spells/targeted/projectile/fireball.dm
Normal file
39
code/modules/spells/targeted/projectile/fireball.dm
Normal file
@@ -0,0 +1,39 @@
|
||||
/spell/targeted/projectile/dumbfire/fireball
|
||||
name = "Fireball"
|
||||
desc = "This spell fires a fireball at a target and does not require wizard garb."
|
||||
|
||||
proj_type = /obj/item/projectile/spell_projectile/fireball
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 100
|
||||
spell_flags = 0
|
||||
invocation = "ONI SOMA"
|
||||
invocation_type = SpI_SHOUT
|
||||
range = 20
|
||||
cooldown_min = 20 //10 deciseconds reduction per rank
|
||||
|
||||
spell_flags = 0
|
||||
|
||||
duration = 20
|
||||
proj_step_delay = 1
|
||||
|
||||
amt_dam_brute = 20
|
||||
amt_dam_fire = 25
|
||||
|
||||
var/ex_severe = -1
|
||||
var/ex_heavy = 1
|
||||
var/ex_light = 2
|
||||
var/ex_flash = 5
|
||||
|
||||
hud_state = "wiz_fireball"
|
||||
|
||||
/spell/targeted/projectile/dumbfire/fireball/prox_cast(var/list/targets, spell_holder)
|
||||
for(var/mob/living/M in targets)
|
||||
apply_spell_damage(M)
|
||||
explosion(get_turf(spell_holder), ex_severe, ex_heavy, ex_light, ex_flash)
|
||||
|
||||
//PROJECTILE
|
||||
|
||||
/obj/item/projectile/spell_projectile/fireball
|
||||
name = "fireball"
|
||||
icon_state = "fireball"
|
||||
40
code/modules/spells/targeted/projectile/magic_missile.dm
Normal file
40
code/modules/spells/targeted/projectile/magic_missile.dm
Normal file
@@ -0,0 +1,40 @@
|
||||
/spell/targeted/projectile/magic_missile
|
||||
name = "Magic Missile"
|
||||
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 150
|
||||
spell_flags = NEEDSCLOTHES
|
||||
invocation = "FORTI GY AMA"
|
||||
invocation_type = SpI_SHOUT
|
||||
range = 7
|
||||
cooldown_min = 90 //15 deciseconds reduction per rank
|
||||
|
||||
max_targets = 0
|
||||
|
||||
proj_type = /obj/item/projectile/spell_projectile/seeking/magic_missile
|
||||
duration = 10
|
||||
proj_step_delay = 5
|
||||
|
||||
hud_state = "wiz_mm"
|
||||
|
||||
amt_paralysis = 3
|
||||
amt_stunned = 3
|
||||
|
||||
amt_dam_fire = 10
|
||||
|
||||
/spell/targeted/projectile/magic_missile/prox_cast(var/list/targets, atom/spell_holder)
|
||||
spell_holder.visible_message("<span class='danger'>\The [spell_holder] pops with a flash!</span>")
|
||||
for(var/mob/living/M in targets)
|
||||
apply_spell_damage(M)
|
||||
return
|
||||
|
||||
//PROJECTILE
|
||||
|
||||
/obj/item/projectile/spell_projectile/seeking/magic_missile
|
||||
name = "magic missile"
|
||||
icon_state = "magicm"
|
||||
|
||||
proj_trail = 1
|
||||
proj_trail_lifespan = 5
|
||||
proj_trail_icon_state = "magicmd"
|
||||
53
code/modules/spells/targeted/projectile/projectile.dm
Normal file
53
code/modules/spells/targeted/projectile/projectile.dm
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
Projectile spells make special projectiles (obj/item/spell_projectile) and fire them at targets
|
||||
Dumbfire projectile spells fire directly ahead of the user
|
||||
spell_projectiles call their spell's (carried) prox_cast when they get in range of a target
|
||||
If the spell_projectile is seeking, it will update its target every process and follow them
|
||||
*/
|
||||
|
||||
/spell/targeted/projectile
|
||||
name = "projectile spell"
|
||||
|
||||
range = 7
|
||||
|
||||
var/proj_type = /obj/item/projectile/spell_projectile //use these. They are very nice
|
||||
|
||||
var/proj_step_delay = 1 //lower = faster
|
||||
var/cast_prox_range = 1
|
||||
|
||||
/spell/targeted/projectile/cast(list/targets, mob/user = usr)
|
||||
|
||||
if(istext(proj_type))
|
||||
proj_type = text2path(proj_type) // sanity filters
|
||||
|
||||
for(var/atom/target in targets)
|
||||
var/obj/item/projectile/projectile = new proj_type(user.loc, user.dir)
|
||||
|
||||
if(!projectile)
|
||||
return
|
||||
|
||||
projectile.original = target
|
||||
projectile.starting = get_turf(user)
|
||||
projectile.shot_from = user //fired from the user
|
||||
projectile.current = projectile.original
|
||||
projectile.yo = target.y - user.y
|
||||
projectile.xo = target.x - user.x
|
||||
projectile.kill_count = src.duration
|
||||
projectile.hitscan = !proj_step_delay
|
||||
projectile.step_delay = proj_step_delay
|
||||
if(istype(projectile, /obj/item/projectile/spell_projectile))
|
||||
var/obj/item/projectile/spell_projectile/SP = projectile
|
||||
SP.carried = src //casting is magical
|
||||
spawn projectile.process()
|
||||
return
|
||||
|
||||
/spell/targeted/projectile/proc/choose_prox_targets(mob/user = usr, var/atom/movable/spell_holder)
|
||||
var/list/targets = list()
|
||||
for(var/mob/living/M in range(spell_holder, cast_prox_range))
|
||||
if(M == user && !(spell_flags & INCLUDEUSER))
|
||||
continue
|
||||
targets += M
|
||||
return targets
|
||||
|
||||
/spell/targeted/projectile/proc/prox_cast(var/list/targets, var/atom/movable/spell_holder)
|
||||
return targets
|
||||
24
code/modules/spells/targeted/shift.dm
Normal file
24
code/modules/spells/targeted/shift.dm
Normal file
@@ -0,0 +1,24 @@
|
||||
/spell/targeted/ethereal_jaunt/shift
|
||||
name = "Phase Shift"
|
||||
desc = "This spell allows you to pass through walls"
|
||||
|
||||
charge_max = 200
|
||||
spell_flags = Z2NOCAST | INCLUDEUSER | CONSTRUCT_CHECK
|
||||
invocation_type = SpI_NONE
|
||||
range = -1
|
||||
duration = 50 //in deciseconds
|
||||
|
||||
hud_state = "const_shift"
|
||||
|
||||
/spell/targeted/ethereal_jaunt/shift/jaunt_disappear(var/atom/movable/overlay/animation, var/mob/living/target)
|
||||
animation.icon_state = "phase_shift"
|
||||
animation.dir = target.dir
|
||||
flick("phase_shift",animation)
|
||||
|
||||
/spell/targeted/ethereal_jaunt/shift/jaunt_reappear(var/atom/movable/overlay/animation, var/mob/living/target)
|
||||
animation.icon_state = "phase_shift2"
|
||||
animation.dir = target.dir
|
||||
flick("phase_shift2",animation)
|
||||
|
||||
/spell/targeted/ethereal_jaunt/shift/jaunt_steam(var/mobloc)
|
||||
return
|
||||
20
code/modules/spells/targeted/subjugate.dm
Normal file
20
code/modules/spells/targeted/subjugate.dm
Normal file
@@ -0,0 +1,20 @@
|
||||
/spell/targeted/subjugation
|
||||
name = "Subjugation"
|
||||
desc = "This spell temporarily subjugates a target's mind and does not require wizard garb."
|
||||
|
||||
school = "transmutation"
|
||||
charge_max = 300
|
||||
spell_flags = 0
|
||||
invocation = "DII ODA BAJI"
|
||||
invocation_type = SpI_WHISPER
|
||||
message = "<span class='danger'>You suddenly feel completely overwhelmed!<span>"
|
||||
|
||||
max_targets = 1
|
||||
|
||||
amt_dizziness = 300
|
||||
amt_confused = 300
|
||||
amt_stuttering = 300
|
||||
|
||||
compatible_mobs = list(/mob/living/carbon/human)
|
||||
|
||||
hud_state = "wiz_subj"
|
||||
145
code/modules/spells/targeted/targeted.dm
Normal file
145
code/modules/spells/targeted/targeted.dm
Normal file
@@ -0,0 +1,145 @@
|
||||
/*
|
||||
Targeted spells (with the exception of dumbfire) select from all the mobs in the defined range
|
||||
Targeted spells have two useful flags: INCLUDEUSER and SELECTABLE. These are explained in setup.dm
|
||||
*/
|
||||
|
||||
|
||||
/spell/targeted //can mean aoe for mobs (limited/unlimited number) or one target mob
|
||||
var/max_targets = 1 //leave 0 for unlimited targets in range, more for limited number of casts (can all target one guy, depends on target_ignore_prev) in range
|
||||
var/target_ignore_prev = 1 //only important if max_targets > 1, affects if the spell can be cast multiple times at one person from one cast
|
||||
|
||||
|
||||
var/amt_weakened = 0
|
||||
var/amt_paralysis = 0
|
||||
var/amt_stunned = 0
|
||||
|
||||
var/amt_dizziness = 0
|
||||
var/amt_confused = 0
|
||||
var/amt_stuttering = 0
|
||||
|
||||
//set to negatives for healing
|
||||
var/amt_dam_fire = 0
|
||||
var/amt_dam_brute = 0
|
||||
var/amt_dam_oxy = 0
|
||||
var/amt_dam_tox = 0
|
||||
|
||||
var/amt_eye_blind = 0
|
||||
var/amt_eye_blurry = 0
|
||||
|
||||
var/list/compatible_mobs = list()
|
||||
|
||||
|
||||
/spell/targeted/choose_targets(mob/user = usr)
|
||||
var/list/targets = list()
|
||||
|
||||
if(max_targets == 0) //unlimited
|
||||
if(range == -2)
|
||||
targets = living_mob_list
|
||||
else
|
||||
for(var/mob/living/target in view_or_range(range, user, selection_type))
|
||||
targets += target
|
||||
|
||||
else if(max_targets == 1) //single target can be picked
|
||||
if((range == 0 || range == -1) && spell_flags & INCLUDEUSER)
|
||||
targets += user
|
||||
else
|
||||
var/list/possible_targets = list()
|
||||
var/list/starting_targets
|
||||
if(range == -2)
|
||||
starting_targets = living_mob_list
|
||||
else
|
||||
starting_targets = view_or_range(range, user, selection_type)
|
||||
|
||||
for(var/mob/living/M in starting_targets)
|
||||
if(!(spell_flags & INCLUDEUSER) && M == user)
|
||||
continue
|
||||
if(compatible_mobs && compatible_mobs.len)
|
||||
if(!is_type_in_list(M, compatible_mobs)) continue
|
||||
if(compatible_mobs && compatible_mobs.len && !is_type_in_list(M, compatible_mobs))
|
||||
continue
|
||||
possible_targets += M
|
||||
|
||||
if(possible_targets.len)
|
||||
if(spell_flags & SELECTABLE) //if we are allowed to choose. see setup.dm for details
|
||||
var/mob/temp_target = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
|
||||
if(temp_target)
|
||||
targets += temp_target
|
||||
else
|
||||
targets += pick(possible_targets)
|
||||
//Adds a safety check post-input to make sure those targets are actually in range.
|
||||
|
||||
|
||||
else
|
||||
var/list/possible_targets = list()
|
||||
var/list/starting_targets
|
||||
|
||||
if(range == -2)
|
||||
starting_targets = living_mob_list
|
||||
else
|
||||
starting_targets = view_or_range(range, user, selection_type)
|
||||
|
||||
for(var/mob/living/target in starting_targets)
|
||||
if(!(spell_flags & INCLUDEUSER) && target == user)
|
||||
continue
|
||||
if(compatible_mobs && !is_type_in_list(target, compatible_mobs))
|
||||
continue
|
||||
possible_targets += target
|
||||
|
||||
if(spell_flags & SELECTABLE)
|
||||
for(var/i = 1; i<=max_targets, i++)
|
||||
if(!possible_targets.len)
|
||||
break
|
||||
var/mob/M = input(user, "Choose the target for the spell.", "Targeting") as null|mob in possible_targets
|
||||
if(!M)
|
||||
break
|
||||
if(range != -2)
|
||||
if(!(M in view_or_range(range, user, selection_type)))
|
||||
continue
|
||||
targets += M
|
||||
possible_targets -= M
|
||||
else
|
||||
for(var/i=1,i<=max_targets,i++)
|
||||
if(!possible_targets.len)
|
||||
break
|
||||
if(target_ignore_prev)
|
||||
var/target = pick(possible_targets)
|
||||
possible_targets -= target
|
||||
targets += target
|
||||
else
|
||||
targets += pick(possible_targets)
|
||||
|
||||
if(!(spell_flags & INCLUDEUSER) && (user in targets))
|
||||
targets -= user
|
||||
|
||||
if(compatible_mobs && compatible_mobs.len)
|
||||
for(var/mob/living/target in targets) //filters out all the non-compatible mobs
|
||||
if(!is_type_in_list(target, compatible_mobs))
|
||||
targets -= target
|
||||
|
||||
return targets
|
||||
|
||||
/spell/targeted/cast(var/list/targets, mob/user)
|
||||
for(var/mob/living/target in targets)
|
||||
if(range >= 0)
|
||||
if(!(target in view_or_range(range, user, selection_type))) //filter at time of casting
|
||||
targets -= target
|
||||
continue
|
||||
apply_spell_damage(target)
|
||||
|
||||
/spell/targeted/proc/apply_spell_damage(mob/living/target)
|
||||
target.adjustBruteLoss(amt_dam_brute)
|
||||
target.adjustFireLoss(amt_dam_fire)
|
||||
target.adjustToxLoss(amt_dam_tox)
|
||||
target.adjustOxyLoss(amt_dam_oxy)
|
||||
//disabling
|
||||
target.Weaken(amt_weakened)
|
||||
target.Paralyse(amt_paralysis)
|
||||
target.Stun(amt_stunned)
|
||||
if(amt_weakened || amt_paralysis || amt_stunned)
|
||||
if(target.buckled)
|
||||
target.buckled = null
|
||||
target.eye_blind += amt_eye_blind
|
||||
target.eye_blurry += amt_eye_blurry
|
||||
target.dizziness += amt_dizziness
|
||||
target.confused += amt_confused
|
||||
target.stuttering += amt_stuttering
|
||||
@@ -1,28 +0,0 @@
|
||||
/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/Del()
|
||||
for(var/spell in contents)
|
||||
del(spell)
|
||||
|
||||
..()
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/trigger/cast(list/targets)
|
||||
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
|
||||
@@ -1,34 +0,0 @@
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport
|
||||
name = "Turf Teleport"
|
||||
desc = "This spell teleports the target to the turf in range."
|
||||
|
||||
var/inner_tele_radius = 1
|
||||
var/outer_tele_radius = 2
|
||||
|
||||
var/include_space = 0 //whether it includes space tiles in possible teleport locations
|
||||
var/include_dense = 0 //whether it includes dense tiles in possible teleport locations
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/turf_teleport/cast(list/targets)
|
||||
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/space) && !include_space) continue
|
||||
if(T.density && !include_dense) continue
|
||||
if(T.x>world.maxx-outer_tele_radius || T.x<outer_tele_radius) continue //putting them at the edge is dumb
|
||||
if(T.y>world.maxy-outer_tele_radius || T.y<outer_tele_radius) continue
|
||||
turfs += T
|
||||
|
||||
if(!turfs.len)
|
||||
var/list/turfs_to_pick_from = list()
|
||||
for(var/turf/T in orange(target,outer_tele_radius))
|
||||
if(!(T in orange(target,inner_tele_radius)))
|
||||
turfs_to_pick_from += T
|
||||
turfs += pick(/turf in turfs_to_pick_from)
|
||||
|
||||
var/turf/picked = pick(turfs)
|
||||
|
||||
if(!picked || !isturf(picked))
|
||||
return
|
||||
|
||||
target.loc = picked
|
||||
@@ -1,59 +0,0 @@
|
||||
// Veil render //
|
||||
|
||||
/obj/item/weapon/veilrender
|
||||
name = "veil render"
|
||||
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast city."
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "render"
|
||||
item_state = "render"
|
||||
force = 15
|
||||
throwforce = 10
|
||||
w_class = 3
|
||||
var/charged = 1
|
||||
|
||||
|
||||
/obj/effect/rend
|
||||
name = "Tear in the fabric of reality"
|
||||
desc = "You should run now"
|
||||
icon = 'icons/obj/wizard.dmi'
|
||||
icon_state = "rift"
|
||||
density = 1
|
||||
unacidable = 1
|
||||
anchored = 1.0
|
||||
|
||||
|
||||
/obj/effect/rend/New()
|
||||
spawn(50)
|
||||
new /obj/machinery/singularity/narsie/wizard(get_turf(src))
|
||||
del(src)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
/obj/item/weapon/veilrender/attack_self(mob/user as mob)
|
||||
if(charged == 1)
|
||||
new /obj/effect/rend(get_turf(usr))
|
||||
charged = 0
|
||||
visible_message("\red <B>[src] hums with power as [usr] deals a blow to reality itself!</B>")
|
||||
else
|
||||
user << "\red The unearthly energies that powered the blade are now dormant"
|
||||
|
||||
// Scrying orb //
|
||||
|
||||
/obj/item/weapon/scrying
|
||||
name = "scrying orb"
|
||||
desc = "An incandescent orb of otherworldly energy, staring into it gives you vision beyond mortal means."
|
||||
icon = 'icons/obj/projectiles.dmi'
|
||||
icon_state = "bluespace"
|
||||
throw_speed = 3
|
||||
throw_range = 7
|
||||
throwforce = 10
|
||||
damtype = BURN
|
||||
force = 10
|
||||
hitsound = 'sound/items/welder2.ogg'
|
||||
|
||||
/obj/item/weapon/scrying/attack_self(mob/user as mob)
|
||||
user << "<span class='info'>You can see... everything!</span>"
|
||||
visible_message("<span class='danger'>[usr] stares into [src], their eyes glazing over.</span>")
|
||||
announce_ghost_joinleave(user.ghostize(1), 1, "You feel that they used a powerful artifact to [pick("invade","disturb","disrupt","infest","taint","spoil","blight")] this place with their presence.")
|
||||
return
|
||||
@@ -1,327 +0,0 @@
|
||||
/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 = 150
|
||||
clothes_req = 1
|
||||
invocation = "FORTI GY AMA"
|
||||
invocation_type = "shout"
|
||||
range = 7
|
||||
|
||||
max_targets = 0
|
||||
|
||||
proj_icon_state = "magicm"
|
||||
proj_name = "a magic missile"
|
||||
proj_lingering = 1
|
||||
proj_type = "/obj/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"
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/magic_missile
|
||||
amt_weakened = 5
|
||||
amt_dam_fire = 10
|
||||
|
||||
/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"
|
||||
message = "\blue You feel strong! You feel a pressure building behind your eyes!"
|
||||
range = -1
|
||||
include_user = 1
|
||||
|
||||
mutations = list(LASER, HULK)
|
||||
duration = 300
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/disintegrate
|
||||
name = "Disintegrate"
|
||||
desc = "This spell instantly kills somebody adjacent to you with the vilest of magick."
|
||||
|
||||
school = "evocation"
|
||||
charge_max = 600
|
||||
clothes_req = 1
|
||||
invocation = "EI NATH"
|
||||
invocation_type = "shout"
|
||||
range = 1
|
||||
|
||||
destroys = "gib_brain"
|
||||
|
||||
sparks_spread = 1
|
||||
sparks_amt = 4
|
||||
|
||||
/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
|
||||
|
||||
smoke_spread = 2
|
||||
smoke_amt = 10
|
||||
|
||||
/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
|
||||
|
||||
emp_heavy = 6
|
||||
emp_light = 10
|
||||
|
||||
/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
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_amt = 10
|
||||
|
||||
inner_tele_radius = 0
|
||||
outer_tele_radius = 6
|
||||
|
||||
centcomm_cancast = 0 //prevent people from getting to centcomm
|
||||
|
||||
/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
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_amt = 5
|
||||
|
||||
/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
|
||||
|
||||
summon_type = list("/obj/effect/forcefield")
|
||||
summon_lifespan = 300
|
||||
|
||||
|
||||
/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)
|
||||
|
||||
|
||||
/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)
|
||||
|
||||
|
||||
/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)
|
||||
|
||||
/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 = "\blue Your eyes cry out in pain!"
|
||||
|
||||
starting_spells = list("/obj/effect/proc_holder/spell/targeted/inflict_handler/blind","/obj/effect/proc_holder/spell/targeted/genetic/blind")
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/inflict_handler/blind
|
||||
amt_eye_blind = 10
|
||||
amt_eye_blurry = 20
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/genetic/blind
|
||||
disabilities = 1
|
||||
duration = 300
|
||||
|
||||
/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 = 100
|
||||
clothes_req = 0
|
||||
invocation = "ONI SOMA"
|
||||
invocation_type = "shout"
|
||||
range = 20
|
||||
|
||||
proj_icon_state = "fireball"
|
||||
proj_name = "a fireball"
|
||||
proj_type = "/obj/effect/proc_holder/spell/turf/fireball"
|
||||
|
||||
proj_lifespan = 200
|
||||
proj_step_delay = 1
|
||||
|
||||
/obj/effect/proc_holder/spell/turf/fireball/cast(var/turf/T)
|
||||
explosion(T, -1, 1, 2, 3)
|
||||
|
||||
|
||||
/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
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//////////////////////////////Construct Spells/////////////////////////
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/construct/lesser
|
||||
charge_max = 1800
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/floor
|
||||
name = "Floor Construction"
|
||||
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/simulated/floor/engine/cult)
|
||||
centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
|
||||
|
||||
/obj/effect/proc_holder/spell/aoe_turf/conjure/wall
|
||||
name = "Leser Construction"
|
||||
desc = "This spell constructs a cult wall"
|
||||
|
||||
school = "conjuration"
|
||||
charge_max = 100
|
||||
clothes_req = 0
|
||||
invocation = "none"
|
||||
invocation_type = "none"
|
||||
range = 0
|
||||
summon_type = list(/turf/simulated/wall/cult)
|
||||
centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
|
||||
|
||||
/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
|
||||
centcomm_cancast = 0 //Stop crashing the server by spawning turfs on transit tiles
|
||||
delay = 50
|
||||
|
||||
summon_type = list(/turf/simulated/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
|
||||
|
||||
summon_type = list(/obj/item/device/soulstone)
|
||||
|
||||
|
||||
/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)
|
||||
summon_lifespan = 50
|
||||
|
||||
|
||||
/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
|
||||
phaseshift = 1
|
||||
jaunt_duration = 50 //in deciseconds
|
||||
centcomm_cancast = 0 //Stop people from getting to centcomm
|
||||
Reference in New Issue
Block a user