mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-23 20:16:55 +01:00
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:
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user