Psionics Rework: Kyoushiki Murasaki (#16951)

* Your unbeatable smile wrecks the media

 We wanna know your secret, so mysterious

* Even the things she lacks end up in her area

Such a perfect liar, you are

* Miss ingenious, godly idol!

(You're my savior, you're my saving grace)

* So, what'd you eat today?

What's your favorite book?

* And if you wanna go to play, where are you gonna go?

I haven't eaten at all

* That's a secret

No matter what you ask

* She's elusive, evasive

* So nonchalant

Yet still shining bright;

* Her secret: out of sight, as if visible, has the taste of honey

There is none, none, none of this

* And also none, none, none of that

What type of guy do you like?

* Who is your partner?

Come on, answer me

* "I don't understand what falling in love with someone else is like" (Hey! Hey!)

I cannot tell what is true from what is a lie (Hey! Hey! Hey! Hey!)

* And yet again, someone falls for such words (Hey! Hey! Hey! Hey!)

Gently lulled into love

* Drawing everyone's eyes

You are the perfect, ultimate idol

* Never to appear again

A reincarnation of Venus

* With that smile, with that "I love you"

You captivate everyone

* Even if those eyes, those words, are false

They make up a perfect love (Ai)

* Yeah, yeah, that girl stands out, exceptional

We were extras from the beginning

* BS that acted as adornments for the star's leading role

Everything we've accomplished is thanks to her — no!

* How impudent

How could envy and jealousy not exist?

* examine

* This isn't some made-up drama for appearances

So I cannot forgive

* You're not perfect, I cannot forgive you

I cannot forgive myself

* I cannot accept any version of you other than the one stronger than everyone else

* Everybody trusts and worships

The very strongest, most invincible idol

* Weaknesses and whatnot are not to be found

Carrying the morning star within

* Showing any weakness is no good, no good (Hey! Hey!)

Don't let them see anything that they don't want to know (Hey! Hey! Hey! Hey!)

* Anything but being one-of-a-kind is a definite no, no (Hey! Hey! Hey! Hey!)

That is the real love (Hey!)

* can commune fixes

* can commune rename

* fix is psi blocked

* fixes agian

* My signature smile that fires up the media

The only secret that I shall keep is this:

* My career was built upon fake "I love you"s

This is love, in my own way

* Even the flowing sweats are beautiful Aqua

These eyelids that hid the Ruby within

* Sing, dance, flutter, I am Maria —

Right, lying is the most exquisite form of love

* I have never been loved by anyone

Nor have I loved anyone else

* That such lies of mine will become true someday

I trust in it

* Someday, surely, I will have it all in hand

I am such a greedy idol

* Because I wish to love everybody properly in a life-sized way

I shall lie today as well (Hey! Hey! Hey! Hey!)

* a

* b

* c

* d

* And yet, still, (Hey! Hey!)

I have been unable to tell you, and you, alone (Hey! Hey! Hey! Hey!)

* jesus christ

* Update code/controllers/subsystems/processing/psi.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/controllers/subsystems/processing/psi.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/controllers/subsystems/processing/psi.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/game/gamemodes/technomancer/spell_objs.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

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

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/mob/living/carbon/human/human_helpers.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/organs/organ_external.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/assay.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/command.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/emotional_suggestion.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/grip.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/grip.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/mend.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/mend.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/mend.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/psi_search.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/shockwave.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/shockwave.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/singularity.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/abilities/time_stop.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/events/mini_spasm.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* Update code/modules/psionics/interface/ui_hub.dm

Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>

* cl update

---------

Co-authored-by: Matt Atlas <liermattia@gmail.com>
Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com>
This commit is contained in:
Matt Atlas
2023-07-31 20:56:52 +02:00
committed by GitHub
co-authored by Fluffy Matt Atlas
parent a894c77990
commit d9b79db97b
146 changed files with 3213 additions and 1617 deletions
@@ -0,0 +1,29 @@
/singleton/psionic_power
/// Ability name.
var/name
/// Description of what the ability does.
var/desc
/// Spell object to spawn. Must be a path.
var/spell_path
/// Spell icon state.
var/icon_state
/// Ability flags define who can pick an ability - ship characters, adminspawn characters, antags.
var/ability_flags
/// Minimum required rank to use an ability.
var/minimum_rank = PSI_RANK_SENSITIVE
/// Point shop cost.
var/point_cost = 1
/// Called when a power is given to a mob.
/singleton/psionic_power/proc/apply(var/mob/living/carbon/human/H)
if(H.ability_master)
var/obj/spellbutton/spell = new(H, spell_path, name, icon_state)
H.ability_master.add_psionic_ability(spell, icon_state, src)
H.psi.psionic_powers |= type
return TRUE
else
log_debug("Psionic power [src.name] given to mob [H] without ability master!")
return FALSE
/// A psionic power is made up of two elements: the psionic power singleton (which defines the ability metadata such as its name, description, and cost)
/// and the physical spell object, which defines its behaviour when used. Keep in mind that ALL psionic abilities MUST have the ASPECT_PSIONIC aspect!
@@ -0,0 +1,58 @@
/singleton/psionic_power/air_bullet
name = "Air Bullet"
desc = "Wrap air in a psionic bubble, compress it, then send it flying at your enemies. Activate the spell in hand to create up to six air bullets, then \
fire them by clicking something."
icon_state = "tech_frostaura"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/projectile/air_bullet
/obj/item/spell/projectile/air_bullet
name = "air bullet"
desc = "Not really a big bang attack, but it's actually pretty close."
icon_state = "force_missile"
cast_methods = CAST_RANGED|CAST_USE
aspect = ASPECT_PSIONIC
spell_projectile = /obj/item/projectile/air_bullet
fire_sound = 'sound/weapons/wave.ogg'
cooldown = 5
psi_cost = 0
var/bullets = 0
var/max_bullets = 6
/obj/item/spell/projectile/air_bullet/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(!isliving(user))
return
var/mob/living/L = user
if(bullets < max_bullets)
if(do_after(L, 0.5 SECONDS))
to_chat(L, SPAN_NOTICE("You compress some air bullets between your fingers."))
bullets = min(bullets + 2, 6)
maptext = SMALL_FONTS(7, bullets)
playsound(L, 'sound/weapons/unjam.ogg', 25)
L.psi.spend_power(3)
if(bullets >= 6)
to_chat(L, SPAN_NOTICE("You finish compressing all the bullets you can hold."))
return
on_use_cast(L)
/obj/item/spell/projectile/air_bullet/on_ranged_cast(atom/hit_atom, mob/living/user, atom/pb_target)
if(!bullets)
to_chat(user, SPAN_WARNING("You flick your fingers, but find that you don't have any air bullets left!"))
return
. = ..(hit_atom, user, pb_target)
if(.)
bullets--
maptext = SMALL_FONTS(7, bullets)
/obj/item/projectile/air_bullet
name = "air bullet"
icon_state = "plasma_bolt"
damage = 30
armor_penetration = 10
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_BULLET_MEAT, BULLET_IMPACT_METAL = SOUNDS_BULLET_METAL)
damage_flags = DAMAGE_FLAG_BULLET
damage_type = DAMAGE_BRUTE
+80
View File
@@ -0,0 +1,80 @@
/singleton/psionic_power/assay
name = "Assay"
desc = "Assay a creature's psionic level. Using Assay will also allow you to see psionic auras."
icon_state = "wiz_blind"
point_cost = 0
ability_flags = PSI_FLAG_FOUNDATIONAL
spell_path = /obj/item/spell/assay
/obj/item/spell/assay
name = "assay"
desc = "Read someone's psionic potential."
icon_state = "generic"
cast_methods = CAST_MELEE|CAST_INNATE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 2
/obj/item/spell/assay/on_innate_cast(mob/user)
if(!isliving(user))
return
. = ..()
if(!.)
return
var/mob/living/L = user
to_chat(user, SPAN_NOTICE("You can now see psionic auras."))
L.psi.show_auras()
/obj/item/spell/assay/Destroy()
if(isliving(owner))
var/mob/living/L = owner
to_chat(L, SPAN_NOTICE("You can no longer see psionic auras."))
L.psi.hide_auras()
return ..()
/obj/item/spell/assay/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
if(!ishuman(hit_atom))
return
if(!isliving(user))
return
var/mob/living/carbon/human/target = hit_atom
if(target.stat == DEAD || HAS_FLAG(target.status_flags, FAKEDEATH))
to_chat(user, SPAN_WARNING("Psionic power does not flow through a dead person."))
return
var/psi_blocked = target.is_psi_blocked()
if(psi_blocked)
to_chat(user, psi_blocked)
return
user.visible_message(SPAN_NOTICE("[user] lays both [user.get_pronoun("his")] palms on [target]'s temples..."),
SPAN_NOTICE("You lay your palms on [target]'s temples and begin tracing their Nlom signature..."))
if(do_mob(user, target, 4 SECONDS))
if(!target.psi)
to_chat(user, SPAN_NOTICE("[target] is psionically perceptive, but nothing more: [target.get_pronoun("he")] cannot manipulate the fabric that weaves \
this universe."))
if(target.psi)
switch(target.psi.get_rank())
if(PSI_RANK_SENSITIVE)
to_chat(user, SPAN_NOTICE("[target] is psionically sensitive, just like your typical Skrell. They can manipulate psionics, but not to a very \
precise degree."))
if(PSI_RANK_HARMONIOUS)
to_chat(user, SPAN_WARNING("[target] is psionically harmonious. This isn't a feat just about anyone can manage: only those born with a certain \
psionic attitude among Skrell can reach this level, and with strenuous training. They are capable of using psionics \
with very fine precision."))
if(PSI_RANK_APEX)
to_chat(user, SPAN_DANGER("Your psionic power is dwarfed by [target]. Just like a supernova in the night sky, their signature is absolutely brilliant \
beyond comprehension. This is the apex of psionic power, you are sure."))
if(PSI_RANK_LIMITLESS)
to_chat(user, SPAN_DANGER("A psionic power like this shouldn't be possible... what in the Stars is going on?"))
@@ -0,0 +1,30 @@
/singleton/psionic_power/barrier
name = "Psionic Barrier"
desc = "Activate in hand to give yourself psionic armour. This armour is slightly worse than generic heavy armour, and has a small passive upkeep."
icon_state = "const_mend"
point_cost = 1
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/barrier
/obj/item/spell/barrier
name = "psionic barrier"
icon_state = "generic"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 20
psi_cost = 30
/obj/item/spell/barrier/on_use_cast(mob/user, bypass_psi_check)
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = user
var/armor = H.psi.GetComponent(/datum/component/armor/psionic)
if(armor)
to_chat(H, SPAN_WARNING("You are already enveloped by psionic armour!"))
return
to_chat(H, SPAN_NOTICE("You are enveloped by a protective warmth."))
H.psi.AddComponent(/datum/component/armor/psionic, list(laser = ARMOR_LASER_MEDIUM, bullet = ARMOR_BALLISTIC_CARBINE, energy = ARMOR_ENERGY_RESISTANT, melee = ARMOR_MELEE_RESISTANT))
+33
View File
@@ -0,0 +1,33 @@
/singleton/psionic_power/bubble
name = "Bubble"
desc = "Create a protective bubble around you that removes your need to breathe or wear voidsuits in EVA."
icon_state = "tech_condensation"
point_cost = 1
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/bubble
/obj/item/spell/bubble
name = "bubble"
icon_state = "shield"
cast_methods = CAST_INNATE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 10
/obj/item/spell/bubble/Destroy()
to_chat(owner, SPAN_NOTICE("Your bubble fades away."))
REMOVE_TRAIT(owner, TRAIT_NO_BREATHE, TRAIT_SOURCE_PSIONICS)
REMOVE_TRAIT(owner, TRAIT_PRESSURE_IMMUNITY, TRAIT_SOURCE_PSIONICS)
return ..()
/obj/item/spell/bubble/on_innate_cast(mob/user)
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = user
H.visible_message(SPAN_NOTICE("A protective bubble forms around [H]."), SPAN_NOTICE("You form a protective bubble around yourself."))
ADD_TRAIT(H, TRAIT_NO_BREATHE, TRAIT_SOURCE_PSIONICS)
ADD_TRAIT(H, TRAIT_PRESSURE_IMMUNITY, TRAIT_SOURCE_PSIONICS)
+32
View File
@@ -0,0 +1,32 @@
/singleton/psionic_power/charge
name = "Charge"
desc = "Use this spell on an item with a cell to charge it."
icon_state = "wiz_charge"
point_cost = 1
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/charge
/obj/item/spell/charge
name = "charge"
icon_state = "audible_deception"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 5
psi_cost = 5
/obj/item/spell/charge/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
var/obj/item/cell/C = hit_atom.get_cell()
if(!C)
return
if(C.percent() >= 100)
to_chat(user, SPAN_WARNING("That cell is already charged."))
return
psi_cost = C.maxcharge * 0.001
. = ..()
if(!.)
return
user.visible_message(SPAN_NOTICE("[user] lays [get_pronoun("his")] hand on \the [C]..."), SPAN_NOTICE("You lay your hand on \the [C]..."),)
if(do_after(user, 1 SECOND))
to_chat(user, SPAN_WARNING("You restore some power to \the [C]."))
C.give(C.maxcharge * 0.1)
psi_cost = initial(psi_cost)
@@ -0,0 +1,78 @@
/singleton/psionic_power/command
name = "Command"
desc = "Send a psionic command to a target. It must be one word. The suggestion ends when they finish the task, when a minute passes or \
when they take notable damage."
icon_state = "wiz_blink"
spell_path = /obj/item/spell/command
ability_flags = PSI_FLAG_EVENT
/obj/item/spell/command
name = "command"
desc = "Send a psionic command to a target."
icon_state = "apportation"
cast_methods = CAST_RANGED|CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 50
/obj/item/spell/command/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
command(hit_atom, user)
/obj/item/spell/command/on_ranged_cast(atom/hit_atom, mob/user)
. = ..()
if(!.)
return
command(hit_atom, user)
/obj/item/spell/command/proc/command(atom/hit_atom, mob/user)
if(!isliving(hit_atom))
return
if(!isliving(user))
return
var/mob/living/L = user
var/multi_word = L.psi.get_rank() > PSI_RANK_HARMONIOUS
var/mob/living/target = hit_atom
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead."))
return
var/psi_blocked = target.is_psi_blocked()
if(psi_blocked)
to_chat(user, psi_blocked)
return
user.visible_message(SPAN_CULT("[user] opens a palm and aims it at [hit_atom]..."))
var/text = input("Enter your command. [multi_word ? "This command may be up to 5 words." : "This command may only be one word."]", "Command", null, null)
if(!text)
return
text = formalize_text(text)
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead."))
return
log_say("[key_name(user)] issued a [multi_word ? "multi-word" : "single-word"] command to [key_name(target)]: [text]",ckey=key_name(src))
to_chat(user, SPAN_CULT("You psionically command to [target]: [text]"))
for (var/mob/M in player_list)
if (istype(M, /mob/abstract/new_player))
continue
else if(M.stat == DEAD && HAS_FLAG(M.client.prefs.toggles, CHAT_GHOSTEARS))
to_chat(M, "<span class='notice'>[user] psionically commands to [target]:</span> [text]")
var/mob/living/carbon/human/H = target
if(H.has_psionics())
to_chat(H, SPAN_CULT("<b>You are psionically commanded to carry out the following task:</b> [text]."))
else if(target.has_psi_aug())
to_chat(H, SPAN_CULT("<b>You sense [user]'s psyche link with your psi-receiver, a command sliding into your mind:</b> [text]"))
else
to_chat(H, SPAN_CULT("<b>A thought from outside your consciousness slips into your mind:</b> [text]"))
to_chat(H, SPAN_DANGER("You are required to follow this command. It ends when a minute has passed, when you carry it out, or when you take a significant amount \
of damage. [multi_word ? "You are required to follow up to five words." : "You are required to only follow the first word of the command."]"))
@@ -0,0 +1,71 @@
/singleton/psionic_power/commune
name = "Commune"
desc = "Psionically commune with the target."
icon_state = "tech_audibledeception"
point_cost = 0
ability_flags = PSI_FLAG_FOUNDATIONAL
spell_path = /obj/item/spell/commune
/obj/item/spell/commune
name = "commune"
desc = "Déjà-vu."
icon_state = "overload"
cast_methods = CAST_RANGED|CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 15
/obj/item/spell/commune/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
commune(hit_atom, user)
/obj/item/spell/commune/on_ranged_cast(atom/hit_atom, mob/user)
. = ..()
if(!.)
return
commune(hit_atom, user)
/obj/item/spell/commune/proc/commune(atom/hit_atom, mob/user)
if(!isliving(hit_atom))
return
var/mob/living/target = hit_atom
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead."))
return
var/psi_blocked = target.is_psi_blocked()
if(psi_blocked)
to_chat(user, psi_blocked)
return
user.visible_message(SPAN_NOTICE("<i>[user] blinks, their eyes briefly developing an unnatural shine.</i>"))
var/text = input("What would you like to say?", "Speak to creature", null, null)
text = sanitize(text)
if(!text)
return
text = formalize_text(text)
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead."))
return
log_say("[key_name(user)] communed to [key_name(target)]: [text]",ckey=key_name(src))
to_chat(user, SPAN_CULT("You psionically say to [target]: [text]"))
for (var/mob/M in player_list)
if (istype(M, /mob/abstract/new_player))
continue
else if(M.stat == DEAD && M.client.prefs.toggles & CHAT_GHOSTEARS)
to_chat(M, "<span class='notice'>[user] psionically says to [target]:</span> [text]")
var/mob/living/carbon/human/H = target
if(H.has_psionics())
to_chat(H, SPAN_CULT("<b>You instinctively sense [user] passing a thought into your mind:</b> [text]"))
else if(target.has_psi_aug())
to_chat(H, SPAN_CULT("<b>You sense [user]'s psyche link with your psi-receiver, a thought sliding into your mind:</b> [text]"))
else
to_chat(H, SPAN_ALIEN("<b>A thought from outside your consciousness slips into your mind:</b> [text]"))
@@ -0,0 +1,30 @@
/singleton/psionic_power/electrocute
name = "Electrocute"
desc = "Administer a painful amount of psionic shock to the nervous system of a foe in melee range, causing burn and agony damage. "
icon_state = "tech_shockaura"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/electrocute
/obj/item/spell/electrocute
name = "electrocute"
icon_state = "chain_lightning"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 5
hitsound = 'sound/effects/psi/power_evoke.ogg'
attack_verb = list("lays a palm on")
/obj/item/spell/electrocute/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!ishuman(hit_atom))
to_chat(user, SPAN_WARNING("That won't work!"))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = hit_atom
H.adjustHalLoss(20)
H.adjustFireLoss(20)
H.flash_pain(20)
to_chat(H, SPAN_DANGER("A sharp, stinging pain enters your mind!"))
@@ -0,0 +1,70 @@
/singleton/psionic_power/emotional_suggestion
name = "Emotional Suggestion"
desc = "Allows you to psionically commune with the target."
icon_state = "tech_gambit"
ability_flags = PSI_FLAG_EVENT|PSI_FLAG_CANON
spell_path = /obj/item/spell/emotional_suggestion
/obj/item/spell/emotional_suggestion
name = "emotional suggestion"
desc = "Suggest an emotion to someone."
icon_state = "generic"
cast_methods = CAST_RANGED|CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 15
/obj/item/spell/emotional_suggestion/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
emotional_suggestion(hit_atom, user)
/obj/item/spell/emotional_suggestion/on_ranged_cast(atom/hit_atom, mob/user)
. = ..()
if(!.)
return
emotional_suggestion(hit_atom, user)
/obj/item/spell/emotional_suggestion/proc/emotional_suggestion(atom/hit_atom, mob/user)
if(!isliving(hit_atom))
return
var/mob/living/target = hit_atom
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can suggest to the dead."))
return
var/psi_blocked = target.is_psi_blocked()
if(psi_blocked)
to_chat(user, psi_blocked)
return
user.visible_message(SPAN_NOTICE("<i>[user] blinks, their eyes briefly developing an unnatural shine.</i>"))
var/text = input("Which emotion would you like to suggest?", "Emotional Suggestion") as null|anything in list("Calm", "Happiness", "Sadness", "Fear", "Anger", "Stress", "Confusion")
if(!text)
return
text = lowertext(text)
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can suggest to the dead."))
return
log_say("[key_name(user)] suggested an emotion to [key_name(target)]: [text]",ckey=key_name(src))
to_chat(user, SPAN_CULT("You psionically suggest an emotion to [target]: [text]"))
for (var/mob/M in player_list)
if (istype(M, /mob/abstract/new_player))
continue
else if(M.stat == DEAD && HAS_FLAG(M.client.prefs.toggles, CHAT_GHOSTEARS))
to_chat(M, "<span class='notice'>[user] psionically suggests an emotion to [target]:</span> [text]")
var/mob/living/carbon/human/H = target
if(H.has_psionics())
to_chat(H, SPAN_NOTICE("You feel an emotion of <b>[text]</b> washing through your mind."))
else if(target.has_psi_aug())
to_chat(H, SPAN_NOTICE("You sense [user]'s psyche link with your psi-receiver, and an emotion envelops your mind: <b>[text]</b>."))
else
to_chat(H, SPAN_NOTICE("An emotion from outside your consciousness slips into your mind: <b>[text]</b>."))
+28
View File
@@ -0,0 +1,28 @@
/singleton/psionic_power/focus
name = "Focus"
desc = "Activate this spell in your hand to generate five units of synaptizine in your bloodstream."
icon_state = "tech_phaseshift"
point_cost = 1
ability_flags = PSI_FLAG_EVENT
spell_path = /obj/item/spell/focus
/obj/item/spell/focus
name = "focus"
desc = "Psionic drugs? No way."
icon_state = "blink"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 20
/obj/item/spell/focus/on_use_cast(mob/user)
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = user
if(do_after(user, 1 SECOND))
to_chat(H, SPAN_WARNING("A calm rush envelops your mind.."))
H.reagents.add_reagent(/singleton/reagent/synaptizine, 5)
H.update_canmove()
+51
View File
@@ -0,0 +1,51 @@
/singleton/psionic_power/grip
name = "Grip"
desc = "Grip a victim with psionic energy. You can squeeze your grip to crush them."
icon_state = "ling_bioelectrogenesis"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/grip
/obj/item/spell/grip
name = "stasis"
desc = "General Kenobi..."
icon_state = "blink"
cast_methods = CAST_RANGED|CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 15
psi_cost = 5
var/mob/living/victim
/obj/item/spell/grip/Destroy()
victim.captured = FALSE
victim.update_canmove()
victim = null
return ..()
/obj/item/spell/grip/on_use_cast(mob/user, bypass_psi_check)
if(!victim)
to_chat(user, SPAN_WARNING("You need to grip someone first!"))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_WARNING("[user] squeezes [user.get_pronoun("his")] hand!"), SPAN_WARNING("You squeeze your hand to tighten the psionic force around [victim]."))
to_chat(victim, SPAN_DANGER(FONT_HUGE("You are crushed by an invisible force!")))
victim.apply_damage(30, DAMAGE_BRUTE, armor_pen = 30, damage_flags = DAMAGE_FLAG_DISPERSED)
/obj/item/spell/grip/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!isliving(hit_atom))
return
if(victim)
to_chat(user, SPAN_WARNING("You can't target more than one person with this!"))
return
. = ..()
if(!.)
return
var/mob/living/M = hit_atom
user.visible_message(SPAN_DANGER("[user] extends [user.get_pronoun("his")] arm and makes a grab motion towards [M]!"),
SPAN_DANGER("You extend your arm and grab [M] with your psionic energy!"))
to_chat(M, SPAN_DANGER(FONT_HUGE("You feel an invisible force tighten around you!")))
M.captured = TRUE
M.update_canmove()
victim = M
@@ -0,0 +1,106 @@
/singleton/psionic_power/hollow_purple
name = "Hollow Technique: Purple"
desc = "This technique brings the concept of motion and reversal into reality. Purple is born from merging both infinites: Blue and Red, \
to produce an imaginary mass that rushes forth and erases everything in its path. Rather than the attraction of Blue or the repulsion of Red, \
Purple is an extraordinarily destructive energy wave of annihilation that rips whatever it hits from existence."
icon_state = "hollow_purple"
point_cost = 0
ability_flags = PSI_FLAG_LIMITLESS
minimum_rank = PSI_FLAG_LIMITLESS
spell_path = /obj/item/spell/projectile/hollow_purple
/obj/item/spell/projectile/hollow_purple
name = "hollow purple"
desc = "Throughout Heaven and Earth, I alone am the honored one!"
icon_state = "destablize"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
spell_projectile = /obj/item/projectile/hollow_purple
fire_sound = 'sound/magic/WandODeath.ogg'
cooldown = 10
psi_cost = 50
var/stage = 0
/obj/item/spell/projectile/hollow_purple/on_ranged_cast(atom/hit_atom, mob/living/user, atom/pb_target)
if(!isliving(user))
return
stage = 1
user.visible_message(SPAN_NOTICE("<b><font size=4>[user] puts [user.get_pronoun("his")] palms together...</font></b>"))
START_PROCESSING(SSprocessing, src)
user.say("Cursed Technique Amplification: Blue...")
user.set_light(7, 10, COLOR_BLUE)
color = COLOR_BLUE
if(do_after(user, 4 SECONDS))
stage = 2
color = COLOR_RED
user.say("Cursed Technique Reversal: Red...")
user.set_light(0)
user.set_light(7, 10, COLOR_RED)
if(do_after(user, 4 SECONDS))
user.say("Hollow Technique: Purple!")
user.set_light(0)
user.visible_message(SPAN_CULT("<b><font size=4>[user] fires a gigantic purple sphere from [user.get_pronoun("his")] hand!</font></b>"))
. = ..()
STOP_PROCESSING(SSprocessing, src)
color = initial(color)
user.set_light(0)
stage = 0
/obj/item/spell/projectile/hollow_purple/process()
if(stage >= 1)
for(var/mob/living/L in get_hearers_in_view(7, src))
shake_camera(L, 5, 5)
/obj/item/projectile/hollow_purple
name = "hollow purple"
icon_state = "hollow_purple"
color = COLOR_PURPLE
damage = 1000
armor_penetration = 1000
penetrating = 100
range = 250
accuracy = 100
anti_materiel_potential = 100
damage_type = DAMAGE_BRUTE
/obj/item/projectile/hollow_purple/Initialize()
. = ..()
set_light(10, 10, COLOR_PURPLE)
/obj/item/projectile/hollow_purple/Destroy()
return ..()
/obj/item/projectile/hollow_purple/on_impact(var/atom/A)
if(ismob(A))
if(A != firer)
var/mob/M = A
M.gib()
explosion(A, 5, 5, 5)
..()
/obj/item/projectile/hollow_purple/on_hit(atom/target, blocked, def_zone)
if(ismob(target))
if(target != firer)
var/mob/M = target
M.gib()
explosion(target, 5, 5, 5)
..()
/obj/item/projectile/hollow_purple/check_penetrate(atom/A)
on_hit(A)
return TRUE
/obj/item/projectile/hollow_purple/after_move()
for(var/a in range(3, src))
if(isliving(a) && a != firer)
var/mob/living/M = a
M.gib()
playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
else if(isturf(a) || isobj(a))
var/atom/A = a
if(!A.density)
continue
A.ex_act(3)
playsound(src, 'sound/magic/LightningShock.ogg', 75, 1)
+24
View File
@@ -0,0 +1,24 @@
/singleton/psionic_power/ion
name = "Ion Blast"
desc = "Activate in hand to release a 3x3 ion blast around you. Be careful, this ability is expensive to use."
icon_state = "const_mend"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/ion
/obj/item/spell/ion
name = "ion blast"
icon_state = "generic"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 20
psi_cost = 30
/obj/item/spell/ion/on_use_cast(mob/user, bypass_psi_check)
. = ..()
if(!.)
return
user.visible_message(SPAN_DANGER("<font size=4>[user] opens their arms and releases an ion blast around them!</font>"),
SPAN_DANGER("<font size=4>You open your arms and release an ion blast around you!</font>"))
empulse(get_turf(user), 3, 3)
+22
View File
@@ -0,0 +1,22 @@
/singleton/psionic_power/jump
name = "Jump"
desc = "Teleport to a destination you click on."
icon_state = "tech_dispel"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/jump
/obj/item/spell/jump
name = "jump"
icon_state = "warp_strike"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 15
/obj/item/spell/jump/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
. = ..()
if(!.)
return
user.visible_message(SPAN_WARNING("[user] warps and disappears!"), SPAN_WARNING("You weave the Nlom to bring you to your destination!"))
do_teleport(user, hit_atom)
@@ -0,0 +1,59 @@
/singleton/psionic_power/lightning
name = "Lightning"
desc = "Fire a concentrated lightning bolt. Activate this spell in hand to switch to a second mode that hits living beings in a 4x3 area in front of you."
icon_state = "tech_instabilitytapold"
point_cost = 0
ability_flags = PSI_FLAG_APEX
minimum_rank = PSI_RANK_APEX
spell_path = /obj/item/spell/projectile/psi_lightning
/obj/item/spell/projectile/psi_lightning
name = "lightning"
icon_state = "chain_lightning"
cast_methods = CAST_RANGED|CAST_USE
aspect = ASPECT_PSIONIC
spell_projectile = /obj/item/projectile/beam/psi_lightning
fire_sound = 'sound/magic/LightningShock.ogg'
cooldown = 10
psi_cost = 15
var/mode = 0
/obj/item/spell/projectile/psi_lightning/on_use_cast(mob/user, bypass_psi_check)
. = ..(user, TRUE)
mode = !mode
if(mode)
to_chat(user, SPAN_NOTICE("You will now fire area-of-effect lightning in a 4x3 area in front of you."))
spell_projectile = /obj/item/projectile/beam/psi_lightning/wide
else
to_chat(user, SPAN_NOTICE("You will now fire a normal lightning bolt."))
spell_projectile = /obj/item/projectile/beam/psi_lightning
/obj/item/projectile/beam/psi_lightning
name = "psionic lightning"
damage = 30
armor_penetration = 30
damage_type = DAMAGE_BURN
pass_flags = PASSTABLE | PASSGRILLE | PASSRAILING
range = 40
accuracy = 100
muzzle_type = /obj/effect/projectile/muzzle/tesla
tracer_type = /obj/effect/projectile/tracer/tesla
impact_type = /obj/effect/projectile/impact/tesla
/obj/item/projectile/beam/psi_lightning/pellet
damage = 20
armor_penetration = 20
/obj/item/projectile/beam/psi_lightning/wide
damage = 20
armor_penetration = 20
/obj/item/projectile/beam/psi_lightning/wide/Initialize()
for(var/i = 1 to 4)
var/turf/new_turf = get_random_turf_in_range(get_turf(firer), i + rand(0, i), 0, TRUE, FALSE)
var/obj/item/projectile/beam/psi_lightning/pellet/pellet = new type(new_turf)
var/turf/front_turf = get_step(pellet, pellet.dir)
pellet.launch_projectile(front_turf)
+69
View File
@@ -0,0 +1,69 @@
/singleton/psionic_power/mend
name = "Mend"
desc = "Mend a creature's wounds. This handles internal wounds as well, such as ruptured organs and broken bones."
icon_state = "tech_biomedaura"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/mend
/obj/item/spell/mend
name = "mend"
desc = "Clear!"
icon_state = "mend_wounds"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 30
/obj/item/spell/mend/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!ishuman(hit_atom))
return
var/mob/living/carbon/human/H = hit_atom
if(!H.has_zona_bovinae())
to_chat(user, SPAN_WARNING("Psionic power cannot flow through this being."))
return
if(H.stat == DEAD || H.status_flags & FAKEDEATH)
to_chat(user, SPAN_WARNING("Psionic power does not flow through a dead person."))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_NOTICE("[user] lays a palm on [H]..."), SPAN_NOTICE("You lay your palm on [H] and get to work."))
to_chat(user, SPAN_NOTICE("You start by flowing your regenerative psionic energy through their vital organs..."))
for(var/obj/item/organ/O in H.internal_organs)
if(do_mob(user, H, 15 SECONDS))
if(O.damage > 0) // Fix internal damage
to_chat(SPAN_NOTICE("You mend their [O]'s bruising."))
O.heal_damage(O.damage)
if(HAS_FLAG(O.status, ORGAN_BROKEN))
to_chat(SPAN_NOTICE("You restart their [O]'s functionality."))
O.status &= ~ORGAN_BROKEN
if(O.damage <= 5 && O.organ_tag == BP_EYES) // Fix eyes
H.sdisabilities &= ~BLIND
to_chat(user, SPAN_NOTICE("You continue by flowing your regenerative psionic energy through their limbs..."))
for(var/obj/item/organ/external/O in H.organs) // Fix limbs
if(!O.robotic < ORGAN_ROBOT) // No robot parts for this.
continue
if(do_mob(user, H, 15 SECONDS))
to_chat(SPAN_NOTICE("You mend their [O]'s bruising."))
O.heal_damage(0, O.damage, internal = TRUE, robo_repair = FALSE)
to_chat(user, SPAN_NOTICE("Finally, you flowing your regenerative psionic energy through their broken limbs..."))
for(var/obj/item/organ/E in H.bad_external_organs) // Fix bones
var/obj/item/organ/external/affected = E
if(do_mob(user, H, 10 SECONDS))
if((affected.damage < affected.min_broken_damage * config.organ_health_multiplier) && (affected.status & ORGAN_BROKEN))
to_chat(SPAN_NOTICE("You mend their [affected] together."))
affected.status &= ~ORGAN_BROKEN
if(HAS_FLAG(affected.status, ORGAN_ARTERY_CUT))
to_chat(SPAN_NOTICE("You mend a spliced artery in their [affected]."))
affected.status &= ~ORGAN_ARTERY_CUT
if(HAS_FLAG(affected.status, ORGAN_DEAD))
to_chat(SPAN_NOTICE("You mend some necrosis from their [affected]."))
affected.status &= ~ORGAN_DEAD
user.visible_message(SPAN_NOTICE("[user] raises their palm from [H]."), SPAN_NOTICE("You raise your palm, having finished your work."))
@@ -0,0 +1,29 @@
/singleton/psionic_power/mind_muddle
name = "Mind Muddle"
desc = "Use this at range to confuse a target and give them a little bit of pain."
icon_state = "wiz_tele"
point_cost = 1
ability_flags = PSI_FLAG_EVENT
spell_path = /obj/item/spell/mind_muddle
/obj/item/spell/mind_muddle
name = "mind muddle"
desc = "Confuse people. That's all it does. Oh, and the pain."
icon_state = "warp_strike"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 20
psi_cost = 10
/obj/item/spell/mind_muddle/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!ishuman(hit_atom))
to_chat(user, SPAN_WARNING("That won't work on them!"))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = hit_atom
H.confused += 20
to_chat(H, SPAN_DANGER("A stinging sensation fills your mind! You feel nauseated..."))
H.adjustHalLoss(15)
@@ -0,0 +1,53 @@
/singleton/psionic_power/mirror_shade
name = "Mirror Shade"
desc = "Activate this spell to generate two psionic copies of yourself that will attack nearby mobs. These clones are not dense, will deal pain damage, and disappear \
after thirty seconds."
icon_state = "wiz_jaunt"
point_cost = 2
ability_flags = PSI_FLAG_EVENT
spell_path = /obj/item/spell/mirror_shade
/obj/item/spell/mirror_shade
name = "mirror shade"
desc = "Photocopy yourself."
icon_state = "darkness"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 100
psi_cost = 20
/obj/item/spell/mirror_shade/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(do_after(user, 1 SECOND))
to_chat(user, SPAN_WARNING("You weave your psionic force into two copies of yourself!"))
for(var/i = 1 to 2)
var/mob/living/simple_animal/hostile/mirror_shade/MS = new(pick(get_adjacent_open_turfs(user)))
MS.appearance = user.appearance
MS.name = user.name
MS.owner = user
/mob/living/simple_animal/hostile/mirror_shade
damage_type = DAMAGE_PAIN
density = FALSE
destroy_surroundings = FALSE
melee_damage_lower = 10
melee_damage_upper = 15
attack_emote = "tries shambling towards"
attacktext = "phases its arms through"
var/mob/living/carbon/human/owner
/mob/living/simple_animal/hostile/mirror_shade/Initialize()
. = ..()
friends += owner
QDEL_IN(src, 30 SECONDS)
/mob/living/simple_animal/hostile/mirror_shade/examine(mob/user)
/// Technically suspicious, but these have 30 seconds of lifetime so it's probably fine.
return owner.examine(user)
/mob/living/simple_animal/hostile/mirror_shade/Destroy()
owner = null
visible_message(SPAN_WARNING("[src] dissipates into nothingness, as if it were air all along!"))
return ..()
@@ -0,0 +1,76 @@
/singleton/psionic_power/nlom_eyes
name = "Nlom Eyes"
desc = "Roughly locate a mob on your z-level."
icon_state = "tech_control"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/nlom_eyes
/obj/item/spell/nlom_eyes
name = "nlom eyes"
desc = "Psionic drugs? No way."
icon_state = "track"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 5
/// The mob we are tracking.
var/mob/living/tracked
/// If we are tracking a mob.
var/tracking = FALSE
/obj/item/spell/nlom_eyes/Destroy()
tracked = null
tracking = 0
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/item/spell/nlom_eyes/on_use_cast(mob/user)
if(tracking)
tracking = FALSE
to_chat(user, SPAN_NOTICE("You stop looking in the Nlom for \the [tracked]'s whereabouts."))
tracked = null
STOP_PROCESSING(SSprocessing, src)
icon_state = "track"
return
. = ..()
if(!.)
return
var/list/mob_choices = list()
for(var/mob/living/L in mob_list)
if(L == user)
continue
if(!L.is_psi_blocked())
continue
if(GET_Z(L) != GET_Z(user))
continue
mob_choices += L
var/choice = input(user, "Decide who to track.", "Nlom Eyes") as null|anything in mob_choices
if(choice)
tracked = choice
tracking = TRUE
START_PROCESSING(SSprocessing, src)
/obj/item/spell/track/process()
if(!tracking)
icon_state = "track"
return
if(!tracked)
icon_state = "track_unknown"
if(GET_Z(tracked) != GET_Z(owner))
icon_state = "track_unknown"
else
set_dir(get_dir(src,get_turf(tracked)))
switch(get_dist(src,get_turf(tracked)))
if(0)
icon_state = "track_direct"
if(1 to 8)
icon_state = "track_close"
if(9 to 16)
icon_state = "track_medium"
if(16 to INFINITY)
icon_state = "track_far"
@@ -0,0 +1,43 @@
/singleton/psionic_power/awaken
name = "Awaken"
desc = "Stimulate a living being's Zona Bovinae and bring them to Psionically Harmonious rank."
icon_state = "tech_corona"
point_cost = 0
ability_flags = PSI_FLAG_APEX
minimum_rank = PSI_RANK_APEX
spell_path = /obj/item/spell/awaken
/obj/item/spell/awaken
name = "awaken"
icon_state = "energy_siphon_drain"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 20
psi_cost = 100
/obj/item/spell/awaken/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!isliving(hit_atom))
return
var/mob/living/L = hit_atom
if(!L.has_zona_bovinae())
to_chat(user, SPAN_WARNING("This being doesn't have a Zona Bovinae."))
return
if(L.psi && L.psi.get_rank() >= PSI_RANK_HARMONIOUS)
to_chat(user, SPAN_WARNING("This wouldn't do anything on them."))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_DANGER("[user] grabs [L]'s head..."), SPAN_DANGER("You grab [L]'s head..."))
if(do_mob(user, L, 5 SECONDS))
L.set_psi_rank(PSI_RANK_HARMONIOUS)
L.flash_pain(50)
L.adjustHalLoss(20)
playsound(get_turf(L), 'sound/effects/psi/power_feedback.ogg', 100)
user.visible_message(SPAN_DANGER("[user] unleashes a psionic shock through [L]'s head!"),
SPAN_DANGER("You unleash a psionic shock through [L]'s head, targeting their Zona Bovinae and stimulating it it."))
to_chat(L, SPAN_HIGHDANGER("A large, painful shock courses through your head. You can see the weave of the universe... and manipulate it."))
@@ -0,0 +1,57 @@
/singleton/psionic_power/psi_drain
name = "Psi-Drain"
desc = "Drain psi-stamina from a living being. This can be used both in melee and at range."
icon_state = "gen_project"
point_cost = 0
ability_flags = PSI_FLAG_APEX
minimum_rank = PSI_RANK_APEX
spell_path = /obj/item/spell/psi_drain
/obj/item/spell/psi_drain
name = "psi-drain"
icon_state = "chain_lightning"
cast_methods = CAST_MELEE|CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 5
/obj/item/spell/psi_drain/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!isliving(hit_atom))
return
var/mob/living/L = hit_atom
if(!L.has_zona_bovinae())
to_chat(user, SPAN_WARNING("This being doesn't have a Zona Bovinae."))
return
. = ..()
if(!.)
return
psi_drain(L, user)
/obj/item/spell/psi_drain/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!isliving(hit_atom))
return
var/mob/living/L = hit_atom
if(!L.has_zona_bovinae())
to_chat(user, SPAN_WARNING("This being doesn't have a Zona Bovinae."))
return
. = ..()
if(!.)
return
psi_drain(L, user)
/obj/item/spell/psi_drain/proc/psi_drain(mob/living/L, mob/living/user)
user.visible_message(SPAN_DANGER("[user] squeezes [user.get_pronoun("his")] hand at [L]!"), SPAN_DANGER("You squeeze your hand at [L] and siphon [L.get_pronoun("his")] psionic energy!"))
var/psi_taken = min(user.psi.max_stamina, rand(10, 25))
if(L.psi)
L.psi.spend_power(psi_taken)
else
L.adjustHalLoss(psi_taken * 1.5)
L.flash_pain(psi_taken * 1.5)
playsound(get_turf(user), 'sound/effects/psi/power_evoke.ogg', 100)
to_chat(L, SPAN_DANGER("You feel a headache split apart your mind!"))
@@ -0,0 +1,31 @@
/singleton/psionic_power/punch
name = "Psi-Punch"
desc = "Imbue your fists with psionic power."
icon_state = "const_fist"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/punch
/obj/item/spell/punch
name = "psi-punch"
icon_state = "generic"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
force = 20
armor_penetration = 20
cooldown = 0
psi_cost = 3
flags = 0
hitsound = 'sound/weapons/resonator_blast.ogg'
/obj/item/spell/punch/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!isliving(hit_atom))
return
. = ..()
if(!.)
return
var/mob/living/M = hit_atom
if(prob(15))
M.throw_at(get_edge_target_turf(loc, loc.dir), 2, 7)
M.visible_message(SPAN_DANGER("[M] is floored by psychic energy!"), SPAN_DANGER("You are floored by psychic energy!"))
M.apply_effect(2, WEAKEN)
@@ -0,0 +1,37 @@
/singleton/psionic_power/psi_recovery
name = "Psionic Recovery"
desc = "Activate in hand to regenerate psi-stamina."
icon_state = "swarm_zeropoint"
point_cost = 0
ability_flags = PSI_FLAG_FOUNDATIONAL
spell_path = /obj/item/spell/psi_recovery
/obj/item/spell/psi_recovery
name = "psionic recovery"
desc = "It's an aura recharge."
icon_state = "generic"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 5
psi_cost = 0
/obj/item/spell/psi_recovery/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(!isliving(user))
return
var/mob/living/L = user
L.visible_message(SPAN_NOTICE("[user] puts [user.get_pronoun("his")] hands together and focuses..."),
SPAN_NOTICE("You put your hands together and begin focusing on recovering your psionic energy..."))
psi_recovery(user)
/obj/item/spell/psi_recovery/proc/psi_recovery(mob/user)
var/mob/living/L = user
if(do_after(user, 0.5 SECONDS))
L.psi.stamina = min(L.psi.max_stamina, L.psi.stamina + rand(1,3))
if(L.psi.stamina >= L.psi.max_stamina)
to_chat(user, SPAN_NOTICE("You've recovered all your psionic energy."))
return TRUE
psi_recovery(user)
@@ -0,0 +1,68 @@
/singleton/psionic_power/psi_search
name = "Psionic Search"
desc = "Scan your Z-level for Nlom signatures. The distance will be slightly inaccurate for weak signatures."
icon_state = "wiz_shield"
point_cost = 0
ability_flags = PSI_FLAG_FOUNDATIONAL
spell_path = /obj/item/spell/psi_search
/obj/item/spell/psi_search
name = "psionic search"
desc = "A psionic magnifying glass."
icon_state = "generic"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 5
psi_cost = 10
/obj/item/spell/psi_search/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(!isliving(user))
return
var/mob/living/L = user
L.visible_message(SPAN_NOTICE("[L] puts two fingers to [L.get_pronoun("his")] forehead and focuses..."),
SPAN_NOTICE("You put two fingers to your temple and focus on locating Nlom signatures..."))
if(do_after(L, 3 SECONDS))
var/list/level_humans = list()
var/found_apex = FALSE
for(var/mob/living/carbon/human/H in human_mob_list)
if(H == L)
continue
if((GET_Z(H) == GET_Z(L)) && !H.is_psi_blocked())
if(HAS_TRAIT(H, TRAIT_PSIONIC_SUPPRESSION))
continue
level_humans |= H
if(H.psi)
if(H.psi.get_rank() >= PSI_RANK_APEX)
found_apex = TRUE
if(!length(level_humans))
to_chat(L, SPAN_WARNING("The Nlom is quiet and empty here."))
return TRUE
if(found_apex)
to_chat(L, SPAN_DANGER(FONT_HUGE("You reach out into the Nlom and your senses are overwhelmed by a massive signature!")))
L.flash_pain(20)
L.adjustHalLoss(20)
return
var/list/signatures = list()
var/harmonious_signatures = 0
var/sensitive_signatures = 0
var/perceptive_signatures = 0
for(var/mob/living/carbon/human/H in level_humans)
if(!H.psi)
perceptive_signatures++
continue
if(H.psi && H.psi.get_rank() == PSI_RANK_SENSITIVE)
sensitive_signatures++
continue
if(H.psi && H.psi.get_rank() == PSI_RANK_HARMONIOUS)
harmonious_signatures++
continue
if(perceptive_signatures)
signatures += "[perceptive_signatures] weak signature[perceptive_signatures > 1 ? "s" : ""]"
if(sensitive_signatures)
signatures += "[sensitive_signatures] robust signature[sensitive_signatures > 1 ? "s" : ""]"
if(harmonious_signatures)
signatures += "[harmonious_signatures] very powerful signature[harmonious_signatures > 1 ? "s" : ""]"
to_chat(user, SPAN_NOTICE("Reaching out into the Nlom, you sense [english_list(signatures)]."))
@@ -0,0 +1,27 @@
/singleton/psionic_power/psi_stamina
name = "Psi-Stamina Weave"
desc = "Activate this spell in your hand to regenerate your psi-stamina a little bit."
icon_state = "tech_mend_template"
point_cost = 1
ability_flags = PSI_FLAG_EVENT|PSI_FLAG_CANON
spell_path = /obj/item/spell/psi_stamina
/obj/item/spell/psi_stamina
name = "psi-stamina weave"
desc = "Kind of like charging up your aura."
icon_state = "generic"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 0
psi_cost = 0
/obj/item/spell/psi_stamina/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(do_after(user, 1 SECOND))
to_chat(user, SPAN_NOTICE("You feel a bit more refreshed."))
owner.psi.stamina = min(owner.psi.max_stamina, owner.psi.stamina + rand(2,5))
if(owner.psi.stamina >= owner.psi.max_stamina)
to_chat(user, SPAN_NOTICE("You're ready to go again!"))
return TRUE
@@ -0,0 +1,44 @@
/singleton/psionic_power/sunder
name = "Sunder"
desc = "Destroy a living being's Zona Bovinae. This will make them psionically deaf."
icon_state = "ling_berserk"
point_cost = 0
ability_flags = PSI_FLAG_APEX
minimum_rank = PSI_RANK_APEX
spell_path = /obj/item/spell/sunder
/obj/item/spell/sunder
name = "sunder"
icon_state = "chain_lightning"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 30
psi_cost = 20
/obj/item/spell/sunder/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!isliving(hit_atom))
return
var/mob/living/L = hit_atom
if(!L.has_zona_bovinae())
to_chat(user, SPAN_WARNING("This being doesn't have a Zona Bovinae."))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_DANGER("[user] grabs [L]'s head..."), SPAN_DANGER("You grab [L]'s head..."))
if(do_mob(user, L, 5 SECONDS))
if(L.psi)
QDEL_NULL(L.psi)
ADD_TRAIT(L, TRAIT_PSIONICALLY_DEAF, TRAIT_SOURCE_PSIONICS)
L.flash_pain(100)
L.adjustHalLoss(50)
L.stuttering += 20
playsound(get_turf(L), 'sound/effects/psi/power_feedback.ogg', 100)
user.visible_message(SPAN_DANGER("[user] unleashes a psionic shock through [L]'s head!"),
SPAN_DANGER("You unleash a psionic shock through [L]'s head, targeting their Zona Bovinae and destroying it."))
to_chat(L, SPAN_HIGHDANGER("A large, painful shock courses through your head. Part of your brain feels like it's gone."))
if(isskrell(L))
to_chat(L, SPAN_CULT("You feel absolutely empty..."))
@@ -0,0 +1,27 @@
/singleton/psionic_power/psi_suppression
name = "Psionic Suppression"
desc = "Hold in one of your hands to make yourself invisible to Psi-Search."
icon_state = "tech_shield"
point_cost = 1
ability_flags = PSI_FLAG_CANON
spell_path = /obj/item/spell/psi_suppression
/obj/item/spell/psi_suppression
name = "psionic suppression"
icon_state = "generic"
cast_methods = CAST_INNATE
aspect = ASPECT_PSIONIC
psi_cost = 5
/obj/item/spell/psi_suppression/Destroy()
to_chat(owner, SPAN_NOTICE("You are no longer hidden from Psi-Search."))
REMOVE_TRAIT(owner, TRAIT_PSIONIC_SUPPRESSION, TRAIT_SOURCE_PSIONICS)
return ..()
/obj/item/spell/psi_suppression/on_innate_cast(mob/user)
. = ..()
if(!.)
return
to_chat(user, SPAN_NOTICE("You are now hidden from Psi-Search."))
ADD_TRAIT(user, TRAIT_PSIONIC_SUPPRESSION, TRAIT_SOURCE_PSIONICS)
@@ -0,0 +1,32 @@
/singleton/psionic_power/psi_sword
name = "Psi-Sword"
desc = "Create a psionic sword."
icon_state = "psiblade"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/psi_sword
/obj/item/spell/psi_sword
name = "psi-tool"
icon_state = "generic"
cast_methods = CAST_INNATE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 5
/obj/item/spell/psi_sword/on_innate_cast(mob/user)
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = user
var/obj/item/psychic_power/psiblade/PT = new(user)
if(H.put_in_any_hand_if_possible(PT))
qdel(src)
return TRUE
else
to_chat(H, SPAN_WARNING("You need an empty hand for this!"))
return FALSE
@@ -0,0 +1,32 @@
/singleton/psionic_power/psi_tool
name = "Psi-Tool"
desc = "Create a psionic tool that can change into a screwdriver, crowbar, wrench or wirecutters."
icon_state = "psitool"
point_cost = 1
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/psi_tool
/obj/item/spell/psi_tool
name = "psi-tool"
icon_state = "generic"
cast_methods = CAST_INNATE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 5
/obj/item/spell/psi_tool/on_innate_cast(mob/user)
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = user
var/obj/item/psychic_power/tinker/PT = new(user)
if(H.put_in_any_hand_if_possible(PT))
qdel(src)
return TRUE
else
to_chat(H, SPAN_WARNING("You need an empty hand for this!"))
return FALSE
+38
View File
@@ -0,0 +1,38 @@
/singleton/psionic_power/pull
name = "Pull"
desc = "Pulls the target straight towards the user, smashing windows along the way. If it can be held in your hands, \
it goes straight to your hand. Note that you can catch items you pull to yourself if you toggle throw mode before pulling an item."
icon_state = "tech_passwall"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/pull
/obj/item/spell/pull
name = "pull"
desc = "Not as cool as the Mass Effect one."
icon_state = "control"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 10
/obj/item/spell/pull/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!ismovable(hit_atom))
return
if(!ishuman(user))
return
. = ..()
if(!.)
return
var/atom/movable/AM = hit_atom
var/mob/living/carbon/human/H = user
if(isobj(hit_atom) && w_class < ITEMSIZE_IMMENSE)
if(length(get_line(hit_atom, user)))
if(H.put_in_any_hand_if_possible(hit_atom))
return
user.visible_message(SPAN_WARNING("[user] extends [user.get_pronoun("his")] hand at [hit_atom]and pulls!"), SPAN_WARNING("You mimic pulling at [hit_atom]!"))
if(ismob(hit_atom))
to_chat(hit_atom, SPAN_WARNING("A psychic force pulls you!"))
AM.throw_at(user, 10, 7)
playsound(user, 'sound/effects/psi/power_evoke.ogg')
@@ -0,0 +1,77 @@
/singleton/psionic_power/read_mind
name = "Read Mind"
desc = "Rip thoughts from someone's mind. If your rank is Psionically Sensitive, you may only skim the surface thoughts from a person's mind. \
If your rank is Psionically Harmonious or above, your target is forced to respond to a five-word question with the truth."
icon_state = "tech_illusion"
spell_path = /obj/item/spell/read_mind
ability_flags = PSI_FLAG_EVENT|PSI_FLAG_CANON
/obj/item/spell/read_mind
name = "read mind"
desc = "Rip thoughts from someone's mind."
icon_state = "generic"
cast_methods = CAST_MELEE|CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 50
/obj/item/spell/read_mind/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
read_mind(hit_atom, user)
/obj/item/spell/read_mind/proc/read_mind(atom/hit_atom, mob/user)
if(!isliving(hit_atom))
return
if(!isliving(user))
return
var/mob/living/target = hit_atom
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("Not even a psion of your level can speak to the dead."))
return
var/psi_blocked = target.is_psi_blocked()
if(psi_blocked)
to_chat(user, psi_blocked)
return
var/safe_mode = FALSE
var/mob/living/L = user
if(L.psi.get_rank() < PSI_RANK_HARMONIOUS)
safe_mode = TRUE
user.visible_message(SPAN_WARNING("[user] lays a palm on [hit_atom]'s forehead..."))
var/question
if(!safe_mode)
question = sanitize(input(user, "Ask your question.", "Read Mind") as null|text)
if((!safe_mode && !question) || user.incapacitated())
return TRUE
var/started_mindread = world.time
if(target.has_psi_aug())
to_chat(user, SPAN_NOTICE("<b>Your psyche links with [target]'s psi-receiver, seeking [safe_mode ? "their surface thoughts." : "an answer from their mind's surface: <i>[question]</i>"]</b>"))
to_chat(target, SPAN_NOTICE("<b>[user]'s psyche links with your psi-receiver. [safe_mode ? "What are you thinking about, currently?" : "You cannot avoid the following question, and must answer truthfully: <i>[question]</i>"]</b>"))
else
to_chat(user, SPAN_NOTICE("<b>You dip your mentality into the surface layer of \the [target]'s mind, seeking an answer: <i>[question]</i></b>"))
to_chat(target, SPAN_NOTICE("<b>Your mind is compelled to answer. [safe_mode ? "What are you thinking about, currently?" : "You cannot avoid the following question, and must answer truthfully: <i>[question]</i>"]</b>"))
var/answer = sanitize(input(target, "[question]\n[safe_mode ? "You must answer with what you are currently thinking about." : "You must answer truthfully."]\nYou have 25 seconds to type a response.", "Read Mind") as null|text)
if(!answer || world.time > started_mindread + 25 SECONDS || user.stat != CONSCIOUS)
to_chat(user, SPAN_NOTICE("<b>You receive nothing useful from \the [target].</b>"))
to_chat(target, SPAN_NOTICE("Your mind blanks out momentarily."))
else
if(safe_mode)
to_chat(user, SPAN_NOTICE("<b>You skim the first thoughts in [target]'s mind: <i>[answer]</i></b>"))
else
to_chat(user, SPAN_NOTICE("<b>You pry the answer to your question from [target]'s mind: <i>[answer]</i></b>"))
msg_admin_attack("[key_name(user)] read mind of [key_name(target)] [safe_mode ? "skimming their surface thoughts" : "forcing them to answer truthfully with question \"[question]\""] and [answer?"got answer \"[answer]\".":"got no answer."]")
if(safe_mode)
target.confused += 15
target.adjustBrainLoss(10)
to_chat(target, SPAN_WARNING("You feel somewhat nauseated, and a headache's come up too..."))
else
target.adjustBrainLoss(20)
target.confused += 20
to_chat(target, SPAN_DANGER("Your head feels like it's going to explode, and you feel nauseated..."))
@@ -0,0 +1,38 @@
/singleton/psionic_power/rejuvenate
name = "Rejuvenate"
desc = "Restore a creature's blood."
icon_state = "tech_oxygenate"
point_cost = 1
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/rejuvenate
/obj/item/spell/rejuvenate
name = "rejuvenate"
desc = "Blood bag who?"
icon_state = "mend_life"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 30
/obj/item/spell/rejuvenate/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!ishuman(hit_atom))
return
var/mob/living/carbon/human/target = hit_atom
if(!target.has_zona_bovinae())
to_chat(user, SPAN_WARNING("Psionic power cannot flow through this being."))
return
if(target.stat == DEAD || target.status_flags & FAKEDEATH)
to_chat(user, SPAN_WARNING("Psionic power does not flow through a dead person."))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_NOTICE("[user] lays both palms on [target]..."), SPAN_NOTICE("You lay your palms on [target] and get to work."))
if(do_mob(user, target, 10 SECONDS))
target.restore_blood()
user.visible_message(SPAN_NOTICE("[user] removes their palms from [target]."), SPAN_NOTICE("You remove your palms from [target], having restored their blood."))
+64
View File
@@ -0,0 +1,64 @@
/singleton/psionic_power/rend
name = "Rend"
desc = "Rend an adjacent target's biomolecular state apart. Very powerful, but with an extremely long cooldown and a huge psi-stamina cost. \
Activate it in your hand to switch to a structure mode, in which you cannot target living beings (synthetics included) but you can tear apart \
walls and airlocks much faster."
icon_state = "gen_dissolve"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/rend
/obj/item/spell/rend
name = "rend"
icon_state = "chain_lightning"
cast_methods = CAST_USE|CAST_MELEE
aspect = ASPECT_PSIONIC
force = 40
armor_penetration = 30
cooldown = 30
psi_cost = 35
attack_verb = list("rends apart", "disintegrates")
hitsound = 'sound/weapons/heavysmash.ogg'
flags = 0
var/structure_mode = FALSE
/obj/item/spell/rend/on_use_cast(mob/user, bypass_psi_check)
. = ..(user, TRUE)
structure_mode = !structure_mode
if(structure_mode)
to_chat(user, SPAN_WARNING("You reconfigure your rending to damage structures. It can no longer be used on organics or synthetics, but it is much cheaper \
to damage structures with."))
maptext = SMALL_FONTS(7, "S")
psi_cost = 15
else
to_chat(user, SPAN_WARNING("You reconfigure your rending to damage organics again."))
maptext = SMALL_FONTS(7, "O")
psi_cost = initial(psi_cost)
/obj/item/spell/rend/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(structure_mode && isliving(hit_atom))
to_chat(user, SPAN_WARNING("Your rending is not configured for organics!"))
return
. = ..()
if(!.)
return
if(structure_mode)
if(iswall(hit_atom))
var/turf/simulated/wall/W = hit_atom
var/base_time = 5 SECONDS
if(W.reinf_material)
base_time += (W.reinf_material.hardness / 10) SECONDS
user.visible_message(SPAN_WARNING("[user] lays [user.get_pronoun("his")] palms on \the [W] and begins discharging psionic energy on it..."),
SPAN_WARNING("You lay your palms on \the [W] and begin permeating psionic energy through its structure..."))
if(do_after(user, base_time))
user.visible_message(SPAN_WARNING("[user] disintegrates \the [W]!"), SPAN_WARNING("You disintegrate \the [W]!"))
W.dismantle_wall(TRUE, FALSE, TRUE)
else if(isairlock(hit_atom))
var/obj/machinery/door/airlock/A = hit_atom
var/base_time = (round(A.maxhealth / 60)) SECONDS
user.visible_message(SPAN_WARNING("[user] lays [user.get_pronoun("his")] palms on \the [A] and begins discharging psionic energy on it..."),
SPAN_WARNING("You lay your palms on \the [A] and begin permeating psionic energy through its structure..."))
if(do_after(user, base_time))
user.visible_message(SPAN_WARNING("[user] disintegrates \the [A]!"), SPAN_WARNING("You disintegrate \the [A]!"))
playsound(A, 'sound/effects/meteorimpact.ogg')
qdel(A)
@@ -0,0 +1,42 @@
/singleton/psionic_power/shockwave
name = "Shockwave"
desc = "Create a wave of telekinetic energy to pummel the ground in a straight line in the direction you're facing. \
Anyone caught in it falls over unless wearing magboots."
icon_state = "tech_haste"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/shockwave
/obj/item/spell/shockwave
name = "shockwave"
icon_state = "flame_tongue"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 20
/obj/item/spell/shockwave/on_use_cast(mob/user, bypass_psi_check)
. = ..()
if(!.)
return
var/user_dir = user.dir
var/turf/T = get_turf(user)
if(isspaceturf(T))
to_chat(user, SPAN_WARNING("You charge your shockwave, slam your foot down... and then remember that you're in space."))
return
user.visible_message(SPAN_DANGER(FONT_HUGE("[user] charges [user.get_pronoun("his")] foot with psionic energy and slams it down!")),
SPAN_DANGER(FONT_HUGE("You charge your foot with psionic energy and slam it down!")))
playsound(T, 'sound/effects/meteorimpact.ogg', 100)
for(var/mob/M in get_hearers_in_view(7, src))
shake_camera(M, 5, 5)
for(var/i = 1 to 5)
T = get_step(T, user_dir)
if(isspaceturf(T))
break
for(var/mob/living/M in T)
if(M.Check_Shoegrip())
continue
M.apply_effect(3, WEAKEN)
M.flash_pain(20)
to_chat(M, SPAN_DANGER("You get caught in the shockwave and fall down!"))
@@ -0,0 +1,59 @@
/singleton/psionic_power/singularity
name = "Singularity"
desc = "Creates a psionic illusion. Anyone within four tiles of it is forced to walk towards it. It will dissipate after ten seconds."
icon_state = "tech_energysiphon"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/singularity
/obj/item/spell/singularity
name = "singularity"
icon_state = "destablize"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 200
psi_cost = 20
var/obj/effect/singularity/singularity
/obj/item/spell/singularity/Destroy()
QDEL_NULL(singularity)
return ..()
/obj/item/spell/singularity/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!QDELETED(singularity))
to_chat(user, SPAN_WARNING("You can't make more than one singularity!"))
return
. = ..()
if(!.)
return
var/obj/effect/singularity/S = new(get_turf(hit_atom))
S.creator = user
singularity = S
playsound(get_turf(user), 'sound/effects/fingersnap.ogg')
user.visible_message(SPAN_DANGER(FONT_HUGE("[user] snaps [user.get_pronoun("his")] fingers and generates a hole of psionic energy!")),
SPAN_DANGER("You snap your fingers and generate a vortex of psionic energy."))
/obj/effect/singularity
name = "psionic singularity"
icon_state = "bluestream_fade"
var/mob/living/creator
/obj/effect/singularity/process()
for(var/mob/living/M in get_hearers_in_LOS(4, src))
if(M == creator)
continue
to_chat(M, SPAN_DANGER("Your eyes can't move away from \the [src]... you feel compelled to move towards it!"))
M.AdjustStunned(1)
step_towards(M, src)
/obj/effect/singularity/Initialize(mapload, ...)
. = ..()
QDEL_IN(src, 10 SECONDS)
START_PROCESSING(SSprocessing, src)
/obj/effect/singularity/Destroy()
visible_message(SPAN_WARNING("\The [src] dissipates harmlessly with a light 'fwoosh' sound."))
creator = null
STOP_PROCESSING(SSprocessing, src)
return ..()
@@ -0,0 +1,67 @@
/singleton/psionic_power/skinsight
name = "Skinsight"
desc = "Get information on a creature's vitals. Activate in your hand to switch between a normal mode or a slower, more detailed mode. Note that the body scan mode \
is not 100% accurate with the numbers given."
icon_state = "wiz_blind"
point_cost = 1
ability_flags = PSI_FLAG_EVENT|PSI_FLAG_CANON
spell_path = /obj/item/spell/skinsight
/obj/item/spell/skinsight
name = "skinsight"
desc = "A health analyzer, but cooler."
icon_state = "blink"
cast_methods = CAST_MELEE|CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 10
var/body_scan_mode = FALSE
/obj/item/spell/skinsight/on_use_cast(mob/user)
. = ..()
body_scan_mode = !body_scan_mode
if(body_scan_mode)
psi_cost = 30
to_chat(user, SPAN_NOTICE("You will now use more psionic energy for a more detailed readout."))
else
psi_cost = 10
to_chat(user, SPAN_NOTICE("You will now use less psionic energy for a more standard readout."))
/obj/item/spell/skinsight/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!ishuman(hit_atom))
return
var/mob/living/carbon/human/target = hit_atom
if(!target.has_zona_bovinae())
to_chat(user, SPAN_WARNING("Psionic power cannot flow through this being."))
return
if(!isliving(user))
return
if(target.stat == DEAD)
to_chat(user, SPAN_WARNING("The total lack of psionic energy flowing through this person can only mean one thing: they are dead."))
return
. = ..()
if(!.)
return
if(!body_scan_mode)
user.visible_message(SPAN_NOTICE("[user] passes [user.get_pronoun("his")] hand over [target]."), SPAN_NOTICE("You pass your hand over [target]."))
health_scan_mob(target, user, TRUE, TRUE)
else
user.visible_message(SPAN_NOTICE("[user] slowly passes [user.get_pronoun("his")] hand over [target]..."),
SPAN_NOTICE("You slowly pass your hand over [target]..."))
if(do_mob(user, target, 10 SECONDS))
for(var/obj/item/organ/internal/I in target.internal_organs)
if(I.is_bruised())
to_chat(user, SPAN_WARNING("You notice some irregularity in the psionic flow through their [I]."))
if(I.is_broken())
to_chat(user, SPAN_WARNING("Your psionic flow through their [I] is <b>highly irregular</b>."))
if(I.damage)
to_chat(user, SPAN_WARNING("You are sure there is some damage in their [I]."))
var/pulse = target.get_pulse()
to_chat(user, SPAN_NOTICE("Their pulse is [pulse]."))
var/oxygenation = max(min(target.get_blood_oxygenation() + rand(-10, 10), 100), 0)
to_chat(user, SPAN_NOTICE("Their oxygenation is more or less [oxygenation]%."))
+30
View File
@@ -0,0 +1,30 @@
/singleton/psionic_power/spasm
name = "Spasm"
desc = "Force a target to drop the items in its hands. Note that this has a hefty power use and cooldown."
icon_state = "genetics_closed"
point_cost = 1
ability_flags = PSI_FLAG_EVENT
spell_path = /obj/item/spell/spasm
/obj/item/spell/spasm
name = "spasm"
desc = "Made you drop your gun."
icon_state = "control"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 100
/// This looks like a lot, but this ability is really strong.
psi_cost = 20
/obj/item/spell/spasm/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!ishuman(hit_atom))
to_chat(user, SPAN_WARNING("That won't work!"))
return
. = ..()
if(!.)
return
var/mob/living/carbon/human/H = hit_atom
H.drop_l_hand()
H.drop_r_hand()
to_chat(H, SPAN_DANGER("Your mind is filled by an acute pain making you drop what you're holding!"))
H.flash_pain(50)
+58
View File
@@ -0,0 +1,58 @@
/singleton/psionic_power/stasis
name = "Stasis"
desc = "Condenses the Nlom field around one person at a time. This immobilises them like an energy net and also applies stasis to them."
icon_state = "gen_ice"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/stasis
/obj/item/spell/stasis
name = "stasis"
desc = "Almost as cool as the Mass Effect one."
icon_state = "overload"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
cooldown = 100
psi_cost = 20
var/obj/effect/energy_net/our_net
/obj/item/spell/stasis/Destroy()
qdel(our_net)
our_net = null
return ..()
/obj/item/spell/stasis/on_ranged_cast(atom/hit_atom, mob/user, bypass_psi_check)
if(!isliving(hit_atom))
return
if(!QDELETED(our_net))
to_chat(user, SPAN_WARNING("You can't target more than one person with this!"))
return
. = ..()
if(!.)
return
var/mob/living/M = hit_atom
var/obj/effect/energy_net/EN = locate() in get_turf(M)
if(EN)
qdel(EN)
var/turf/T = get_turf(M)
if(T)
var/obj/effect/energy_net/stasis/net = new(T)
net.layer = M.layer + 1
M.captured = TRUE
M.update_canmove()
net.affecting = M
our_net = net
M.visible_message(SPAN_DANGER("A field of condensed Nlom appears around [M]!"), SPAN_DANGER("You are immobilised by a field of condensed Nlom! You feel your body and mind slow down..."))
/obj/effect/energy_net/stasis
name = "condensed nlom field"
desc = "A crystallized field of pure Nlom energy."
icon_state = "shield2"
health = 100
/obj/effect/energy_net/stasis/process()
. = ..()
if(iscarbon(affecting))
var/mob/living/carbon/C = affecting
C.SetStasis(10)
+93
View File
@@ -0,0 +1,93 @@
/singleton/psionic_power/throw_item
name = "Throw"
desc = "Click this spell with an item to prepare it to be thrown, then use the spell to throw the item with lethal force."
icon_state = "wiz_mm"
point_cost = 3
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/projectile/throw_item
/obj/item/spell/projectile/throw_item
name = "throw"
desc = "Almost as cool as the Mass Effect one, but still not as cool."
icon_state = "aspect_bolt"
cast_methods = CAST_RANGED
aspect = ASPECT_PSIONIC
spell_projectile = /obj/item/projectile/psionic_throw
fire_sound = 'sound/weapons/wave.ogg'
cooldown = 20
psi_cost = 20
var/obj/item_to_throw
/obj/item/spell/projectile/throw_item/attackby(obj/item/W, mob/user)
. = ..()
if(!item_to_throw)
owner.drop_item(W)
W.forceMove(src)
to_chat(user, SPAN_NOTICE("You imbue [W] with psionic energy!"))
add_overlay("controlled")
item_to_throw = W
/obj/item/spell/projectile/throw_item/Destroy()
if(item_to_throw)
item_to_throw.forceMove(loc)
item_to_throw = null
return ..()
/obj/item/spell/projectile/throw_item/on_use_cast(mob/user)
. = ..(user, TRUE)
if(item_to_throw)
owner.put_in_hands(item_to_throw)
item_to_throw = null
cut_overlays()
/obj/item/spell/projectile/throw_item/on_ranged_cast(atom/hit_atom, mob/living/user, atom/pb_target)
if(!item_to_throw)
to_chat(user, SPAN_WARNING("You need to imbue an item with psionic energy first!"))
return
. = ..()
item_to_throw = null
cut_overlays()
/obj/item/spell/projectile/throw_item/make_projectile(obj/item/projectile/projectile_type, mob/living/user)
var/obj/item/projectile/psionic_throw/P = ..()
if(P && item_to_throw)
var/base_damage = item_to_throw.force > 5 ? item_to_throw.force : 10
/// Why is it called a fucking divisor? It's a multiplier...
var/thrown_force_divisor = 1
if(istype(item_to_throw, /obj/item/material/twohanded))
var/obj/item/material/twohanded/MT = item_to_throw
base_damage = MT.force_wielded > MT.force ? MT.force_wielded : force
thrown_force_divisor = MT.thrown_force_divisor
/// There are different throwforce calculations, which means that we have to do this manually.
if(base_damage < (item_to_throw.throwforce * thrown_force_divisor))
base_damage = item_to_throw.throwforce * thrown_force_divisor
var/base_armor_penetration
if(item_to_throw.armor_penetration > 2)
base_armor_penetration = item_to_throw.armor_penetration
else
base_armor_penetration = 2
P.name = item_to_throw.name
P.appearance = item_to_throw.appearance
P.damage = base_damage * (item_to_throw.w_class / 2)
P.armor_penetration = base_armor_penetration * item_to_throw.w_class
/// We need to do this again because we're overriding the base make_projectile.
if(owner.psi.get_rank() >= PSI_RANK_APEX)
if(P.damage)
P.damage *= 1.1
P.armor_penetration *= 1.1
P.damage_flags |= item_to_throw.damage_flags()
P.damage_type = item_to_throw.damtype
P.source_item = item_to_throw
return P
/obj/item/projectile/psionic_throw
name = "thrown projectile"
damage_type = DAMAGE_BRUTE
impact_sounds = list(BULLET_IMPACT_MEAT = SOUNDS_BULLET_MEAT, BULLET_IMPACT_METAL = SOUNDS_BULLET_METAL)
var/obj/source_item
/obj/item/projectile/psionic_throw/Destroy()
if(source_item)
source_item.forceMove(loc)
source_item = null
return ..()
@@ -0,0 +1,47 @@
/singleton/psionic_power/time_stop
name = "Time Stop"
desc = "Freeze living beings around you in a 5x5 area. This ability is very expensive, so be careful."
icon_state = "tech_control"
point_cost = 2
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/time_stop
/obj/item/spell/time_stop
name = "nlom eyes"
desc = "Psionic drugs? No way."
icon_state = "track"
cast_methods = CAST_USE
aspect = ASPECT_PSIONIC
cooldown = 10
psi_cost = 30
/obj/item/spell/time_stop/Destroy()
for(var/mob/living/L in get_hearers_in_view(5, owner))
if(L == owner)
continue
to_chat(L, SPAN_DANGER("Time around you returns to normal!"))
L.stunned = 0
L.silent = 0
return ..()
/obj/item/spell/time_stop/on_use_cast(mob/user)
. = ..()
if(!.)
return
if(do_after(user, 1 SECOND))
user.visible_message(SPAN_DANGER(FONT_HUGE("[user] extends [user.get_pronoun("his")] arms to [user.get_pronoun("his")] sides!")),
SPAN_DANGER("You extend your arms to your side and crystallize the Nlom around you!"))
time_stop(user)
/obj/item/spell/time_stop/proc/time_stop(mob/living/user)
for(var/mob/living/L in get_hearers_in_view(5, user))
if(L == user)
continue
to_chat(L, SPAN_DANGER("Time around you slows down to a crawl..."))
L.AdjustStunned(5)
L.silent += 30
if(do_after(user, 1 SECOND))
if(user.psi.spend_power(20))
time_stop(user)
+75
View File
@@ -0,0 +1,75 @@
/singleton/psionic_power/warp
name = "Warp"
desc = "Warp through objects."
icon_state = "tech_blink"
point_cost = 4
ability_flags = PSI_FLAG_ANTAG
spell_path = /obj/item/spell/warp
/obj/item/spell/warp
name = "warp"
icon_state = "warp_strike"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 50
psi_cost = 10
var/maximum_distance = 20 //Measured in tiles.
var/busy = FALSE
/obj/item/spell/warp/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
. = ..()
if(!.)
return
if(busy) //Prevent someone from trying to get two uses of the spell from one instance.
return FALSE
if(!allowed_to_teleport())
to_chat(user, SPAN_WARNING("You can't teleport here."))
return FALSE
var/turf/T = get_turf(hit_atom) //Turf we touched.
var/turf/our_turf = get_turf(user) //Where we are.
if(!T.density)
if(!T.check_density())
to_chat(user, SPAN_WARNING("This spell is for solid objects."))
return FALSE
var/direction = get_dir(our_turf, T)
var/turf/checked_turf = T //Turf we're currently checking for density in the loop below.
var/turf/found_turf = null //Our destination, if one is found.
var/i = maximum_distance
visible_message(SPAN_NOTICE("[user] rests a hand on \the [hit_atom]."))
busy = TRUE
spark(our_turf, 3, cardinal)
while(i)
checked_turf = get_step(checked_turf, direction) //Advance in the given direction
i--
if(!checked_turf.density) //If we found a destination (a non-dense turf), then we can stop.
var/dense_objs_on_turf = 0
for(var/atom/movable/stuff in checked_turf.contents) //Make sure nothing dense is where we want to go, like an airlock or window.
if(stuff.density)
dense_objs_on_turf = 1
if(!dense_objs_on_turf) //If we found a non-dense turf with nothing dense on it, then that's our destination.
found_turf = checked_turf
break
sleep(10)
if(found_turf)
if(user.loc != our_turf)
to_chat(user, SPAN_WARNING("You need to stand still in order to phase through \the [hit_atom]."))
return FALSE
if(!user.incapacitated())
visible_message(SPAN_WARNING("[user] appears to phase through \the [hit_atom]!"))
to_chat(user, SPAN_NOTICE("You find a destination on the other side of \the [hit_atom], and phase through it."))
spark(src, 5, 0)
user.forceMove(found_turf)
qdel(src)
return TRUE
else
to_chat(user, SPAN_WARNING("You don't have enough energy to phase through these walls!"))
busy = FALSE
else
to_chat(user, SPAN_NOTICE("You weren't able to find an open space to go to."))
busy = FALSE
@@ -0,0 +1,41 @@
/singleton/psionic_power/zona_absorption
name = "Zona Bovinae Absorption"
desc = "Absorb a psionic energy from a being's Zona Bovinae, granting you an extra point to be used in the Point Shop."
icon_state = "tech_shield_old"
point_cost = 0
ability_flags = PSI_FLAG_SPECIAL
spell_path = /obj/item/spell/zona_absorption
/obj/item/spell/zona_absorption
name = "zona bovinae absorption"
icon_state = "chain_lightning"
cast_methods = CAST_MELEE
aspect = ASPECT_PSIONIC
cooldown = 30
psi_cost = 10
/obj/item/spell/zona_absorption/on_melee_cast(atom/hit_atom, mob/living/user, def_zone)
if(!isliving(hit_atom))
return
var/mob/living/L = hit_atom
if(!L.has_zona_bovinae())
to_chat(user, SPAN_WARNING("This being doesn't have a Zona Bovinae."))
return
if(HAS_TRAIT(L, TRAIT_ZONA_BOVINAE_ABSORBED))
to_chat(user, SPAN_WARNING("You already absorbed points from this creature!"))
return
. = ..()
if(!.)
return
user.visible_message(SPAN_DANGER("[user] grabs [L]'s head..."), SPAN_DANGER("You grab [L]'s head..."))
if(do_mob(user, L, 5 SECONDS))
L.flash_pain(20)
L.adjustHalLoss(20)
playsound(get_turf(L), 'sound/effects/psi/power_feedback.ogg', 100)
user.visible_message(SPAN_DANGER("[user] absorbs tendrils of psionic energy from [L]!"),
SPAN_DANGER("You absorb psionic energy from [L], granting you an extra Psionic Point Shop point."))
var/mob/living/M = user
M.psi.psi_points++
to_chat(L, SPAN_DANGER("A splitting headache courses through your mind! Your head feels a bit lighter..."))
ADD_TRAIT(L, TRAIT_ZONA_BOVINAE_ABSORBED, TRAIT_SOURCE_PSIONICS)