Datumizes spells (#24242)

* datumized spells

* finished

* last changes

* conflict

* Update code/datums/spells/alien_spells/transfer_plasma.dm

* conflicts

* shitty runtime fix until i get to this tomorrow

* Update code/datums/spell.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spell_handler/alien_spell_handler.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/alien_spells/regurgitate.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/alien_spells/regurgitate.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/bloodcrawl.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/bloodcrawl.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/modules/antagonists/vampire/vampire_powers/hemomancer_powers.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/modules/antagonists/vampire/vampire_powers/vampire_powers.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/modules/awaymissions/mission_code/ruins/wizardcrash.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/modules/research/xenobiology/xenobiology.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/modules/mob/living/carbon/superheroes.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/conjure.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/ethereal_jaunt.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/emplosion.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/turf_teleport.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/wizard_spells.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/wizard_spells.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/game/dna/mutations/mutation_powers.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/wizard_spells.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/datums/spells/wizard_spells.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/game/dna/mutations/mutation_powers.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* Update code/game/gamemodes/miniantags/revenant/revenant_abilities.dm

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>

* guess who just rework the entire malf ai actionsf ai

* gc better

---------

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
GDN
2024-04-01 02:42:21 -05:00
committed by GitHub
parent d52535a041
commit eee8878024
149 changed files with 1358 additions and 1536 deletions
+2 -2
View File
@@ -600,9 +600,9 @@
#define COMSIG_ITEM_PICKUP "item_pickup"
///from base of mob/living/carbon/attacked_by(): (mob/living/carbon/target, mob/living/user, hit_zone)
#define COMSIG_ITEM_ATTACK_ZONE "item_attack_zone"
///return a truthy value to prevent ensouling, checked in /obj/effect/proc_holder/spell/lichdom/cast(): (mob/user)
///return a truthy value to prevent ensouling, checked in /datum/spell/lichdom/cast(): (mob/user)
#define COMSIG_ITEM_IMBUE_SOUL "item_imbue_soul"
///called before marking an object for retrieval, checked in /obj/effect/proc_holder/spell/summonitem/cast() : (mob/user)
///called before marking an object for retrieval, checked in /datum/spell/summonitem/cast() : (mob/user)
#define COMSIG_ITEM_MARK_RETRIEVAL "item_mark_retrieval"
#define COMPONENT_BLOCK_MARK_RETRIEVAL (1<<0)
///from base of obj/item/hit_reaction(): (list/args)
+6 -6
View File
@@ -637,7 +637,7 @@
/datum/action/spell_action/New(Target)
..()
var/obj/effect/proc_holder/spell/S = target
var/datum/spell/S = target
S.action = src
name = S.name
desc = S.desc
@@ -648,7 +648,7 @@
/datum/action/spell_action/Destroy()
var/obj/effect/proc_holder/spell/S = target
var/datum/spell/S = target
S.action = null
return ..()
@@ -656,27 +656,27 @@
if(!..())
return FALSE
if(target)
var/obj/effect/proc_holder/spell = target
var/datum/spell/spell = target
spell.Click()
return TRUE
/datum/action/spell_action/AltTrigger()
if(target)
var/obj/effect/proc_holder/spell/spell = target
var/datum/spell/spell = target
spell.AltClick(usr)
return TRUE
/datum/action/spell_action/IsAvailable()
if(!target)
return FALSE
var/obj/effect/proc_holder/spell/spell = target
var/datum/spell/spell = target
if(owner)
return spell.can_cast(owner)
return FALSE
/datum/action/spell_action/apply_unavailable_effect(atom/movable/screen/movable/action_button/button)
var/obj/effect/proc_holder/spell/S = target
var/datum/spell/S = target
if(!istype(S))
return ..()
+5 -5
View File
@@ -1052,7 +1052,7 @@
log_admin("[key_name(usr)] has removed [key_name(current)]'s vampire subclass.")
message_admins("[key_name_admin(usr)] has removed [key_name_admin(current)]'s vampire subclass.")
else
vamp.upgrade_tiers -= /obj/effect/proc_holder/spell/vampire/self/specialize
vamp.upgrade_tiers -= /datum/spell/vampire/self/specialize
vamp.change_subclass(subclass_type)
log_admin("[key_name(usr)] has removed [key_name(current)]'s vampire subclass.")
message_admins("[key_name_admin(usr)] has removed [key_name_admin(current)]'s vampire subclass.")
@@ -1676,14 +1676,14 @@
SEND_SOUND(H, sound('sound/ambience/antag/abductors.ogg'))
H.create_log(MISC_LOG, "[H] was made into an abductor")
/datum/mind/proc/AddSpell(obj/effect/proc_holder/spell/S)
/datum/mind/proc/AddSpell(datum/spell/S)
spell_list += S
S.action.Grant(current)
/datum/mind/proc/RemoveSpell(obj/effect/proc_holder/spell/spell) //To remove a specific spell from a mind
/datum/mind/proc/RemoveSpell(datum/spell/spell) //To remove a specific spell from a mind
if(!spell)
return
for(var/obj/effect/proc_holder/spell/S in spell_list)
for(var/datum/spell/S in spell_list)
if(istype(S, spell))
qdel(S)
spell_list -= S
@@ -1696,7 +1696,7 @@
/datum/mind/proc/transfer_mindbound_actions(mob/living/new_character)
for(var/X in spell_list)
var/obj/effect/proc_holder/spell/S = X
var/datum/spell/S = X
if(!S.on_mind_transfer(new_character))
current.RemoveSpell(S)
continue
+2 -2
View File
@@ -1410,8 +1410,8 @@
box = /obj/item/storage/box/wizard
//The spells that the enforcer has.
var/list/spell_paths = list(/obj/effect/proc_holder/spell/aoe/conjure/summon_supermatter,
/obj/effect/proc_holder/spell/charge_up/bounce/lightning, /obj/effect/proc_holder/spell/summonitem)
var/list/spell_paths = list(/datum/spell/aoe/conjure/summon_supermatter,
/datum/spell/charge_up/bounce/lightning, /datum/spell/summonitem)
/datum/outfit/admin/enforcer/post_equip(mob/living/carbon/human/H)
. = ..()
+63 -71
View File
@@ -1,29 +1,9 @@
/obj/effect/proc_holder
var/panel = "Debug"//What panel the proc holder needs to go on.
var/active = FALSE //Used by toggle based abilities.
var/ranged_mousepointer
var/mob/ranged_ability_user
/obj/effect/proc_holder/singularity_act()
return
/obj/effect/proc_holder/singularity_pull()
return
GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
/obj/effect/proc_holder/proc/InterceptClickOn(mob/user, params, atom/A)
if(user.ranged_ability != src)
to_chat(user, "<span class='warning'><b>[user.ranged_ability.name]</b> has been disabled.")
user.ranged_ability.remove_ranged_ability(user)
return TRUE //TRUE for failed, FALSE for passed.
user.face_atom(A)
return FALSE
GLOBAL_LIST_INIT(spells, typesof(/datum/spell))
/datum/click_intercept/proc_holder
var/obj/effect/proc_holder/spell
var/datum/spell/spell
/datum/click_intercept/proc_holder/New(client/C, obj/effect/proc_holder/spell_to_cast)
/datum/click_intercept/proc_holder/New(client/C, datum/spell/spell_to_cast)
. = ..()
spell = spell_to_cast
@@ -34,7 +14,15 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
spell.remove_ranged_ability(spell.ranged_ability_user)
return ..()
/obj/effect/proc_holder/proc/add_ranged_ability(mob/user, msg)
/datum/spell/proc/InterceptClickOn(mob/user, params, atom/A)
if(user.ranged_ability != src)
to_chat(user, "<span class='warning'><b>[user.ranged_ability.name]</b> has been disabled.</span>")
user.ranged_ability.remove_ranged_ability(user)
return TRUE //TRUE for failed, FALSE for passed.
user.face_atom(A)
return FALSE
/datum/spell/proc/add_ranged_ability(mob/user, msg)
if(!user || !user.client)
return
if(user.ranged_ability && user.ranged_ability != src)
@@ -47,17 +35,20 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
active = TRUE
if(msg)
to_chat(user, msg)
update_icon()
update_spell_icon()
/obj/effect/proc_holder/proc/add_mousepointer(client/C)
/datum/spell/proc/update_spell_icon()
return
/datum/spell/proc/add_mousepointer(client/C)
if(C && ranged_mousepointer && C.mouse_pointer_icon == initial(C.mouse_pointer_icon))
C.mouse_pointer_icon = ranged_mousepointer
/obj/effect/proc_holder/proc/remove_mousepointer(client/C)
/datum/spell/proc/remove_mousepointer(client/C)
if(C && ranged_mousepointer && C.mouse_pointer_icon == ranged_mousepointer)
C.mouse_pointer_icon = initial(C.mouse_pointer_icon)
/obj/effect/proc_holder/proc/remove_ranged_ability(mob/user, msg)
/datum/spell/proc/remove_ranged_ability(mob/user, msg)
if(!user || (user.ranged_ability && user.ranged_ability != src)) //To avoid removing the wrong ability
return
user.ranged_ability = null
@@ -69,14 +60,12 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
remove_mousepointer(user.client)
if(msg)
to_chat(user, msg)
update_icon()
update_spell_icon()
/obj/effect/proc_holder/spell
name = "Spell" // Only rename this if the spell you're making is not abstract
desc = "A wizard spell"
panel = "Spells"//What panel the proc holder needs to go on.
density = FALSE
opacity = FALSE
/datum/spell
var/name = "Spell" // Only rename this if the spell you're making is not abstract
var/desc = "A wizard spell"
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?
///recharge time in deciseconds
@@ -87,6 +76,9 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
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/active = FALSE //Used by toggle based abilities.
var/ranged_mousepointer
var/mob/ranged_ability_user
var/ghost = FALSE // Skip life check.
var/clothes_req = TRUE //see if it requires clothes
@@ -153,7 +145,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* @param start_recharge If the proc should set the cooldown
* @param user The caster of the spell
*/
/obj/effect/proc_holder/spell/proc/cast_check(charge_check = TRUE, start_recharge = TRUE, 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
/datum/spell/proc/cast_check(charge_check = TRUE, start_recharge = TRUE, 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
// SHOULD_NOT_OVERRIDE(TRUE) Todo for another refactor
if(!can_cast(user, charge_check, TRUE))
return FALSE
@@ -178,7 +170,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* * target - Who is being considered
* * user - Who is the user of this spell
*/
/obj/effect/proc_holder/spell/proc/valid_target(target, user)
/datum/spell/proc/valid_target(target, user)
return TRUE
/**
@@ -187,7 +179,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Arguments:
* * user - Who used this spell?
*/
/obj/effect/proc_holder/spell/proc/spend_spell_cost(mob/user)
/datum/spell/proc/spend_spell_cost(mob/user)
SHOULD_CALL_PARENT(TRUE)
custom_handler?.spend_spell_cost(user, src)
@@ -195,7 +187,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
if(action)
action.UpdateButtons()
/obj/effect/proc_holder/spell/proc/invocation(mob/user) //spelling the spell out and setting it on recharge/reducing charges amount
/datum/spell/proc/invocation(mob/user) //spelling the spell out and setting it on recharge/reducing charges amount
switch(invocation_type)
if("shout")
if(!user.IsVocal() || user.cannot_speak_loudly())
@@ -213,10 +205,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
if("emote")
user.visible_message(invocation, invocation_emote_self) //same style as in mob/living/emote.dm
/obj/effect/proc_holder/spell/proc/playMagSound()
/datum/spell/proc/playMagSound()
playsound(get_turf(usr), sound,50,1)
/obj/effect/proc_holder/spell/New()
/datum/spell/New()
..()
action = new(src)
still_recharging_msg = "<span class='notice'>[name] is still recharging.</span>"
@@ -236,7 +228,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
cooldown_handler = create_new_cooldown()
cooldown_handler.cooldown_init(src)
/obj/effect/proc_holder/spell/Destroy()
/datum/spell/Destroy()
QDEL_NULL(action)
QDEL_NULL(cooldown_handler)
return ..()
@@ -245,7 +237,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Creates and returns the targeting datum for this spell type. Override this!
* Should return a value of type [/datum/spell_targeting]
*/
/obj/effect/proc_holder/spell/proc/create_new_targeting()
/datum/spell/proc/create_new_targeting()
RETURN_TYPE(/datum/spell_targeting)
return
@@ -254,7 +246,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Override this if you want a custom spell handler.
* Should return a value of type [/datum/spell_handler] or NONE
*/
/obj/effect/proc_holder/spell/proc/create_new_handler()
/datum/spell/proc/create_new_handler()
RETURN_TYPE(/datum/spell_handler)
return NONE
@@ -263,29 +255,30 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Override this if you wish to use a different method of cooldown
*/
/obj/effect/proc_holder/spell/proc/create_new_cooldown()
/datum/spell/proc/create_new_cooldown()
RETURN_TYPE(/datum/spell_cooldown)
var/datum/spell_cooldown/S = new
S.recharge_duration = base_cooldown
S.starts_off_cooldown = starts_charged
return S
/obj/effect/proc_holder/spell/Click()
/datum/spell/proc/Click()
if(cast_check(TRUE, FALSE, usr))
choose_targets(usr)
return 1
/obj/effect/proc_holder/spell/AltClick(mob/user)
/datum/spell/proc/AltClick(mob/user)
return Click()
/obj/effect/proc_holder/spell/InterceptClickOn(mob/user, params, atom/A)
/datum/spell/InterceptClickOn(mob/user, params, atom/A)
. = ..()
if(.)
return
targeting.InterceptClickOn(user, params, A, src)
if(targeting)
targeting.InterceptClickOn(user, params, A, src)
///Lets the spell have a special effect applied to it when upgraded. By default, does nothing.
/obj/effect/proc_holder/spell/proc/on_purchase_upgrade()
/datum/spell/proc/on_purchase_upgrade()
return
/**
@@ -295,7 +288,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Arguments:
* * user - The caster of the spell
*/
/obj/effect/proc_holder/spell/proc/choose_targets(mob/user)
/datum/spell/proc/choose_targets(mob/user)
SHOULD_NOT_OVERRIDE(TRUE)
if(targeting.use_intercept_click)
if(active)
@@ -317,7 +310,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* * targets - The targets the spell is being performed on
* * user - The caster of the spell
*/
/obj/effect/proc_holder/spell/proc/try_perform(list/targets, mob/user)
/datum/spell/proc/try_perform(list/targets, mob/user)
SHOULD_NOT_OVERRIDE(TRUE)
if(!length(targets))
to_chat(user, "<span class='warning'>No suitable target found.</span>")
@@ -333,7 +326,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* Called in `try_perform` before removing the click interceptor. useful to override if you have a spell that requires more than 1 click
*/
/obj/effect/proc_holder/spell/proc/should_remove_click_intercept()
/datum/spell/proc/should_remove_click_intercept()
return TRUE
/**
@@ -344,7 +337,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* * recharge - Whether or not the spell should go recharge
* * user - The caster of the spell
*/
/obj/effect/proc_holder/spell/proc/perform(list/targets, recharge = TRUE, mob/user = usr) //if recharge is started is important for the trigger spells
/datum/spell/proc/perform(list/targets, recharge = TRUE, mob/user = usr) //if recharge is started is important for the trigger spells
SHOULD_NOT_OVERRIDE(TRUE)
before_cast(targets, user)
invocation(user)
@@ -371,11 +364,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* * targets - The targets being targeted by the spell
* * user - The user of the spell
*/
/obj/effect/proc_holder/spell/proc/write_custom_logs(list/targets, mob/user)
/datum/spell/proc/write_custom_logs(list/targets, mob/user)
return
/obj/effect/proc_holder/spell/proc/before_cast(list/targets, mob/user)
/datum/spell/proc/before_cast(list/targets, mob/user)
SHOULD_CALL_PARENT(TRUE)
if(overlay)
for(var/atom/target in targets)
@@ -394,7 +386,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
custom_handler?.before_cast(targets, user, src)
/obj/effect/proc_holder/spell/proc/after_cast(list/targets, mob/user)
/datum/spell/proc/after_cast(list/targets, mob/user)
SHOULD_CALL_PARENT(TRUE)
for(var/atom/target in targets)
var/location
@@ -427,21 +419,21 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
* * targets - The targets being targeted by the spell
* * user - The caster of the spell
*/
/obj/effect/proc_holder/spell/proc/cast(list/targets, mob/user = usr)
/datum/spell/proc/cast(list/targets, mob/user = usr)
return
/obj/effect/proc_holder/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
/datum/spell/proc/revert_cast(mob/user = usr) //resets recharge or readds a charge
cooldown_handler.revert_cast()
custom_handler?.revert_cast(user, src)
if(action)
action.UpdateButtons()
/obj/effect/proc_holder/spell/proc/UpdateButtons()
/datum/spell/proc/UpdateButtons()
if(action)
action.UpdateButtons()
/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
/datum/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)
@@ -462,10 +454,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
return
///This proc is ran when a mind is transfered to a new mob. Tells it if the action should be transfered on return true, and tells it not to remove it on false
/obj/effect/proc_holder/spell/proc/on_mind_transfer(mob/living/L)
/datum/spell/proc/on_mind_transfer(mob/living/L)
return TRUE
/obj/effect/proc_holder/spell/aoe
/datum/spell/aoe
name = "Spell"
create_attack_logs = FALSE
create_custom_logs = TRUE
@@ -474,10 +466,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
// Normally, AoE spells will generate an attack log for every turf they loop over, while searching for targets.
// With this override, all /aoe type spells will only generate 1 log, saying that the user has cast the spell.
/obj/effect/proc_holder/spell/aoe/write_custom_logs(list/targets, mob/user)
/datum/spell/aoe/write_custom_logs(list/targets, mob/user)
add_attack_logs(user, null, "Cast the AoE spell [name]", ATKLOG_ALL)
/obj/effect/proc_holder/spell/proc/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
/datum/spell/proc/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
if(((!user.mind) || !(src in user.mind.spell_list)) && !(src in user.mob_spell_list))
if(show_message)
to_chat(user, "<span class='warning'>You shouldn't have this spell! Something's wrong.</span>")
@@ -509,8 +501,8 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
if(ishuman(user))
var/mob/living/carbon/human/H = user
var/clothcheck = locate(/obj/effect/proc_holder/spell/noclothes) in user.mob_spell_list
var/clothcheck2 = user.mind && (locate(/obj/effect/proc_holder/spell/noclothes) in user.mind.spell_list)
var/clothcheck = locate(/datum/spell/noclothes) in user.mob_spell_list
var/clothcheck2 = user.mind && (locate(/datum/spell/noclothes) in user.mind.spell_list)
if(clothes_req && !clothcheck && !clothcheck2) //clothes check
var/obj/item/clothing/robe = H.wear_suit
var/obj/item/clothing/hat = H.head
@@ -538,7 +530,7 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
return TRUE
/obj/effect/proc_holder/spell/summonmob
/datum/spell/summonmob
name = "Summon Servant"
desc = "This spell can be used to call your servant, whenever you need it."
base_cooldown = 10 SECONDS
@@ -552,10 +544,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell))
action_icon_state = "summons"
/obj/effect/proc_holder/spell/summonmob/create_new_targeting()
/datum/spell/summonmob/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/summonmob/cast(list/targets, mob/user = usr)
/datum/spell/summonmob/cast(list/targets, mob/user = usr)
if(!target_mob)
return
var/turf/Start = get_turf(user)
+1 -1
View File
@@ -8,7 +8,7 @@
/// the time at which a spell charge can be used
var/charge_time
/datum/spell_cooldown/charges/cooldown_init(obj/effect/proc_holder/spell/new_spell)
/datum/spell_cooldown/charges/cooldown_init(datum/spell/new_spell)
. = ..()
if(starts_off_cooldown)
current_charges = max_charges
+2 -2
View File
@@ -6,13 +6,13 @@
/// does it start off cooldown?
var/starts_off_cooldown = TRUE
/// holds a ref to the spell
var/obj/effect/proc_holder/spell/spell_parent
var/datum/spell/spell_parent
/datum/spell_cooldown/Destroy()
spell_parent = null
return ..()
/datum/spell_cooldown/proc/cooldown_init(obj/effect/proc_holder/spell/new_spell)
/datum/spell_cooldown/proc/cooldown_init(datum/spell/new_spell)
spell_parent = new_spell
if(!starts_off_cooldown)
start_recharge()
@@ -8,24 +8,24 @@ This was also the case with the verb implementation, it's just much more obvious
/// Amount of plasma required to use this ability
var/plasma_cost = 0
/datum/spell_handler/alien/can_cast(mob/living/carbon/user, charge_check, show_message, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/alien/can_cast(mob/living/carbon/user, charge_check, show_message, datum/spell/spell)
var/obj/item/organ/internal/alien/plasmavessel/vessel = user.get_int_organ(/obj/item/organ/internal/alien/plasmavessel)
if(!vessel)
return 0
return FALSE
if(vessel.stored_plasma < plasma_cost)
if(show_message)
to_chat(user, "<span class='warning'>You require at least [plasma_cost] plasma to use this ability!</span>")
return FALSE
return TRUE
/datum/spell_handler/alien/spend_spell_cost(mob/living/carbon/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/alien/spend_spell_cost(mob/living/carbon/user, datum/spell/spell)
user.use_plasma_spell(plasma_cost, user)
/datum/spell_handler/alien/before_cast(list/targets, mob/living/carbon/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/alien/before_cast(list/targets, mob/living/carbon/user, datum/spell/spell)
to_chat(user, "<span class='boldnotice'>You have [user.get_plasma()] plasma left to use.</span>")
user.update_plasma_display(user)
/datum/spell_handler/alien/revert_cast(mob/living/carbon/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/alien/revert_cast(mob/living/carbon/user, datum/spell/spell)
user.add_plasma(plasma_cost, user)
to_chat(user, "<span class='boldnotice'>You have [user.get_plasma()] plasma left to use.</span>")
user.update_plasma_display(user)
@@ -2,7 +2,7 @@
/// How much food it costs the morph to use this
var/hunger_cost = 0
/datum/spell_handler/morph/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/morph/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message, datum/spell/spell)
if(!istype(user))
if(show_message)
to_chat(user, "<span class='warning'>You should not be able to use this abilty! Report this as a bug on github please.</span>")
@@ -15,13 +15,13 @@
return TRUE
/datum/spell_handler/morph/spend_spell_cost(mob/living/simple_animal/hostile/morph/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/morph/spend_spell_cost(mob/living/simple_animal/hostile/morph/user, datum/spell/spell)
user.use_food(hunger_cost)
/datum/spell_handler/morph/before_cast(list/targets, mob/living/simple_animal/hostile/morph/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/morph/before_cast(list/targets, mob/living/simple_animal/hostile/morph/user, datum/spell/spell)
if(hunger_cost)
to_chat(user, "<span class='boldnotice'>You have [user.gathered_food] left to use.</span>")
/datum/spell_handler/morph/revert_cast(mob/living/simple_animal/hostile/morph/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/morph/revert_cast(mob/living/simple_animal/hostile/morph/user, datum/spell/spell)
user.add_food(hunger_cost)
to_chat(user, "<span class='boldnotice'>You have [user.gathered_food] left to use.</span>")
+5 -5
View File
@@ -6,17 +6,17 @@
/datum/spell_handler
/datum/spell_handler/proc/can_cast(mob/user, charge_check, show_message, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/proc/can_cast(mob/user, charge_check, show_message, datum/spell/spell)
return TRUE
/datum/spell_handler/proc/spend_spell_cost(mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/proc/spend_spell_cost(mob/user, datum/spell/spell)
return
/datum/spell_handler/proc/revert_cast(mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/proc/revert_cast(mob/user, datum/spell/spell)
return
/datum/spell_handler/proc/before_cast(list/targets, mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/proc/before_cast(list/targets, mob/user, datum/spell/spell)
return
/datum/spell_handler/proc/after_cast(list/targets, mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/proc/after_cast(list/targets, mob/user, datum/spell/spell)
return
+3 -3
View File
@@ -3,7 +3,7 @@
/// If the blood cost should be handled by this handler. Or if the spell will handle it itself
var/deduct_blood_on_cast = TRUE
/datum/spell_handler/vampire/can_cast(mob/user, charge_check, show_message, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/vampire/can_cast(mob/user, charge_check, show_message, datum/spell/spell)
var/datum/antagonist/vampire/vampire = user.mind.has_antag_datum(/datum/antagonist/vampire)
if(!vampire)
@@ -31,7 +31,7 @@
return FALSE
return TRUE
/datum/spell_handler/vampire/spend_spell_cost(mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/vampire/spend_spell_cost(mob/user, datum/spell/spell)
if(!required_blood || !deduct_blood_on_cast) //don't take the blood yet if this is false!
return
@@ -44,7 +44,7 @@
var/blood_cost = round(required_blood * blood_cost_modifier)
return blood_cost
/datum/spell_handler/vampire/after_cast(list/targets, mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_handler/vampire/after_cast(list/targets, mob/user, datum/spell/spell)
if(!spell.should_recharge_after_cast)
return
if(!required_blood)
+1 -1
View File
@@ -4,7 +4,7 @@
/datum/spell_targeting/alive_mob_list
allowed_type = /mob/living
/datum/spell_targeting/alive_mob_list/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/alive_mob_list/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/possible_targets = list()
for(var/mob/living/possible_target as anything in GLOB.alive_mob_list)
if(valid_target(possible_target, user, spell, FALSE))
+1 -1
View File
@@ -6,7 +6,7 @@
/// The radius of turfs not being affected. -1 is inactive
var/inner_radius = -1
/datum/spell_targeting/aoe/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/aoe/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/targets = list()
var/spell_center = use_turf_of_user ? get_turf(user) : user
@@ -9,7 +9,7 @@
var/random_target_priority = SPELL_TARGET_CLOSEST
/datum/spell_targeting/click/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/click/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/targets = list()
if(valid_target(clicked_atom, user, spell))
targets.Add(clicked_atom)
+2 -2
View File
@@ -4,11 +4,11 @@
/datum/spell_targeting/clicked_atom
use_intercept_click = TRUE
/datum/spell_targeting/clicked_atom/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/clicked_atom/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
if(clicked_atom)
return list(clicked_atom)
/datum/spell_targeting/clicked_atom/external/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/clicked_atom/external/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
. = ..()
if(!.)
return list()
@@ -25,7 +25,7 @@
/obj/item/bio_chip
)
/datum/spell_targeting/matter_eater/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/matter_eater/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/possible_targets = list()
for(var/atom/movable/O in view_or_range(range, user, selection_type))
@@ -3,7 +3,7 @@
*/
/datum/spell_targeting/reachable_turfs
/datum/spell_targeting/reachable_turfs/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/reachable_turfs/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/turf/locs = list()
for(var/direction in GLOB.alldirs)
if(length(locs) == max_targets) //we found 2 locations and thats all we need
@@ -3,7 +3,7 @@
*/
/datum/spell_targeting/remoteview
/datum/spell_targeting/remoteview/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/remoteview/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/remoteviewers = list()
for(var/mob/M in GLOB.alive_mob_list)
if(M == user)
@@ -3,5 +3,5 @@
*/
/datum/spell_targeting/self
/datum/spell_targeting/self/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/self/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
return list(user) // That's how simple it is
@@ -34,14 +34,14 @@
* * params - Params given by the intercept click. Only available if use_intercept_click is TRUE
* * clicked_atom - The atom clicked on. Only available if use_intercept_click is TRUE
*/
/datum/spell_targeting/proc/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/proc/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
RETURN_TYPE(/list)
return
/**
* Will attempt to auto target the spell. Only works with 1 target currently
*/
/datum/spell_targeting/proc/attempt_auto_target(mob/user, obj/effect/proc_holder/spell/spell)
/datum/spell_targeting/proc/attempt_auto_target(mob/user, datum/spell/spell)
var/atom/target
for(var/atom/A in view_or_range(range, use_turf_of_user ? get_turf(user) : user, selection_type))
if(valid_target(A, user, spell, FALSE))
@@ -64,7 +64,7 @@
* * A - Atom the user clicked on
* * spell - The spell being cast
*/
/datum/spell_targeting/proc/InterceptClickOn(mob/user, params, atom/A, obj/effect/proc_holder/spell/spell)
/datum/spell_targeting/proc/InterceptClickOn(mob/user, params, atom/A, datum/spell/spell)
var/list/targets = choose_targets(user, spell, params, A)
spell.try_perform(targets, user)
@@ -77,7 +77,7 @@
* * spell - The spell being cast
* * check_if_in_range - If a view/range check has to be done to see if the target is valid
*/
/datum/spell_targeting/proc/valid_target(target, user, obj/effect/proc_holder/spell/spell, check_if_in_range = TRUE)
/datum/spell_targeting/proc/valid_target(target, user, datum/spell/spell, check_if_in_range = TRUE)
SHOULD_CALL_PARENT(TRUE)
return istype(target, allowed_type) && (include_user || target != user) && \
spell.valid_target(target, user) && (!check_if_in_range || (target in view_or_range(range, use_turf_of_user ? get_turf(user) : user, selection_type))) \
+1 -1
View File
@@ -9,7 +9,7 @@
/// Who to target when too many targets are found. Only matters when max_targets = 1
var/target_priority = SPELL_TARGET_CLOSEST
/datum/spell_targeting/targeted/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/targeted/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/targets = list()
var/list/possible_targets = list()
var/atom/spell_location = use_turf_of_user ? get_turf(user) : user
+1 -1
View File
@@ -3,7 +3,7 @@
*/
/datum/spell_targeting/telepathic
/datum/spell_targeting/telepathic/choose_targets(mob/user, obj/effect/proc_holder/spell/spell, params, atom/clicked_atom)
/datum/spell_targeting/telepathic/choose_targets(mob/user, datum/spell/spell, params, atom/clicked_atom)
var/list/valid_targets = list()
var/turf/T = get_turf(user)
var/list/mobs_in_view = user.get_visible_mobs()
@@ -17,7 +17,7 @@ Updates the spell's actions on use as well, so they know when they can or can't
for(var/datum/action/spell_action/action in actions)
action.UpdateButtons()
/obj/effect/proc_holder/spell/alien_spell
/datum/spell/alien_spell
action_background_icon_state = "bg_alien"
clothes_req = FALSE
base_cooldown = 0
@@ -28,15 +28,15 @@ Updates the spell's actions on use as well, so they know when they can or can't
var/plasma_cost = 0
/// Every single alien spell uses a "spell name + plasmacost" format
/obj/effect/proc_holder/spell/alien_spell/Initialize(mapload)
. = ..()
/datum/spell/alien_spell/New()
..()
if(plasma_cost)
name = "[name] ([plasma_cost])"
/obj/effect/proc_holder/spell/alien_spell/write_custom_logs(list/targets, mob/user)
/datum/spell/alien_spell/write_custom_logs(list/targets, mob/user)
user.create_log(ATTACK_LOG, "Cast the spell [name]")
/obj/effect/proc_holder/spell/alien_spell/create_new_handler()
/datum/spell/alien_spell/create_new_handler()
var/datum/spell_handler/alien/handler = new
handler.plasma_cost = plasma_cost
return handler
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/alien_spell
/datum/spell/touch/alien_spell
name = "Basetype Alien spell"
desc = "You should not see this in game, if you do file a github report!"
hand_path = "/obj/item/melee/touch_attack/alien"
@@ -15,20 +15,20 @@
var/plasma_cost = 0
action_icon_state = "gib"
/obj/effect/proc_holder/spell/touch/alien_spell/Initialize(mapload)
. = ..()
/datum/spell/touch/alien_spell/New()
..()
if(plasma_cost)
name = "[name] ([plasma_cost])"
/obj/effect/proc_holder/spell/touch/alien_spell/Click(mob/user = usr)
/datum/spell/touch/alien_spell/Click(mob/user = usr)
if(attached_hand)
to_chat(user, "<span class='noticealien'>You withdraw your [src].</span>")
..()
/obj/effect/proc_holder/spell/touch/alien_spell/write_custom_logs(list/targets, mob/user)
/datum/spell/touch/alien_spell/write_custom_logs(list/targets, mob/user)
user.create_log(ATTACK_LOG, "Cast the spell [name]")
/obj/effect/proc_holder/spell/touch/alien_spell/create_new_handler()
/datum/spell/touch/alien_spell/create_new_handler()
var/datum/spell_handler/alien/H = new
H.plasma_cost = plasma_cost
return H
@@ -1,16 +1,16 @@
/obj/effect/proc_holder/spell/alien_spell/build_resin
/datum/spell/alien_spell/build_resin
name = "Build Resin Structure"
desc = "Allows you to create resin structures. Does not work while in space."
plasma_cost = 55
action_icon_state = "alien_resin"
/obj/effect/proc_holder/spell/alien_spell/build_resin/create_new_targeting()
/datum/spell/alien_spell/build_resin/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/build_resin/cast(list/targets, mob/living/carbon/user)
var/static/list/resin_buildings = list("Resin Wall" = image(icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi', icon_state = "resin_wall-0"),
"Resin Nest" = image(icon = 'icons/mob/alien.dmi', icon_state = "nest"),
"Resin Door" = image(icon = 'icons/obj/smooth_structures/alien/resin_door.dmi', icon_state = "resin"),
/datum/spell/alien_spell/build_resin/cast(list/targets, mob/living/carbon/user)
var/static/list/resin_buildings = list("Resin Wall (55)" = image(icon = 'icons/obj/smooth_structures/alien/resin_wall.dmi', icon_state = "resin_wall-0"),
"Resin Nest (55)" = image(icon = 'icons/mob/alien.dmi', icon_state = "nest"),
"Resin door (80)" = image(icon = 'icons/obj/smooth_structures/alien/resin_door.dmi', icon_state = "resin"),
"Revival Nest" = image(icon = 'icons/mob/alien.dmi', icon_state = "placeholder_rejuv_nest"))
var/choice = show_radial_menu(user, user, resin_buildings, src, radius = 40)
var/turf/turf_to_spawn_at = user.loc
@@ -29,7 +29,7 @@
to_chat(user, "<span class='danger'>There is already a resin construction here.</span>")
revert_cast(user)
return
visible_message("<span class='alertalien'>[user] vomits up a thick purple substance and shapes it!</span>")
user.visible_message("<span class='alertalien'>[user] vomits up a thick purple substance and shapes it!</span>")
switch(choice)
if("Resin Wall")
new /obj/structure/alien/resin/wall(turf_to_spawn_at)
@@ -40,7 +40,7 @@
if("Revival Nest")
new /obj/structure/bed/revival_nest(turf_to_spawn_at)
/obj/effect/proc_holder/spell/touch/alien_spell/consume_resin
/datum/spell/touch/alien_spell/consume_resin
name = "Consume resin structures"
desc = "Allows you to rip and tear straight through resin structures."
action_icon_state = "alien_resin"
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/alien_spell/corrosive_acid
/datum/spell/touch/alien_spell/corrosive_acid
name = "Corrosive acid"
desc = "Spit acid on someone in range, this acid melts through nearly anything and heavily damages anyone lacking proper safety equipment."
hand_path = "/obj/item/melee/touch_attack/alien/corrosive_acid"
@@ -32,7 +32,7 @@
to_chat(user, "<span class='noticealien'>You cannot dissolve this object.</span>")
..()
/obj/effect/proc_holder/spell/touch/alien_spell/burning_touch
/datum/spell/touch/alien_spell/burning_touch
name = "Blazing touch"
desc = "Boil acid within your hand to burn through anything you touch with it, deals a lot of damage to aliens and destroys resin structures instantly."
hand_path = "/obj/item/melee/touch_attack/alien/burning_touch"
@@ -1,13 +1,13 @@
// Make this reflect amount grown, can't do that currently
/obj/effect/proc_holder/spell/alien_spell/evolve_larva
/datum/spell/alien_spell/evolve_larva
name = "Evolve."
desc = "Evolve into a fully grown Alien."
action_icon_state = "alien_evolve_larva"
/obj/effect/proc_holder/spell/alien_spell/evolve_larva/create_new_targeting()
/datum/spell/alien_spell/evolve_larva/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/evolve_larva/cast(list/targets, mob/living/carbon/alien/larva/user)
/datum/spell/alien_spell/evolve_larva/cast(list/targets, mob/living/carbon/alien/larva/user)
if(user.stat != CONSCIOUS)
return
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/alien_spell/plant_weeds/eggs
/datum/spell/alien_spell/plant_weeds/eggs
name = "Plant alien eggs"
desc = "Allows you to plant alien eggs on your current turf, does not work while in space."
plasma_cost = 75
@@ -7,17 +7,17 @@
action_icon_state = "alien_egg"
requires_do_after = FALSE
/obj/effect/proc_holder/spell/alien_spell/combust_facehuggers
/datum/spell/alien_spell/combust_facehuggers
name = "Combust facehuggers and eggs"
desc = "Take over the programming of facehuggers and eggs, sending out a shockwave which causes them to combust."
plasma_cost = 25
action_icon_state = "alien_egg"
base_cooldown = 3 SECONDS
/obj/effect/proc_holder/spell/alien_spell/combust_facehuggers/create_new_targeting()
/datum/spell/alien_spell/combust_facehuggers/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/alien_spell/combust_facehuggers/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/combust_facehuggers/cast(list/targets, mob/living/carbon/user)
var/obj/target = targets[1]
var/turf/T = user.loc
if(!istype(T) || !istype(target))
@@ -33,7 +33,7 @@
to_chat(user, "<span class='noticealien'>[target] will explode in 3 seconds!</span>")
return TRUE
/obj/effect/proc_holder/spell/alien_spell/combust_facehuggers/proc/blow_it_up(obj/target, mob/user)
/datum/spell/alien_spell/combust_facehuggers/proc/blow_it_up(obj/target, mob/user)
add_attack_logs(user, target, "Caused it to explode")
explosion(get_turf(target), 0, 2, 3, 3, cause = user)
to_chat(user, "<span class='noticealien'>[target] has detonated!</span>")
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/alien_spell/neurotoxin
/datum/spell/alien_spell/neurotoxin
name = "Neurotoxin spit"
desc = "This ability allows you to fire some neurotoxin. Knocks down anyone you hit, applies a small amount of stamina damage as well."
base_cooldown = 3 SECONDS
@@ -9,16 +9,16 @@
action_icon_state = "alien_neurotoxin_0"
active = FALSE
/obj/effect/proc_holder/spell/alien_spell/neurotoxin/create_new_targeting()
/datum/spell/alien_spell/neurotoxin/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/alien_spell/neurotoxin/update_icon_state()
/datum/spell/alien_spell/neurotoxin/update_spell_icon()
if(!action)
return
action.button_icon_state = "alien_neurotoxin_[active]"
action.UpdateButtons()
/obj/effect/proc_holder/spell/alien_spell/neurotoxin/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/neurotoxin/cast(list/targets, mob/living/carbon/user)
var/target = targets[1]
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // A little aimbot is fine
@@ -35,7 +35,7 @@
return TRUE
/obj/effect/proc_holder/spell/alien_spell/neurotoxin/death_to_xenos
/datum/spell/alien_spell/neurotoxin/death_to_xenos
name = "Neurotoxin spit"
desc = "This ability allows you to fire some neurotoxin. Knocks aliens down."
neurotoxin_type = /obj/item/projectile/bullet/anti_alien_toxin
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/alien_spell/plant_weeds
/datum/spell/alien_spell/plant_weeds
name = "Plant weeds"
desc = "Allows you to plant some alien weeds on the floor below you. Does not work while in space."
plasma_cost = 50
@@ -7,10 +7,10 @@
action_icon_state = "alien_plant"
var/requires_do_after = TRUE
/obj/effect/proc_holder/spell/alien_spell/plant_weeds/create_new_targeting()
/datum/spell/alien_spell/plant_weeds/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/plant_weeds/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/plant_weeds/cast(list/targets, mob/living/carbon/user)
var/turf/T = user.loc
if(locate(weed_type) in T)
to_chat(user, "<span class='noticealien'>There's already \a [weed_name] here.</span>")
@@ -1,13 +1,13 @@
/obj/effect/proc_holder/spell/alien_spell/evolve_queen
/datum/spell/alien_spell/evolve_queen
name = "Evolve into an alien queen"
desc = "Evolve into an alien queen."
plasma_cost = 300
action_icon_state = "alien_evolve_drone"
/obj/effect/proc_holder/spell/alien_spell/evolve_queen/create_new_targeting()
/datum/spell/alien_spell/evolve_queen/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/evolve_queen/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/evolve_queen/cast(list/targets, mob/living/carbon/user)
/// First we check if there is a living queen
for(var/mob/living/carbon/alien/humanoid/queen/living_queen in GLOB.alive_mob_list)
if(living_queen.key || !living_queen.get_int_organ(/obj/item/organ/internal/brain)) // We do a once over to check the queen didn't end up going away into the magic land of semi-dead
@@ -1,18 +1,18 @@
/obj/effect/proc_holder/spell/alien_spell/regurgitate
/datum/spell/alien_spell/regurgitate
name = "Regurgitate"
desc = "Empties the contents of your stomach onto the ground."
action_icon_state = "alien_barf"
/obj/effect/proc_holder/spell/alien_spell/regurgitate/create_new_targeting()
/datum/spell/alien_spell/regurgitate/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/regurgitate/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/regurgitate/cast(list/targets, mob/living/carbon/user)
for(var/mob/M in user.stomach_contents)
var/turf/output_loc = user.loc
if(!istype(output_loc))
return
user.stomach_contents -= M
M.forceMove(output_loc)
visible_message("<span class='alertalien'><B>[user] hurls out the contents of [p_their()] stomach!</span>")
user.visible_message("<span class='alertalien'><b>[user] hurls out the contents of [p_their()] stomach!</b></span>")
return
visible_message("<span class='alertalien'><B>[user] dry heaves!</span>")
user.visible_message("<span class='alertalien'><b>[user] dry heaves!</b></span>")
+3 -3
View File
@@ -1,13 +1,13 @@
/obj/effect/proc_holder/spell/alien_spell/tail_lash
/datum/spell/alien_spell/tail_lash
name = "Tail lash"
desc = "Knocks down anyone around you."
action_icon_state = "tailsweep"
base_cooldown = 10 SECONDS
/obj/effect/proc_holder/spell/alien_spell/tail_lash/create_new_targeting()
/datum/spell/alien_spell/tail_lash/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/alien_spell/tail_lash/cast(list/targets, mob/user)
/datum/spell/alien_spell/tail_lash/cast(list/targets, mob/user)
var/turf/T = user.loc
var/cast_resolved = FALSE
if(!istype(T))
@@ -1,13 +1,13 @@
/obj/effect/proc_holder/spell/alien_spell/transfer_plasma
/datum/spell/alien_spell/transfer_plasma
name = "Transfer Plasma"
desc = "Transfers 50 plasma to a nearby alien"
action_icon_state = "alien_transfer"
plasma_cost = 50
/obj/effect/proc_holder/spell/alien_spell/transfer_plasma/create_new_targeting()
/datum/spell/alien_spell/transfer_plasma/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/alien_spell/transfer_plasma/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/transfer_plasma/cast(list/targets, mob/living/carbon/user)
var/mob/living/carbon/alien/target = targets[1]
var/turf/T = user.loc
if(!istype(T) || !istype(target))
@@ -20,17 +20,17 @@
to_chat(target, "<span class='noticealien'>[user] has transfered 50 plasma to you!</span>")
return TRUE
/obj/effect/proc_holder/spell/alien_spell/syphon_plasma
/datum/spell/alien_spell/syphon_plasma
name = "Syphon plasma"
desc = "Syphons 150 plasma from a nearby alien."
action_icon_state = "alien_transfer"
plasma_cost = 0
base_cooldown = 10 SECONDS
/obj/effect/proc_holder/spell/alien_spell/syphon_plasma/create_new_targeting()
/datum/spell/alien_spell/syphon_plasma/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/alien_spell/syphon_plasma/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/syphon_plasma/cast(list/targets, mob/living/carbon/user)
var/mob/living/carbon/alien/target = targets[1]
var/turf/T = user.loc
if(!istype(T) || !istype(target))
+3 -3
View File
@@ -1,11 +1,11 @@
/obj/effect/proc_holder/spell/alien_spell/whisper
/datum/spell/alien_spell/whisper
name = "Whisper"
desc = "Whisper into a target's mind."
plasma_cost = 10
action_icon_state = "alien_whisper"
var/target
/obj/effect/proc_holder/spell/alien_spell/whisper/create_new_targeting() // Yeah this is copy and pasted code from cryoken and it's good enough
/datum/spell/alien_spell/whisper/create_new_targeting() // Yeah this is copy and pasted code from cryoken and it's good enough
var/datum/spell_targeting/click/T = new()
T.allowed_type = /mob/living
T.click_radius = 0
@@ -14,7 +14,7 @@
T.include_user = TRUE
return T
/obj/effect/proc_holder/spell/alien_spell/whisper/cast(list/targets, mob/living/carbon/user)
/datum/spell/alien_spell/whisper/cast(list/targets, mob/living/carbon/user)
var/mob/living/target = targets[1]
var/msg = tgui_input_text(user, "Message:", "Alien Whisper")
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/area_teleport
/datum/spell/area_teleport
nonabstract_req = TRUE
var/randomise_selection = 0 //if it lets the usr choose the teleport loc or picks it from the list
@@ -8,7 +8,7 @@
var/sound2 = 'sound/weapons/zapbang.ogg'
var/area/selected_area
/obj/effect/proc_holder/spell/area_teleport/before_cast(list/targets, mob/user)
/datum/spell/area_teleport/before_cast(list/targets, mob/user)
..()
selected_area = null // Reset it
var/area_name
@@ -30,7 +30,7 @@
selected_area = thearea
/obj/effect/proc_holder/spell/area_teleport/cast(list/targets, mob/living/user)
/datum/spell/area_teleport/cast(list/targets, mob/living/user)
if(!selected_area)
revert_cast(user)
return
@@ -78,7 +78,7 @@
return
/obj/effect/proc_holder/spell/area_teleport/invocation(mob/user)
/datum/spell/area_teleport/invocation(mob/user)
if(!invocation_area || !selected_area)
return
switch(invocation_type)
+2 -2
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/banana
/datum/spell/touch/banana
name = "Banana Touch"
desc = "A spell popular at wizard birthday parties, this spell will put on a clown costume on the target, \
stun them with a loud HONK, and mutate them to make them more entertaining! \
@@ -19,7 +19,7 @@
icon_state = "banana_touch"
item_state = "banana_touch"
/obj/effect/proc_holder/spell/touch/banana/apprentice
/datum/spell/touch/banana/apprentice
hand_path = /obj/item/melee/touch_attack/banana/apprentice
/obj/item/melee/touch_attack/banana/apprentice
+28 -28
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/bloodcrawl
/datum/spell/bloodcrawl
name = "Blood Crawl"
desc = "Use pools of blood to phase out of existence."
base_cooldown = 1 SECONDS
@@ -12,7 +12,7 @@
var/allowed_type = /obj/effect/decal/cleanable
var/phased = FALSE
/obj/effect/proc_holder/spell/bloodcrawl/create_new_targeting()
/datum/spell/bloodcrawl/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.selection_type = SPELL_SELECTION_RANGE
T.allowed_type = allowed_type
@@ -21,17 +21,17 @@
T.use_turf_of_user = TRUE
return T
/obj/effect/proc_holder/spell/bloodcrawl/valid_target(obj/effect/decal/cleanable/target, user)
/datum/spell/bloodcrawl/valid_target(obj/effect/decal/cleanable/target, user)
return target.can_bloodcrawl_in()
/obj/effect/proc_holder/spell/bloodcrawl/can_cast(mob/living/user, charge_check, show_message)
/datum/spell/bloodcrawl/can_cast(mob/living/user, charge_check, show_message)
. = ..()
if(!.)
return
if(!isliving(user))
return FALSE
/obj/effect/proc_holder/spell/bloodcrawl/cast(list/targets, mob/living/user)
/datum/spell/bloodcrawl/cast(list/targets, mob/living/user)
var/atom/target = targets[1]
if(!phased)
if(phaseout(target, user))
@@ -78,7 +78,7 @@
return
/obj/effect/proc_holder/spell/bloodcrawl/proc/block_hands(mob/living/carbon/C)
/datum/spell/bloodcrawl/proc/block_hands(mob/living/carbon/C)
if(C.l_hand || C.r_hand)
to_chat(C, "<span class='warning'>You may not hold items while blood crawling!</span>")
return FALSE
@@ -101,13 +101,13 @@
. = ..()
flick(animation_state, src) // Setting the icon_state to the animation has timing issues and can cause frame skips
/obj/effect/proc_holder/spell/bloodcrawl/proc/sink_animation(atom/A, mob/living/L)
/datum/spell/bloodcrawl/proc/sink_animation(atom/A, mob/living/L)
var/turf/mob_loc = get_turf(L)
visible_message("<span class='danger'>[L] sinks into [A].</span>")
playsound(mob_loc, 'sound/misc/enter_blood.ogg', 100, 1, -1)
mob_loc.visible_message("<span class='danger'>[L] sinks into [A].</span>")
playsound(mob_loc, 'sound/misc/enter_blood.ogg', 100, TRUE, -1)
new /obj/effect/temp_visual/dir_setting/bloodcrawl(mob_loc, L.dir, "jaunt")
/obj/effect/proc_holder/spell/bloodcrawl/proc/handle_consumption(mob/living/L, mob/living/victim, atom/A, obj/effect/dummy/slaughter/holder)
/datum/spell/bloodcrawl/proc/handle_consumption(mob/living/L, mob/living/victim, atom/A, obj/effect/dummy/slaughter/holder)
if(!HAS_TRAIT(L, TRAIT_BLOODCRAWL_EAT))
return
@@ -176,10 +176,10 @@
victim.ghostize()
qdel(victim)
/obj/effect/proc_holder/spell/bloodcrawl/proc/post_phase_in(mob/living/L, obj/effect/dummy/slaughter/holder)
/datum/spell/bloodcrawl/proc/post_phase_in(mob/living/L, obj/effect/dummy/slaughter/holder)
L.notransform = FALSE
/obj/effect/proc_holder/spell/bloodcrawl/proc/phaseout(obj/effect/decal/cleanable/B, mob/living/L)
/datum/spell/bloodcrawl/proc/phaseout(obj/effect/decal/cleanable/B, mob/living/L)
if(iscarbon(L) && !block_hands(L))
return FALSE
@@ -187,7 +187,7 @@
INVOKE_ASYNC(src, PROC_REF(async_phase), B, L)
return TRUE
/obj/effect/proc_holder/spell/bloodcrawl/proc/async_phase(obj/effect/decal/cleanable/B, mob/living/L)
/datum/spell/bloodcrawl/proc/async_phase(obj/effect/decal/cleanable/B, mob/living/L)
var/turf/mobloc = get_turf(L)
sink_animation(B, L)
var/obj/effect/dummy/slaughter/holder = new /obj/effect/dummy/slaughter(mobloc)
@@ -196,24 +196,24 @@
handle_consumption(L, L.pulling, B, holder)
post_phase_in(L, holder)
/obj/effect/proc_holder/spell/bloodcrawl/proc/rise_animation(turf/tele_loc, mob/living/L, atom/A)
/datum/spell/bloodcrawl/proc/rise_animation(turf/tele_loc, mob/living/L, atom/A)
new /obj/effect/temp_visual/dir_setting/bloodcrawl(tele_loc, L.dir, "jauntup")
if(prob(25) && isdemon(L))
var/list/voice = list('sound/hallucinations/behind_you1.ogg', 'sound/hallucinations/im_here1.ogg', 'sound/hallucinations/turn_around1.ogg', 'sound/hallucinations/i_see_you1.ogg')
playsound(tele_loc, pick(voice),50, 1, -1)
A.visible_message("<span class='warning'><b>[L] rises out of [A]!</b>")
playsound(get_turf(tele_loc), 'sound/misc/exit_blood.ogg', 100, 1, -1)
playsound(tele_loc, pick(voice),50, TRUE, -1)
A.visible_message("<span class='warning'><b>[L] rises out of [A]!</b></span>")
playsound(get_turf(tele_loc), 'sound/misc/exit_blood.ogg', 100, TRUE, -1)
/obj/effect/proc_holder/spell/bloodcrawl/proc/unblock_hands(mob/living/carbon/C)
/datum/spell/bloodcrawl/proc/unblock_hands(mob/living/carbon/C)
if(!istype(C))
return
for(var/obj/item/bloodcrawl/BC in C)
qdel(BC)
/obj/effect/proc_holder/spell/bloodcrawl/proc/rise_message(atom/A)
/datum/spell/bloodcrawl/proc/rise_message(atom/A)
A.visible_message("<span class='warning'>[A] starts to bubble...</span>")
/obj/effect/proc_holder/spell/bloodcrawl/proc/post_phase_out(atom/A, mob/living/L)
/datum/spell/bloodcrawl/proc/post_phase_out(atom/A, mob/living/L)
if(isslaughterdemon(L))
var/mob/living/simple_animal/demon/slaughter/S = L
S.speed = 0
@@ -222,7 +222,7 @@
addtimer(VARSET_CALLBACK(L, color, null), 6 SECONDS)
/obj/effect/proc_holder/spell/bloodcrawl/proc/phasein(atom/A, mob/living/L)
/datum/spell/bloodcrawl/proc/phasein(atom/A, mob/living/L)
if(L.notransform)
to_chat(L, "<span class='warning'>Finish eating first!</span>")
@@ -246,30 +246,30 @@
post_phase_out(A, L)
return TRUE
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl
/datum/spell/bloodcrawl/shadow_crawl
name = "Shadow Crawl"
desc = "Fade into the shadows, increasing your speed and making you incomprehensible. Will not work in brightened terrane."
allowed_type = /turf
action_background_icon_state = "shadow_demon_bg"
action_icon_state = "shadow_crawl"
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/valid_target(turf/target, user)
/datum/spell/bloodcrawl/shadow_crawl/valid_target(turf/target, user)
return target.get_lumcount() < 0.2
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/rise_message(atom/A)
/datum/spell/bloodcrawl/shadow_crawl/rise_message(atom/A)
return
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/rise_animation(turf/tele_loc, mob/living/L, atom/A)
/datum/spell/bloodcrawl/shadow_crawl/rise_animation(turf/tele_loc, mob/living/L, atom/A)
new /obj/effect/temp_visual/dir_setting/bloodcrawl(get_turf(L), L.dir, "shadowwalk_appear")
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/handle_consumption(mob/living/L, mob/living/victim, atom/A, obj/effect/dummy/slaughter/holder)
/datum/spell/bloodcrawl/shadow_crawl/handle_consumption(mob/living/L, mob/living/victim, atom/A, obj/effect/dummy/slaughter/holder)
return
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/sink_animation(atom/A, mob/living/L)
/datum/spell/bloodcrawl/shadow_crawl/sink_animation(atom/A, mob/living/L)
A.visible_message("<span class='danger'>[L] sinks into the shadows...</span>")
new /obj/effect/temp_visual/dir_setting/bloodcrawl(get_turf(L), L.dir, "shadowwalk_disappear")
/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/post_phase_in(mob/living/L, obj/effect/dummy/slaughter/holder)
/datum/spell/bloodcrawl/shadow_crawl/post_phase_in(mob/living/L, obj/effect/dummy/slaughter/holder)
..()
if(!istype(L, /mob/living/simple_animal/demon/shadow))
return
+4 -4
View File
@@ -1,5 +1,5 @@
/obj/effect/proc_holder/spell/chaplain_bless
/datum/spell/chaplain_bless
name = "Bless"
desc = "Blesses a single person."
@@ -14,16 +14,16 @@
cooldown_min = 20
action_icon_state = "shield"
/obj/effect/proc_holder/spell/chaplain_bless/create_new_targeting()
/datum/spell/chaplain_bless/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.range = 1
T.click_radius = -1
return T
/obj/effect/proc_holder/spell/chaplain_bless/valid_target(mob/living/carbon/human/target, mob/user)
/datum/spell/chaplain_bless/valid_target(mob/living/carbon/human/target, mob/user)
return target.mind && target.ckey && !target.stat
/obj/effect/proc_holder/spell/chaplain_bless/cast(list/targets, mob/living/user = usr)
/datum/spell/chaplain_bless/cast(list/targets, mob/living/user = usr)
if(!istype(user))
to_chat(user, "Somehow, you are not a living mob. This should never happen. Report this bug.")
revert_cast()
+5 -5
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/charge
/datum/spell/charge
name = "Charge"
desc = "This spell can be used to recharge a variety of things in your hands, from magical artifacts to electrical components. A creative wizard can even use it to grant magical power to a fellow magic user."
school = "transmutation"
@@ -9,10 +9,10 @@
cooldown_min = 400 //50 deciseconds reduction per rank
action_icon_state = "charge"
/obj/effect/proc_holder/spell/charge/create_new_targeting()
/datum/spell/charge/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/charge/cast(list/targets, mob/user = usr)
/datum/spell/charge/cast(list/targets, mob/user = usr)
for(var/mob/living/L in targets)
var/list/hand_items = list(L.get_active_hand(),L.get_inactive_hand())
var/charged_item = null
@@ -21,10 +21,10 @@
if(L.pulling && (isliving(L.pulling)))
var/mob/living/M = L.pulling
if(M.mob_spell_list.len != 0 || (M.mind && M.mind.spell_list.len != 0))
for(var/obj/effect/proc_holder/spell/S in M.mob_spell_list)
for(var/datum/spell/S in M.mob_spell_list)
S.cooldown_handler.revert_cast()
if(M.mind)
for(var/obj/effect/proc_holder/spell/S in M.mind.spell_list)
for(var/datum/spell/S in M.mind.spell_list)
S.cooldown_handler.revert_cast()
to_chat(M, "<span class='notice'>You feel raw magical energy flowing through you, it feels good!</span>")
else
+11 -11
View File
@@ -2,7 +2,7 @@
* A click-based spell template which starts charging up once you click the action button/verb. Click again on something to activate the actual spell
*/
/obj/effect/proc_holder/spell/charge_up
/datum/spell/charge_up
var/start_time = 0
/// The overlay used to show that you are charging. Create this in the New of the spell
var/image/charge_up_overlay
@@ -17,13 +17,13 @@
/// The text shown when you are over the charge limit and thus can't stop.
var/stop_charging_fail_text
/obj/effect/proc_holder/spell/charge_up/create_new_targeting()
/datum/spell/charge_up/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.allowed_type = /mob/living
T.try_auto_target = FALSE
return T
/obj/effect/proc_holder/spell/charge_up/Click()
/datum/spell/charge_up/Click()
if(cast_check(TRUE, FALSE, usr))
if(!start_time)
INVOKE_ASYNC(src, PROC_REF(StartChargeup), usr)
@@ -33,7 +33,7 @@
return ..()
/obj/effect/proc_holder/spell/charge_up/proc/try_stop_buildup(mob/user)
/datum/spell/charge_up/proc/try_stop_buildup(mob/user)
var/energy_perc = get_energy_charge() / max_charge_time
if(energy_perc < 0.5)
cooldown_handler.start_recharge((1 - energy_perc) * cooldown_handler.recharge_duration) // Shorten the cooldown based on how long it was charged for.
@@ -44,10 +44,10 @@
to_chat(user, "<span class='danger'>[stop_charging_fail_text]</span>")
return FALSE
/obj/effect/proc_holder/spell/charge_up/proc/get_energy_charge()
/datum/spell/charge_up/proc/get_energy_charge()
return min(world.time - start_time, max_charge_time)
/obj/effect/proc_holder/spell/charge_up/proc/StartChargeup(mob/user)
/datum/spell/charge_up/proc/StartChargeup(mob/user)
to_chat(user, "<span class='notice'>[start_charging_text]</span>")
user.add_overlay(charge_up_overlay)
playsound(user, charge_sound, 50, FALSE, channel = charge_sound.channel)
@@ -56,25 +56,25 @@
if(start_time)
Discharge(user)
/obj/effect/proc_holder/spell/charge_up/proc/stopped_casting()
/datum/spell/charge_up/proc/stopped_casting()
return start_time == 0
/obj/effect/proc_holder/spell/charge_up/proc/Reset(mob/user)
/datum/spell/charge_up/proc/Reset(mob/user)
start_time = 0
user.cut_overlay(charge_up_overlay)
remove_ranged_ability(user)
playsound(user, null, 50, FALSE, channel = charge_sound.channel)
/obj/effect/proc_holder/spell/charge_up/revert_cast(mob/user)
/datum/spell/charge_up/revert_cast(mob/user)
Reset(user)
..()
/obj/effect/proc_holder/spell/charge_up/proc/Discharge(mob/user)
/datum/spell/charge_up/proc/Discharge(mob/user)
to_chat(user, "<span class='danger'>You lose control over the spell!</span>")
Reset(user)
spend_spell_cost(user)
cooldown_handler.start_recharge()
/obj/effect/proc_holder/spell/charge_up/after_cast(list/targets, mob/user)
/datum/spell/charge_up/after_cast(list/targets, mob/user)
..()
Reset(user)
+8 -8
View File
@@ -2,17 +2,17 @@
* A spell template that adds bounces to the charge_up spell template. The spell will bounce between targets once released.
* Don't override cast and instead override apply_bounce_effect and the other procs
*/
/obj/effect/proc_holder/spell/charge_up/bounce
/datum/spell/charge_up/bounce
var/bounce_hit_sound
/obj/effect/proc_holder/spell/charge_up/bounce/create_new_targeting()
/datum/spell/charge_up/bounce/create_new_targeting()
var/datum/spell_targeting/click/T = new
T.allowed_type = /mob/living
T.try_auto_target = FALSE
T.use_obstacle_check = TRUE
return T
/obj/effect/proc_holder/spell/charge_up/bounce/cast(list/targets, mob/user = usr)
/datum/spell/charge_up/bounce/cast(list/targets, mob/user = usr)
var/mob/living/target = targets[1]
bounce(user, target, get_bounce_energy(), get_bounce_amount(), user)
@@ -20,13 +20,13 @@
/**
* How much energy should each bounce have?
*/
/obj/effect/proc_holder/spell/charge_up/bounce/proc/get_bounce_energy()
/datum/spell/charge_up/bounce/proc/get_bounce_energy()
return
/**
* How much bounces should there be in total?
*/
/obj/effect/proc_holder/spell/charge_up/bounce/proc/get_bounce_amount()
/datum/spell/charge_up/bounce/proc/get_bounce_amount()
return
/**
@@ -36,7 +36,7 @@
* * origin - Where the bounce came from
* * target - The mob that got hit
*/
/obj/effect/proc_holder/spell/charge_up/bounce/proc/create_beam(mob/origin, mob/target)
/datum/spell/charge_up/bounce/proc/create_beam(mob/origin, mob/target)
return
/**
@@ -49,10 +49,10 @@
* * energy - How much energy the bounce has
* * user - The caster of the spell
*/
/obj/effect/proc_holder/spell/charge_up/bounce/proc/apply_bounce_effect(mob/origin, mob/target, energy, mob/user)
/datum/spell/charge_up/bounce/proc/apply_bounce_effect(mob/origin, mob/target, energy, mob/user)
return
/obj/effect/proc_holder/spell/charge_up/bounce/proc/bounce(mob/origin, mob/target, energy, bounces, mob/user)
/datum/spell/charge_up/bounce/proc/bounce(mob/origin, mob/target, energy, bounces, mob/user)
SHOULD_CALL_PARENT(TRUE)
create_beam(origin, target)
apply_bounce_effect(origin, target, energy, user)
+1 -1
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/cluwne
/datum/spell/touch/cluwne
name = "Curse of the Cluwne"
desc = "Turns the target into a fat and cursed monstrosity of a clown."
hand_path = /obj/item/melee/touch_attack/cluwne
+5 -6
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/aoe/conjure
/datum/spell/aoe/conjure
desc = "This spell conjures objs of the specified types in range."
var/list/summon_type = list() //determines what exactly will be summoned
@@ -15,14 +15,14 @@
var/cast_sound = 'sound/items/welder.ogg'
/obj/effect/proc_holder/spell/aoe/conjure/create_new_targeting()
/datum/spell/aoe/conjure/create_new_targeting()
var/datum/spell_targeting/aoe/turf/targeting = new()
targeting.range = aoe_range
return targeting
/obj/effect/proc_holder/spell/aoe/conjure/cast(list/targets,mob/living/user = usr)
/datum/spell/aoe/conjure/cast(list/targets,mob/living/user = usr)
var/list/what_conjure_summoned = list()
playsound(get_turf(user), cast_sound, 50,1)
playsound(get_turf(user), cast_sound, 50, TRUE)
for(var/turf/T in targets)
if(T.density && !summon_ignore_density)
targets -= T
@@ -57,8 +57,7 @@
return what_conjure_summoned
/// test purposes
/obj/effect/proc_holder/spell/aoe/conjure/summonEdSwarm
/datum/spell/aoe/conjure/summonEdSwarm
name = "Dispense Wizard Justice"
desc = "This spell dispenses wizard justice."
summon_type = list(/mob/living/simple_animal/bot/ed209)
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/conjure_item
/datum/spell/conjure_item
name = "Summon weapon"
desc = "A generic spell that should not exist. This summons an instance of a specific type of item, or if one already exists, un-summons it."
invocation_type = "none"
@@ -9,10 +9,10 @@
base_cooldown = 15 SECONDS
cooldown_min = 10
/obj/effect/proc_holder/spell/conjure_item/create_new_targeting()
/datum/spell/conjure_item/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/conjure_item/cast(list/targets, mob/user = usr)
/datum/spell/conjure_item/cast(list/targets, mob/user = usr)
if(item)
QDEL_NULL(item)
else
@@ -21,6 +21,6 @@
item = new item_type
C.put_in_hands(item)
/obj/effect/proc_holder/spell/conjure_item/Destroy()
/datum/spell/conjure_item/Destroy()
QDEL_NULL(item)
return ..()
+20 -19
View File
@@ -1,14 +1,14 @@
//////////////////////////////Construct Spells/////////////////////////
/obj/effect/proc_holder/spell/aoe/conjure/construct/lesser
/datum/spell/aoe/conjure/construct/lesser
base_cooldown = 1800
action_icon_state = "artificer"
action_background_icon_state = "bg_cult"
/obj/effect/proc_holder/spell/aoe/conjure/build
/datum/spell/aoe/conjure/build
aoe_range = 0
/obj/effect/proc_holder/spell/aoe/conjure/build/floor
/datum/spell/aoe/conjure/build/floor
name = "Summon Cult Floor"
desc = "This spell constructs a cult floor"
action_icon_state = "floorconstruct"
@@ -22,7 +22,7 @@
centcom_cancast = FALSE //Stop crashing the server by spawning turfs on transit tiles
holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel
/obj/effect/proc_holder/spell/aoe/conjure/build/wall
/datum/spell/aoe/conjure/build/wall
name = "Summon Cult Wall"
desc = "This spell constructs a cult wall"
action_icon_state = "cultforcewall"
@@ -36,7 +36,7 @@
centcom_cancast = FALSE //Stop crashing the server by spawning turfs on transit tiles
holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel
/obj/effect/proc_holder/spell/aoe/conjure/build/wall/reinforced
/datum/spell/aoe/conjure/build/wall/reinforced
name = "Greater Construction"
desc = "This spell constructs a reinforced metal wall"
school = "conjuration"
@@ -50,7 +50,7 @@
summon_type = list(/turf/simulated/wall/r_wall)
/obj/effect/proc_holder/spell/aoe/conjure/build/soulstone
/datum/spell/aoe/conjure/build/soulstone
name = "Summon Soulstone"
desc = "This spell uses vile sorcery to create a spirit-trapping soulstone."
action_icon_state = "summonsoulstone"
@@ -64,12 +64,12 @@
summon_type = list(/obj/item/soulstone)
/obj/effect/proc_holder/spell/aoe/conjure/build/soulstone/holy
/datum/spell/aoe/conjure/build/soulstone/holy
action_icon_state = "summonsoulstone_holy"
summon_type = list(/obj/item/soulstone/anybody/purified)
/obj/effect/proc_holder/spell/aoe/conjure/build/pylon
/datum/spell/aoe/conjure/build/pylon
name = "Cult Pylon"
desc = "This spell uses dark magic to craft an unholy beacon. Heals cultists, and makes a handy light source."
action_icon_state = "pylon"
@@ -84,7 +84,7 @@
summon_type = list(/obj/structure/cult/functional/pylon)
/obj/effect/proc_holder/spell/aoe/conjure/build/lesserforcewall
/datum/spell/aoe/conjure/build/lesserforcewall
name = "Shield"
desc = "This spell creates a temporary forcefield to shield yourself and allies from incoming fire"
action_icon_state = "cultforcewall"
@@ -105,7 +105,7 @@
icon_state = "m_shield_cult"
light_color = LIGHT_COLOR_PURE_RED
/obj/effect/proc_holder/spell/ethereal_jaunt/shift
/datum/spell/ethereal_jaunt/shift
name = "Phase Shift"
desc = "This spell allows you to pass through walls"
action_icon_state = "phaseshift"
@@ -119,7 +119,7 @@
jaunt_in_type = /obj/effect/temp_visual/dir_setting/wraith
jaunt_out_type = /obj/effect/temp_visual/dir_setting/wraith/out
/obj/effect/proc_holder/spell/ethereal_jaunt/shift/do_jaunt(mob/living/target)
/datum/spell/ethereal_jaunt/shift/do_jaunt(mob/living/target)
target.set_light(0)
..()
if(isconstruct(target))
@@ -129,10 +129,10 @@
else
C.set_light(2, 3, l_color = GET_CULT_DATA(construct_glow, LIGHT_COLOR_BLOOD_MAGIC))
/obj/effect/proc_holder/spell/ethereal_jaunt/shift/jaunt_steam(mobloc)
/datum/spell/ethereal_jaunt/shift/jaunt_steam(mobloc)
return
/obj/effect/proc_holder/spell/projectile/magic_missile/lesser
/datum/spell/projectile/magic_missile/lesser
name = "Lesser Magic Missile"
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
action_background_icon_state = "bg_cult"
@@ -144,20 +144,21 @@
holy_area_cancast = FALSE //Stops cult magic from working on holy ground eg: chapel
proj_lifespan = 10
proj_step_delay = 5
proj_type = "/obj/effect/proc_holder/spell/inflict_handler/magic_missile/lesser"
proj_type = /obj/item/projectile/magic/magic_missile/lesser
/obj/effect/proc_holder/spell/projectile/magic_missile/lesser/create_new_targeting()
/datum/spell/projectile/magic_missile/lesser/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living
T.random_target = TRUE
T.max_targets = 6
return T
/obj/effect/proc_holder/spell/inflict_handler/magic_missile/lesser
amt_knockdown = 6 SECONDS
amt_weakened = 0
/obj/item/projectile/magic/magic_missile/lesser
name = "lesser magic missile"
knockdown = 6 SECONDS
weaken = 0
/obj/effect/proc_holder/spell/smoke/disable
/datum/spell/smoke/disable
name = "Paralysing Smoke"
desc = "This spell spawns a cloud of paralysing smoke."
action_icon_state = "parasmoke"
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/disguise_self
/datum/spell/disguise_self
name = "Disguise Self"
desc = "Disguise yourself as a crewmember, based on your current location. Also changes your voice. \
The disguise will not hold up to being examined directly, and will break if you're damaged."
@@ -12,10 +12,10 @@
action_icon_state = "disguise_self"
sound = null
/obj/effect/proc_holder/spell/disguise_self/create_new_targeting()
/datum/spell/disguise_self/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/disguise_self/cast(list/targets, mob/user = usr)
/datum/spell/disguise_self/cast(list/targets, mob/user = usr)
if(!ishuman(user))
return FALSE
var/mob/living/carbon/human/H = user
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/emplosion
/datum/spell/emplosion
name = "Emplosion"
desc = "This spell emplodes an area."
@@ -7,12 +7,12 @@
action_icon_state = "emp"
/obj/effect/proc_holder/spell/emplosion/create_new_targeting()
/datum/spell/emplosion/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/emplosion/cast(list/targets, mob/user = usr)
/datum/spell/emplosion/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
empulse(target.loc, emp_heavy, emp_light, 1)
empulse(target.loc, emp_heavy, emp_light, TRUE)
return
+6 -6
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/ethereal_jaunt
/datum/spell/ethereal_jaunt
name = "Ethereal Jaunt"
desc = "This spell creates your ethereal form, temporarily making you invisible and able to pass through walls."
@@ -20,18 +20,18 @@
action_icon_state = "jaunt"
/obj/effect/proc_holder/spell/ethereal_jaunt/create_new_targeting()
/datum/spell/ethereal_jaunt/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/ethereal_jaunt/cast(list/targets, mob/user = usr) //magnets, so mostly hardcoded
playsound(get_turf(user), sound1, 50, 1, -1)
/datum/spell/ethereal_jaunt/cast(list/targets, mob/user = usr) //magnets, so mostly hardcoded
playsound(get_turf(user), sound1, 50, TRUE, -1)
for(var/mob/living/target in targets)
if(!target.can_safely_leave_loc()) // No more brainmobs hopping out of their brains
to_chat(target, "<span class='warning'>You are somehow too bound to your current location to abandon it.</span>")
continue
INVOKE_ASYNC(src, PROC_REF(do_jaunt), target)
/obj/effect/proc_holder/spell/ethereal_jaunt/proc/do_jaunt(mob/living/target)
/datum/spell/ethereal_jaunt/proc/do_jaunt(mob/living/target)
target.notransform = TRUE
var/turf/mobloc = get_turf(target)
var/obj/effect/dummy/spell_jaunt/holder = new jaunt_type_path(mobloc)
@@ -74,7 +74,7 @@
REMOVE_TRAIT(target, TRAIT_IMMOBILIZED, "jaunt")
target.remove_CC()
/obj/effect/proc_holder/spell/ethereal_jaunt/proc/jaunt_steam(mobloc)
/datum/spell/ethereal_jaunt/proc/jaunt_steam(mobloc)
var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread()
steam.set_up(10, 0, mobloc)
steam.start()
+1 -1
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/fake_disintegrate
/datum/spell/touch/fake_disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
hand_path = "/obj/item/melee/touch_attack/fake_disintegrate"
+9 -5
View File
@@ -1,12 +1,12 @@
/obj/effect/proc_holder/spell/genetic
/datum/spell/genetic
desc = "This spell inflicts a set of mutations and disabilities upon the target."
var/list/active_on = list()
var/list/traits = list() // traits
var/list/mutations = list() // mutation defines. Set these in Initialize. Refactor this nonsense one day
var/duration = 100 // deciseconds
var/duration = 10 SECONDS
/obj/effect/proc_holder/spell/genetic/cast(list/targets, mob/user = usr)
/datum/spell/genetic/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
if(!target.dna)
continue
@@ -17,15 +17,19 @@
ADD_TRAIT(target, A, MAGIC_TRAIT)
active_on += target
target.regenerate_icons()
do_additional_effects(target)
if(duration < base_cooldown)
addtimer(CALLBACK(src, PROC_REF(remove), target), duration, TIMER_OVERRIDE|TIMER_UNIQUE)
/obj/effect/proc_holder/spell/genetic/Destroy()
/datum/spell/genetic/proc/do_additional_effects(mob/target)
return
/datum/spell/genetic/Destroy()
for(var/V in active_on)
remove(V)
return ..()
/obj/effect/proc_holder/spell/genetic/proc/remove(mob/living/carbon/target)
/datum/spell/genetic/proc/remove(mob/living/carbon/target)
active_on -= target
if(!QDELETED(target))
for(var/A in mutations)
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/horsemask
/datum/spell/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"
@@ -15,13 +15,13 @@
action_icon_state = "barn"
sound = 'sound/magic/HorseHead_curse.ogg'
/obj/effect/proc_holder/spell/horsemask/create_new_targeting()
/datum/spell/horsemask/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.selection_type = SPELL_SELECTION_RANGE
return T
/obj/effect/proc_holder/spell/horsemask/cast(list/targets, mob/user = usr)
/datum/spell/horsemask/cast(list/targets, mob/user = usr)
if(!targets.len)
to_chat(user, "<span class='notice'>No target found in range.</span>")
return
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/infinite_guns
/datum/spell/infinite_guns
name = "Lesser Summon Guns"
desc = "Why reload when you have infinite guns? Summons an unending stream of bolt action rifles. Requires both hands free to use."
invocation_type = "none"
@@ -10,10 +10,10 @@
action_icon_state = "bolt_action"
var/gun_type = /obj/item/gun/projectile/shotgun/boltaction/enchanted
/obj/effect/proc_holder/spell/infinite_guns/create_new_targeting()
/datum/spell/infinite_guns/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/infinite_guns/cast(list/targets, mob/user = usr)
/datum/spell/infinite_guns/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/C in targets)
C.drop_item()
C.swap_hand()
@@ -21,7 +21,7 @@
var/obj/item/gun/projectile/shotgun/boltaction/enchanted/GUN = new gun_type()
C.put_in_hands(GUN)
/obj/effect/proc_holder/spell/infinite_guns/fireball
/datum/spell/infinite_guns/fireball
name = "Rapid-fire Fireball"
desc = "Multiple Fireballs. Need I explain more? Requires both hands free to use."
-62
View File
@@ -1,62 +0,0 @@
/obj/effect/proc_holder/spell/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
var/amt_knockdown = 0
//set to negatives for healing
var/amt_dam_fire = 0
var/amt_dam_brute = 0
var/amt_dam_oxy = 0
var/amt_dam_tox = 0
var/amt_eye_blind = 0
var/amt_eye_blurry = 0
var/destroys = "none" //can be "none", "gib" or "disintegrate"
var/summon_type = null //this will put an obj at the target's location
/obj/effect/proc_holder/spell/inflict_handler/create_new_targeting()
return new /datum/spell_targeting/self // Dummy value since it is never used for this spell... why is this even a spell
/obj/effect/proc_holder/spell/inflict_handler/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
switch(destroys)
if("gib")
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.adjustOxyLoss(amt_dam_oxy)
//disabling
target.Weaken(amt_weakened)
target.Paralyse(amt_paralysis)
target.Stun(amt_stunned)
target.KnockDown(amt_knockdown)
target.AdjustEyeBlind(amt_eye_blind)
target.AdjustEyeBlurry(amt_eye_blurry)
//summoning
if(summon_type)
new summon_type(target.loc, target)
+7 -7
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/aoe/knock
/datum/spell/aoe/knock
name = "Knock"
desc = "This spell opens nearby doors and does not require wizard garb."
@@ -13,31 +13,31 @@
sound = 'sound/magic/knock.ogg'
aoe_range = 3
/obj/effect/proc_holder/spell/aoe/knock/create_new_targeting()
/datum/spell/aoe/knock/create_new_targeting()
var/datum/spell_targeting/aoe/turf/targeting = new()
targeting.range = aoe_range
return targeting
/obj/effect/proc_holder/spell/aoe/knock/cast(list/targets, mob/user = usr)
/datum/spell/aoe/knock/cast(list/targets, mob/user = usr)
for(var/turf/T in targets)
for(var/obj/machinery/door/door in T.contents)
INVOKE_ASYNC(src, PROC_REF(try_open_airlock), door)
for(var/obj/structure/closet/C in T.contents)
INVOKE_ASYNC(src, PROC_REF(try_open_closet), C)
/obj/effect/proc_holder/spell/aoe/knock/proc/try_open_airlock(obj/machinery/door/door)
/datum/spell/aoe/knock/proc/try_open_airlock(obj/machinery/door/door)
if(istype(door, /obj/machinery/door/airlock))
var/obj/machinery/door/airlock/A = door
A.unlock(TRUE) //forced because it's magic!
door.open()
/obj/effect/proc_holder/spell/aoe/knock/proc/try_open_closet(obj/structure/closet/C)
/datum/spell/aoe/knock/proc/try_open_closet(obj/structure/closet/C)
if(istype(C, /obj/structure/closet/secure_closet))
var/obj/structure/closet/secure_closet/SC = C
SC.locked = FALSE
C.open()
/obj/effect/proc_holder/spell/aoe/knock/greater
/datum/spell/aoe/knock/greater
name = "Greater Knock"
desc = "On first cast, will remove access restrictions on all airlocks on the station, and announce this spell's use to the station. On any further cast, will open all doors in sight. Cannot be refunded once bought!"
@@ -50,7 +50,7 @@
action_icon_state = "greater_knock"
/obj/effect/proc_holder/spell/aoe/knock/greater/cast(list/targets, mob/user = usr)
/datum/spell/aoe/knock/greater/cast(list/targets, mob/user = usr)
if(!used)
used = TRUE
for(var/obj/machinery/door/airlock/A in GLOB.airlocks)
+12 -12
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/lichdom
/datum/spell/lichdom
name = "Bind Soul"
desc = "A dark necromantic pact that can forever bind your soul to an item of your choosing. So long as both your body and the item remain intact and on the same plane you can revive from death, though the time between reincarnations grows steadily with use."
school = "necromancy"
@@ -17,26 +17,26 @@
action_icon_state = "skeleton"
/obj/effect/proc_holder/spell/lichdom/create_new_targeting()
/datum/spell/lichdom/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/lichdom/Destroy()
/datum/spell/lichdom/Destroy()
for(var/datum/mind/M in SSticker.mode.wizards) //Make sure no other bones are about
for(var/obj/effect/proc_holder/spell/S in M.spell_list)
if(istype(S,/obj/effect/proc_holder/spell/lichdom) && S != src)
for(var/datum/spell/S in M.spell_list)
if(istype(S,/datum/spell/lichdom) && S != src)
return ..()
if(existence_stops_round_end)
GLOB.configuration.gamemode.disable_certain_round_early_end = FALSE
return ..()
/obj/effect/proc_holder/spell/lichdom/cast(list/targets, mob/user = usr)
/datum/spell/lichdom/cast(list/targets, mob/user = usr)
for(var/mob/M in targets)
if(stat_allowed)
attempt_revive(M)
else if(!marked_item_uid)
attempt_mark_item(M)
/obj/effect/proc_holder/spell/lichdom/proc/attempt_revive(mob/user)
/datum/spell/lichdom/proc/attempt_revive(mob/user)
// Can only cast when unconscious/dead
if(user.stat == CONSCIOUS)
to_chat(user, "<span class='notice'>You aren't dead enough to revive!</span>")
@@ -95,7 +95,7 @@
cooldown_handler.recharge_duration += 1 MINUTES
to_chat(lich, "<span class='warning'>Your bones clatter and shudder as they're pulled back into this world!</span>")
/obj/effect/proc_holder/spell/lichdom/proc/attempt_mark_item(mob/user)
/datum/spell/lichdom/proc/attempt_mark_item(mob/user)
var/obj/item/target = user.get_active_hand()
if(!target)
to_chat(user, "<span class='warning'>You must hold an item you wish to make your phylactery!</span>")
@@ -141,7 +141,7 @@
existence_stops_round_end = TRUE
GLOB.configuration.gamemode.disable_certain_round_early_end = TRUE
/obj/effect/proc_holder/spell/lichdom/proc/is_revive_possible()
/datum/spell/lichdom/proc/is_revive_possible()
var/obj/item/marked_item = locateUID(marked_item_uid)
if(QDELETED(marked_item))
return FALSE
@@ -153,12 +153,12 @@
return FALSE
return TRUE
/obj/effect/proc_holder/spell/lichdom/proc/check_revivability_handler()
/datum/spell/lichdom/proc/check_revivability_handler()
SIGNAL_HANDLER
// There are other liches about, so round may still continue
for(var/datum/mind/M in SSticker.mode.wizards)
for(var/obj/effect/proc_holder/spell/lichdom/S in M.spell_list)
for(var/datum/spell/lichdom/S in M.spell_list)
if(S == src)
continue
// Other lich can still revive
@@ -170,7 +170,7 @@
GLOB.configuration.gamemode.disable_certain_round_early_end = is_revive_possible()
/obj/effect/proc_holder/spell/lichdom/proc/equip_lich(mob/living/carbon/human/H)
/datum/spell/lichdom/proc/equip_lich(mob/living/carbon/human/H)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/wizrobe/black(H), SLOT_HUD_OUTER_SUIT)
H.equip_to_slot_or_del(new /obj/item/clothing/head/wizard/black(H), SLOT_HUD_HEAD)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H), SLOT_HUD_SHOES)
+7 -7
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/charge_up/bounce/lightning
/datum/spell/charge_up/bounce/lightning
name = "Lightning Bolt"
desc = "Throws a lightning bolt at your enemies. Classic. When clicked will start to charge in power. Then click on a mob to send the bolt before it overloads with power."
base_cooldown = 30 SECONDS
@@ -15,29 +15,29 @@
bounce_hit_sound = 'sound/magic/lightningshock.ogg'
var/damaging = TRUE
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/New()
/datum/spell/charge_up/bounce/lightning/New()
..()
charge_up_overlay = image(icon = 'icons/effects/effects.dmi', icon_state = "electricity", layer = EFFECTS_LAYER)
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/lightnian
/datum/spell/charge_up/bounce/lightning/lightnian
clothes_req = FALSE
invocation_type = "none"
damaging = FALSE
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/get_bounce_energy()
/datum/spell/charge_up/bounce/lightning/get_bounce_energy()
if(damaging)
return max(15, get_energy_charge() / 2)
return 0
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/get_bounce_amount()
/datum/spell/charge_up/bounce/lightning/get_bounce_amount()
if(damaging)
return 5
return round(get_energy_charge() / 20)
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/create_beam(mob/origin, mob/target)
/datum/spell/charge_up/bounce/lightning/create_beam(mob/origin, mob/target)
origin.Beam(target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5)
/obj/effect/proc_holder/spell/charge_up/bounce/lightning/apply_bounce_effect(mob/origin, mob/living/target, energy, mob/user)
/datum/spell/charge_up/bounce/lightning/apply_bounce_effect(mob/origin, mob/living/target, energy, mob/user)
if(damaging)
target.electrocute_act(energy, "Lightning Bolt", flags = SHOCK_NOGLOVES)
else
+7 -7
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/charge_up/bounce/magnet
/datum/spell/charge_up/bounce/magnet
name = "Magnetic Pull"
desc = "Pulls metalic objects from enemies hands with the power of MAGNETS."
action_icon_state = "magnet"
@@ -14,22 +14,22 @@
start_charging_text = "You start gathering magnetism around you."
bounce_hit_sound = 'sound/machines/defib_zap.ogg'
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/New()
/datum/spell/charge_up/bounce/magnet/New()
..()
charge_up_overlay = image(icon = 'icons/effects/effects.dmi', icon_state = "electricity", layer = EFFECTS_LAYER)
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/get_bounce_energy()
/datum/spell/charge_up/bounce/magnet/get_bounce_energy()
return get_energy_charge()
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/get_bounce_amount()
/datum/spell/charge_up/bounce/magnet/get_bounce_amount()
if(get_energy_charge() >= 75)
return 5
return 0
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/create_beam(mob/origin, mob/target)
/datum/spell/charge_up/bounce/magnet/create_beam(mob/origin, mob/target)
origin.Beam(target, icon_state = "lightning[rand(1, 12)]", icon = 'icons/effects/effects.dmi', time = 5)
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/apply_bounce_effect(mob/origin, mob/target, energy, mob/user)
/datum/spell/charge_up/bounce/magnet/apply_bounce_effect(mob/origin, mob/target, energy, mob/user)
var/list/items_to_throw = list()
switch(energy)
if(0 to 25)
@@ -47,7 +47,7 @@
for(var/I in items_to_throw)
try_throw_object(user, target, I)
/obj/effect/proc_holder/spell/charge_up/bounce/magnet/proc/try_throw_object(mob/user, mob/thrower, obj/item/to_throw)
/datum/spell/charge_up/bounce/magnet/proc/try_throw_object(mob/user, mob/thrower, obj/item/to_throw)
if(!(to_throw.flags & CONDUCT) || !thrower.unEquip(to_throw, silent = TRUE))
return FALSE
thrower.visible_message("<span class='warning'>[to_throw] gets thrown out of [thrower] [thrower.p_their()] hands!</span>",
+21 -21
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/aoe/conjure/build/mime_wall
/datum/spell/aoe/conjure/build/mime_wall
name = "Invisible Wall"
desc = "The mime's performance transmutates into physical reality."
school = "mime"
@@ -15,7 +15,7 @@
action_icon_state = "mime"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/aoe/conjure/build/mime_wall/Click()
/datum/spell/aoe/conjure/build/mime_wall/Click()
if(usr && usr.mind)
if(!usr.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
@@ -25,10 +25,10 @@
invocation_type ="none"
..()
/obj/effect/proc_holder/spell/mime/create_new_targeting()
/datum/spell/mime/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/mime/speak
/datum/spell/mime/speak
name = "Speech"
desc = "Make or break a vow of silence."
school = "mime"
@@ -40,7 +40,7 @@
action_icon_state = "mime_silence"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/mime/speak/Click()
/datum/spell/mime/speak/Click()
if(!usr)
return
if(!ishuman(usr))
@@ -52,7 +52,7 @@
still_recharging_msg = "<span class='warning'>You'll have to wait before you can give your vow of silence again!</span>"
..()
/obj/effect/proc_holder/spell/mime/speak/cast(list/targets,mob/user = usr)
/datum/spell/mime/speak/cast(list/targets,mob/user = usr)
for(var/mob/living/carbon/human/H in targets)
H.mind.miming=!H.mind.miming
if(H.mind.miming)
@@ -62,7 +62,7 @@
//Advanced Mimery traitor item spells
/obj/effect/proc_holder/spell/forcewall/mime
/datum/spell/forcewall/mime
name = "Invisible Greater Wall"
desc = "Form an invisible three tile wide blockade."
school = "mime"
@@ -77,7 +77,7 @@
action_icon_state = "mime_bigwall"
action_background_icon_state = "bg_mime"
/obj/effect/proc_holder/spell/forcewall/mime/Click()
/datum/spell/forcewall/mime/Click()
if(usr && usr.mind)
if(!usr.mind.miming)
to_chat(usr, "<span class='notice'>You must dedicate yourself to silence first.</span>")
@@ -87,7 +87,7 @@
invocation_type ="none"
..()
/obj/effect/proc_holder/spell/mime/fingergun
/datum/spell/mime/fingergun
name = "Finger Gun"
desc = "Shoot lethal, silencing bullets out of your fingers! 3 bullets available per cast. Use your fingers to holster them manually."
school = "mime"
@@ -101,7 +101,7 @@
var/gun = /obj/item/gun/projectile/revolver/fingergun
var/obj/item/gun/projectile/revolver/fingergun/current_gun
/obj/effect/proc_holder/spell/mime/fingergun/cast(list/targets, mob/user = usr)
/datum/spell/mime/fingergun/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/human/C in targets)
if(!current_gun)
to_chat(user, "<span class='notice'>You draw your fingers!</span>")
@@ -114,33 +114,33 @@
revert_cast(user)
/obj/effect/proc_holder/spell/mime/fingergun/Destroy()
/datum/spell/mime/fingergun/Destroy()
current_gun = null
return ..()
/obj/effect/proc_holder/spell/mime/fingergun/proc/holster_hand(atom/target, any=FALSE)
/datum/spell/mime/fingergun/proc/holster_hand(atom/target, any=FALSE)
SIGNAL_HANDLER
if(!current_gun || !any && action.owner.get_active_hand() != current_gun)
return
to_chat(action.owner, "<span class='notice'>You holster your fingers. Another time perhaps...</span>")
QDEL_NULL(current_gun)
/obj/effect/proc_holder/spell/mime/fingergun/fake
/datum/spell/mime/fingergun/fake
desc = "Pretend you're shooting bullets out of your fingers! 3 bullets available per cast. Use your fingers to holster them manually."
gun = /obj/item/gun/projectile/revolver/fingergun/fake
// Mime Spellbooks
/obj/item/spellbook/oneuse/mime
spell = /obj/effect/proc_holder/spell/aoe/conjure/build/mime_wall
spell = /datum/spell/aoe/conjure/build/mime_wall
spellname = "Invisible Wall"
name = "Miming Manual : "
desc = "It contains various pictures of mimes mid-performance, aswell as some illustrated tutorials."
icon_state = "bookmime"
/obj/item/spellbook/oneuse/mime/attack_self(mob/user)
var/obj/effect/proc_holder/spell/S = new spell
for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
var/datum/spell/S = new spell
for(var/datum/spell/knownspell in user.mind.spell_list)
if(knownspell.type == S.type)
if(user.mind)
to_chat(user, "<span class='notice'>You've already read this one.</span>")
@@ -159,19 +159,19 @@
/obj/item/spellbook/oneuse/mime/onlearned(mob/user)
used = TRUE
if(!locate(/obj/effect/proc_holder/spell/mime/speak) in user.mind.spell_list) //add vow of silence if not known by user
user.mind.AddSpell(new /obj/effect/proc_holder/spell/mime/speak)
if(!locate(/datum/spell/mime/speak) in user.mind.spell_list) //add vow of silence if not known by user
user.mind.AddSpell(new /datum/spell/mime/speak)
to_chat(user, "<span class='notice'>You have learned how to use silence to improve your performance.</span>")
/obj/item/spellbook/oneuse/mime/fingergun
spell = /obj/effect/proc_holder/spell/mime/fingergun
spell = /datum/spell/mime/fingergun
spellname = "Finger Gun"
desc = "It contains illustrations of guns and how to mime them."
/obj/item/spellbook/oneuse/mime/fingergun/fake
spell = /obj/effect/proc_holder/spell/mime/fingergun/fake
spell = /datum/spell/mime/fingergun/fake
/obj/item/spellbook/oneuse/mime/greaterwall
spell = /obj/effect/proc_holder/spell/forcewall/mime
spell = /datum/spell/forcewall/mime
spellname = "Invisible Greater Wall"
desc = "It contains illustrations of the great walls of human history."
+1 -1
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/touch/mime_malaise
/datum/spell/touch/mime_malaise
name = "Mime Malaise"
desc = "A spell popular with theater nerd wizards and contrarian pranksters, this spell will put on a mime costume on the target, \
stun them so that they may contemplate Art, and silence them. \
+21 -21
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/mimic
/datum/spell/mimic
name = "Mimic"
desc = "Learn a new form to mimic or become one of your known forms"
clothes_req = FALSE
@@ -32,7 +32,7 @@
)
/obj/effect/proc_holder/spell/mimic/create_new_targeting()
/datum/spell/mimic/create_new_targeting()
var/datum/spell_targeting/click/T = new
T.include_user = TRUE // To change forms
T.allowed_type = /atom/movable
@@ -40,7 +40,7 @@
T.click_radius = -1
return T
/obj/effect/proc_holder/spell/mimic/valid_target(atom/target, user)
/datum/spell/mimic/valid_target(atom/target, user)
if(is_type_in_list(target, black_listed_form_types))
return FALSE
if(istype(target, /atom/movable))
@@ -51,7 +51,7 @@
return FALSE
return ..()
/obj/effect/proc_holder/spell/mimic/cast(list/targets, mob/user)
/datum/spell/mimic/cast(list/targets, mob/user)
var/atom/movable/A = targets[1]
if(A == user)
INVOKE_ASYNC(src, PROC_REF(pick_form), user)
@@ -59,7 +59,7 @@
INVOKE_ASYNC(src, PROC_REF(remember_form), A, user)
/obj/effect/proc_holder/spell/mimic/proc/remember_form(atom/movable/A, mob/user)
/datum/spell/mimic/proc/remember_form(atom/movable/A, mob/user)
if(A.name in available_forms)
to_chat(user, "<span class='warning'>[A] is already an available form.</span>")
revert_cast(user)
@@ -83,7 +83,7 @@
available_forms[A.name] = new /datum/mimic_form(A, user)
to_chat(user, "<span class='sinister'>You learn the form of [A].</span>")
/obj/effect/proc_holder/spell/mimic/proc/pick_form(mob/user)
/datum/spell/mimic/proc/pick_form(mob/user)
if(!length(available_forms) && !selected_form)
to_chat(user, "<span class='warning'>No available forms. Learn more forms by using this spell on other objects first.</span>")
revert_cast(user)
@@ -109,7 +109,7 @@
return
take_form(available_forms[what], user)
/obj/effect/proc_holder/spell/mimic/proc/take_form(datum/mimic_form/form, mob/user)
/datum/spell/mimic/proc/take_form(datum/mimic_form/form, mob/user)
var/old_name = "[user]"
if(ishuman(user))
// Not fully finished yet
@@ -132,10 +132,10 @@
selected_form = form
/obj/effect/proc_holder/spell/mimic/proc/show_change_form_message(mob/user, old_name, new_name)
/datum/spell/mimic/proc/show_change_form_message(mob/user, old_name, new_name)
user.visible_message("<span class='warning'>[old_name] contorts and slowly becomes [new_name]!</span>", "<span class='sinister'>You take form of [new_name].</span>", "You hear loud cracking noises!")
/obj/effect/proc_holder/spell/mimic/proc/restore_form(mob/user, show_message = TRUE)
/datum/spell/mimic/proc/restore_form(mob/user, show_message = TRUE)
selected_form = null
var/old_name = "[user]"
@@ -157,21 +157,21 @@
UnregisterSignal(user, list(COMSIG_PARENT_EXAMINE, COMSIG_MOB_DEATH))
/obj/effect/proc_holder/spell/mimic/proc/show_restore_form_message(mob/user, old_name, new_name)
/datum/spell/mimic/proc/show_restore_form_message(mob/user, old_name, new_name)
user.visible_message("<span class='warning'>[old_name] shakes and contorts and quickly becomes [new_name]!</span>", "<span class='sinister'>You take return to your normal self.</span>", "You hear loud cracking noises!")
/obj/effect/proc_holder/spell/mimic/proc/examine_override(datum/source, mob/user, list/examine_list)
/datum/spell/mimic/proc/examine_override(datum/source, mob/user, list/examine_list)
examine_list.Cut()
examine_list += selected_form.examine_text
if(!perfect_disguise && get_dist(user, source) <= 3)
examine_list += "<span class='warning'>It doesn't look quite right...</span>"
/obj/effect/proc_holder/spell/mimic/proc/on_death(mob/user, gibbed)
/datum/spell/mimic/proc/on_death(mob/user, gibbed)
if(!gibbed)
restore_form(user, FALSE)
show_death_message(user)
/obj/effect/proc_holder/spell/mimic/proc/show_death_message(mob/user)
/datum/spell/mimic/proc/show_death_message(mob/user)
user.visible_message("<span class='warning'>[user] shakes and contorts as [user.p_they()] die[user.p_s()], returning to [user.p_their()] true form!</span>", "<span class='deadsay'>Your disguise fails as your life forces drain away.</span>", "You hear loud cracking noises followed by a thud!")
@@ -188,34 +188,34 @@
examine_text = form.examine(user)
name = form.name
/obj/effect/proc_holder/spell/mimic/morph
/datum/spell/mimic/morph
action_background_icon_state = "bg_morph"
/obj/effect/proc_holder/spell/mimic/morph/create_new_handler()
/datum/spell/mimic/morph/create_new_handler()
var/datum/spell_handler/morph/H = new
return H
/obj/effect/proc_holder/spell/mimic/morph/valid_target(atom/target, user)
/datum/spell/mimic/morph/valid_target(atom/target, user)
if(target != user && ismorph(target))
return FALSE
return ..()
/obj/effect/proc_holder/spell/mimic/morph/take_form(datum/mimic_form/form, mob/living/simple_animal/hostile/morph/user)
/datum/spell/mimic/morph/take_form(datum/mimic_form/form, mob/living/simple_animal/hostile/morph/user)
..()
user.assume()
/obj/effect/proc_holder/spell/mimic/morph/restore_form(mob/living/simple_animal/hostile/morph/user, show_message = TRUE)
/datum/spell/mimic/morph/restore_form(mob/living/simple_animal/hostile/morph/user, show_message = TRUE)
..()
user.restore()
/obj/effect/proc_holder/spell/mimic/morph/show_change_form_message(mob/user, old_name, new_name)
/datum/spell/mimic/morph/show_change_form_message(mob/user, old_name, new_name)
user.visible_message("<span class='warning'>[old_name] suddenly twists and changes shape, becoming a copy of [new_name]!</span>", \
"<span class='notice'>You twist your body and assume the form of [new_name].</span>")
/obj/effect/proc_holder/spell/mimic/morph/show_restore_form_message(mob/user, old_name, new_name)
/datum/spell/mimic/morph/show_restore_form_message(mob/user, old_name, new_name)
user.visible_message("<span class='warning'>[old_name] suddenly collapses in on itself, dissolving into a pile of green flesh!</span>", \
"<span class='notice'>You reform to your normal body.</span>")
/obj/effect/proc_holder/spell/mimic/morph/show_death_message(mob/user)
/datum/spell/mimic/morph/show_death_message(mob/user)
user.visible_message("<span class='warning'>[user] twists and dissolves into a pile of green flesh!</span>", \
"<span class='userdanger'>Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--</span>")
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/mind_transfer
/datum/spell/mind_transfer
name = "Mind Transfer"
desc = "This spell allows the user to switch bodies with a target."
@@ -15,14 +15,14 @@
var/paralysis_amount_victim = 40 SECONDS //how much the victim is paralysed for after the spell
action_icon_state = "mindswap"
/obj/effect/proc_holder/spell/mind_transfer/create_new_targeting()
/datum/spell/mind_transfer/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.allowed_type = /mob/living
T.range = 1
T.click_radius = 0
return T
/obj/effect/proc_holder/spell/mind_transfer/valid_target(mob/living/target, mob/user)
/datum/spell/mind_transfer/valid_target(mob/living/target, mob/user)
return target.stat != DEAD && target.key && target.mind
/*
@@ -30,7 +30,7 @@ Urist: I don't feel like figuring out how you store object spells so I'm leaving
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/mind_transfer/cast(list/targets, mob/user = usr)
/datum/spell/mind_transfer/cast(list/targets, mob/user = usr)
var/mob/living/target = targets[1]
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/night_vision
/datum/spell/night_vision
name = "Toggle Nightvision"
desc = "Toggle your nightvision mode."
@@ -7,10 +7,10 @@
message = "<span class='notice'>You toggle your night vision!</span>"
/obj/effect/proc_holder/spell/night_vision/create_new_targeting()
/datum/spell/night_vision/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/night_vision/cast(list/targets, mob/user = usr)
/datum/spell/night_vision/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
switch(target.lighting_alpha)
if(LIGHTING_PLANE_ALPHA_VISIBLE)
+14 -26
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/projectile
/datum/spell/projectile
desc = "This spell summons projectiles which try to hit the targets."
var/proj_icon = 'icons/obj/projectiles.dmi'
@@ -10,7 +10,8 @@
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
/// The projectile we spawn. Make sure to override this
var/proj_type
var/proj_lingering = 0 //if it lingers or disappears upon hitting an obstacle
var/proj_homing = 1 //if it follows the target
@@ -20,64 +21,51 @@
var/proj_lifespan = 15 //in deciseconds * proj_step_delay
var/proj_step_delay = 1 //lower = faster
/obj/effect/proc_holder/spell/projectile/cast(list/targets, mob/user = usr)
/datum/spell/projectile/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
spawn(0)
var/obj/effect/proc_holder/spell/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/trigger(user)
projectile:linked_spells += proj_type
var/obj/item/projectile/projectile = new proj_type(get_turf(user))
projectile.icon = proj_icon
projectile.icon_state = proj_icon_state
projectile.dir = get_dir(target,projectile)
projectile.dir = get_dir(target, projectile)
projectile.name = proj_name
var/current_loc = get_turf(projectile)
var/current_loc = user.loc
projectile.loc = current_loc
for(var/i = 0,i < proj_lifespan,i++)
for(var/i in 1 to proj_lifespan)
if(!projectile)
break
if(proj_homing)
if(proj_insubstantial)
projectile.dir = get_dir(projectile,target)
projectile.loc = get_step_to(projectile,target)
projectile.forceMove(get_step_to(projectile, target))
else
step_to(projectile,target)
else
if(proj_insubstantial)
projectile.loc = get_step(projectile,dir)
projectile.forceMove(get_step(projectile, projectile.dir))
else
step(projectile,dir)
step(projectile, projectile.dir)
if(!projectile) // step and step_to sleeps so we'll have to check again.
break
if(!proj_lingering && projectile.loc == current_loc) //if it didn't move since last time
if(!proj_lingering && (get_turf(projectile) == current_loc)) //if it didn't move since last time
qdel(projectile)
break
if(proj_trail && projectile)
spawn(0)
if(projectile)
var/obj/effect/overlay/trail = new /obj/effect/overlay(projectile.loc)
var/obj/effect/overlay/trail = new /obj/effect/overlay(get_turf(projectile))
trail.icon = proj_trail_icon
trail.icon_state = proj_trail_icon_state
trail.density = FALSE
spawn(proj_trail_lifespan)
qdel(trail)
if(projectile.loc in range(target.loc,proj_trigger_range))
projectile.perform(list(target), user = user)
break
current_loc = projectile.loc
current_loc = get_turf(projectile)
sleep(proj_step_delay)
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/rathens
/datum/spell/rathens
name = "Rathen's Secret"
desc = "Summons a powerful shockwave around you that tears the appendix out of enemies, and occasionally removes their limbs."
base_cooldown = 50 SECONDS
@@ -8,12 +8,12 @@
cooldown_min = 20 SECONDS
action_icon_state = "lungpunch"
/obj/effect/proc_holder/spell/rathens/create_new_targeting()
/datum/spell/rathens/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.max_targets = INFINITY
return T
/obj/effect/proc_holder/spell/rathens/cast(list/targets, mob/user = usr)
/datum/spell/rathens/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/human/H in targets)
var/datum/effect_system/smoke_spread/s = new
s.set_up(5, FALSE, H)
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/rod_form
/datum/spell/rod_form
name = "Rod Form"
desc = "Take on the form of an immovable rod, destroying all in your path."
clothes_req = TRUE
@@ -13,10 +13,10 @@
sound = 'sound/effects/whoosh.ogg'
var/rod_delay = 2
/obj/effect/proc_holder/spell/rod_form/create_new_targeting()
/datum/spell/rod_form/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/rod_form/cast(list/targets,mob/user = usr)
/datum/spell/rod_form/cast(list/targets,mob/user = usr)
if(get_turf(user) != user.loc)
to_chat(user, "<span class='warning'>You cannot summon a rod in the ether, the spell fizzles out!</span>")
revert_cast()
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/sentient_sword_lunge
/datum/spell/sentient_sword_lunge
name = "Lunge"
desc = "Lunge at something in your view range."
clothes_req = FALSE
@@ -8,10 +8,10 @@
sound = 'sound/magic/repulse.ogg'
action_icon_state = "lunge"
/obj/effect/proc_holder/spell/sentient_sword_lunge/create_new_targeting()
/datum/spell/sentient_sword_lunge/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/sentient_sword_lunge/cast(list/targets, mob/user = usr)
/datum/spell/sentient_sword_lunge/cast(list/targets, mob/user = usr)
if(!istype(user.loc, /obj/item))
to_chat(user, "<span class='warning'>You cannot use this ability if you're outside a blade!</span>")
return
+10 -10
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/shapeshift
/datum/spell/shapeshift
name = "Shapechange"
desc = "Take on the shape of another for a time to use their natural abilities. Once you've made your choice it cannot be changed."
clothes_req = FALSE
@@ -17,10 +17,10 @@
/mob/living/simple_animal/bot/ed209,
/mob/living/simple_animal/hostile/construct/armoured)
/obj/effect/proc_holder/spell/shapeshift/create_new_targeting()
/datum/spell/shapeshift/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/shapeshift/cast(list/targets, mob/user = usr)
/datum/spell/shapeshift/cast(list/targets, mob/user = usr)
for(var/mob/living/M in targets)
if(!shapeshift_type)
var/list/animal_list = list()
@@ -36,7 +36,7 @@
else
Shapeshift(M)
/obj/effect/proc_holder/spell/shapeshift/proc/Shapeshift(mob/living/caster)
/datum/spell/shapeshift/proc/Shapeshift(mob/living/caster)
for(var/mob/living/M in caster)
if(M.status_flags & GODMODE)
to_chat(caster, "<span class='warning'>You're already shapeshifted!</span>")
@@ -53,7 +53,7 @@
caster.mind.transfer_to(shape)
/obj/effect/proc_holder/spell/shapeshift/proc/Restore(mob/living/shape)
/datum/spell/shapeshift/proc/Restore(mob/living/shape)
var/mob/living/caster
for(var/mob/living/M in shape)
if(M in current_casters)
@@ -72,7 +72,7 @@
shape.mind.transfer_to(caster)
qdel(shape) //Gib it maybe ?
/obj/effect/proc_holder/spell/shapeshift/dragon
/datum/spell/shapeshift/dragon
name = "Dragon Form"
desc = "Take on the shape a lesser ash drake after a short delay."
invocation = "*scream"
@@ -82,7 +82,7 @@
current_casters = list()
possible_shapes = list(/mob/living/simple_animal/hostile/megafauna/dragon/lesser)
/obj/effect/proc_holder/spell/shapeshift/dragon/Shapeshift(mob/living/caster)
/datum/spell/shapeshift/dragon/Shapeshift(mob/living/caster)
caster.visible_message("<span class='danger'>[caster] screams in agony as bones and claws erupt out of their flesh!</span>",
"<span class='danger'>You begin channeling the transformation.</span>")
if(!do_after(caster, 5 SECONDS, FALSE, caster))
@@ -90,7 +90,7 @@
return
return ..()
/obj/effect/proc_holder/spell/shapeshift/bats
/datum/spell/shapeshift/bats
name = "Bat Form"
desc = "Take on the shape of a swarm of bats."
invocation = "none"
@@ -103,7 +103,7 @@
current_casters = list()
possible_shapes = list(/mob/living/simple_animal/hostile/scarybat/adminvampire)
/obj/effect/proc_holder/spell/shapeshift/hellhound
/datum/spell/shapeshift/hellhound
name = "Lesser Hellhound Form"
desc = "Take on the shape of a Hellhound."
invocation = "none"
@@ -117,7 +117,7 @@
current_casters = list()
possible_shapes = list(/mob/living/simple_animal/hostile/hellhound)
/obj/effect/proc_holder/spell/shapeshift/hellhound/greater
/datum/spell/shapeshift/hellhound/greater
name = "Greater Hellhound Form"
shapeshift_type = /mob/living/simple_animal/hostile/hellhound/greater
current_shapes = list(/mob/living/simple_animal/hostile/hellhound/greater)
+8 -8
View File
@@ -1,5 +1,5 @@
// This could probably be an aoe spell but it's a little cursed, so I'm not touching it
/obj/effect/proc_holder/spell/spacetime_dist
/datum/spell/spacetime_dist
name = "Spacetime Distortion"
desc = "Entangle the strings of space-time in an area around you, \
randomizing the layout and making proper movement impossible. The strings vibrate... \
@@ -25,23 +25,23 @@
/// A lazylist of all scramble effects this spell has created.
var/list/effects
/obj/effect/proc_holder/spell/spacetime_dist/Destroy()
/datum/spell/spacetime_dist/Destroy()
QDEL_LIST_CONTENTS(effects)
return ..()
/obj/effect/proc_holder/spell/spacetime_dist/create_new_targeting()
/datum/spell/spacetime_dist/create_new_targeting()
var/datum/spell_targeting/spiral/targeting = new()
targeting.range = scramble_radius + 3 * spell_level
return targeting
/obj/effect/proc_holder/spell/spacetime_dist/on_purchase_upgrade()
/datum/spell/spacetime_dist/on_purchase_upgrade()
. = ..()
targeting = create_new_targeting()
/obj/effect/proc_holder/spell/spacetime_dist/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/user = usr)
/datum/spell/spacetime_dist/cast_check(charge_check = TRUE, start_recharge = TRUE, mob/user = usr)
return ..() && ready
/obj/effect/proc_holder/spell/spacetime_dist/cast(list/targets, mob/user = usr)
/datum/spell/spacetime_dist/cast(list/targets, mob/user = usr)
. = ..()
var/list/turf/to_switcharoo = targets
if(!length(to_switcharoo))
@@ -64,12 +64,12 @@
effects += effect_b
/obj/effect/proc_holder/spell/spacetime_dist/after_cast(list/targets, mob/user)
/datum/spell/spacetime_dist/after_cast(list/targets, mob/user)
. = ..()
addtimer(CALLBACK(src, PROC_REF(clean_turfs)), duration)
/// Callback which cleans up our effects list after the duration expires.
/obj/effect/proc_holder/spell/spacetime_dist/proc/clean_turfs()
/datum/spell/spacetime_dist/proc/clean_turfs()
QDEL_LIST_CONTENTS(effects)
ready = TRUE
+2 -2
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/aoe/conjure/summon_supermatter
/datum/spell/aoe/conjure/summon_supermatter
name = "Summon Supermatter Crystal"
desc = "Summons an active supermatter crystal. Imbues you with some supermatter, giving you resistance to it's hallucinations and radiation immunity."
base_cooldown = 5 MINUTES
@@ -8,7 +8,7 @@
summon_amt = 1
aoe_range = 0
/obj/effect/proc_holder/spell/aoe/conjure/summon_supermatter/cast(list/targets, mob/living/user = usr)
/datum/spell/aoe/conjure/summon_supermatter/cast(list/targets, mob/living/user = usr)
var/list/summoned_objects = ..()
for(var/obj/machinery/atmospherics/supermatter_crystal/our_crystal in summoned_objects)
addtimer(CALLBACK(our_crystal, TYPE_PROC_REF(/obj/machinery/atmospherics/supermatter_crystal, manual_start), 3000), 3 SECONDS)
+3 -3
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/summonitem
/datum/spell/summonitem
name = "Instant Summons"
desc = "This spell can be used to recall a previously marked item to your hand from anywhere in the universe."
school = "transmutation"
@@ -14,10 +14,10 @@
var/static/list/blacklisted_summons = list(/obj/machinery/computer/cryopod = TRUE, /obj/machinery/atmospherics = TRUE, /obj/structure/disposalholder = TRUE, /obj/machinery/disposal = TRUE)
action_icon_state = "summons"
/obj/effect/proc_holder/spell/summonitem/create_new_targeting()
/datum/spell/summonitem/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/summonitem/cast(list/targets, mob/user = usr)
/datum/spell/summonitem/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
var/list/hand_items = list(target.get_active_hand(),target.get_inactive_hand())
var/butterfingers = FALSE
+7 -7
View File
@@ -1,19 +1,19 @@
/obj/effect/proc_holder/spell/touch
/datum/spell/touch
var/hand_path = /obj/item/melee/touch_attack
var/obj/item/melee/touch_attack/attached_hand = null
var/on_remove_message = TRUE
invocation_type = "none" //you scream on connecting, not summoning
/obj/effect/proc_holder/spell/touch/create_new_targeting()
/datum/spell/touch/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/touch/Click(mob/user = usr)
/datum/spell/touch/Click(mob/user = usr)
if(attached_hand)
discharge_hand(user, TRUE)
return FALSE
charge_hand(user)
/obj/effect/proc_holder/spell/touch/proc/charge_hand(mob/living/carbon/user)
/datum/spell/touch/proc/charge_hand(mob/living/carbon/user)
var/hand_handled = 1
attached_hand = new hand_path(src)
RegisterSignal(user, COMSIG_MOB_WILLINGLY_DROP, PROC_REF(discharge_hand))
@@ -36,7 +36,7 @@
to_chat(user, "<span class='notice'>You channel the power of the spell to your hand.</span>")
return 1
/obj/effect/proc_holder/spell/touch/proc/discharge_hand(atom/target, any = FALSE)
/datum/spell/touch/proc/discharge_hand(atom/target, any = FALSE)
SIGNAL_HANDLER
var/mob/living/carbon/user = action.owner
if(!istype(attached_hand))
@@ -48,7 +48,7 @@
to_chat(user, "<span class='notice'>You draw the power out of your hand.</span>")
/obj/effect/proc_holder/spell/touch/disintegrate
/datum/spell/touch/disintegrate
name = "Disintegrate"
desc = "This spell charges your hand with vile energy that can be used to violently explode victims."
hand_path = /obj/item/melee/touch_attack/disintegrate
@@ -60,7 +60,7 @@
action_icon_state = "gib"
/obj/effect/proc_holder/spell/touch/flesh_to_stone
/datum/spell/touch/flesh_to_stone
name = "Flesh to Stone"
desc = "This spell charges your hand with the power to turn victims into inert statues for a long period of time."
hand_path = /obj/item/melee/touch_attack/fleshtostone
-28
View File
@@ -1,28 +0,0 @@
/obj/effect/proc_holder/spell/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/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/trigger/Destroy()
for(var/spell in contents)
qdel(spell)
linked_spells = null
starting_spells = null
return ..()
/obj/effect/proc_holder/spell/trigger/cast(list/targets, mob/user = usr)
for(var/mob/living/target in targets)
for(var/obj/effect/proc_holder/spell/spell in contents)
spell.perform(list(target), 0, user = user)
for(var/obj/effect/proc_holder/spell/spell in linked_spells)
spell.perform(list(target), 0, user = user)
return
+4 -4
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/turf_teleport
/datum/spell/turf_teleport
name = "Turf Teleport"
desc = "This spell teleports the target to the turf in range."
nonabstract_req = TRUE
@@ -14,12 +14,12 @@
var/sound1 = 'sound/weapons/zapbang.ogg'
var/sound2 = 'sound/weapons/zapbang.ogg'
/obj/effect/proc_holder/spell/turf_teleport/create_new_targeting()
/datum/spell/turf_teleport/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/turf_teleport/cast(list/targets,mob/living/user = usr)
/datum/spell/turf_teleport/cast(list/targets,mob/living/user = usr)
if(sound1)
playsound(get_turf(user), sound1, 50,1)
playsound(get_turf(user), sound1, 50, TRUE)
for(var/mob/living/target in targets)
var/list/turfs = new/list()
+64 -73
View File
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/projectile/magic_missile
/datum/spell/projectile/magic_missile
name = "Magic Missile"
desc = "This spell fires several, slow moving, magic projectiles at nearby targets."
@@ -12,7 +12,7 @@
proj_icon_state = "magicm"
proj_name = "a magic missile"
proj_lingering = 1
proj_type = "/obj/effect/proc_holder/spell/inflict_handler/magic_missile"
proj_type = /obj/item/projectile/magic/magic_missile
proj_lifespan = 20
proj_step_delay = 2
@@ -25,33 +25,33 @@
sound = 'sound/magic/magic_missile.ogg'
/obj/effect/proc_holder/spell/projectile/magic_missile/create_new_targeting()
/datum/spell/projectile/magic_missile/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living
T.max_targets = INFINITY
return T
/obj/effect/proc_holder/spell/inflict_handler/magic_missile
amt_weakened = 6 SECONDS
sound = 'sound/magic/mm_hit.ogg'
/obj/item/projectile/magic/magic_missile
name = "Magic Missile"
hitsound = 'sound/magic/mm_hit.ogg'
weaken = 6 SECONDS
/obj/effect/proc_holder/spell/projectile/honk_missile
/datum/spell/projectile/honk_missile
name = "Honk Missile"
desc = "This spell fires several, slow moving, magic bikehorns at nearby targets."
school = "evocation"
base_cooldown = 60
base_cooldown = 6 SECONDS
clothes_req = FALSE
invocation = "HONK GY AMA"
invocation_type = "shout"
cooldown_min = 60 //35 deciseconds reduction per rank
cooldown_min = 6 SECONDS
proj_icon = 'icons/obj/items.dmi'
proj_icon_state = "bike_horn"
proj_name = "A bike horn"
proj_lingering = 1
proj_type = "/obj/effect/proc_holder/spell/inflict_handler/honk_missile"
proj_type = /obj/item/projectile/magic/magic_missile/honk_missile
proj_lifespan = 20
proj_step_delay = 5
@@ -65,25 +65,25 @@
sound = 'sound/items/bikehorn.ogg'
/obj/effect/proc_holder/spell/projectile/honk_missile/create_new_targeting()
/datum/spell/projectile/honk_missile/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living
T.max_targets = INFINITY
return T
/obj/effect/proc_holder/spell/inflict_handler/honk_missile
amt_weakened = 6 SECONDS
sound = 'sound/items/bikehorn.ogg'
/obj/item/projectile/magic/magic_missile/honk_missile
name = "Funny Missile"
hitsound = 'sound/items/bikehorn.ogg'
/obj/effect/proc_holder/spell/noclothes
/datum/spell/noclothes
name = "No Clothes"
desc = "This always-on spell allows you to cast magic without your garments."
action_icon_state = "no_clothes"
/obj/effect/proc_holder/spell/noclothes/create_new_targeting()
/datum/spell/noclothes/create_new_targeting()
return new /datum/spell_targeting/self // Dummy value
/obj/effect/proc_holder/spell/genetic/mutate
/datum/spell/genetic/mutate
name = "Mutate"
desc = "This spell causes you to turn into a hulk and gain laser vision for a short while."
@@ -102,14 +102,14 @@
action_icon_state = "mutate"
sound = 'sound/magic/mutate.ogg'
/obj/effect/proc_holder/spell/genetic/mutate/Initialize(mapload)
. = ..()
/datum/spell/genetic/mutate/New()
..()
mutations = list(GLOB.hulkblock)
/obj/effect/proc_holder/spell/genetic/mutate/create_new_targeting()
/datum/spell/genetic/mutate/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/smoke
/datum/spell/smoke
name = "Smoke"
desc = "This spell spawns a cloud of choking smoke at your location and does not require wizard garb."
@@ -125,13 +125,13 @@
action_icon_state = "smoke"
/obj/effect/proc_holder/spell/smoke/create_new_targeting()
/datum/spell/smoke/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/emplosion/disable_tech
/datum/spell/emplosion/disable_tech
name = "Disable Tech"
desc = "This spell disables all weapons, cameras and most other technology in range."
base_cooldown = 400
base_cooldown = 40 SECONDS
clothes_req = TRUE
invocation = "NEC CANTIO"
invocation_type = "shout"
@@ -142,7 +142,7 @@
sound = 'sound/magic/disable_tech.ogg'
/obj/effect/proc_holder/spell/turf_teleport/blink
/datum/spell/turf_teleport/blink
name = "Blink"
desc = "This spell randomly teleports you a short distance."
@@ -167,10 +167,10 @@
sound1 = 'sound/magic/blink.ogg'
sound2 = 'sound/magic/blink.ogg'
/obj/effect/proc_holder/spell/turf_teleport/blink/create_new_targeting()
/datum/spell/turf_teleport/blink/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/area_teleport/teleport
/datum/spell/area_teleport/teleport
name = "Teleport"
desc = "This spell teleports you to a type of area of your selection."
@@ -187,10 +187,10 @@
sound1 = 'sound/magic/teleport_diss.ogg'
sound2 = 'sound/magic/teleport_app.ogg'
/obj/effect/proc_holder/spell/area_teleport/teleport/create_new_targeting()
/datum/spell/area_teleport/teleport/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/return_to_teacher
/datum/spell/return_to_teacher
name = "Return to Teacher"
desc = "This spell teleports you back to your teacher."
@@ -204,16 +204,16 @@
action_icon_state = "spell_teleport"
var/datum/mind/teacher
/obj/effect/proc_holder/spell/return_to_teacher/create_new_targeting()
/datum/spell/return_to_teacher/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/return_to_teacher/cast(list/targets, mob/living/user = usr)
/datum/spell/return_to_teacher/cast(list/targets, mob/living/user = usr)
if(!(teacher && teacher.current))
to_chat(user, "<span class='danger'>The link to your teacher is broken!</span>")
return
do_teleport(user, teacher.current, 1, sound_in = 'sound/magic/blink.ogg', sound_out = 'sound/magic/blink.ogg', safe_turf_pick = TRUE)
/obj/effect/proc_holder/spell/forcewall
/datum/spell/forcewall
name = "Force Wall"
desc = "This spell creates a 3 tile wide unbreakable wall that only you can pass through, and does not need wizard garb. Lasts 30 seconds."
@@ -227,10 +227,10 @@
cooldown_min = 5 SECONDS //25 deciseconds reduction per rank
var/wall_type = /obj/effect/forcefield/wizard
/obj/effect/proc_holder/spell/forcewall/create_new_targeting()
/datum/spell/forcewall/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/forcewall/cast(list/targets, mob/user = usr)
/datum/spell/forcewall/cast(list/targets, mob/user = usr)
new wall_type(get_turf(user), user)
if(user.dir == SOUTH || user.dir == NORTH)
new wall_type(get_step(user, EAST), user)
@@ -239,10 +239,10 @@
new wall_type(get_step(user, NORTH), user)
new wall_type(get_step(user, SOUTH), user)
/obj/effect/proc_holder/spell/aoe/conjure/timestop
/datum/spell/aoe/conjure/timestop
name = "Stop Time"
desc = "This spell stops time for everyone except for you, allowing you to move freely while your enemies and even projectiles are frozen."
base_cooldown = 500
base_cooldown = 50 SECONDS
clothes_req = TRUE
invocation = "TOKI WO TOMARE"
invocation_type = "shout"
@@ -255,7 +255,7 @@
aoe_range = 0
/obj/effect/proc_holder/spell/aoe/conjure/carp
/datum/spell/aoe/conjure/carp
name = "Summon Carp"
desc = "This spell conjures a simple carp."
@@ -270,7 +270,7 @@
cast_sound = 'sound/magic/summon_karp.ogg'
aoe_range = 1
/obj/effect/proc_holder/spell/aoe/conjure/construct
/datum/spell/aoe/conjure/construct
name = "Artificer"
desc = "This spell conjures a construct which may be controlled by Shades"
@@ -286,7 +286,7 @@
cast_sound = 'sound/magic/summonitems_generic.ogg'
aoe_range = 0
/obj/effect/proc_holder/spell/aoe/conjure/creature
/datum/spell/aoe/conjure/creature
name = "Summon Creature Swarm"
desc = "This spell tears the fabric of reality, allowing horrific daemons to spill forth"
@@ -301,10 +301,9 @@
cast_sound = 'sound/magic/summonitems_generic.ogg'
aoe_range = 3
/obj/effect/proc_holder/spell/trigger/blind
/datum/spell/genetic/blind
name = "Blind"
desc = "This spell temporarily blinds a single person and does not require wizard garb."
school = "transmutation"
base_cooldown = 10 SECONDS
clothes_req = FALSE
@@ -312,30 +311,22 @@
invocation_type = "whisper"
message = "<span class='notice'>Your eyes cry out in pain!</span>"
cooldown_min = 2 SECONDS
traits = list(TRAIT_BLIND)
starting_spells = list("/obj/effect/proc_holder/spell/inflict_handler/blind","/obj/effect/proc_holder/spell/genetic/blind")
duration = 30 SECONDS
sound = 'sound/magic/blind.ogg'
action_icon_state = "blind"
/obj/effect/proc_holder/spell/trigger/blind/create_new_targeting()
/datum/spell/genetic/blind/create_new_targeting()
var/datum/spell_targeting/click/C = new()
C.allowed_type = /mob/living
return C
/obj/effect/proc_holder/spell/inflict_handler/blind
amt_eye_blind = 10
amt_eye_blurry = 20
sound = 'sound/magic/blind.ogg'
/datum/spell/genetic/blind/do_additional_effects(mob/living/target)
target.EyeBlurry(20 SECONDS)
target.EyeBlind(10 SECONDS)
SEND_SOUND(target, sound('sound/magic/blind.ogg'))
/obj/effect/proc_holder/spell/genetic/blind
traits = list(TRAIT_BLIND)
duration = 300
sound = 'sound/magic/blind.ogg'
/obj/effect/proc_holder/spell/genetic/blind/create_new_targeting()
return new /datum/spell_targeting/self // Dummy value since it is never used by an user directly
/obj/effect/proc_holder/spell/fireball
/datum/spell/fireball
name = "Fireball"
desc = "This spell fires a fireball at a target and does not require wizard garb."
@@ -355,21 +346,21 @@
active = FALSE
/obj/effect/proc_holder/spell/fireball/apprentice
/datum/spell/fireball/apprentice
centcom_cancast = FALSE
/obj/effect/proc_holder/spell/fireball/create_new_targeting()
/datum/spell/fireball/create_new_targeting()
var/datum/spell_targeting/clicked_atom/external/C = new()
C.range = 20
return C
/obj/effect/proc_holder/spell/fireball/update_icon_state()
/datum/spell/fireball/update_spell_icon()
if(!action)
return
action.button_icon_state = "fireball[active]"
action.UpdateButtons()
/obj/effect/proc_holder/spell/fireball/cast(list/targets, mob/living/user = usr)
/datum/spell/fireball/cast(list/targets, mob/living/user = usr)
var/target = targets[1] //There is only ever one target for fireball
var/turf/T = user.loc
var/turf/U = get_step(user, user.dir) // Get the tile infront of the move, based on their direction
@@ -386,7 +377,7 @@
return TRUE
/obj/effect/proc_holder/spell/fireball/toolbox
/datum/spell/fireball/toolbox
name = "Homing Toolbox"
desc = "This spell summons and throws a magical homing toolbox at your opponent."
sound = 'sound/weapons/smash.ogg'
@@ -396,7 +387,7 @@
selection_activated_message = "<span class='notice'>You prepare to cast your homing toolbox! <B>Left-click to cast at a target!</B></span>"
selection_deactivated_message = "<span class='notice'>You unrobust your toolbox...for now.</span>"
/obj/effect/proc_holder/spell/fireball/homing
/datum/spell/fireball/homing
name = "Greater Homing Fireball"
desc = "This spell fires a strong homing fireball at a target."
invocation = "ZI-ONI SOMA"
@@ -405,10 +396,10 @@
selection_activated_message = "<span class='notice'>You prepare to cast your greater homing fireball spell! <B>Left-click to cast at a target!</B></span>"
base_cooldown = 6 SECONDS
/obj/effect/proc_holder/spell/aoe/repulse
/datum/spell/aoe/repulse
name = "Repulse"
desc = "This spell throws everything around the user away."
base_cooldown = 400
base_cooldown = 40 SECONDS
clothes_req = TRUE
invocation = "GITTAH WEIGH"
invocation_type = "shout"
@@ -419,12 +410,12 @@
action_icon_state = "repulse"
aoe_range = 5
/obj/effect/proc_holder/spell/aoe/repulse/create_new_targeting()
/datum/spell/aoe/repulse/create_new_targeting()
var/datum/spell_targeting/aoe/turf/targeting = new()
targeting.range = aoe_range
return targeting
/obj/effect/proc_holder/spell/aoe/repulse/cast(list/targets, mob/user = usr, stun_amt = 4 SECONDS)
/datum/spell/aoe/repulse/cast(list/targets, mob/user = usr, stun_amt = 4 SECONDS)
var/list/thrownatoms = list()
var/atom/throwtarget
var/distfromcaster
@@ -455,24 +446,24 @@
spawn(0)
AM.throw_at(throwtarget, ((clamp((maxthrow - (clamp(distfromcaster - 2, 0, distfromcaster))), 3, maxthrow))), 1)//So stuff gets tossed around at the same time.
/obj/effect/proc_holder/spell/sacred_flame
/datum/spell/sacred_flame
name = "Sacred Flame"
desc = "Makes everyone around you more flammable, and lights yourself on fire."
base_cooldown = 60
base_cooldown = 6 SECONDS
clothes_req = FALSE
invocation = "FI'RAN DADISKO"
invocation_type = "shout"
action_icon_state = "sacredflame"
sound = 'sound/magic/fireball.ogg'
/obj/effect/proc_holder/spell/sacred_flame/create_new_targeting()
/datum/spell/sacred_flame/create_new_targeting()
var/datum/spell_targeting/aoe/A = new()
A.include_user = TRUE
A.range = 6
A.allowed_type = /mob/living
return A
/obj/effect/proc_holder/spell/sacred_flame/cast(list/targets, mob/user = usr)
/datum/spell/sacred_flame/cast(list/targets, mob/user = usr)
for(var/mob/living/L in targets)
L.adjust_fire_stacks(20)
if(isliving(user))
+4 -4
View File
@@ -481,13 +481,13 @@
desc = "The subject becomes able to convert excess cellular energy into thermal energy."
activation_messages = list("You suddenly feel rather hot.")
deactivation_messages = list("You no longer feel uncomfortably hot.")
spelltype = /obj/effect/proc_holder/spell/immolate
spelltype = /datum/spell/immolate
/datum/mutation/grant_spell/immolate/New()
..()
block = GLOB.immolateblock
/obj/effect/proc_holder/spell/immolate
/datum/spell/immolate
name = "Incendiary Mitochondria"
desc = "The subject becomes able to convert excess cellular energy into thermal energy."
panel = "Abilities"
@@ -501,10 +501,10 @@
action_icon_state = "genetic_incendiary"
/obj/effect/proc_holder/spell/immolate/create_new_targeting()
/datum/spell/immolate/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/immolate/cast(list/targets, mob/living/user = usr)
/datum/spell/immolate/cast(list/targets, mob/living/user = usr)
var/mob/living/carbon/L = user
L.adjust_fire_stacks(0.5)
L.visible_message("<span class='danger'>[L.name]</b> suddenly bursts into flames!</span>")
+47 -47
View File
@@ -247,7 +247,7 @@
/////////////////////////////////////////////////////////////////////////////////////////
/datum/mutation/grant_spell
var/obj/effect/proc_holder/spell/spelltype
var/datum/spell/spelltype
/datum/mutation/grant_spell/activate(mob/M)
M.AddSpell(new spelltype(null))
@@ -255,7 +255,7 @@
return TRUE
/datum/mutation/grant_spell/deactivate(mob/M)
for(var/obj/effect/proc_holder/spell/S in M.mob_spell_list)
for(var/datum/spell/S in M.mob_spell_list)
if(istype(S, spelltype))
M.RemoveSpell(S)
..()
@@ -268,13 +268,13 @@
activation_messages = list("You notice a strange cold tingle in your fingertips.")
deactivation_messages = list("Your fingers feel warmer.")
instability = GENE_INSTABILITY_MODERATE
spelltype = /obj/effect/proc_holder/spell/cryokinesis
spelltype = /datum/spell/cryokinesis
/datum/mutation/grant_spell/cryo/New()
..()
block = GLOB.cryoblock
/obj/effect/proc_holder/spell/cryokinesis
/datum/spell/cryokinesis
name = "Cryokinesis"
desc = "Drops the bodytemperature of another person."
panel = "Abilities"
@@ -291,7 +291,7 @@
action_icon_state = "genetic_cryo"
/obj/effect/proc_holder/spell/cryokinesis/create_new_targeting()
/datum/spell/cryokinesis/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.allowed_type = /mob/living/carbon
T.click_radius = 0
@@ -300,7 +300,7 @@
T.include_user = TRUE
return T
/obj/effect/proc_holder/spell/cryokinesis/cast(list/targets, mob/user = usr)
/datum/spell/cryokinesis/cast(list/targets, mob/user = usr)
var/mob/living/carbon/C = targets[1]
@@ -339,13 +339,13 @@
deactivation_messages = list("You don't feel quite so hungry anymore.")
instability = GENE_INSTABILITY_MODERATE
spelltype=/obj/effect/proc_holder/spell/eat
spelltype=/datum/spell/eat
/datum/mutation/grant_spell/mattereater/New()
..()
block = GLOB.eatblock
/obj/effect/proc_holder/spell/eat
/datum/spell/eat
name = "Eat"
desc = "Eat just about anything!"
panel = "Abilities"
@@ -358,10 +358,10 @@
action_icon_state = "genetic_eat"
/obj/effect/proc_holder/spell/eat/create_new_targeting()
/datum/spell/eat/create_new_targeting()
return new /datum/spell_targeting/matter_eater
/obj/effect/proc_holder/spell/eat/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
/datum/spell/eat/can_cast(mob/user = usr, charge_check = TRUE, show_message = FALSE)
. = ..()
if(!.)
return
@@ -374,7 +374,7 @@
can_eat = FALSE
return can_eat
/obj/effect/proc_holder/spell/eat/proc/doHeal(mob/user)
/datum/spell/eat/proc/doHeal(mob/user)
if(ishuman(user))
var/mob/living/carbon/human/H = user
for(var/name in H.bodyparts_by_name)
@@ -390,7 +390,7 @@
/obj/effect/proc_holder/spell/eat/cast(list/targets, mob/user = usr)
/datum/spell/eat/cast(list/targets, mob/user = usr)
if(!targets.len)
to_chat(user, "<span class='notice'>No target found in range.</span>")
return
@@ -462,13 +462,13 @@
deactivation_messages = list("Your leg muscles shrink back to normal.")
instability = GENE_INSTABILITY_MODERATE
spelltype =/obj/effect/proc_holder/spell/leap
spelltype =/datum/spell/leap
/datum/mutation/grant_spell/jumpy/New()
..()
block = GLOB.jumpblock
/obj/effect/proc_holder/spell/leap
/datum/spell/leap
name = "Jump"
desc = "Leap great distances!"
panel = "Abilities"
@@ -481,10 +481,10 @@
action_icon_state = "genetic_jump"
/obj/effect/proc_holder/spell/leap/create_new_targeting()
/datum/spell/leap/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/leap/cast(list/targets, mob/living/user = usr)
/datum/spell/leap/cast(list/targets, mob/living/user = usr)
var/failure = FALSE
if(ismob(user.loc) || IS_HORIZONTAL(user) || user.IsStunned() || user.buckled || user.stat)
to_chat(user, "<span class='warning'>You can't jump right now!</span>")
@@ -551,7 +551,7 @@
name = "Polymorphism"
desc = "Enables the subject to reconfigure their appearance to mimic that of others."
spelltype =/obj/effect/proc_holder/spell/polymorph
spelltype =/datum/spell/polymorph
//cooldown = 1800
activation_messages = list("You don't feel entirely like yourself somehow.")
deactivation_messages = list("You feel secure in your identity.")
@@ -561,7 +561,7 @@
..()
block = GLOB.polymorphblock
/obj/effect/proc_holder/spell/polymorph
/datum/spell/polymorph
name = "Polymorph"
desc = "Mimic the appearance of others!"
panel = "Abilities"
@@ -577,7 +577,7 @@
action_icon_state = "genetic_poly"
/obj/effect/proc_holder/spell/polymorph/create_new_targeting()
/datum/spell/polymorph/create_new_targeting()
var/datum/spell_targeting/click/T = new()
T.try_auto_target = FALSE
T.click_radius = -1
@@ -585,7 +585,7 @@
T.selection_type = SPELL_SELECTION_RANGE
return T
/obj/effect/proc_holder/spell/polymorph/cast(list/targets, mob/user = usr)
/datum/spell/polymorph/cast(list/targets, mob/user = usr)
var/mob/living/carbon/human/target = targets[1]
user.visible_message("<span class='warning'>[user]'s body shifts and contorts.</span>")
@@ -605,7 +605,7 @@
name = "Empathic Thought"
desc = "The subject becomes able to read the minds of others for certain information."
spelltype = /obj/effect/proc_holder/spell/empath
spelltype = /datum/spell/empath
activation_messages = list("You suddenly notice more about others than you did before.")
deactivation_messages = list("You no longer feel able to sense intentions.")
instability = GENE_INSTABILITY_MINOR
@@ -614,10 +614,10 @@
..()
block = GLOB.empathblock
/obj/effect/proc_holder/spell/empath
/datum/spell/empath
name = "Read Mind"
desc = "Read the minds of others for information."
base_cooldown = 180
base_cooldown = 18 SECONDS
clothes_req = FALSE
human_req = TRUE
stat_allowed = CONSCIOUS
@@ -625,13 +625,13 @@
action_icon_state = "genetic_empath"
/obj/effect/proc_holder/spell/empath/create_new_targeting()
/datum/spell/empath/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living/carbon
T.selection_type = SPELL_SELECTION_RANGE
return T
/obj/effect/proc_holder/spell/empath/cast(list/targets, mob/user = usr)
/datum/spell/empath/cast(list/targets, mob/user = usr)
for(var/mob/living/carbon/M in targets)
if(!iscarbon(M))
to_chat(user, "<span class='warning'>You may only use this on other organic beings.</span>")
@@ -714,7 +714,7 @@
/datum/mutation/grant_spell/morph
name = "Morphism"
desc = "Enables the subject to reconfigure their appearance to that of any human."
spelltype =/obj/effect/proc_holder/spell/morph
spelltype =/datum/spell/morph
activation_messages = list("Your body feels like it can alter its appearance.")
deactivation_messages = list("Your body doesn't feel capable of altering its appearance.")
instability = GENE_INSTABILITY_MODERATE
@@ -723,7 +723,7 @@
..()
block = GLOB.morphblock
/obj/effect/proc_holder/spell/morph
/datum/spell/morph
name = "Morph"
desc = "Mimic the appearance of your choice!"
panel = "Abilities"
@@ -735,10 +735,10 @@
action_icon_state = "genetic_morph"
/obj/effect/proc_holder/spell/morph/create_new_targeting()
/datum/spell/morph/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/morph/cast(list/targets, mob/user = usr)
/datum/spell/morph/cast(list/targets, mob/user = usr)
if(!ishuman(user))
return
@@ -897,7 +897,7 @@
deactivation_messages = list("You no longer feel you can project your thoughts.")
instability = GENE_INSTABILITY_MINOR
spelltype =/obj/effect/proc_holder/spell/remotetalk
spelltype =/datum/spell/remotetalk
/datum/mutation/grant_spell/remotetalk/New()
..()
@@ -905,15 +905,15 @@
/datum/mutation/grant_spell/remotetalk/activate(mob/living/M)
..()
M.AddSpell(new /obj/effect/proc_holder/spell/mindscan(null))
M.AddSpell(new /datum/spell/mindscan(null))
/datum/mutation/grant_spell/remotetalk/deactivate(mob/user)
..()
for(var/obj/effect/proc_holder/spell/S in user.mob_spell_list)
if(istype(S, /obj/effect/proc_holder/spell/mindscan))
for(var/datum/spell/S in user.mob_spell_list)
if(istype(S, /datum/spell/mindscan))
user.RemoveSpell(S)
/obj/effect/proc_holder/spell/remotetalk
/datum/spell/remotetalk
name = "Project Mind"
desc = "Make people understand your thoughts!"
base_cooldown = 0
@@ -924,10 +924,10 @@
action_icon_state = "genetic_project"
/obj/effect/proc_holder/spell/remotetalk/create_new_targeting()
/datum/spell/remotetalk/create_new_targeting()
return new /datum/spell_targeting/telepathic
/obj/effect/proc_holder/spell/remotetalk/cast(list/targets, mob/user = usr)
/datum/spell/remotetalk/cast(list/targets, mob/user = usr)
if(!ishuman(user))
return
if(user.mind?.miming) // Dont let mimes telepathically talk
@@ -949,7 +949,7 @@
for(var/mob/dead/observer/G in GLOB.player_list)
G.show_message("<i>Telepathic message from <b>[user]</b> ([ghost_follow_link(user, ghost=G)]) to <b>[target]</b> ([ghost_follow_link(target, ghost=G)]): [say]</i>")
/obj/effect/proc_holder/spell/mindscan
/datum/spell/mindscan
name = "Scan Mind"
desc = "Offer people a chance to share their thoughts!"
base_cooldown = 0
@@ -959,10 +959,10 @@
action_icon_state = "genetic_mindscan"
var/list/available_targets = list()
/obj/effect/proc_holder/spell/mindscan/create_new_targeting()
/datum/spell/mindscan/create_new_targeting()
return new /datum/spell_targeting/telepathic
/obj/effect/proc_holder/spell/mindscan/cast(list/targets, mob/user = usr)
/datum/spell/mindscan/cast(list/targets, mob/user = usr)
if(!ishuman(user))
return
for(var/mob/living/target in targets)
@@ -974,13 +974,13 @@
available_targets += target
addtimer(CALLBACK(src, PROC_REF(removeAvailability), target), 100)
/obj/effect/proc_holder/spell/mindscan/proc/removeAvailability(mob/living/target)
/datum/spell/mindscan/proc/removeAvailability(mob/living/target)
if(target in available_targets)
available_targets -= target
if(!(target in available_targets))
target.show_message("<i><span class='abductor'>You feel the sensation fade...</span></i>")
/obj/effect/proc_holder/spell/mindscan/Topic(href, href_list)
/datum/spell/mindscan/Topic(href, href_list)
var/mob/living/user
if(href_list["user"])
user = locateUID(href_list["user"])
@@ -1005,7 +1005,7 @@
for(var/mob/dead/observer/G in GLOB.player_list)
G.show_message("<i>Telepathic response from <b>[target]</b> ([ghost_follow_link(target, ghost=G)]) to <b>[user]</b> ([ghost_follow_link(user, ghost=G)]): [say]</i>")
/obj/effect/proc_holder/spell/mindscan/Destroy()
/datum/spell/mindscan/Destroy()
available_targets.Cut()
return ..()
@@ -1015,7 +1015,7 @@
deactivation_messages = list("Your mind can no longer can see things from afar.")
instability = GENE_INSTABILITY_MINOR
spelltype =/obj/effect/proc_holder/spell/remoteview
spelltype =/datum/spell/remoteview
/datum/mutation/grant_spell/remoteview/New()
..()
@@ -1028,10 +1028,10 @@
H.remoteview_target = null
H.reset_perspective()
/obj/effect/proc_holder/spell/remoteview
/datum/spell/remoteview
name = "Remote View"
desc = "Spy on people from any range!"
base_cooldown = 100
base_cooldown = 10 SECONDS
clothes_req = FALSE
stat_allowed = CONSCIOUS
@@ -1039,10 +1039,10 @@
action_icon_state = "genetic_view"
/obj/effect/proc_holder/spell/remoteview/create_new_targeting()
/datum/spell/remoteview/create_new_targeting()
return new /datum/spell_targeting/remoteview
/obj/effect/proc_holder/spell/remoteview/cast(list/targets, mob/user = usr)
/datum/spell/remoteview/cast(list/targets, mob/user = usr)
var/mob/living/carbon/human/H
if(ishuman(user))
H = user
+6 -6
View File
@@ -265,7 +265,7 @@
name = "Hallucinations"
desc = "Gives hallucinations to a target at range. A silent and invisible spell."
button_icon_state = "horror"
var/obj/effect/proc_holder/horror/PH
var/datum/spell/horror/PH
charges = 4
/datum/action/innate/cult/blood_spell/horror/New()
@@ -274,7 +274,7 @@
..()
/datum/action/innate/cult/blood_spell/horror/Destroy()
var/obj/effect/proc_holder/horror/destroy = PH
var/datum/spell/horror/destroy = PH
. = ..()
if(!QDELETED(destroy))
QDEL_NULL(destroy)
@@ -283,24 +283,24 @@
PH.toggle(owner) //the important bit
return TRUE
/obj/effect/proc_holder/horror
/datum/spell/horror
active = FALSE
ranged_mousepointer = 'icons/effects/cult_target.dmi'
var/datum/action/innate/cult/blood_spell/attached_action
/obj/effect/proc_holder/horror/Destroy()
/datum/spell/horror/Destroy()
var/datum/action/innate/cult/blood_spell/AA = attached_action
. = ..()
if(!QDELETED(AA))
QDEL_NULL(AA)
/obj/effect/proc_holder/horror/proc/toggle(mob/user)
/datum/spell/horror/proc/toggle(mob/user)
if(active)
remove_ranged_ability(user, "<span class='cult'>You dispel the magic...</span>")
else
add_ranged_ability(user, "<span class='cult'>You prepare to horrify a target...</span>")
/obj/effect/proc_holder/horror/InterceptClickOn(mob/living/user, params, atom/target)
/datum/spell/horror/InterceptClickOn(mob/living/user, params, atom/target)
if(..())
return
if(ranged_ability_user.incapacitated() || !IS_CULTIST(user))
+240 -292
View File
@@ -4,117 +4,91 @@
// crit percent
#define MALF_AI_ROLL_CRIT_CHANCE 5
//The malf AI action subtype. All malf actions are subtypes of this.
/datum/action/innate/ai
name = "AI Action"
//The malf AI spell subtype. All malf actions are subtypes of this.
/datum/spell/ai_spell
name = "AI Spell"
desc = "You aren't entirely sure what this does, but it's very beepy and boopy."
background_icon_state = "bg_tech_blue"
var/mob/living/silicon/ai/owner_AI //The owner AI, so we don't have to typecast every time
action_background_icon_state = "bg_tech_blue"
clothes_req = FALSE
base_cooldown = 0
var/uses //If we have multiple uses of the same power
var/auto_use_uses = TRUE //If we automatically use up uses on each activation
var/cooldown_period //If applicable, the time in deciseconds we have to wait before using any more modules
/datum/action/innate/ai/Grant(mob/living/L)
. = ..()
if(!isAI(owner))
WARNING("AI action [name] attempted to grant itself to non-AI mob [L.real_name] ([L.key])!")
qdel(src)
else
owner_AI = owner
/datum/spell/ai_spell/create_new_targeting()
return new /datum/spell_targeting/self
/datum/action/innate/ai/IsAvailable()
/datum/spell/ai_spell/can_cast(mob/living/silicon/ai/user, charge_check, show_message)
. = ..()
if(owner_AI && owner_AI.malf_cooldown > world.time)
if(!.)
return
if(!istype(user))
stack_trace("A non ai ([user]) tried to cast an AI spell.")
user.RemoveSpell(src)
return FALSE
/datum/action/innate/ai/Trigger(left_click)
/datum/spell/ai_spell/after_cast(list/targets, mob/user)
. = ..()
if(auto_use_uses)
adjust_uses(-1)
if(cooldown_period)
owner_AI.malf_cooldown = world.time + cooldown_period
adjust_uses(-1, user)
/datum/action/innate/ai/proc/adjust_uses(amt, silent)
/datum/spell/ai_spell/proc/adjust_uses(amt, mob/living/silicon/ai/owner, silent)
uses += amt
if(!silent && uses)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
if(!uses)
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
qdel(src)
owner.RemoveSpell(src)
if(QDELETED(src) || uses) //Not sure if not having src here would cause a runtime, so it's here to be safe
return
desc = "[initial(desc)] It has [uses] use\s remaining."
UpdateButtons()
//Framework for ranged abilities that can have different effects by left-clicking stuff.
/datum/action/innate/ai/ranged
/datum/spell/ai_spell/ranged
name = "Ranged AI Action"
auto_use_uses = FALSE //This is so we can do the thing and disable/enable freely without having to constantly add uses
var/obj/effect/proc_holder/ranged_ai/linked_ability //The linked proc holder that contains the actual ability code
var/linked_ability_type //The path of our linked ability
selection_activated_message = "<span class='notice'>Hello World!</span>"
selection_deactivated_message = "<span class='danger'>Goodbye Cruel World!</span>"
/datum/action/innate/ai/ranged/New()
if(!linked_ability_type)
WARNING("Ranged AI action [name] attempted to spawn without a linked ability!")
qdel(src) //uh oh!
return
linked_ability = new linked_ability_type()
linked_ability.attached_action = src
..()
/datum/action/innate/ai/ranged/adjust_uses(amt, silent)
/datum/spell/ai_spell/ranged/adjust_uses(amt, mob/living/silicon/ai/owner, silent)
uses += amt
if(!silent && uses)
to_chat(owner, "<span class='notice'>[name] now has <b>[uses]</b> use[uses > 1 ? "s" : ""] remaining.</span>")
if(!uses)
if(initial(uses) > 1) //no need to tell 'em if it was one-use anyway!
to_chat(owner, "<span class='warning'>[name] has run out of uses!</span>")
Remove(owner)
QDEL_IN(src, 100) //let any active timers on us finish up
owner.mob_spell_list -= src
QDEL_IN(src, 10 SECONDS) //let any active timers on us finish up
/datum/action/innate/ai/ranged/Destroy()
QDEL_NULL(linked_ability)
return ..()
/datum/spell/ai_spell/ranged/create_new_targeting()
var/datum/spell_targeting/clicked_atom/external/C = new()
C.range = INFINITY
return C
/datum/action/innate/ai/ranged/Activate()
linked_ability.toggle(owner)
return TRUE
//The actual ranged proc holder.
/obj/effect/proc_holder/ranged_ai
var/enable_text = "<span class='notice'>Hello World!</span>" //Appears when the user activates the ability
var/disable_text = "<span class='danger'>Goodbye Cruel World!</span>" //Context clues!
var/datum/action/innate/ai/ranged/attached_action
/obj/effect/proc_holder/ranged_ai/proc/toggle(mob/user)
if(active)
remove_ranged_ability(user, disable_text)
else
add_ranged_ability(user, enable_text)
/datum/action/innate/ai/choose_modules
/datum/spell/ai_spell/choose_modules
name = "Choose Modules"
desc = "Spend your processing time to gain a variety of different abilities."
button_icon_state = "choose_module"
action_icon_state = "choose_module"
auto_use_uses = FALSE // This is an infinite ability.
create_attack_logs = FALSE
/datum/action/innate/ai/choose_modules/Trigger(left_click)
/datum/spell/ai_spell/choose_modules/cast(list/targets, mob/living/silicon/ai/user)
. = ..()
owner_AI.malf_picker.use(owner_AI)
user.malf_picker.use(user)
/datum/action/innate/ai/return_to_core
/datum/spell/ai_spell/return_to_core
name = "Return to Main Core"
desc = "Leave the APC you are shunted to, and return to your core."
icon_icon = 'icons/obj/power.dmi'
button_icon_state = "apcemag"
action_icon = 'icons/obj/power.dmi'
action_icon_state = "apcemag"
auto_use_uses = FALSE // Here just to prevent the "You have X uses remaining" from popping up.
/datum/action/innate/ai/return_to_core/Trigger(left_click)
/datum/spell/ai_spell/return_to_core/cast(list/targets, mob/living/silicon/ai/user)
. = ..()
var/obj/machinery/power/apc/apc = owner_AI.loc
var/obj/machinery/power/apc/apc = user.loc
if(!istype(apc)) // This shouldn't happen but here for safety.
to_chat(src, "<span class='notice'>You are already in your Main Core.</span>")
to_chat(user, "<span class='notice'>You are already in your Main Core.</span>")
return
apc.malfvacate()
qdel(src)
@@ -127,9 +101,9 @@
/datum/module_picker/New()
possible_modules = list()
for(var/type in typesof(/datum/AI_Module))
for(var/type in subtypesof(/datum/AI_Module))
var/datum/AI_Module/AM = new type
if((AM.power_type && AM.power_type != /datum/action/innate/ai) || AM.upgrade)
if(AM.power_type || AM.upgrade)
possible_modules += AM
/datum/module_picker/proc/use(mob/user)
@@ -167,7 +141,7 @@
temp = "You cannot afford this module."
break
var/datum/action/innate/ai/action = locate(AM.power_type) in A.actions
var/datum/spell/ai_spell/action = locate(AM.power_type) in A.mob_spell_list
// Give the power and take away the money.
if(AM.upgrade) //upgrade and upgrade() are separate, be careful!
@@ -178,8 +152,8 @@
else
if(AM.power_type)
if(!action) //Unlocking for the first time
var/datum/action/AC = new AM.power_type
AC.Grant(A)
var/datum/spell/ai_spell/AC = new AM.power_type
A.AddSpell(AC)
A.current_modules += new AM.type
temp = AM.description
if(AM.one_purchase)
@@ -207,7 +181,7 @@
var/description = ""
var/cost = 5
var/one_purchase = FALSE //If this module can only be purchased once. This always applies to upgrades, even if the variable is set to false.
var/power_type = /datum/action/innate/ai //If the module gives an active ability, use this. Mutually exclusive with upgrade.
var/power_type = /datum/spell/ai_spell //If the module gives an active ability, use this. Mutually exclusive with upgrade.
var/upgrade //If the module gives a passive upgrade, use this. Mutually exclusive with power_type.
var/unlock_text = "<span class='notice'>Hello World!</span>" //Text shown when an ability is unlocked
var/unlock_sound //Sound played when an ability is unlocked
@@ -223,36 +197,39 @@
description = "Activate a weapon that will disintegrate all organic life on the station after a 450 second delay. Can only be used while on the station, will fail if your core is moved off station or destroyed."
cost = 130
one_purchase = TRUE
power_type = /datum/action/innate/ai/nuke_station
power_type = /datum/spell/ai_spell/nuke_station
unlock_text = "<span class='notice'>You slowly, carefully, establish a connection with the on-station self-destruct. You can now activate it at any time.</span>"
unlock_sound = 'sound/items/timer.ogg'
/datum/action/innate/ai/nuke_station
/datum/spell/ai_spell/nuke_station
name = "Doomsday Device"
desc = "Activates the doomsday device. This is not reversible."
button_icon_state = "doomsday_device"
action_icon_state = "doomsday_device"
auto_use_uses = FALSE
var/in_use
/datum/action/innate/ai/nuke_station/Activate()
var/turf/T = get_turf(owner)
/datum/spell/ai_spell/nuke_station/cast(list/targets, mob/living/silicon/ai/user)
var/turf/T = get_turf(user)
if(!istype(T) || !is_station_level(T.z))
to_chat(owner, "<span class='warning'>You cannot activate the doomsday device while off-station!</span>")
to_chat(user, "<span class='warning'>You cannot activate the doomsday device while off-station!</span>")
return
if(tgui_alert(owner, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", list("confirm = TRUE;", "confirm = FALSE;")) != "confirm = TRUE;")
if(tgui_alert(user, "Send arming signal? (true = arm, false = cancel)", "purge_all_life()", list("confirm = TRUE;", "confirm = FALSE;")) != "confirm = TRUE;")
return
if(active)
if(!istype(user) || QDELETED(user))
return
if(in_use)
return //prevent the AI from activating an already active doomsday
active = TRUE
set_us_up_the_bomb()
in_use = TRUE
set_us_up_the_bomb(user)
/datum/action/innate/ai/nuke_station/proc/set_us_up_the_bomb()
to_chat(owner_AI, "<span class='notice'>Nuclear device armed.</span>")
/datum/spell/ai_spell/nuke_station/proc/set_us_up_the_bomb(mob/living/silicon/ai/user)
to_chat(user, "<span class='notice'>Nuclear device armed.</span>")
GLOB.major_announcement.Announce("Hostile runtimes detected in all station systems, please deactivate your AI to prevent possible damage to its morality core.", "Anomaly Alert", 'sound/AI/aimalf.ogg')
SSsecurity_level.set_level(SEC_LEVEL_DELTA)
owner_AI.nuking = TRUE
var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(owner_AI)
owner_AI.doomsday_device = DOOM
owner_AI.doomsday_device.start()
user.nuking = TRUE
var/obj/machinery/doomsday_device/DOOM = new /obj/machinery/doomsday_device(user)
user.doomsday_device = DOOM
user.doomsday_device.start()
for(var/obj/item/pinpointer/point in GLOB.pinpointer_list)
for(var/mob/living/silicon/ai/A in GLOB.ai_list)
if((A.stat != DEAD) && A.nuking)
@@ -352,17 +329,17 @@
opening all doors on the station."
cost = 30
one_purchase = TRUE
power_type = /datum/action/innate/ai/lockdown
power_type = /datum/spell/ai_spell/lockdown
unlock_text = "<span class='notice'>You upload a sleeper trojan into the door control systems. You can send a signal to set it off at any time.</span>"
/datum/action/innate/ai/lockdown
/datum/spell/ai_spell/lockdown
name = "Lockdown"
desc = "Closes, bolts, and depowers every airlock, firelock, and blast door on the station. After 90 seconds, they will reset themselves."
button_icon_state = "lockdown"
action_icon_state = "lockdown"
uses = 1
/datum/action/innate/ai/lockdown/Activate()
to_chat(owner, "<span class='warning'>Lockdown Initiated. Network reset in 90 seconds.</span>")
/datum/spell/ai_spell/lockdown/cast(list/targets, mob/user)
to_chat(user, "<span class='warning'>Lockdown Initiated. Network reset in 90 seconds.</span>")
new /datum/event/door_runtime()
//Destroy RCDs: Detonates all non-cyborg RCDs on the station.
@@ -372,17 +349,17 @@
description = "Send a specialised pulse to detonate all hand-held and exosuit Rapid Construction Devices on the station."
cost = 25
one_purchase = TRUE
power_type = /datum/action/innate/ai/destroy_rcds
power_type = /datum/spell/ai_spell/destroy_rcds
unlock_text = "<span class='notice'>After some improvisation, you rig your onboard radio to be able to send a signal to detonate all RCDs.</span>"
/datum/action/innate/ai/destroy_rcds
/datum/spell/ai_spell/destroy_rcds
name = "Destroy RCDs"
desc = "Detonate all non-cyborg RCDs on the station."
button_icon_state = "detonate_rcds"
action_icon_state = "detonate_rcds"
uses = 1
cooldown_period = 10 SECONDS
base_cooldown = 10 SECONDS
/datum/action/innate/ai/destroy_rcds/Activate()
/datum/spell/ai_spell/destroy_rcds/cast(list/targets, mob/user)
for(var/obj/item/rcd/RCD in GLOB.rcd_list)
if(istype(RCD, /obj/item/rcd/borg)) //Ensures that cyborg RCDs are spared.
continue
@@ -390,8 +367,8 @@
if(is_level_reachable(RCD_turf.z))
RCD.detonate_pulse()
to_chat(owner, "<span class='danger'>RCD detonation pulse emitted.</span>")
owner.playsound_local(owner, 'sound/machines/twobeep.ogg', 50, FALSE, use_reverb = FALSE)
to_chat(user, "<span class='danger'>RCD detonation pulse emitted.</span>")
user.playsound_local(user, 'sound/machines/twobeep.ogg', 50, FALSE, use_reverb = FALSE)
//Unlock Mech Domination: Unlocks the ability to dominate mechs. Big shocker, right?
/datum/AI_Module/mecha_domination
@@ -415,22 +392,22 @@
Anyone can check the fire alarm's interface and may be tipped off by its status."
one_purchase = TRUE
cost = 25
power_type = /datum/action/innate/ai/break_fire_alarms
power_type = /datum/spell/ai_spell/break_fire_alarms
unlock_text = "<span class='notice'>You replace the thermal sensing capabilities of all fire alarms with a manual override, allowing you to turn them off at will.</span>"
/datum/action/innate/ai/break_fire_alarms
/datum/spell/ai_spell/break_fire_alarms
name = "Override Thermal Sensors"
desc = "Disables the automatic temperature sensing on all fire alarms, making them effectively useless."
button_icon_state = "break_fire_alarms"
action_icon_state = "break_fire_alarms"
uses = 1
/datum/action/innate/ai/break_fire_alarms/Activate()
/datum/spell/ai_spell/break_fire_alarms/cast(list/targets, mob/user)
for(var/obj/machinery/firealarm/F in GLOB.machines)
if(!is_station_level(F.z))
continue
F.emagged = TRUE
to_chat(owner, "<span class='notice'>All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.</span>")
owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, FALSE, use_reverb = FALSE)
to_chat(user, "<span class='notice'>All thermal sensors on the station have been disabled. Fire alerts will no longer be recognized.</span>")
user.playsound_local(user, 'sound/machines/terminal_off.ogg', 50, FALSE, use_reverb = FALSE)
//Air Alarm Safety Override: Unlocks the ability to enable flooding on all air alarms.
/datum/AI_Module/break_air_alarms
@@ -440,23 +417,22 @@
Anyone can check the air alarm's interface and may be tipped off by their nonfunctionality."
one_purchase = TRUE
cost = 50
power_type = /datum/action/innate/ai/break_air_alarms
power_type = /datum/spell/ai_spell/break_air_alarms
unlock_text = "<span class='notice'>You remove the safety overrides on all air alarms, but you leave the confirm prompts open. You can hit 'Yes' at any time... you bastard.</span>"
/datum/action/innate/ai/break_air_alarms
/datum/spell/ai_spell/break_air_alarms
name = "Override Air Alarm Safeties"
desc = "Enables the Flood setting on all air alarms."
button_icon_state = "break_air_alarms"
action_icon_state = "break_air_alarms"
uses = 1
/datum/action/innate/ai/break_air_alarms/Activate()
/datum/spell/ai_spell/break_air_alarms/cast(list/targets, mob/user)
for(var/obj/machinery/alarm/AA in GLOB.machines)
if(!is_station_level(AA.z))
continue
AA.emagged = TRUE
to_chat(owner, "<span class='notice'>All air alarm safeties on the station have been overridden. Air alarms may now use the Flood environmental mode.")
owner.playsound_local(owner, 'sound/machines/terminal_off.ogg', 50, FALSE, use_reverb = FALSE)
to_chat(user, "<span class='notice'>All air alarm safeties on the station have been overridden. Air alarms may now use the Flood environmental mode.")
user.playsound_local(user, 'sound/machines/terminal_off.ogg', 50, FALSE, use_reverb = FALSE)
//Overload Machine: Allows the AI to overload a machine, detonating it after a delay. Two uses per purchase.
/datum/AI_Module/overload_machine
@@ -464,95 +440,78 @@
mod_pick_name = "overload"
description = "Overheats an electrical machine, causing a moderately-sized explosion and destroying it. Four uses per purchase."
cost = 20
power_type = /datum/action/innate/ai/ranged/overload_machine
power_type = /datum/spell/ai_spell/ranged/overload_machine
unlock_text = "<span class='notice'>You enable the ability for the station's APCs to direct intense energy into machinery.</span>"
/datum/action/innate/ai/ranged/overload_machine
/datum/spell/ai_spell/ranged/overload_machine
name = "Overload Machine"
desc = "Overheats a machine, causing a moderately-sized explosion after a short time."
button_icon_state = "overload_machine"
action_icon_state = "overload_machine"
uses = 4
linked_ability_type = /obj/effect/proc_holder/ranged_ai/overload_machine
active = FALSE
ranged_mousepointer = 'icons/effects/cult_target.dmi'
selection_activated_message = "<span class='notice'>You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.</span>"
selection_deactivated_message = "<span class='notice'>You release your hold on the powernet.</span>"
/datum/action/innate/ai/ranged/overload_machine/proc/detonate_machine(obj/machinery/M)
/datum/spell/ai_spell/ranged/overload_machine/cast(list/targets, mob/user)
var/obj/machinery/target = targets[1]
if(!istype(target))
to_chat(user, "<span class='warning'>You can only overload machines!</span>")
return
if(target.flags_2 & NO_MALF_EFFECT_2)
to_chat(user, "<span class='warning'>That machine can't be overloaded!</span>")
return
user.playsound_local(user, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [target]!</span>")
addtimer(CALLBACK(src, PROC_REF(detonate_machine), target), 5 SECONDS) //kaboom!
to_chat(user, "<span class='warning'>Overloading machine circuitry...</span>")
return TRUE
/datum/spell/ai_spell/ranged/overload_machine/proc/detonate_machine(obj/machinery/M)
if(M && !QDELETED(M))
explosion(get_turf(M), 0, 3, 5, 0)
if(M) //to check if the explosion killed it before we try to delete it
qdel(M)
/obj/effect/proc_holder/ranged_ai/overload_machine
active = FALSE
ranged_mousepointer = 'icons/effects/cult_target.dmi'
enable_text = "<span class='notice'>You tap into the station's powernet. Click on a machine to detonate it, or use the ability again to cancel.</span>"
disable_text = "<span class='notice'>You release your hold on the powernet.</span>"
/obj/effect/proc_holder/ranged_ai/overload_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target)
if(..())
return
if(ranged_ability_user.incapacitated())
remove_ranged_ability()
return
if(!istype(target))
to_chat(ranged_ability_user, "<span class='warning'>You can only overload machines!</span>")
return
if(target.flags_2 & NO_MALF_EFFECT_2)
to_chat(ranged_ability_user, "<span class='warning'>That machine can't be overloaded!</span>")
return
ranged_ability_user.playsound_local(ranged_ability_user, "sparks", 50, FALSE, use_reverb = FALSE)
attached_action.adjust_uses(-1)
target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [target]!</span>")
addtimer(CALLBACK(attached_action, TYPE_PROC_REF(/datum/action/innate/ai/ranged/overload_machine, detonate_machine), target), 50) //kaboom!
remove_ranged_ability(ranged_ability_user, "<span class='warning'>Overloading machine circuitry...</span>")
return TRUE
//Override Machine: Allows the AI to override a machine, animating it into an angry, living version of itself.
/datum/AI_Module/override_machine
module_name = "Machine Override"
mod_pick_name = "override"
description = "Overrides a machine's programming, causing it to rise up and attack everyone except other machines. Four uses."
cost = 30
power_type = /datum/action/innate/ai/ranged/override_machine
power_type = /datum/spell/ai_spell/ranged/override_machine
unlock_text = "<span class='notice'>You procure a virus from the Space Dark Web and distribute it to the station's machines.</span>"
/datum/action/innate/ai/ranged/override_machine
/datum/spell/ai_spell/ranged/override_machine
name = "Override Machine"
desc = "Animates a targeted machine, causing it to attack anyone nearby."
button_icon_state = "override_machine"
action_icon_state = "override_machine"
uses = 4
linked_ability_type = /obj/effect/proc_holder/ranged_ai/override_machine
/datum/action/innate/ai/ranged/override_machine/proc/animate_machine(obj/machinery/M)
if(M && !QDELETED(M))
new/mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, owner, 1)
/obj/effect/proc_holder/ranged_ai/override_machine
active = FALSE
ranged_mousepointer = 'icons/effects/override_machine_target.dmi'
enable_text = "<span class='notice'>You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.</span>"
disable_text = "<span class='notice'>You release your hold on the powernet.</span>"
selection_activated_message = "<span class='notice'>You tap into the station's powernet. Click on a machine to animate it, or use the ability again to cancel.</span>"
selection_deactivated_message = "<span class='notice'>You release your hold on the powernet.</span>"
/obj/effect/proc_holder/ranged_ai/override_machine/InterceptClickOn(mob/living/caller, params, obj/machinery/target)
if(..())
return
if(ranged_ability_user.incapacitated())
remove_ranged_ability()
return
/datum/spell/ai_spell/ranged/override_machine/cast(list/targets, mob/user)
var/obj/machinery/target = targets[1]
if(!istype(target))
to_chat(ranged_ability_user, "<span class='warning'>You can only animate machines!</span>")
to_chat(user, "<span class='warning'>You can only animate machines!</span>")
return
if(target.flags_2 & NO_MALF_EFFECT_2)
to_chat(ranged_ability_user, "<span class='warning'>That machine can't be overridden!</span>")
to_chat(user, "<span class='warning'>That machine can't be overridden!</span>")
return
ranged_ability_user.playsound_local(ranged_ability_user, 'sound/misc/interference.ogg', 50, FALSE, use_reverb = FALSE)
attached_action.adjust_uses(-1)
user.playsound_local(user, 'sound/misc/interference.ogg', 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
target.audible_message("<span class='userdanger'>You hear a loud electrical buzzing sound coming from [target]!</span>")
addtimer(CALLBACK(attached_action, TYPE_PROC_REF(/datum/action/innate/ai/ranged/override_machine, animate_machine), target), 50) //kabeep!
remove_ranged_ability(ranged_ability_user, "<span class='danger'>Sending override signal...</span>")
addtimer(CALLBACK(src, PROC_REF(animate_machine), target), 5 SECONDS) //kabeep!
to_chat(user, "<span class='danger'>Sending override signal...</span>")
return TRUE
/datum/spell/ai_spell/ranged/override_machine/proc/animate_machine(obj/machinery/M, mob/user)
if(M && !QDELETED(M))
new /mob/living/simple_animal/hostile/mimic/copy/machine(get_turf(M), M, user, 1)
//Robotic Factory: Places a large machine that converts humans that go through it into cyborgs. Unlocking this ability removes shunting.
/datum/AI_Module/place_cyborg_transformer
@@ -561,46 +520,47 @@
description = "Build a machine anywhere, using expensive nanomachines, that can convert a living human into a loyal cyborg slave when placed inside."
cost = 100
one_purchase = TRUE
power_type = /datum/action/innate/ai/place_transformer
power_type = /datum/spell/ai_spell/place_transformer
unlock_text = "<span class='notice'>You prepare a robotics factory for deployment.</span>"
unlock_sound = 'sound/machines/ping.ogg'
/datum/action/innate/ai/place_transformer
/datum/spell/ai_spell/place_transformer
name = "Place Robotics Factory"
desc = "Places a machine that converts humans into cyborgs. Conveyor belts included!"
button_icon_state = "robotic_factory"
action_icon_state = "robotic_factory"
uses = 1
auto_use_uses = FALSE //So we can attempt multiple times
var/list/turfOverlays
var/in_use = FALSE
/datum/action/innate/ai/place_transformer/New()
/datum/spell/ai_spell/place_transformer/New()
..()
for(var/i in 1 to 3)
var/image/I = image("icon"='icons/turf/overlays.dmi')
LAZYADD(turfOverlays, I)
/datum/action/innate/ai/place_transformer/Activate()
if(!owner_AI.can_place_transformer(src))
/datum/spell/ai_spell/place_transformer/cast(list/targets, mob/living/silicon/ai/user)
if(!user.can_place_transformer(src))
return
active = TRUE
if(tgui_alert(owner, "Are you sure you want to place the machine here?", "Are you sure?", list("Yes", "No")) != "Yes")
in_use = TRUE
if(tgui_alert(user, "Are you sure you want to place the machine here?", "Are you sure?", list("Yes", "No")) != "Yes")
active = FALSE
return
if(!owner_AI.can_place_transformer(src))
if(!user.can_place_transformer(src))
active = FALSE
return
var/turf/T = get_turf(owner_AI.eyeobj)
new /obj/machinery/transformer(T, owner_AI)
var/turf/T = get_turf(user.eyeobj)
new /obj/machinery/transformer(T, user)
playsound(T, 'sound/effects/phasein.ogg', 100, 1)
owner_AI.can_shunt = FALSE
to_chat(owner, "<span class='warning'>You are no longer able to shunt your core to APCs.</span>")
adjust_uses(-1)
user.can_shunt = FALSE
to_chat(user, "<span class='warning'>You are no longer able to shunt your core to APCs.</span>")
adjust_uses(-1, user)
/mob/living/silicon/ai/proc/remove_transformer_image(client/C, image/I, turf/T)
if(C && I.loc == T)
C.images -= I
/mob/living/silicon/ai/proc/can_place_transformer(datum/action/innate/ai/place_transformer/action)
/mob/living/silicon/ai/proc/can_place_transformer(datum/spell/ai_spell/place_transformer/action)
if(!eyeobj || !isturf(loc) || incapacitated() || !action)
return
var/turf/middle = get_turf(eyeobj)
@@ -634,46 +594,46 @@
mod_pick_name = "turretdeployer"
description = "Build a turret anywhere that lethally targets organic life in sight."
cost = 30
power_type = /datum/action/innate/ai/place_turret
power_type = /datum/spell/ai_spell/place_turret
unlock_text = "<span class='notice'>You prepare an energy turret for deployment.</span>"
unlock_sound = 'sound/items/rped.ogg'
/datum/action/innate/ai/place_turret
/datum/spell/ai_spell/place_turret
name = "Deploy Turret"
desc = "Build a turret anywhere that lethally targets organic life in sight."
button_icon_state = "deploy_turret"
action_icon_state = "deploy_turret"
uses = 1
auto_use_uses = FALSE
var/image/turf_overlay
var/in_use = FALSE
/datum/action/innate/ai/place_turret/New()
/datum/spell/ai_spell/place_turret/New()
..()
turf_overlay = image('icons/turf/overlays.dmi')
/datum/action/innate/ai/place_turret/Activate()
if(active)
to_chat(owner, "<span class='notice'>Your assemblers can only construct one turret at a time.</span>")
/datum/spell/ai_spell/place_turret/cast(list/targets, mob/living/silicon/ai/user)
if(in_use)
to_chat(user, "<span class='notice'>Your assemblers can only construct one turret at a time.</span>")
return
if(!owner_AI.can_place_turret(src))
if(!user.can_place_turret(src))
return
active = TRUE
var/response = alert(owner, "Are you sure you want to place a turret here? Deployment will take a few seconds to complete, in which the turret will be vulnerable.", "Are you sure?", "No", "Yes")
if(!response || response == "No")
active = FALSE
in_use = TRUE
if(tgui_alert(user, "Are you sure you want to place a turret here? Deployment will take a few seconds to complete, in which the turret will be vulnerable.", "Are you sure?", list("No", "Yes")) != "Yes")
in_use = FALSE
return
if(!owner_AI.can_place_turret(src))
active = FALSE
if(!user.can_place_turret(src))
in_use = FALSE
return
deploy_turret()
active = FALSE
deploy_turret(user)
in_use = FALSE
/datum/action/innate/ai/place_turret/proc/deploy_turret()
var/turf/T = get_turf(owner_AI.eyeobj)
/datum/spell/ai_spell/place_turret/proc/deploy_turret(mob/living/silicon/ai/user)
var/turf/T = get_turf(user.eyeobj)
//Handles the turret construction and configuration
playsound(T, 'sound/items/rped.ogg', 100, TRUE) //Plays a sound both at the location of the construction to alert players and to the user as feedback
owner.playsound_local(owner, 'sound/items/rped.ogg', 50, FALSE, use_reverb = FALSE)
to_chat(owner, "<span class='notice'>You order your electronics to assemble a turret. This will take a few seconds.</span>")
user.playsound_local(user, 'sound/items/rped.ogg', 50, FALSE, use_reverb = FALSE)
to_chat(user, "<span class='notice'>You order your electronics to assemble a turret. This will take a few seconds.</span>")
var/obj/effect/temp_visual/rcd_effect/spawning_effect = new(T)
QDEL_IN(spawning_effect, 5 SECONDS)
@@ -687,21 +647,21 @@
turret.invisibility = 100
//If turrets are already upgraded, beef it up
if(owner_AI.turrets_upgraded)
if(user.turrets_upgraded)
turret.health += 30
turret.eprojectile = /obj/item/projectile/beam/laser/ai_turret/heavylaser //Big gun
turret.eshot_sound = 'sound/weapons/lasercannonfire.ogg'
if(do_after_once(owner, 5 SECONDS, target = T, allow_moving = TRUE)) //Once this is done, turret is armed and dangerous
if(do_after_once(user, 5 SECONDS, target = T, allow_moving = TRUE)) //Once this is done, turret is armed and dangerous
turret.raised = initial(turret.raised)
turret.invisibility = initial(turret.invisibility)
turret.disabled = initial(turret.disabled)
new /obj/effect/temp_visual/rcd_effect/end(T)
playsound(T, 'sound/items/deconstruct.ogg', 100, TRUE)
to_chat(owner, "<span class='notice'>Turret deployed.</span>")
adjust_uses(-1)
to_chat(user, "<span class='notice'>Turret deployed.</span>")
adjust_uses(-1, user)
/mob/living/silicon/ai/proc/can_place_turret(datum/action/innate/ai/place_turret/action)
/mob/living/silicon/ai/proc/can_place_turret(datum/spell/ai_spell/place_turret/action)
if(!eyeobj || !isturf(eyeobj.loc) || incapacitated() || !action)
return
@@ -735,26 +695,26 @@
mod_pick_name = "blackout"
description = "Attempts to overload the lighting circuits on the station, destroying some bulbs. Three uses."
cost = 15
power_type = /datum/action/innate/ai/blackout
power_type = /datum/spell/ai_spell/blackout
unlock_text = "<span class='notice'>You hook into the powernet and route bonus power towards the station's lighting.</span>"
/datum/action/innate/ai/blackout
/datum/spell/ai_spell/blackout
name = "Blackout"
desc = "Overloads random lights across the station."
button_icon_state = "blackout"
action_icon_state = "blackout"
uses = 3
auto_use_uses = FALSE
/datum/action/innate/ai/blackout/Activate()
/datum/spell/ai_spell/blackout/cast(list/targets, mob/user)
for(var/thing in GLOB.apcs)
var/obj/machinery/power/apc/apc = thing
if(prob(30 * apc.overload))
INVOKE_ASYNC(apc, TYPE_PROC_REF(/obj/machinery/power/apc, overload_lighting))
else
apc.overload++
to_chat(owner, "<span class='notice'>Overcurrent applied to the powernet.</span>")
owner.playsound_local(owner, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1)
to_chat(user, "<span class='notice'>Overcurrent applied to the powernet.</span>")
user.playsound_local(user, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
//Reactivate Camera Network: Reactivates up to 30 cameras across the station.
/datum/AI_Module/reactivate_cameras
@@ -762,19 +722,18 @@
mod_pick_name = "recam"
description = "Runs a network-wide diagnostic on the camera network, resetting focus and re-routing power to failed cameras. Can be used to repair up to 30 cameras."
cost = 10
power_type = /datum/action/innate/ai/reactivate_cameras
power_type = /datum/spell/ai_spell/reactivate_cameras
unlock_text = "<span class='notice'>You deploy nanomachines to the cameranet.</span>"
/datum/action/innate/ai/reactivate_cameras
/datum/spell/ai_spell/reactivate_cameras
name = "Reactivate Cameras"
desc = "Reactivates disabled cameras across the station; remaining uses can be used later."
button_icon_state = "reactivate_cameras"
action_icon_state = "reactivate_cameras"
uses = 10
auto_use_uses = FALSE
cooldown_period = 3 SECONDS
base_cooldown = 3 SECONDS
/datum/action/innate/ai/reactivate_cameras/Activate()
var/mob/living/silicon/ai/user = usr
/datum/spell/ai_spell/reactivate_cameras/cast(list/targets, mob/living/silicon/ai/user)
var/repaired_cameras = 0
if(!istype(user))
return
@@ -782,14 +741,14 @@
if(!uses)
break
if(!camera_to_repair.status || camera_to_repair.view_range != initial(camera_to_repair.view_range))
camera_to_repair.toggle_cam(owner_AI, 0)
camera_to_repair.toggle_cam(user, 0)
camera_to_repair.view_range = initial(camera_to_repair.view_range)
camera_to_repair.wires.cut_wires.Cut()
repaired_cameras++
uses--
to_chat(owner, "<span class='notice'>Diagnostic complete! Cameras reactivated: <b>[repaired_cameras]</b>. Reactivations remaining: <b>[uses]</b>.</span>")
owner.playsound_local(owner, 'sound/items/wirecutter.ogg', 50, FALSE, use_reverb = FALSE)
adjust_uses(0, TRUE)
to_chat(user, "<span class='notice'>Diagnostic complete! Cameras reactivated: <b>[repaired_cameras]</b>. Reactivations remaining: <b>[uses]</b>.</span>")
user.playsound_local(user, 'sound/items/wirecutter.ogg', 50, FALSE, use_reverb = FALSE)
adjust_uses(0, user, TRUE)
//Upgrade Camera Network: EMP-proofs all cameras, in addition to giving them X-ray vision.
/datum/AI_Module/upgrade_cameras
@@ -880,124 +839,113 @@
mod_pick_name = "repair_borg"
description = "Causes an electrical surge in the targeted cyborg, rebooting and repairing most of its subsystems. Requires two uses on a cyborg with broken armor."
cost = 20
power_type = /datum/action/innate/ai/ranged/repair_cyborg
power_type = /datum/spell/ai_spell/ranged/repair_cyborg
unlock_text = "<span class='notice'>TLB exception on load: Error pointing to address 0000001H, Proceed with execution anywa- SURGE protocols installed, welcome to open APC!</span>"
unlock_sound = 'sound/items/rped.ogg'
/datum/action/innate/ai/ranged/repair_cyborg
/datum/spell/ai_spell/ranged/repair_cyborg
name = "Repair Cyborg"
desc = "Shocks a cyborg back to 'life' after a short delay."
button_icon_state = "overload_machine"
action_icon_state = "overload_machine"
uses = 2
linked_ability_type = /obj/effect/proc_holder/ranged_ai/repair_cyborg
ranged_mousepointer = 'icons/effects/overload_machine_target.dmi'
selection_activated_message = "<span class='notice'>Call to address 0FFFFFFF in APC logic thread, awaiting user response.</span>"
selection_deactivated_message = "<span class='notice'>APC logic thread restarting...</span>"
var/is_active = FALSE
/datum/spell/ai_spell/ranged/repair_cyborg/create_new_targeting()
var/datum/spell_targeting/click/T = new
T.allowed_type = /mob/living/silicon/robot
T.try_auto_target = FALSE
return T
/datum/action/innate/ai/ranged/repair_cyborg/proc/fix_borg(mob/living/silicon/robot/to_repair)
/datum/spell/ai_spell/ranged/repair_cyborg/cast(list/targets, mob/user)
var/mob/living/silicon/robot/robot_target = targets[1]
if(!istype(robot_target))
to_chat(user, "<span class='warning'>You can only repair robots with this ability!</span>")
return
if(is_active)
to_chat(user, "<span class='warning'>You can only repair one robot at a time!</span>")
return
is_active = TRUE
user.playsound_local(user, "sparks", 50, FALSE, use_reverb = FALSE)
adjust_uses(-1, user)
robot_target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [robot_target]!</span>")
if(!do_mob(user, robot_target, 10 SECONDS))
is_active = FALSE
return
is_active = FALSE
fix_borg(robot_target)
to_chat(user, "<span class='warning'>[robot_target] successfully rebooted.</span>")
return TRUE
/datum/spell/ai_spell/ranged/repair_cyborg/proc/fix_borg(mob/living/silicon/robot/to_repair)
for(var/datum/robot_component/component in to_repair.components)
component.brute_damage = 0
component.electronics_damage = 0
component.component_disabled = FALSE
to_repair.revive()
/obj/effect/proc_holder/ranged_ai/repair_cyborg
active = FALSE
ranged_mousepointer = 'icons/effects/overload_machine_target.dmi'
enable_text = "<span class='notice'>Call to address 0FFFFFFF in APC logic thread, awaiting user response.</span>"
disable_text = "<span class='notice'>APC logic thread restarting...</span>"
var/is_active = FALSE
/obj/effect/proc_holder/ranged_ai/repair_cyborg/InterceptClickOn(mob/living/caller, params, mob/living/silicon/robot/robot_target)
if(..())
return
if(ranged_ability_user.incapacitated())
remove_ranged_ability()
return
if(!istype(robot_target))
to_chat(ranged_ability_user, "<span class='warning'>You can only repair robots with this ability!</span>")
return
if(is_active)
to_chat(ranged_ability_user, "<span class='warning'>You can only repair one robot at a time!</span>")
return
is_active = TRUE
ranged_ability_user.playsound_local(ranged_ability_user, "sparks", 50, FALSE, use_reverb = FALSE)
var/datum/action/innate/ai/ranged/repair_cyborg/actual_action = attached_action
actual_action.adjust_uses(-1)
robot_target.audible_message("<span class='italics'>You hear a loud electrical buzzing sound coming from [robot_target]!</span>")
if(!do_mob(caller, robot_target, 10 SECONDS))
is_active = FALSE
return
is_active = FALSE
actual_action.fix_borg(robot_target)
remove_ranged_ability(ranged_ability_user, "<span class='warning'>[robot_target] successfully rebooted.</span>")
return TRUE
/datum/AI_Module/core_tilt
module_name = "Rolling Servos"
mod_pick_name = "watchforrollingcores"
description = "Allows you to slowly roll your core around, crushing anything in your path with your bulk."
cost = 10
one_purchase = FALSE
power_type = /datum/action/innate/ai/ranged/core_tilt
one_purchase = TRUE
power_type = /datum/spell/ai_spell/ranged/core_tilt
unlock_sound = 'sound/effects/bang.ogg'
unlock_text = "<span class='notice'>You gain the ability to roll over and crush anything in your way.</span>"
/datum/action/innate/ai/ranged/core_tilt
/datum/spell/ai_spell/ranged/core_tilt
name = "Roll Over"
button_icon_state = "roll_over"
action_icon_state = "roll_over"
desc = "Allows you to roll over in the direction of your choosing, crushing anything in your way."
auto_use_uses = FALSE
linked_ability_type = /obj/effect/proc_holder/ranged_ai/roll_over
/obj/effect/proc_holder/ranged_ai/roll_over
active = FALSE
ranged_mousepointer = 'icons/effects/cult_target.dmi'
enable_text = "<span class='notice'>Your inner servos shift as you prepare to roll around. Click adjacent tiles to roll into them!</span>"
disable_text = "<span class='notice'>You disengage your rolling protocols.</span>"
selection_activated_message = "<span class='notice'>Your inner servos shift as you prepare to roll around. Click adjacent tiles to roll into them!</span>"
selection_deactivated_message = "<span class='notice'>You disengage your rolling protocols.</span>"
COOLDOWN_DECLARE(time_til_next_tilt)
/// How long does it take us to roll?
var/roll_over_time = MALF_AI_ROLL_TIME
/// How long does it take for the ability to cool down, on top of [roll_over_time]?
var/roll_over_cooldown = MALF_AI_ROLL_COOLDOWN
/obj/effect/proc_holder/ranged_ai/roll_over/InterceptClickOn(mob/living/caller, params, atom/target_atom)
if(..())
/datum/spell/ai_spell/ranged/core_tilt/cast(list/targets, mob/living/silicon/ai/user)
var/atom/target_atom = targets[1]
if(!istype(user))
return
if(!isAI(ranged_ability_user))
return
if(ranged_ability_user.incapacitated() || !isturf(ranged_ability_user.loc))
remove_ranged_ability()
if(!isturf(user.loc))
user.RemoveSpell(src)
return
if(!COOLDOWN_FINISHED(src, time_til_next_tilt))
to_chat(ranged_ability_user, "<span class='warning'>Your rolling capacitors are still powering back up!</span>")
to_chat(user, "<span class='warning'>Your rolling capacitors are still powering back up!</span>")
return
var/turf/target = get_turf(target_atom)
if(isnull(target))
return
if(target == get_turf(ranged_ability_user))
to_chat(ranged_ability_user, "<span class='warning'>You can't roll over on yourself!</span>")
if(target == get_turf(user))
to_chat(user, "<span class='warning'>You can't roll over on yourself!</span>")
return
var/picked_dir = get_dir(caller, target)
var/picked_dir = get_dir(user, target)
if(!picked_dir)
return FALSE
// we can move during the timer so we cant just pass the ref
var/turf/temp_target = get_step(ranged_ability_user, picked_dir)
var/turf/temp_target = get_step(user, picked_dir)
new /obj/effect/temp_visual/single_user/ai_telegraph(temp_target, ranged_ability_user)
ranged_ability_user.visible_message("<span class='danger'>[ranged_ability_user] seems to be winding up!</span>")
addtimer(CALLBACK(src, PROC_REF(do_roll_over), caller, picked_dir), MALF_AI_ROLL_TIME)
new /obj/effect/temp_visual/single_user/ai_telegraph(temp_target, user)
user.visible_message("<span class='danger'>[user] seems to be winding up!</span>")
addtimer(CALLBACK(src, PROC_REF(do_roll_over), user, picked_dir), MALF_AI_ROLL_TIME)
to_chat(ranged_ability_user, "<span class='warning'>Overloading machine circuitry...</span>")
to_chat(user, "<span class='warning'>Overloading machine circuitry...</span>")
COOLDOWN_START(src, time_til_next_tilt, roll_over_cooldown)
return TRUE
/obj/effect/proc_holder/ranged_ai/roll_over/proc/do_roll_over(mob/living/silicon/ai/ai_caller, picked_dir)
/datum/spell/ai_spell/ranged/core_tilt/proc/do_roll_over(mob/living/silicon/ai/ai_caller, picked_dir)
var/turf/target = get_step(ai_caller, picked_dir) // in case we moved we pass the dir not the target turf
if(isnull(target) || ai_caller.incapacitated() || !isturf(ai_caller.loc))
@@ -1009,7 +957,7 @@
ai_caller.fall_and_crush(target, MALF_AI_ROLL_DAMAGE, prob(MALF_AI_ROLL_CRIT_CHANCE), 2, null, paralyze_time, crush_dir = picked_dir, angle = get_rotation_from_dir(picked_dir))
ai_caller.allow_teleporter = FALSE
/obj/effect/proc_holder/ranged_ai/roll_over/proc/get_rotation_from_dir(dir)
/datum/spell/ai_spell/ranged/core_tilt/proc/get_rotation_from_dir(dir)
switch(dir)
if(NORTH, NORTHWEST, WEST, SOUTHWEST)
return 270 // try our best to not return 180 since it works badly with animate
@@ -147,8 +147,8 @@
/mob/living/simple_animal/demon/shadow/Initialize(mapload)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/fireball/shadow_grapple)
var/obj/effect/proc_holder/spell/bloodcrawl/shadow_crawl/S = new
AddSpell(new /datum/spell/fireball/shadow_grapple)
var/datum/spell/bloodcrawl/shadow_crawl/S = new
AddSpell(S)
whisper_action.button_icon_state = "shadow_whisper"
whisper_action.background_icon_state = "shadow_demon_bg"
@@ -176,7 +176,7 @@
return lum_count
/obj/effect/proc_holder/spell/fireball/shadow_grapple
/datum/spell/fireball/shadow_grapple
name = "Shadow Grapple"
desc = "Fire one of your hands, if it hits a person it pulls them in. If you hit a structure you get pulled to the structure. Any light source hit with this will be disabled in a two tile radius."
base_cooldown = 10 SECONDS
@@ -193,7 +193,7 @@
invocation_type = "none"
invocation = null
/obj/effect/proc_holder/spell/fireball/shadow_grapple/update_icon_state()
/datum/spell/fireball/shadow_grapple/update_spell_icon()
return
/obj/item/projectile/magic/shadow_hand
@@ -239,9 +239,9 @@
/obj/item/organ/internal/heart/demon/shadow/insert(mob/living/carbon/M, special = 0)
. = ..()
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/fireball/shadow_grapple)
M.mind.AddSpell(new /datum/spell/fireball/shadow_grapple)
/obj/item/organ/internal/heart/demon/shadow/remove(mob/living/carbon/M, special = 0)
. = ..()
if(M.mind)
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/fireball/shadow_grapple)
M.mind.RemoveSpell(/datum/spell/fireball/shadow_grapple)
@@ -32,7 +32,7 @@
..()
remove_from_all_data_huds()
ADD_TRAIT(src, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
var/obj/effect/proc_holder/spell/bloodcrawl/bloodspell = new
var/datum/spell/bloodcrawl/bloodspell = new
AddSpell(bloodspell)
if(istype(loc, /obj/effect/dummy/slaughter))
bloodspell.phased = TRUE
@@ -102,7 +102,7 @@
to emerge from it. You are fast, powerful, and almost invincible. By dragging a dead or unconscious body into a blood pool with you, you will consume it after a time and fully regain \
your health. You may use the ability 'Sense Victims' in your Cultist tab to locate a random, living heretic.</span></b>"
/obj/effect/proc_holder/spell/sense_victims
/datum/spell/sense_victims
name = "Sense Victims"
desc = "Sense the location of heretics"
base_cooldown = 0
@@ -113,13 +113,13 @@
action_background_icon_state = "bg_cult"
panel = "Demon"
/obj/effect/proc_holder/spell/sense_victims/create_new_targeting()
/datum/spell/sense_victims/create_new_targeting()
return new /datum/spell_targeting/alive_mob_list
/obj/effect/proc_holder/spell/sense_victims/valid_target(mob/living/target, user)
/datum/spell/sense_victims/valid_target(mob/living/target, user)
return target.stat == CONSCIOUS && target.key && !IS_CULTIST(target) // Only conscious, non cultist players
/obj/effect/proc_holder/spell/sense_victims/cast(list/targets, mob/user)
/datum/spell/sense_victims/cast(list/targets, mob/user)
var/mob/living/victim = targets[1]
to_chat(victim, "<span class='userdanger'>You feel an awful sense of being watched...</span>")
victim.Stun(6 SECONDS) //HUE
@@ -153,7 +153,7 @@
S.mind.special_role = "Harbinger of the Slaughter"
to_chat(S, playstyle_string)
S.mind.add_antag_datum(/datum/antagonist/cultist)
var/obj/effect/proc_holder/spell/sense_victims/SV = new
var/datum/spell/sense_victims/SV = new
AddSpell(SV)
S.mind.add_mind_objective(/datum/objective/cult_slaughter)
@@ -257,14 +257,14 @@
/obj/item/organ/internal/heart/demon/slaughter/insert(mob/living/carbon/M, special = 0)
. = ..()
if(M.mind)
M.mind.AddSpell(new /obj/effect/proc_holder/spell/bloodcrawl(null))
M.mind.AddSpell(new /datum/spell/bloodcrawl(null))
/obj/item/organ/internal/heart/demon/slaughter/remove(mob/living/carbon/M, special = 0)
. = ..()
if(M.mind)
REMOVE_TRAIT(M, TRAIT_BLOODCRAWL, "bloodcrawl")
REMOVE_TRAIT(M, TRAIT_BLOODCRAWL_EAT, "bloodcrawl_eat")
M.mind.RemoveSpell(/obj/effect/proc_holder/spell/bloodcrawl)
M.mind.RemoveSpell(/datum/spell/bloodcrawl)
/mob/living/simple_animal/demon/slaughter/laughter
// The laughter demon! It's everyone's best friend! It just wants to hug
@@ -102,7 +102,7 @@
dust_if_respawnable(new_stand)
qdel(src)
/obj/effect/proc_holder/spell/summon_guardian_beacon
/datum/spell/summon_guardian_beacon
name = "Place Teleportation Beacon"
desc = "Mark a floor as your beacon point, allowing you to warp targets to it. Your beacon requires an anchor, will not work on space tiles."
clothes_req = FALSE
@@ -111,10 +111,10 @@
action_background_icon_state = "reset"
action_icon = 'icons/mob/guardian.dmi'
/obj/effect/proc_holder/spell/summon_guardian_beacon/create_new_targeting()
/datum/spell/summon_guardian_beacon/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/summon_guardian_beacon/cast(list/targets, mob/living/user = usr)
/datum/spell/summon_guardian_beacon/cast(list/targets, mob/living/user = usr)
var/target = targets[1]
var/mob/living/simple_animal/hostile/guardian/healer/guardian_user = user
var/turf/beacon_loc = get_turf(target)
@@ -125,7 +125,7 @@
return TRUE
/obj/effect/proc_holder/spell/surveillance_snare
/datum/spell/surveillance_snare
name = "Set Surveillance Snare"
desc = "Places an invisible Surveillance Snare on the ground, if someone walks over it you'll be alerted. Max of 6 snares active at a time"
clothes_req = FALSE
@@ -134,10 +134,10 @@
action_background_icon_state = "reset"
action_icon = 'icons/mob/guardian.dmi'
/obj/effect/proc_holder/spell/surveillance_snare/create_new_targeting()
/datum/spell/surveillance_snare/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/surveillance_snare/cast(list/targets, mob/living/user = usr)
/datum/spell/surveillance_snare/cast(list/targets, mob/living/user = usr)
var/target = targets[1]
var/mob/living/simple_animal/hostile/guardian/ranged/guardian_user = user
if(length(guardian_user.snares) < 6)
@@ -156,7 +156,7 @@
to_chat(user, "<span class='notice'>Snare disarmed.</span>")
revert_cast()
/obj/effect/proc_holder/spell/choose_battlecry
/datum/spell/choose_battlecry
name = "Change battlecry"
desc = "Changes your battlecry."
clothes_req = FALSE
@@ -165,10 +165,10 @@
action_background_icon_state = "communicate"
action_icon = 'icons/mob/guardian.dmi'
/obj/effect/proc_holder/spell/choose_battlecry/create_new_targeting()
/datum/spell/choose_battlecry/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/choose_battlecry/cast(list/targets, mob/living/user = usr)
/datum/spell/choose_battlecry/cast(list/targets, mob/living/user = usr)
var/mob/living/simple_animal/hostile/guardian/punch/guardian_user = user
var/input = tgui_input_text(guardian_user, "What do you want your battlecry to be? Max length of 6 characters.", "Change Battlecry", guardian_user.battlecry, 6)
if(!input)
@@ -36,7 +36,7 @@
/mob/living/simple_animal/hostile/guardian/healer/Initialize(mapload, mob/living/host)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/summon_guardian_beacon(null))
AddSpell(new /datum/spell/summon_guardian_beacon(null))
/mob/living/simple_animal/hostile/guardian/healer/Destroy()
QDEL_NULL(beacon)
@@ -27,7 +27,7 @@
/mob/living/simple_animal/hostile/guardian/ranged/Initialize(mapload, mob/living/host)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/surveillance_snare(null))
AddSpell(new /datum/spell/surveillance_snare(null))
/mob/living/simple_animal/hostile/guardian/ranged/ToggleMode()
if(loc == summoner)
@@ -12,7 +12,7 @@
/mob/living/simple_animal/hostile/guardian/punch/Initialize(mapload, mob/living/host)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/choose_battlecry(null))
AddSpell(new /datum/spell/choose_battlecry(null))
/mob/living/simple_animal/hostile/guardian/punch/AttackingTarget()
. = ..()
@@ -45,11 +45,11 @@
/// How much weaken a successful ambush attack applies
var/ambush_weaken = 6 SECONDS
/// The spell the morph uses to morph
var/obj/effect/proc_holder/spell/mimic/morph/mimic_spell
var/datum/spell/mimic/morph/mimic_spell
/// The ambush action used by the morph
var/obj/effect/proc_holder/spell/morph_spell/ambush/ambush_spell
var/datum/spell/morph_spell/ambush/ambush_spell
/// The spell the morph uses to pass through airlocks
var/obj/effect/proc_holder/spell/morph_spell/pass_airlock/pass_airlock_spell
var/datum/spell/morph_spell/pass_airlock/pass_airlock_spell
/// How much the morph has gathered in terms of food. Used to reproduce and such
var/gathered_food = 20 // Start with a bit to use abilities
@@ -60,8 +60,8 @@
AddSpell(mimic_spell)
ambush_spell = new
AddSpell(ambush_spell)
AddSpell(new /obj/effect/proc_holder/spell/morph_spell/reproduce)
AddSpell(new /obj/effect/proc_holder/spell/morph_spell/open_vent)
AddSpell(new /datum/spell/morph_spell/reproduce)
AddSpell(new /datum/spell/morph_spell/open_vent)
pass_airlock_spell = new
AddSpell(pass_airlock_spell)
@@ -83,8 +83,8 @@
/mob/living/simple_animal/hostile/morph/wizard/Initialize(mapload)
. = ..()
AddSpell(new /obj/effect/proc_holder/spell/smoke)
AddSpell(new /obj/effect/proc_holder/spell/forcewall)
AddSpell(new /datum/spell/smoke)
AddSpell(new /datum/spell/forcewall)
/mob/living/simple_animal/hostile/morph/proc/try_eat(atom/movable/A)
@@ -1,16 +1,16 @@
#define MORPH_AMBUSH_PERFECTION_TIME 15 SECONDS
/obj/effect/proc_holder/spell/morph_spell/ambush
/datum/spell/morph_spell/ambush
name = "Prepare Ambush"
desc = "Prepare an ambush. Dealing significantly more damage on the first hit and you will weaken the target. Only works while morphed. If the target tries to use you with their hands then you will do even more damage. \
Keeping still for another 15 seconds will perfect your disguise."
action_icon_state = "morph_ambush"
base_cooldown = 8 SECONDS
/obj/effect/proc_holder/spell/morph_spell/ambush/create_new_targeting()
/datum/spell/morph_spell/ambush/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/morph_spell/ambush/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
/datum/spell/morph_spell/ambush/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
. = ..()
if(!.)
return
@@ -23,7 +23,7 @@
to_chat(user, "<span class='warning'>You are already prepared!</span>")
return FALSE
/obj/effect/proc_holder/spell/morph_spell/ambush/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
/datum/spell/morph_spell/ambush/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
to_chat(user, "<span class='sinister'>You start preparing an ambush.</span>")
if(!do_after(user, 6 SECONDS, FALSE, user, TRUE, list(CALLBACK(src, PROC_REF(prepare_check), user)), FALSE))
if(!user.morphed)
@@ -33,7 +33,7 @@
return
user.prepare_ambush()
/obj/effect/proc_holder/spell/morph_spell/ambush/proc/prepare_check(mob/living/simple_animal/hostile/morph/user)
/datum/spell/morph_spell/ambush/proc/prepare_check(mob/living/simple_animal/hostile/morph/user)
return !user.morphed
/datum/status_effect/morph_ambush
@@ -1,15 +1,15 @@
/obj/effect/proc_holder/spell/morph_spell
/datum/spell/morph_spell
action_background_icon_state = "bg_morph"
clothes_req = FALSE
/// How much food it costs the morph to use this
var/hunger_cost = 0
/obj/effect/proc_holder/spell/morph_spell/Initialize(mapload)
. = ..()
/datum/spell/morph_spell/New()
..()
if(hunger_cost)
name = "[name] ([hunger_cost])"
/obj/effect/proc_holder/spell/morph_spell/create_new_handler()
/datum/spell/morph_spell/create_new_handler()
var/datum/spell_handler/morph/H = new
H.hunger_cost = hunger_cost
return H
@@ -1,17 +1,17 @@
/obj/effect/proc_holder/spell/morph_spell/open_vent
/datum/spell/morph_spell/open_vent
name = "Open Vents"
desc = "Spit out acidic puke on nearby vents or scrubbers. Will take a little while for the acid to take effect. Not usable from inside a vent."
action_icon_state = "acid_vent"
base_cooldown = 10 SECONDS
hunger_cost = 10
/obj/effect/proc_holder/spell/morph_spell/open_vent/create_new_targeting()
/datum/spell/morph_spell/open_vent/create_new_targeting()
var/datum/spell_targeting/aoe/T = new
T.range = 1
T.allowed_type = /obj/machinery/atmospherics/unary
return T
/obj/effect/proc_holder/spell/morph_spell/open_vent/valid_target(target, user)
/datum/spell/morph_spell/open_vent/valid_target(target, user)
if(istype(target, /obj/machinery/atmospherics/unary/vent_scrubber))
var/obj/machinery/atmospherics/unary/vent_scrubber/S = target
return S.welded
@@ -20,7 +20,7 @@
return V.welded
return FALSE
/obj/effect/proc_holder/spell/morph_spell/open_vent/cast(list/targets, mob/user)
/datum/spell/morph_spell/open_vent/cast(list/targets, mob/user)
if(!length(targets))
to_chat(user, "<span class='warning'>No nearby welded vents found!</span>")
revert_cast(user)
@@ -36,7 +36,7 @@
addtimer(CALLBACK(src, PROC_REF(unweld_vent), U), 2 SECONDS)
playsound(U, 'sound/items/welder.ogg', 100, TRUE)
/obj/effect/proc_holder/spell/morph_spell/open_vent/proc/unweld_vent(obj/machinery/atmospherics/unary/U)
/datum/spell/morph_spell/open_vent/proc/unweld_vent(obj/machinery/atmospherics/unary/U)
if(istype(U, /obj/machinery/atmospherics/unary/vent_scrubber))
var/obj/machinery/atmospherics/unary/vent_scrubber/S = U
S.welded = FALSE
@@ -1,5 +1,5 @@
// TODO refactor when spell code is component based instead of OO based
/obj/effect/proc_holder/spell/morph_spell/pass_airlock
/datum/spell/morph_spell/pass_airlock
name = "Pass Airlock"
desc = "Reform yourself so you can fit through a non bolted airlock. Takes a while to do and can only be used in a non disguised form."
action_background_icon_state = "bg_morph"
@@ -8,7 +8,7 @@
base_cooldown = 10 SECONDS
selection_activated_message = "<span class='sinister'>Click on an airlock to try pass it.</span>"
/obj/effect/proc_holder/spell/morph_spell/pass_airlock/create_new_targeting()
/datum/spell/morph_spell/pass_airlock/create_new_targeting()
var/datum/spell_targeting/click/T = new
T.range = 1
T.allowed_type = /obj/machinery/door/airlock
@@ -16,7 +16,7 @@
return T
/obj/effect/proc_holder/spell/morph_spell/pass_airlock/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
/datum/spell/morph_spell/pass_airlock/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
. = ..()
if(!.)
return
@@ -26,7 +26,7 @@
to_chat(user, "<span class='warning'>You can only pass through airlocks in your true form!</span>")
return FALSE
/obj/effect/proc_holder/spell/morph_spell/pass_airlock/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
/datum/spell/morph_spell/pass_airlock/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
var/obj/machinery/door/airlock/A = targets[1]
if(A.locked)
to_chat(user, "<span class='warning'>[A] is bolted shut! You're unable to create a crack to pass through!</span>")
@@ -49,5 +49,5 @@
user.forceMove(A.loc) // Move into the turf of the airlock
/obj/effect/proc_holder/spell/morph_spell/pass_airlock/proc/pass_check(mob/living/simple_animal/hostile/morph/user, obj/machinery/door/airlock/A)
/datum/spell/morph_spell/pass_airlock/proc/pass_check(mob/living/simple_animal/hostile/morph/user, obj/machinery/door/airlock/A)
return user.morphed || A.locked
@@ -1,4 +1,4 @@
/obj/effect/proc_holder/spell/morph_spell/reproduce
/datum/spell/morph_spell/reproduce
name = "Reproduce"
desc = "Split yourself in half making a new morph. Can only be used while on a floor. Makes you temporarily unable to vent crawl."
hunger_cost = 150 // 5 humans
@@ -6,10 +6,10 @@
action_icon_state = "morph_reproduce"
create_attack_logs = FALSE
/obj/effect/proc_holder/spell/morph_spell/reproduce/create_new_targeting()
/datum/spell/morph_spell/reproduce/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/morph_spell/reproduce/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
/datum/spell/morph_spell/reproduce/can_cast(mob/living/simple_animal/hostile/morph/user, charge_check, show_message)
. = ..()
if(!.)
return
@@ -18,7 +18,7 @@
to_chat(user, "<span class='warning'>You can only split while on flooring!</span>")
return FALSE
/obj/effect/proc_holder/spell/morph_spell/reproduce/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
/datum/spell/morph_spell/reproduce/cast(list/targets, mob/living/simple_animal/hostile/morph/user)
to_chat(user, "<span class='sinister'>You prepare to split in two, making you unable to vent crawl!</span>")
user.ventcrawler = VENTCRAWLER_NONE // Temporarily disable it
var/list/candidates = SSghost_spawns.poll_candidates("Do you want to play as a morph?", ROLE_MORPH, TRUE, poll_time = 10 SECONDS, source = /mob/living/simple_animal/hostile/morph)
@@ -254,16 +254,16 @@
SSticker.mode.traitors |= mind
/mob/living/simple_animal/demon/pulse_demon/proc/give_spells()
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/cycle_camera)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/toggle/do_drain(do_drain))
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/toggle/can_exit_cable(can_exit_cable))
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/cablehop)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/emagtamper)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/emp)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/overload)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/remotehijack)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/remotedrain)
AddSpell(new /obj/effect/proc_holder/spell/pulse_demon/open_upgrades)
AddSpell(new /datum/spell/pulse_demon/cycle_camera)
AddSpell(new /datum/spell/pulse_demon/toggle/do_drain(do_drain))
AddSpell(new /datum/spell/pulse_demon/toggle/can_exit_cable(can_exit_cable))
AddSpell(new /datum/spell/pulse_demon/cablehop)
AddSpell(new /datum/spell/pulse_demon/emagtamper)
AddSpell(new /datum/spell/pulse_demon/emp)
AddSpell(new /datum/spell/pulse_demon/overload)
AddSpell(new /datum/spell/pulse_demon/remotehijack)
AddSpell(new /datum/spell/pulse_demon/remotedrain)
AddSpell(new /datum/spell/pulse_demon/open_upgrades)
/mob/living/simple_animal/demon/pulse_demon/get_status_tab_items()
var/list/status_tab_data = ..()
@@ -299,7 +299,7 @@
forceMove(T)
Move(T)
if(!current_cable && !current_power)
var/obj/effect/proc_holder/spell/pulse_demon/toggle/can_exit_cable/S = locate() in mob_spell_list
var/datum/spell/pulse_demon/toggle/can_exit_cable/S = locate() in mob_spell_list
if(!S.locked && !can_exit_cable)
can_exit_cable = TRUE
S.do_toggle(can_exit_cable)
@@ -318,7 +318,7 @@
if((!prev && !controlling_area) || (prev && controlling_area))
return // only update icons when we get or no longer have ANY area
for(var/obj/effect/proc_holder/spell/pulse_demon/S in mob_spell_list)
for(var/datum/spell/pulse_demon/S in mob_spell_list)
if(!S.action || S.locked)
continue
if(S.requires_area)
@@ -429,7 +429,7 @@
charge_drained += realdelta
update_glow()
for(var/obj/effect/proc_holder/spell/pulse_demon/S in mob_spell_list)
for(var/datum/spell/pulse_demon/S in mob_spell_list)
if(!S.action || S.locked || !S.cast_cost)
continue
var/dist = S.cast_cost - orig
@@ -8,7 +8,7 @@
#define PD_UPGRADE_HEALTH_COST "Efficiency"
#define PD_UPGRADE_MAX_CHARGE "Capacity"
/obj/effect/proc_holder/spell/pulse_demon
/datum/spell/pulse_demon
panel = "Pulse Demon"
school = "pulse demon"
clothes_req = FALSE
@@ -21,11 +21,11 @@
base_cooldown = 20 SECONDS
level_max = 4
/obj/effect/proc_holder/spell/pulse_demon/New()
/datum/spell/pulse_demon/New()
. = ..()
update_info()
/obj/effect/proc_holder/spell/pulse_demon/proc/update_info()
/datum/spell/pulse_demon/proc/update_info()
if(locked)
name = "[initial(name)] (Locked) ([format_si_suffix(unlock_cost)]W)"
desc = "[initial(desc)] It costs [format_si_suffix(unlock_cost)]W to unlock."
@@ -36,7 +36,7 @@
action.desc = desc
action.UpdateButtons()
/obj/effect/proc_holder/spell/pulse_demon/can_cast(mob/living/simple_animal/demon/pulse_demon/user, charge_check, show_message)
/datum/spell/pulse_demon/can_cast(mob/living/simple_animal/demon/pulse_demon/user, charge_check, show_message)
if(!..())
return FALSE
if(!istype(user))
@@ -57,7 +57,7 @@
return FALSE
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/cast(list/targets, mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/cast(list/targets, mob/living/simple_animal/demon/pulse_demon/user)
if(!istype(user) || locked || user.charge < cast_cost || !length(targets))
return FALSE
if(requires_area && !user.controlling_area)
@@ -72,14 +72,14 @@
revert_cast(user)
return FALSE
/obj/effect/proc_holder/spell/pulse_demon/create_new_targeting()
/datum/spell/pulse_demon/create_new_targeting()
return new /datum/spell_targeting/clicked_atom
/obj/effect/proc_holder/spell/pulse_demon/proc/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/proc/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
return FALSE
// handles purchasing and upgrading abilities
/obj/effect/proc_holder/spell/pulse_demon/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
if(!istype(user))
return
@@ -115,11 +115,11 @@
else
to_chat(user, "<span class='warning'>You cannot afford to upgrade this ability! It costs [format_si_suffix(upgrade_cost)]W to upgrade.</span>")
/obj/effect/proc_holder/spell/pulse_demon/proc/do_upgrade(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/proc/do_upgrade(mob/living/simple_animal/demon/pulse_demon/user)
cooldown_handler.recharge_duration = round(base_cooldown / (1.5 ** spell_level))
to_chat(user, "<span class='notice'>You have upgraded [initial(name)] to level [spell_level + 1], it now takes [cooldown_handler.recharge_duration / 10] seconds to recharge.</span>")
/obj/effect/proc_holder/spell/pulse_demon/cablehop
/datum/spell/pulse_demon/cablehop
name = "Cable Hop"
desc = "Jump to another cable in view."
action_icon_state = "pd_cablehop"
@@ -127,7 +127,7 @@
cast_cost = 5 KW
upgrade_cost = 75 KW
/obj/effect/proc_holder/spell/pulse_demon/cablehop/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/cablehop/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
var/turf/O = get_turf(user)
var/turf/T = get_turf(target)
var/obj/structure/cable/C = locate(/obj/structure/cable) in T
@@ -145,7 +145,7 @@
user.Move(T)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/emagtamper
/datum/spell/pulse_demon/emagtamper
name = "Electromagnetic Tamper"
desc = "Unlocks hidden programming in machines. Must be inside a hijacked APC to use."
action_icon_state = "pd_emag"
@@ -154,12 +154,12 @@
upgrade_cost = 200 KW
requires_area = TRUE
/obj/effect/proc_holder/spell/pulse_demon/emagtamper/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/emagtamper/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
to_chat(user, "<span class='warning'>You attempt to tamper with [target]!</span>")
target.emag_act(user)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/emp
/datum/spell/pulse_demon/emp
name = "Electromagnetic Pulse"
desc = "Creates an EMP where you click. Be careful not to use it on yourself!"
action_icon_state = "pd_emp"
@@ -168,12 +168,12 @@
upgrade_cost = 200 KW
requires_area = TRUE
/obj/effect/proc_holder/spell/pulse_demon/emp/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/emp/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
to_chat(user, "<span class='warning'>You attempt to EMP [target]!</span>")
empulse(get_turf(target), 1, 1)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/overload
/datum/spell/pulse_demon/overload
name = "Overload Machine"
desc = "Overloads a machine, causing it to explode."
action_icon_state = "pd_overload"
@@ -182,7 +182,7 @@
upgrade_cost = 500 KW
requires_area = TRUE
/obj/effect/proc_holder/spell/pulse_demon/overload/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/overload/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
var/obj/machinery/M = target
if(!istype(M))
to_chat(user, "<span class='warning'>That is not a machine.</span>")
@@ -194,13 +194,13 @@
addtimer(CALLBACK(src, PROC_REF(detonate), M), 5 SECONDS)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/overload/proc/detonate(obj/machinery/target)
/datum/spell/pulse_demon/overload/proc/detonate(obj/machinery/target)
if(!QDELETED(target))
explosion(get_turf(target), 0, 1, 1, 0)
if(!QDELETED(target))
qdel(target)
/obj/effect/proc_holder/spell/pulse_demon/remotehijack
/datum/spell/pulse_demon/remotehijack
name = "Remote Hijack"
desc = "Remotely hijacks an APC."
action_icon_state = "pd_remotehack"
@@ -209,7 +209,7 @@
level_max = 0
base_cooldown = 3 SECONDS // you have to wait for the regular hijack time anyway
/obj/effect/proc_holder/spell/pulse_demon/remotehijack/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/remotehijack/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
var/obj/machinery/power/apc/A = target
if(!istype(A))
to_chat(user, "<span class='warning'>That is not an APC.</span>")
@@ -218,7 +218,7 @@
to_chat(user, "<span class='warning'>You cannot hijack that APC right now!</span>")
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/remotedrain
/datum/spell/pulse_demon/remotedrain
name = "Remote Drain"
desc = "Remotely drains a power source."
action_icon_state = "pd_remotedrain"
@@ -226,7 +226,7 @@
cast_cost = 100
upgrade_cost = 100 KW
/obj/effect/proc_holder/spell/pulse_demon/remotedrain/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/remotedrain/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
if(isapc(target))
var/drained = user.drain_APC(target, PULSEDEMON_REMOTE_DRAIN_MULTIPLIER)
if(drained == PULSEDEMON_SOURCE_DRAIN_INVALID)
@@ -241,20 +241,20 @@
return FALSE
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/toggle
/datum/spell/pulse_demon/toggle
base_cooldown = 0
cast_cost = 0
create_attack_logs = FALSE
var/base_message = "see messages you shouldn't!"
/obj/effect/proc_holder/spell/pulse_demon/toggle/New(initstate = FALSE)
/datum/spell/pulse_demon/toggle/New(initstate = FALSE)
. = ..()
do_toggle(initstate, null)
/obj/effect/proc_holder/spell/pulse_demon/toggle/create_new_targeting()
/datum/spell/pulse_demon/toggle/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/pulse_demon/toggle/proc/do_toggle(varstate, mob/user)
/datum/spell/pulse_demon/toggle/proc/do_toggle(varstate, mob/user)
if(action)
action.background_icon_state = varstate ? action_background_icon_state : "[action_background_icon_state]_disabled"
action.UpdateButtons()
@@ -262,7 +262,7 @@
to_chat(user, "<span class='notice'>You will [varstate ? "now" : "no longer"] [base_message]</span>")
return varstate
/obj/effect/proc_holder/spell/pulse_demon/toggle/do_drain
/datum/spell/pulse_demon/toggle/do_drain
name = "Toggle Draining"
desc = "Toggle whether you drain charge from power sources."
base_message = "drain charge from power sources."
@@ -270,11 +270,11 @@
locked = FALSE
level_max = 0
/obj/effect/proc_holder/spell/pulse_demon/toggle/do_drain/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/toggle/do_drain/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
user.do_drain = do_toggle(!user.do_drain, user)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/toggle/do_drain/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/toggle/do_drain/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
if(!istype(user))
return
@@ -288,7 +288,7 @@
user.power_drain_rate = amount
to_chat(user, "<span class='notice'>Drain speed has been set to [format_si_suffix(user.power_drain_rate)]W per second.</span>")
/obj/effect/proc_holder/spell/pulse_demon/toggle/can_exit_cable
/datum/spell/pulse_demon/toggle/can_exit_cable
name = "Toggle Self-Sustaining"
desc = "Toggle whether you can move outside of cables or power sources."
base_message = "move outside of cables."
@@ -297,18 +297,18 @@
upgrade_cost = 300 KW
level_max = 3
/obj/effect/proc_holder/spell/pulse_demon/toggle/can_exit_cable/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/toggle/can_exit_cable/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
if(user.can_exit_cable && !(user.current_cable || user.current_power))
to_chat(user, "<span class='warning'>Enter a cable or power source first!</span>")
return FALSE
user.can_exit_cable = do_toggle(!user.can_exit_cable, user)
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/toggle/can_exit_cable/do_upgrade(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/toggle/can_exit_cable/do_upgrade(mob/living/simple_animal/demon/pulse_demon/user)
user.outside_cable_speed = max(initial(user.outside_cable_speed) - spell_level, 1)
to_chat(user, "<span class='notice'>You have upgraded [initial(name)] to level [spell_level + 1], you will now move faster outside of cables.</span>")
/obj/effect/proc_holder/spell/pulse_demon/cycle_camera
/datum/spell/pulse_demon/cycle_camera
name = "Cycle Camera View"
desc = "Jump between the cameras in your APC's area. Alt-click to return to the APC."
action_icon_state = "pd_camera_view"
@@ -320,10 +320,10 @@
requires_area = TRUE
var/current_camera = 0
/obj/effect/proc_holder/spell/pulse_demon/cycle_camera/create_new_targeting()
/datum/spell/pulse_demon/cycle_camera/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/pulse_demon/cycle_camera/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/cycle_camera/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
if(!istype(user))
return
current_camera = 0
@@ -334,7 +334,7 @@
return
user.forceMove(user.current_power)
/obj/effect/proc_holder/spell/pulse_demon/cycle_camera/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/cycle_camera/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
if(!length(user.controlling_area.cameras))
return FALSE
@@ -352,7 +352,7 @@
user.forceMove(locateUID(user.controlling_area.cameras[current_camera + 1]))
return TRUE
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades
/datum/spell/pulse_demon/open_upgrades
name = "Open Upgrade Menu"
desc = "Open the upgrades menu. Alt-click for descriptions and costs."
action_icon_state = "pd_upgrade"
@@ -380,10 +380,10 @@
PD_UPGRADE_MAX_CHARGE = "Increase the total amount of charge you can have at once."
)
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades/create_new_targeting()
/datum/spell/pulse_demon/open_upgrades/create_new_targeting()
return new /datum/spell_targeting/self
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades/proc/calc_cost(mob/living/simple_animal/demon/pulse_demon/user, upgrade)
/datum/spell/pulse_demon/open_upgrades/proc/calc_cost(mob/living/simple_animal/demon/pulse_demon/user, upgrade)
var/cost
switch(upgrade)
if(PD_UPGRADE_HIJACK_SPEED)
@@ -416,7 +416,7 @@
return -1
return round(cost)
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades/proc/get_upgrades(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/open_upgrades/proc/get_upgrades(mob/living/simple_animal/demon/pulse_demon/user)
var/upgrades = list()
for(var/upgrade in upgrade_icons)
var/cost = calc_cost(user, upgrade)
@@ -425,7 +425,7 @@
upgrades["[upgrade] ([format_si_suffix(cost)]W)"] = upgrade_icons[upgrade]
return upgrades
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
/datum/spell/pulse_demon/open_upgrades/AltClick(mob/living/simple_animal/demon/pulse_demon/user)
if(!istype(user))
return
@@ -434,7 +434,7 @@
var/cost = calc_cost(user, upgrade)
to_chat(user, "<b>[upgrade]</b> ([cost == -1 ? "Fully Upgraded" : "[format_si_suffix(cost)]W"]) - [upgrade_descs[upgrade]]")
/obj/effect/proc_holder/spell/pulse_demon/open_upgrades/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
/datum/spell/pulse_demon/open_upgrades/try_cast_action(mob/living/simple_animal/demon/pulse_demon/user, atom/target)
var/upgrades = get_upgrades(user)
if(!length(upgrades))
to_chat(user, "<span class='warning'>You have already fully upgraded everything available!</span>")
@@ -192,13 +192,13 @@
to_chat(src, chat_box_red(messages.Join("<br>")))
/mob/living/simple_animal/revenant/proc/giveSpells()
mind.AddSpell(new /obj/effect/proc_holder/spell/night_vision/revenant(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/revenant_transmit(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/revenant/defile(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/revenant/malfunction(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/revenant/overload(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/revenant/haunt_object(null))
mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/revenant/hallucinations(null))
mind.AddSpell(new /datum/spell/night_vision/revenant(null))
mind.AddSpell(new /datum/spell/revenant_transmit(null))
mind.AddSpell(new /datum/spell/aoe/revenant/defile(null))
mind.AddSpell(new /datum/spell/aoe/revenant/malfunction(null))
mind.AddSpell(new /datum/spell/aoe/revenant/overload(null))
mind.AddSpell(new /datum/spell/aoe/revenant/haunt_object(null))
mind.AddSpell(new /datum/spell/aoe/revenant/hallucinations(null))
return TRUE
@@ -108,7 +108,7 @@
return
//Toggle night vision: lets the revenant toggle its night vision
/obj/effect/proc_holder/spell/night_vision/revenant
/datum/spell/night_vision/revenant
base_cooldown = 0
panel = "Revenant Abilities"
message = "<span class='revennotice'>You toggle your night vision.</span>"
@@ -116,7 +116,7 @@
action_background_icon_state = "bg_revenant"
//Transmit: the revemant's only direct way to communicate. Sends a single message silently to a single mob
/obj/effect/proc_holder/spell/revenant_transmit
/datum/spell/revenant_transmit
name = "Transmit"
desc = "Telepathically transmits a message to the target."
panel = "Revenant Abilities"
@@ -125,12 +125,12 @@
action_icon_state = "r_transmit"
action_background_icon_state = "bg_revenant"
/obj/effect/proc_holder/spell/revenant_transmit/create_new_targeting()
/datum/spell/revenant_transmit/create_new_targeting()
var/datum/spell_targeting/targeted/T = new()
T.allowed_type = /mob/living
return T
/obj/effect/proc_holder/spell/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/revenant_transmit/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
for(var/mob/living/M in targets)
spawn(0)
var/msg = tgui_input_text(user, "What do you wish to tell [M]?", "Transmit")
@@ -141,7 +141,7 @@
to_chat(user, "<span class='revennotice'><b>You transmit to [M]:</b> [msg]</span>")
to_chat(M, "<span class='revennotice'><b>An alien voice resonates from all around...</b></span><i> [msg]</I>")
/obj/effect/proc_holder/spell/aoe/revenant
/datum/spell/aoe/revenant
name = "Spell"
clothes_req = FALSE
action_background_icon_state = "bg_revenant"
@@ -157,20 +157,20 @@
/// How much essence it costs to use
var/cast_amount = 50
/obj/effect/proc_holder/spell/aoe/revenant/New()
/datum/spell/aoe/revenant/New()
..()
if(locked)
name = "[initial(name)] ([unlock_amount]E)"
else
name = "[initial(name)] ([cast_amount]E)"
/obj/effect/proc_holder/spell/aoe/revenant/revert_cast(mob/user)
/datum/spell/aoe/revenant/revert_cast(mob/user)
. = ..()
to_chat(user, "<span class='revennotice'>Your ability wavers and fails!</span>")
var/mob/living/simple_animal/revenant/R = user
R?.essence += cast_amount //refund the spell and reset
/obj/effect/proc_holder/spell/aoe/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, charge_check = TRUE, show_message = FALSE)
/datum/spell/aoe/revenant/can_cast(mob/living/simple_animal/revenant/user = usr, charge_check = TRUE, show_message = FALSE)
if(user.inhibited)
return FALSE
if(cooldown_handler.is_on_cooldown())
@@ -182,7 +182,7 @@
return FALSE
return TRUE
/obj/effect/proc_holder/spell/aoe/revenant/proc/attempt_cast(mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/proc/attempt_cast(mob/living/simple_animal/revenant/user = usr)
if(locked)
if(!user.castcheck(-unlock_amount))
cooldown_handler.revert_cast()
@@ -204,7 +204,7 @@
return TRUE
//Overload Light: Breaks a light that's online and sends out lightning bolts to all nearby people.
/obj/effect/proc_holder/spell/aoe/revenant/overload
/datum/spell/aoe/revenant/overload
name = "Overload Lights"
desc = "Directs a large amount of essence into nearby electrical lights, causing lights to shock those nearby."
base_cooldown = 20 SECONDS
@@ -215,21 +215,21 @@
action_icon_state = "overload_lights"
aoe_range = 5
/obj/effect/proc_holder/spell/aoe/revenant/overload/create_new_targeting()
/datum/spell/aoe/revenant/overload/create_new_targeting()
var/datum/spell_targeting/aoe/targeting = new()
targeting.range = aoe_range
targeting.allowed_type = /obj/machinery/light
return targeting
/obj/effect/proc_holder/spell/aoe/revenant/overload/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/overload/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(attempt_cast(user))
for(var/obj/machinery/light/L as anything in targets)
INVOKE_ASYNC(src, PROC_REF(shock_lights), L, user)
/obj/effect/proc_holder/spell/aoe/revenant/overload/proc/shock_lights(obj/machinery/light/L, mob/living/simple_animal/revenant/user)
/datum/spell/aoe/revenant/overload/proc/shock_lights(obj/machinery/light/L, mob/living/simple_animal/revenant/user)
if(!L.on)
return
L.visible_message("<span class='warning'><b>\The [L] suddenly flares brightly and begins to spark!</span>")
L.visible_message("<span class='warning'><b>\The [L] suddenly flares brightly and begins to spark!</b></span>")
do_sparks(4, 0, L)
new /obj/effect/temp_visual/revenant(L.loc)
sleep(2 SECONDS)
@@ -246,7 +246,7 @@
playsound(M, 'sound/machines/defib_zap.ogg', 50, TRUE, -1)
//Defile: Corrupts nearby stuff, unblesses floor tiles.
/obj/effect/proc_holder/spell/aoe/revenant/defile
/datum/spell/aoe/revenant/defile
name = "Defile"
desc = "Twists and corrupts the nearby area as well as dispelling holy auras on floors."
base_cooldown = 15 SECONDS
@@ -257,12 +257,12 @@
action_icon_state = "defile"
aoe_range = 4
/obj/effect/proc_holder/spell/aoe/revenant/defile/create_new_targeting()
/datum/spell/aoe/revenant/defile/create_new_targeting()
var/datum/spell_targeting/aoe/turf/targeting = new()
targeting.range = aoe_range
return targeting
/obj/effect/proc_holder/spell/aoe/revenant/defile/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/defile/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(!attempt_cast(user))
return
for(var/turf/T in targets)
@@ -271,7 +271,7 @@
A.defile()
//Malfunction: Makes bad stuff happen to robots and machines.
/obj/effect/proc_holder/spell/aoe/revenant/malfunction
/datum/spell/aoe/revenant/malfunction
name = "Malfunction"
desc = "Corrupts and damages nearby machines and mechanical objects."
base_cooldown = 200
@@ -280,18 +280,18 @@
action_icon_state = "malfunction"
aoe_range = 2
/obj/effect/proc_holder/spell/aoe/revenant/malfunction/create_new_targeting()
/datum/spell/aoe/revenant/malfunction/create_new_targeting()
var/datum/spell_targeting/aoe/turf/targeting = new()
targeting.range = aoe_range
return targeting
//A note to future coders: do not replace this with an EMP because it will wreck malf AIs and gang dominators and everyone will hate you.
/obj/effect/proc_holder/spell/aoe/revenant/malfunction/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/malfunction/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(attempt_cast(user))
for(var/turf/T in targets)
INVOKE_ASYNC(src, PROC_REF(effect), user, T)
/obj/effect/proc_holder/spell/aoe/revenant/malfunction/proc/effect(mob/living/simple_animal/revenant/user, turf/T)
/datum/spell/aoe/revenant/malfunction/proc/effect(mob/living/simple_animal/revenant/user, turf/T)
T.rev_malfunction(TRUE)
for(var/atom/A in T.contents)
A.rev_malfunction(TRUE)
@@ -299,7 +299,7 @@
/**
* Makes objects be haunted and then throws them at conscious people to do damage, spooky!
*/
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object
/datum/spell/aoe/revenant/haunt_object
name = "Haunt Objects"
desc = "Empower nearby objects to you with ghostly energy, causing them to attack nearby mortals. \
Items closer to you are more likely to be haunted."
@@ -315,13 +315,13 @@
/// A list of all attack timers started by this spell being cast
var/list/attack_timers = list()
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/create_new_targeting()
/datum/spell/aoe/revenant/haunt_object/create_new_targeting()
var/datum/spell_targeting/aoe/targeting = new()
targeting.range = aoe_range
targeting.allowed_type = /obj/item
return targeting
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/haunt_object/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(!attempt_cast(user))
return
@@ -357,7 +357,7 @@
addtimer(CALLBACK(src, PROC_REF(stop_timers)), 65 SECONDS, TIMER_UNIQUE)
/// Handles making an object haunted and setting it up to attack
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/proc/make_spooky(obj/item/item_to_possess, mob/living/simple_animal/revenant/user)
/datum/spell/aoe/revenant/haunt_object/proc/make_spooky(obj/item/item_to_possess, mob/living/simple_animal/revenant/user)
new /obj/effect/temp_visual/revenant(get_turf(item_to_possess)) // Thematic spooky visuals
var/mob/living/simple_animal/possessed_object/possessed_object = new(item_to_possess) // Begin haunting object
item_to_possess.throwforce = min(item_to_possess.throwforce + 5, 15) // Damage it should do? throwforce+5 or 15, whichever is lower
@@ -372,7 +372,7 @@
addtimer(CALLBACK(possessed_object, TYPE_PROC_REF(/mob/living/simple_animal/possessed_object, death)), 70 SECONDS, TIMER_UNIQUE) // De-haunt the object
/// Handles finding a valid target and throwing us at it
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/proc/attack(mob/living/simple_animal/possessed_object/possessed_object, mob/living/simple_animal/revenant/user)
/datum/spell/aoe/revenant/haunt_object/proc/attack(mob/living/simple_animal/possessed_object/possessed_object, mob/living/simple_animal/revenant/user)
var/list/potential_victims = list()
for(var/turf/turf_to_search in spiral_range_turfs(aoe_range, get_turf(possessed_object)))
for(var/mob/living/carbon/potential_victim in turf_to_search)
@@ -393,20 +393,20 @@
possessed_object.throw_at(victim, aoe_range, 2, user, dodgeable = FALSE)
/// Sets the glow on the haunted object, scales up based on throwforce
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/proc/set_outline(mob/living/simple_animal/possessed_object/possessed_object)
/datum/spell/aoe/revenant/haunt_object/proc/set_outline(mob/living/simple_animal/possessed_object/possessed_object)
possessed_object.remove_filter("haunt_glow")
var/outline_size = min((possessed_object.possessed_item.throwforce / 15) * 3, 3)
possessed_object.add_filter("haunt_glow", 2, list("type" = "outline", "color" = "#7A4FA9", "size" = outline_size)) // Give it spooky purple outline
/// Stop all attack timers cast by the previous spell use
/obj/effect/proc_holder/spell/aoe/revenant/haunt_object/proc/stop_timers()
/datum/spell/aoe/revenant/haunt_object/proc/stop_timers()
for(var/I in attack_timers)
deltimer(I)
/**
* Gives everyone in a 7 tile radius 2 minutes of hallucinations
*/
/obj/effect/proc_holder/spell/aoe/revenant/hallucinations
/datum/spell/aoe/revenant/hallucinations
name = "Hallucination Aura"
desc = "Toy with the living nearby, giving them glimpses of things that could be or once were."
action_icon_state = "hallucinations"
@@ -416,13 +416,13 @@
stun = 1 SECONDS
reveal = 3 SECONDS
/obj/effect/proc_holder/spell/aoe/revenant/hallucinations/create_new_targeting()
/datum/spell/aoe/revenant/hallucinations/create_new_targeting()
var/datum/spell_targeting/aoe/targeting = new()
targeting.range = aoe_range
targeting.allowed_type = /mob/living/carbon
return targeting
/obj/effect/proc_holder/spell/aoe/revenant/hallucinations/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
/datum/spell/aoe/revenant/hallucinations/cast(list/targets, mob/living/simple_animal/revenant/user = usr)
if(!attempt_cast(user))
return
+1 -1
View File
@@ -3,7 +3,7 @@
desc = "High Five?"
var/catchphrase = "High Five!"
var/on_use_sound = null
var/obj/effect/proc_holder/spell/touch/attached_spell
var/datum/spell/touch/attached_spell
icon = 'icons/obj/weapons/magical_weapons.dmi'
icon_state = "disintegrate"
item_state = null
+3 -3
View File
@@ -400,9 +400,9 @@
if(SS.purified)
make_holy()
// Replace regular soulstone summoning with purified soulstones
if(is_type_in_list(/obj/effect/proc_holder/spell/aoe/conjure/build/soulstone, mob_spell_list))
RemoveSpell(/obj/effect/proc_holder/spell/aoe/conjure/build/soulstone)
AddSpell(new /obj/effect/proc_holder/spell/aoe/conjure/build/soulstone/holy)
if(is_type_in_list(/datum/spell/aoe/conjure/build/soulstone, mob_spell_list))
RemoveSpell(/datum/spell/aoe/conjure/build/soulstone)
AddSpell(new /datum/spell/aoe/conjure/build/soulstone/holy)
else if(mind.has_antag_datum(/datum/antagonist/cultist)) // Re-grant cult actions, lost in the transfer
var/datum/action/innate/cult/comm/CC = new
+58 -58
View File
@@ -6,7 +6,7 @@
var/category = "Offensive"
var/cost = 2
var/refundable = TRUE
var/obj/effect/proc_holder/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell
var/datum/spell/S = null //Since spellbooks can be used by only one person anyway we can track the actual spell
var/buy_word = "Learn"
var/limit //used to prevent a spellbook_entry from being bought more than X times with one wizard spellbook
@@ -21,8 +21,8 @@
return LearnSpell(user, book, S)
/datum/spellbook_entry/proc/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, obj/effect/proc_holder/spell/newspell)
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
/datum/spellbook_entry/proc/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, datum/spell/newspell)
for(var/datum/spell/aspell in user.mind.spell_list)
if(initial(newspell.name) == initial(aspell.name)) // Not using directly in case it was learned from one spellbook then upgraded in another
if(aspell.spell_level >= aspell.level_max)
to_chat(user, "<span class='warning'>This spell cannot be improved further.</span>")
@@ -59,7 +59,7 @@
return FALSE
if(!S)
S = new spell_type()
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
for(var/datum/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
return TRUE
return FALSE
@@ -72,7 +72,7 @@
if(!S) //This happens when the spell's source is from another spellbook, from loadouts, or adminery, this create a new template temporary spell
S = new spell_type()
var/spell_levels = 0
for(var/obj/effect/proc_holder/spell/aspell in user.mind.spell_list)
for(var/datum/spell/aspell in user.mind.spell_list)
if(initial(S.name) == initial(aspell.name))
spell_levels = aspell.spell_level
user.mind.spell_list.Remove(aspell)
@@ -97,126 +97,126 @@
//Offensive
/datum/spellbook_entry/blind
name = "Blind"
spell_type = /obj/effect/proc_holder/spell/trigger/blind
spell_type = /datum/spell/genetic/blind
category = "Offensive"
cost = 1
/datum/spellbook_entry/lightningbolt
name = "Lightning Bolt"
spell_type = /obj/effect/proc_holder/spell/charge_up/bounce/lightning
spell_type = /datum/spell/charge_up/bounce/lightning
category = "Offensive"
cost = 1
/datum/spellbook_entry/cluwne
name = "Curse of the Cluwne"
spell_type = /obj/effect/proc_holder/spell/touch/cluwne
spell_type = /datum/spell/touch/cluwne
category = "Offensive"
/datum/spellbook_entry/banana_touch
name = "Banana Touch"
spell_type = /obj/effect/proc_holder/spell/touch/banana
spell_type = /datum/spell/touch/banana
cost = 1
/datum/spellbook_entry/mime_malaise
name = "Mime Malaise"
spell_type = /obj/effect/proc_holder/spell/touch/mime_malaise
spell_type = /datum/spell/touch/mime_malaise
cost = 1
/datum/spellbook_entry/horseman
name = "Curse of the Horseman"
spell_type = /obj/effect/proc_holder/spell/horsemask
spell_type = /datum/spell/horsemask
category = "Offensive"
/datum/spellbook_entry/disintegrate
name = "Disintegrate"
spell_type = /obj/effect/proc_holder/spell/touch/disintegrate
spell_type = /datum/spell/touch/disintegrate
category = "Offensive"
/datum/spellbook_entry/fireball
name = "Fireball"
spell_type = /obj/effect/proc_holder/spell/fireball
spell_type = /datum/spell/fireball
category = "Offensive"
/datum/spellbook_entry/summon_toolbox
name = "Homing Toolbox"
spell_type = /obj/effect/proc_holder/spell/fireball/toolbox
spell_type = /datum/spell/fireball/toolbox
category = "Offensive"
cost = 1
/datum/spellbook_entry/fleshtostone
name = "Flesh to Stone"
spell_type = /obj/effect/proc_holder/spell/touch/flesh_to_stone
spell_type = /datum/spell/touch/flesh_to_stone
category = "Offensive"
/datum/spellbook_entry/mutate
name = "Mutate"
spell_type = /obj/effect/proc_holder/spell/genetic/mutate
spell_type = /datum/spell/genetic/mutate
category = "Offensive"
/datum/spellbook_entry/rod_form
name = "Rod Form"
spell_type = /obj/effect/proc_holder/spell/rod_form
spell_type = /datum/spell/rod_form
category = "Offensive"
/datum/spellbook_entry/infinite_guns
name = "Lesser Summon Guns"
spell_type = /obj/effect/proc_holder/spell/infinite_guns
spell_type = /datum/spell/infinite_guns
category = "Offensive"
//Defensive
/datum/spellbook_entry/disabletech
name = "Disable Tech"
spell_type = /obj/effect/proc_holder/spell/emplosion/disable_tech
spell_type = /datum/spell/emplosion/disable_tech
category = "Defensive"
cost = 1
/datum/spellbook_entry/forcewall
name = "Force Wall"
spell_type = /obj/effect/proc_holder/spell/forcewall
spell_type = /datum/spell/forcewall
category = "Defensive"
cost = 1
/datum/spellbook_entry/rathens
name = "Rathen's Secret"
spell_type = /obj/effect/proc_holder/spell/rathens
spell_type = /datum/spell/rathens
category = "Defensive"
cost = 2
/datum/spellbook_entry/repulse
name = "Repulse"
spell_type = /obj/effect/proc_holder/spell/aoe/repulse
spell_type = /datum/spell/aoe/repulse
category = "Defensive"
cost = 1
/datum/spellbook_entry/smoke
name = "Smoke"
spell_type = /obj/effect/proc_holder/spell/smoke
spell_type = /datum/spell/smoke
category = "Defensive"
cost = 1
/datum/spellbook_entry/lichdom
name = "Bind Soul"
spell_type = /obj/effect/proc_holder/spell/lichdom
spell_type = /datum/spell/lichdom
category = "Defensive"
is_ragin_restricted = TRUE
/datum/spellbook_entry/magicm
name = "Magic Missile"
spell_type = /obj/effect/proc_holder/spell/projectile/magic_missile
spell_type = /datum/spell/projectile/magic_missile
category = "Defensive"
/datum/spellbook_entry/timestop
name = "Time Stop"
spell_type = /obj/effect/proc_holder/spell/aoe/conjure/timestop
spell_type = /datum/spell/aoe/conjure/timestop
category = "Defensive"
/datum/spellbook_entry/sacred_flame
name = "Sacred Flame and Fire Immunity"
spell_type = /obj/effect/proc_holder/spell/sacred_flame
spell_type = /datum/spell/sacred_flame
cost = 1
category = "Defensive"
/datum/spellbook_entry/sacred_flame/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, obj/effect/proc_holder/spell/newspell)
/datum/spellbook_entry/sacred_flame/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, datum/spell/newspell)
to_chat(user, "<span class='notice'>You feel fireproof.</span>")
ADD_TRAIT(user, TRAIT_RESISTHEAT, MAGIC_TRAIT)
ADD_TRAIT(user, TRAIT_RESISTHIGHPRESSURE, MAGIC_TRAIT)
@@ -230,11 +230,11 @@
/datum/spellbook_entry/summon_supermatter
name = "Summon Supermatter Crystal"
spell_type = /obj/effect/proc_holder/spell/aoe/conjure/summon_supermatter
spell_type = /datum/spell/aoe/conjure/summon_supermatter
cost = 3
category = "Defensive"
/datum/spellbook_entry/summon_supermatter/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, obj/effect/proc_holder/spell/newspell)
/datum/spellbook_entry/summon_supermatter/LearnSpell(mob/living/carbon/human/user, obj/item/spellbook/book, datum/spell/newspell)
to_chat(user, "<span class='notice'>You feel a little bit of supermatter enter your body.</span>")
ADD_TRAIT(user, TRAIT_RADIMMUNE, MAGIC_TRAIT)
ADD_TRAIT(user, SM_HALLUCINATION_IMMUNE, MAGIC_TRAIT)
@@ -249,64 +249,64 @@
//Mobility
/datum/spellbook_entry/knock
name = "Knock"
spell_type = /obj/effect/proc_holder/spell/aoe/knock
spell_type = /datum/spell/aoe/knock
category = "Mobility"
cost = 1
/datum/spellbook_entry/blink
name = "Blink"
spell_type = /obj/effect/proc_holder/spell/turf_teleport/blink
spell_type = /datum/spell/turf_teleport/blink
category = "Mobility"
/datum/spellbook_entry/jaunt
name = "Ethereal Jaunt"
spell_type = /obj/effect/proc_holder/spell/ethereal_jaunt
spell_type = /datum/spell/ethereal_jaunt
category = "Mobility"
/datum/spellbook_entry/spacetime_dist
name = "Spacetime Distortion"
spell_type = /obj/effect/proc_holder/spell/spacetime_dist
spell_type = /datum/spell/spacetime_dist
cost = 1 //Better defence than greater forcewall (maybe) but good luck hitting anyone, so 1 point.
category = "Mobility"
/datum/spellbook_entry/greaterknock
name = "Greater Knock"
spell_type = /obj/effect/proc_holder/spell/aoe/knock/greater
spell_type = /datum/spell/aoe/knock/greater
category = "Mobility"
refundable = 0 //global effect on cast
/datum/spellbook_entry/mindswap
name = "Mindswap"
spell_type = /obj/effect/proc_holder/spell/mind_transfer
spell_type = /datum/spell/mind_transfer
category = "Mobility"
/datum/spellbook_entry/teleport
name = "Teleport"
spell_type = /obj/effect/proc_holder/spell/area_teleport/teleport
spell_type = /datum/spell/area_teleport/teleport
category = "Mobility"
//Assistance
/datum/spellbook_entry/charge
name = "Charge"
spell_type = /obj/effect/proc_holder/spell/charge
spell_type = /datum/spell/charge
category = "Assistance"
cost = 1
/datum/spellbook_entry/summonitem
name = "Summon Item"
spell_type = /obj/effect/proc_holder/spell/summonitem
spell_type = /datum/spell/summonitem
category = "Assistance"
cost = 1
/datum/spellbook_entry/disguiseself
name = "Disguise Self"
spell_type = /obj/effect/proc_holder/spell/disguise_self
spell_type = /datum/spell/disguise_self
category = "Assistance"
cost = 1
/datum/spellbook_entry/noclothes
name = "Remove Clothes Requirement"
spell_type = /obj/effect/proc_holder/spell/noclothes
spell_type = /datum/spell/noclothes
category = "Assistance"
cost = 1
@@ -433,7 +433,7 @@
/datum/spellbook_entry/item/soulstones/Buy(mob/living/carbon/human/user, obj/item/spellbook/book)
. = ..()
if(.)
user.mind.AddSpell(new /obj/effect/proc_holder/spell/aoe/conjure/construct(null))
user.mind.AddSpell(new /datum/spell/aoe/conjure/construct(null))
return .
/datum/spellbook_entry/item/wands
@@ -676,7 +676,7 @@
new path(B)
user.put_in_hands(B)
for(var/path in spells_path)
var/obj/effect/proc_holder/spell/S = new path()
var/datum/spell/S = new path()
LearnSpell(user, book, S)
OnBuy(user, book)
return TRUE
@@ -946,7 +946,7 @@
//Single Use Spellbooks
/obj/item/spellbook/oneuse
var/spell = /obj/effect/proc_holder/spell/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic
var/spell = /datum/spell/projectile/magic_missile //just a placeholder to avoid runtimes if someone spawned the generic
var/spellname = "sandbox"
var/used = FALSE
name = "spellbook of "
@@ -961,8 +961,8 @@
return
/obj/item/spellbook/oneuse/attack_self(mob/user)
var/obj/effect/proc_holder/spell/S = new spell
for(var/obj/effect/proc_holder/spell/knownspell in user.mind.spell_list)
var/datum/spell/S = new spell
for(var/datum/spell/knownspell in user.mind.spell_list)
if(knownspell.type == S.type)
if(user.mind)
if(user.mind.special_role == SPECIAL_ROLE_WIZARD_APPRENTICE || user.mind.special_role == SPECIAL_ROLE_WIZARD)
@@ -990,7 +990,7 @@
return
/obj/item/spellbook/oneuse/fireball
spell = /obj/effect/proc_holder/spell/fireball
spell = /datum/spell/fireball
spellname = "fireball"
icon_state = "bookfireball"
desc = "This book feels warm to the touch."
@@ -1001,7 +1001,7 @@
qdel(src)
/obj/item/spellbook/oneuse/smoke
spell = /obj/effect/proc_holder/spell/smoke
spell = /datum/spell/smoke
spellname = "smoke"
icon_state = "booksmoke"
desc = "This book is overflowing with the dank arts."
@@ -1012,7 +1012,7 @@
user.adjust_nutrition(-200)
/obj/item/spellbook/oneuse/blind
spell = /obj/effect/proc_holder/spell/trigger/blind
spell = /datum/spell/genetic/blind
spellname = "blind"
icon_state = "bookblind"
desc = "This book looks blurry, no matter how you look at it."
@@ -1025,7 +1025,7 @@
L.EyeBlind(20 SECONDS)
/obj/item/spellbook/oneuse/mindswap
spell = /obj/effect/proc_holder/spell/mind_transfer
spell = /datum/spell/mind_transfer
spellname = "mindswap"
icon_state = "bookmindswap"
desc = "This book's cover is pristine, though its pages look ragged and torn."
@@ -1049,7 +1049,7 @@
to_chat(user, "<span class='notice'>You stare at the book some more, but there doesn't seem to be anything else to learn...</span>")
return
var/obj/effect/proc_holder/spell/mind_transfer/swapper = new
var/datum/spell/mind_transfer/swapper = new
swapper.cast(user, stored_swap)
to_chat(stored_swap, "<span class='warning'>You're suddenly somewhere else... and someone else?!</span>")
@@ -1057,7 +1057,7 @@
stored_swap = null
/obj/item/spellbook/oneuse/forcewall
spell = /obj/effect/proc_holder/spell/forcewall
spell = /datum/spell/forcewall
spellname = "forcewall"
icon_state = "bookforcewall"
desc = "This book has a dedication to mimes everywhere inside the front cover."
@@ -1070,7 +1070,7 @@
user.drop_item()
/obj/item/spellbook/oneuse/knock
spell = /obj/effect/proc_holder/spell/aoe/knock
spell = /datum/spell/aoe/knock
spellname = "knock"
icon_state = "bookknock"
desc = "This book is hard to hold closed properly."
@@ -1081,7 +1081,7 @@
user.Weaken(40 SECONDS)
/obj/item/spellbook/oneuse/horsemask
spell = /obj/effect/proc_holder/spell/horsemask
spell = /datum/spell/horsemask
spellname = "horses"
icon_state = "bookhorses"
desc = "This book is more horse than your mind has room for."
@@ -1101,7 +1101,7 @@
to_chat(user, "<span class='notice'>I say thee neigh</span>")
/obj/item/spellbook/oneuse/charge
spell = /obj/effect/proc_holder/spell/charge
spell = /datum/spell/charge
spellname = "charging"
icon_state = "bookcharge"
desc = "This book is made of 100% post-consumer wizard."
@@ -1112,7 +1112,7 @@
empulse(src, 1, 1)
/obj/item/spellbook/oneuse/summonitem
spell = /obj/effect/proc_holder/spell/summonitem
spell = /datum/spell/summonitem
spellname = "instant summons"
icon_state = "booksummons"
desc = "This book is bright and garish, very hard to miss."
@@ -1123,13 +1123,13 @@
qdel(src)
/obj/item/spellbook/oneuse/fake_gib
spell = /obj/effect/proc_holder/spell/touch/fake_disintegrate
spell = /datum/spell/touch/fake_disintegrate
spellname = "disintegrate"
icon_state = "bookfireball"
desc = "This book feels like it will rip stuff apart."
/obj/item/spellbook/oneuse/sacredflame
spell = /obj/effect/proc_holder/spell/sacred_flame
spell = /datum/spell/sacred_flame
spellname = "sacred flame"
icon_state = "booksacredflame"
desc = "Become one with the flames that burn within... and invite others to do so as well."
+2 -2
View File
@@ -122,13 +122,13 @@
/mob/proc/spellremove()
if(!mind)
return
for(var/obj/effect/proc_holder/spell/spell_to_remove in mind.spell_list)
for(var/datum/spell/spell_to_remove in mind.spell_list)
qdel(spell_to_remove)
mind.spell_list -= spell_to_remove
//To batch-remove mob spells.
/mob/proc/mobspellremove()
for(var/obj/effect/proc_holder/spell/spell_to_remove in mob_spell_list)
for(var/datum/spell/spell_to_remove in mob_spell_list)
qdel(spell_to_remove)
mob_spell_list -= spell_to_remove
+17 -17
View File
@@ -7,8 +7,8 @@
Ethereal Jaunt and Blink provide escape and mobility, while Magic Missile and Disintegrate can be used together for dangerous or key targets. <br> \
As this set lacks any form of healing or resurrection, healing items should be acquired from the station, and you should be careful to avoid being hurt in the first place. <br><br> \
</i>Provides Mutate, Ethereal Jaunt, Blink, Magic Missile, and Disintegrate.<i>"
spells_path = list(/obj/effect/proc_holder/spell/genetic/mutate, /obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/turf_teleport/blink, \
/obj/effect/proc_holder/spell/projectile/magic_missile, /obj/effect/proc_holder/spell/touch/disintegrate)
spells_path = list(/datum/spell/genetic/mutate, /datum/spell/ethereal_jaunt, /datum/spell/turf_teleport/blink, \
/datum/spell/projectile/magic_missile, /datum/spell/touch/disintegrate)
/datum/spellbook_entry/loadout/lich
name = "Defense Focus - Lich"
@@ -16,8 +16,8 @@
Ethereal Jaunt provides escape, Fireball and Rod Form are your offensive spells, and Disable Tech and Forcewall provides utility in disabling sec equipment or blocking their path. <br> \
Care should be taken in hiding the item you choose as your phylactery after using Bind Soul, as you cannot revive if it destroyed or too far from your body! <br><br> \
</i>Provides Bind Soul, Ethereal Jaunt, Fireball, Rod Form, Disable Tech, and Greater Forcewall.<i>"
spells_path = list(/obj/effect/proc_holder/spell/lichdom, /obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/fireball, \
/obj/effect/proc_holder/spell/rod_form, /obj/effect/proc_holder/spell/emplosion/disable_tech, /obj/effect/proc_holder/spell/forcewall)
spells_path = list(/datum/spell/lichdom, /datum/spell/ethereal_jaunt, /datum/spell/fireball, \
/datum/spell/rod_form, /datum/spell/emplosion/disable_tech, /datum/spell/forcewall)
is_ragin_restricted = TRUE
/datum/spellbook_entry/loadout/wands
@@ -27,8 +27,8 @@
Do not lose any of your wands to the station's crew, as they are extremely deadly even in their hands. Remember that the Revive wand can be used on yourself for a full heal! <br><br> \
</i>Provides a Belt of Wands, Charge, Ethereal Jaunt, Blink, Repulse, and Disintegrate.<i>"
items_path = list(/obj/item/storage/belt/wands/full)
spells_path = list(/obj/effect/proc_holder/spell/charge, /obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/turf_teleport/blink, \
/obj/effect/proc_holder/spell/aoe/repulse, /obj/effect/proc_holder/spell/touch/disintegrate)
spells_path = list(/datum/spell/charge, /datum/spell/ethereal_jaunt, /datum/spell/turf_teleport/blink, \
/datum/spell/aoe/repulse, /datum/spell/touch/disintegrate)
//Unique loadouts, which are more gimmicky. Should contain some unique spell or item that separates it from just buying standard wiz spells, and be balanced around a 10 spell point cost.
/datum/spellbook_entry/loadout/mimewiz
@@ -37,14 +37,14 @@
</i>Provides Finger Gun and Invisible Greater Wall manuals, Mime Robes, a Cane and Duct Tape, Ethereal Jaunt, Blink, Teleport, Mime Malaise, Knock, and Stop Time.<i>"
items_path = list(/obj/item/spellbook/oneuse/mime/fingergun, /obj/item/spellbook/oneuse/mime/greaterwall, /obj/item/clothing/suit/wizrobe/mime, /obj/item/clothing/head/wizard/mime, \
/obj/item/clothing/mask/gas/mime/wizard, /obj/item/clothing/shoes/sandal/marisa, /obj/item/cane, /obj/item/stack/tape_roll)
spells_path = list(/obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/turf_teleport/blink, /obj/effect/proc_holder/spell/area_teleport/teleport, \
/obj/effect/proc_holder/spell/touch/mime_malaise, /obj/effect/proc_holder/spell/aoe/knock, /obj/effect/proc_holder/spell/aoe/conjure/timestop)
spells_path = list(/datum/spell/ethereal_jaunt, /datum/spell/turf_teleport/blink, /datum/spell/area_teleport/teleport, \
/datum/spell/touch/mime_malaise, /datum/spell/aoe/knock, /datum/spell/aoe/conjure/timestop)
category = "Unique"
destroy_spellbook = TRUE
/datum/spellbook_entry/loadout/mimewiz/OnBuy(mob/living/carbon/human/user, obj/item/spellbook/book)
if(user.mind)
user.mind.AddSpell(new /obj/effect/proc_holder/spell/mime/speak(null))
user.mind.AddSpell(new /datum/spell/mime/speak(null))
user.mind.miming = TRUE
/datum/spellbook_entry/loadout/gunreaper
@@ -54,13 +54,13 @@
You will likely need to scavenge additional ammo or weapons aboard the station. <br><br>\
</i>Provides a .357 Revolver, 4 speedloaders of ammo, Ethereal Jaunt, Blink, Summon Item, No Clothes, and Bind Soul, with a unique outfit.<i>"
items_path = list(/obj/item/gun/projectile/revolver, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/ammo_box/a357, /obj/item/clothing/under/syndicate)
spells_path = list(/obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/turf_teleport/blink, \
/obj/effect/proc_holder/spell/summonitem, /obj/effect/proc_holder/spell/noclothes, /obj/effect/proc_holder/spell/lichdom/gunslinger)
spells_path = list(/datum/spell/ethereal_jaunt, /datum/spell/turf_teleport/blink, \
/datum/spell/summonitem, /datum/spell/noclothes, /datum/spell/lichdom/gunslinger)
category = "Unique"
destroy_spellbook = TRUE
is_ragin_restricted = TRUE
/obj/effect/proc_holder/spell/lichdom/gunslinger/equip_lich(mob/living/carbon/human/H)
/datum/spell/lichdom/gunslinger/equip_lich(mob/living/carbon/human/H)
H.equip_to_slot_or_del(new /obj/item/clothing/suit/storage/det_suit(H), SLOT_HUD_OUTER_SUIT)
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/combat(H), SLOT_HUD_SHOES)
H.equip_to_slot_or_del(new /obj/item/clothing/gloves/combat(H), SLOT_HUD_GLOVES)
@@ -74,8 +74,8 @@
</i>Provides His Grace, an Ancient Jumpsuit, an Assistant ID, a Gas Mask and Shoes, Insulated Gloves, a full Toolbelt, Ethereal Jaunt, Force Wall, Homing Toolbox, Knock and No Clothes.<i>"
items_path = list(/obj/item/his_grace, /obj/item/clothing/under/color/grey/glorf, /obj/item/clothing/mask/gas, /obj/item/clothing/shoes/black, \
/obj/item/clothing/gloves/color/yellow, /obj/item/storage/belt/utility/full/multitool)
spells_path = list(/obj/effect/proc_holder/spell/ethereal_jaunt, /obj/effect/proc_holder/spell/forcewall, \
/obj/effect/proc_holder/spell/aoe/knock, /obj/effect/proc_holder/spell/noclothes, /obj/effect/proc_holder/spell/fireball/toolbox)
spells_path = list(/datum/spell/ethereal_jaunt, /datum/spell/forcewall, \
/datum/spell/aoe/knock, /datum/spell/noclothes, /datum/spell/fireball/toolbox)
category = "Unique"
destroy_spellbook = TRUE
@@ -111,8 +111,8 @@
items_path = list(/obj/item/supermatter_halberd, /obj/item/clothing/gloves/color/white/supermatter_immune, \
/obj/item/clothing/suit/hooded/oblivion, /obj/item/clothing/mask/gas/voice_modulator/oblivion, /obj/item/tank/internals/emergency_oxygen/double, \
/obj/item/clothing/under/color/white/enforcer, /obj/item/clothing/shoes/white/enforcer)
spells_path = list(/obj/effect/proc_holder/spell/summonitem, /obj/effect/proc_holder/spell/charge_up/bounce/lightning, \
/obj/effect/proc_holder/spell/aoe/conjure/summon_supermatter)
spells_path = list(/datum/spell/summonitem, /datum/spell/charge_up/bounce/lightning, \
/datum/spell/aoe/conjure/summon_supermatter)
category = "Unique"
destroy_spellbook = TRUE
@@ -125,7 +125,7 @@
name = "Fireball. Fireball. Fireball."
desc = "Who cares about the rest of the spells. Become an expert in fire magic. Devote yourself to the craft. The only spell you need anyways is <b>Fireball.</b><br>\
</i>Provides fire immunity, homing fireballs, rapid-fire fireballs, and some fireball wands. Provides no mobility spells. Replaces your robes with infernal versions.<i>"
spells_path = list(/obj/effect/proc_holder/spell/sacred_flame, /obj/effect/proc_holder/spell/fireball/homing, /obj/effect/proc_holder/spell/infinite_guns/fireball)
spells_path = list(/datum/spell/sacred_flame, /datum/spell/fireball/homing, /datum/spell/infinite_guns/fireball)
category = "Unique"
destroy_spellbook = TRUE

Some files were not shown because too many files have changed in this diff Show More