Revert "Psionics Rework: Kyoushiki Murasaki (#16805)" (#16948)

This reverts commit 27c40bdaf6.
This commit is contained in:
Matt Atlas
2023-07-31 03:51:40 +02:00
committed by GitHub
parent 06ca379a91
commit 87f637564f
145 changed files with 1617 additions and 3162 deletions
+17 -15
View File
@@ -1,28 +1,35 @@
/datum/psi_complexus
var/announced = FALSE // Whether or not we have been announced to our holder yet.
var/suppressed = FALSE // Whether or not we are suppressing our psi powers.
var/suppressed = TRUE // Whether or not we are suppressing our psi powers.
var/use_psi_armor = TRUE // Whether or not we should automatically deflect/block incoming damage.
var/rebuild_power_cache = TRUE // Whether or not we need to rebuild our cache of psi powers.
var/rating = 0 // Overall psi rating.
var/cost_modifier = 1 // Multiplier for power use stamina costs.
var/stun = 0 // Number of process ticks we are stunned for.
var/next_power_use = 0 // world.time minimum before next power use.
var/stamina = 100 // Current psi pool.
var/max_stamina = 100 // Max psi pool.
var/psi_points = 0 // Points spendable in the psi pointshop.
var/spent_psi_points = 0 // Need to keep track of if someone has spent psi-points before for things like updating psi-rank.
var/stamina = 50 // Current psi pool.
var/max_stamina = 50 // Max psi pool.
var/psionic_rank
var/last_psionic_rank
var/list/latencies // List of all currently latent faculties.
var/list/ranks // Assoc list of psi faculties to current rank.
var/list/base_ranks // Assoc list of psi faculties to base rank, in case reset is needed
var/list/manifested_items // List of atoms manifested/maintained by psychic power.
var/list/psionic_powers = list() // List of singleton abilities.
var/next_latency_trigger = 0 // world.time minimum before a trigger can be attempted again.
var/last_armor_check // world.time of last armor check.
var/last_aura_size
var/last_aura_alpha
var/last_aura_color
var/aura_color = "#ff0022"
var/datum/component/armor/psionic/armor_component
// Cached powers.
var/list/melee_powers // Powers used in melee range.
var/list/grab_powers // Powers use by using a grab.
var/list/ranged_powers // Powers used at range.
var/list/manifestation_powers // Powers that create an item.
var/list/powers_by_faculty // All powers within a given faculty.
var/obj/screen/psi/hub/ui // Reference to the master psi UI object.
var/mob/living/owner // Reference to our owner.
var/image/_aura_image // Client image
@@ -63,17 +70,13 @@
/datum/psi_complexus/New(var/mob/_owner)
owner = _owner
SSpsi.all_psi_complexes |= src
START_PROCESSING(SSpsi, src)
/datum/psi_complexus/Destroy()
destroy_aura_image(_aura_image)
SSpsi.all_psi_complexes -= src
QDEL_NULL(armor_component)
STOP_PROCESSING(SSpsi, src)
if(owner)
if(owner.ability_master)
owner.ability_master.remove_all_psionic_abilities()
cancel()
if(owner.client)
owner.client.screen -= ui
for(var/thing in SSpsi.all_aura_images)
@@ -86,5 +89,4 @@
for(var/thing in manifested_items)
qdel(thing)
manifested_items.Cut()
. = ..()
@@ -1,28 +1,38 @@
/datum/psi_complexus/proc/cancel()
sound_to(owner, sound('sound/effects/psi/power_fail.ogg'))
if(LAZYLEN(manifested_items))
for(var/thing in manifested_items)
owner.drop_from_inventory(thing)
qdel(thing)
manifested_items = null
/datum/psi_complexus/proc/stunned(var/amount)
var/old_stun = stun
stun = max(stun, amount)
if(amount && !old_stun)
to_chat(owner, "<span class='danger'>Your concentration has been shattered! You cannot focus your psi power!</span>")
ui.update_icon()
cancel()
/datum/psi_complexus/proc/get_armor(var/armortype)
if(can_use_passive())
last_armor_check = world.time
return round(Clamp(Clamp(4 * get_rank(), 0, 20) * get_rank() / 2, 0, 100) * (stamina/max_stamina))
return round(Clamp(Clamp(4 * rating, 0, 20) * get_rank(SSpsi.armor_faculty_by_type[armortype]), 0, 100) * (stamina/max_stamina))
else
last_armor_check = 0
return 0
/datum/psi_complexus/proc/set_rank(var/rank, var/defer_update)
if(get_rank() != rank)
last_psionic_rank = psionic_rank
psionic_rank = rank
/datum/psi_complexus/proc/get_rank(var/faculty)
return LAZYACCESS(ranks, faculty)
/datum/psi_complexus/proc/set_rank(var/faculty, var/rank, var/defer_update, var/temporary)
if(get_rank(faculty) != rank)
LAZYSET(ranks, faculty, rank)
if(!temporary)
LAZYSET(base_ranks, faculty, rank)
if(!defer_update)
update()
/datum/psi_complexus/proc/get_rank()
return psionic_rank
/datum/psi_complexus/proc/set_cooldown(var/value)
next_power_use = world.time + value
ui.update_icon()
@@ -70,13 +80,11 @@
stunned(value * 2)
set_cooldown(value * 100)
if(prob(value*10))
owner.emote("scream")
if(prob(value*10)) owner.emote("scream")
// Your head asplode.
owner.adjustBrainLoss(value)
owner.adjustHalLoss(value * 25) //Ouch.
owner.psi.hide_auras()
if(ishuman(owner))
var/mob/living/carbon/human/pop = owner
if(pop.should_have_organ(BP_BRAIN))
@@ -89,6 +97,8 @@
/datum/psi_complexus/proc/reset()
aura_color = initial(aura_color)
ranks = base_ranks ? base_ranks.Copy() : null
max_stamina = initial(max_stamina)
stamina = min(stamina, max_stamina)
cancel()
update()
@@ -1,6 +1,17 @@
/datum/psi_complexus/proc/check_psionic_trigger(var/trigger_strength = 0, var/source, var/redactive = FALSE)
/datum/psi_complexus/proc/check_latency_trigger(var/trigger_strength = 0, var/source, var/redactive = FALSE)
if(!LAZYLEN(latencies) || world.time < next_latency_trigger)
return FALSE
if(!prob(trigger_strength))
next_latency_trigger = world.time + rand(100, 300)
return FALSE
var/faculty = pick(latencies)
var/new_rank = rand(2,5)
owner.set_psi_rank(new_rank)
to_chat(owner, SPAN_DANGER("You scream internally as your psionics are forced into operancy by [source]!"))
owner.set_psi_rank(faculty, new_rank)
var/datum/psionic_faculty/faculty_decl = SSpsi.get_faculty(faculty)
to_chat(owner, SPAN_DANGER("You scream internally as your [faculty_decl.name] faculty is forced into operancy by [source]!"))
next_latency_trigger = world.time + rand(600, 1800) * new_rank
if(!redactive) owner.adjustBrainLoss(rand(trigger_strength * 2, trigger_strength * 4))
return TRUE
@@ -0,0 +1,49 @@
/datum/psi_complexus/proc/rebuild_power_cache()
if(rebuild_power_cache)
melee_powers = list()
grab_powers = list()
ranged_powers = list()
manifestation_powers = list()
powers_by_faculty = list()
for(var/faculty in ranks)
var/relevant_rank = get_rank(faculty)
var/datum/psionic_faculty/faculty_decl = SSpsi.get_faculty(faculty)
for(var/thing in faculty_decl.powers)
var/datum/psionic_power/power = thing
if(relevant_rank >= power.min_rank)
if(!powers_by_faculty[power.faculty]) powers_by_faculty[power.faculty] = list()
powers_by_faculty[power.faculty] += power
if(power.use_ranged)
if(!ranged_powers[faculty]) ranged_powers[faculty] = list()
ranged_powers[faculty] += power
if(power.use_melee)
if(!melee_powers[faculty]) melee_powers[faculty] = list()
melee_powers[faculty] += power
if(power.use_manifest)
manifestation_powers += power
if(power.use_grab)
if(!grab_powers[faculty]) grab_powers[faculty] = list()
grab_powers[faculty] += power
rebuild_power_cache = FALSE
/datum/psi_complexus/proc/get_powers_by_faculty(var/faculty)
rebuild_power_cache()
return powers_by_faculty[faculty]
/datum/psi_complexus/proc/get_melee_powers(var/faculty)
rebuild_power_cache()
return melee_powers[faculty]
/datum/psi_complexus/proc/get_ranged_powers(var/faculty)
rebuild_power_cache()
return ranged_powers[faculty]
/datum/psi_complexus/proc/get_grab_powers(var/faculty)
rebuild_power_cache()
return grab_powers[faculty]
/datum/psi_complexus/proc/get_manifestations()
rebuild_power_cache()
return manifestation_powers
@@ -1,15 +1,38 @@
/datum/psi_complexus/proc/update(var/force)
set waitfor = FALSE
if(force || last_psionic_rank != psionic_rank)
if(psionic_rank == 0)
qdel(src)
var/last_rating = rating
var/highest_faculty
var/highest_rank = 0
var/combined_rank = 0
for(var/faculty in ranks)
var/check_rank = get_rank(faculty)
if(check_rank == 1)
LAZYADD(latencies, faculty)
else
if(check_rank <= 0)
ranks -= faculty
LAZYREMOVE(latencies, faculty)
combined_rank += check_rank
if(!highest_faculty || highest_rank < check_rank)
highest_faculty = faculty
highest_rank = check_rank
UNSETEMPTY(latencies)
var/rank_count = max(1, LAZYLEN(ranks))
if(force || last_rating != Ceiling(combined_rank/rank_count))
if(highest_rank <= 1)
if(highest_rank == 0)
qdel(src)
return
else
rebuild_power_cache = TRUE
sound_to(owner, 'sound/effects/psi/power_unlock.ogg')
rating = Ceiling(combined_rank/rank_count)
cost_modifier = 1
if(psionic_rank > 1)
cost_modifier -= min(1, max(0.1, psionic_rank / 10))
if(rating > 1)
cost_modifier -= min(1, max(0.1, (rating-1) / 10))
if(!ui)
ui = new(owner)
if(owner.client)
@@ -17,60 +40,35 @@
else
if(owner.client)
owner.client.screen |= ui
if(!suppressed && owner.client)
for(var/thing in SSpsi.all_aura_images)
owner.client.images |= thing
var/image/aura_image = get_aura_image()
if(psionic_rank >= PSI_RANK_APEX) // spooky boosters
if(rating >= PSI_RANK_PARAMOUNT) // spooky boosters
aura_color = "#aaffaa"
aura_image.blend_mode = BLEND_SUBTRACT
else
aura_image.blend_mode = BLEND_ADD
if(psionic_rank == PSI_RANK_SENSITIVE)
if(highest_faculty == PSI_COERCION)
aura_color = "#cc3333"
else if(highest_faculty == PSI_PSYCHOKINESIS)
aura_color = "#3333cc"
else if(highest_faculty == PSI_REDACTION)
aura_color = "#33cc33"
else if(highest_faculty == PSI_ENERGISTICS)
aura_color = "#cccc33"
else if(psionic_rank == PSI_RANK_HARMONIOUS)
aura_color = "#64c464"
if(psionic_rank > PSI_RANK_SENSITIVE && last_psionic_rank < PSI_RANK_HARMONIOUS)
switch(psionic_rank)
if(PSI_RANK_HARMONIOUS)
psi_points = PSI_POINTS_HARMONIOUS
if(PSI_RANK_APEX)
psi_points = PSI_POINTS_APEX
if(PSI_RANK_LIMITLESS)
psi_points = PSI_POINTS_LIMITLESS
/// We had special abilities unique to our level, so get rid of 'em.
if(last_psionic_rank > PSI_RANK_HARMONIOUS)
wipe_user_abilities()
if(last_psionic_rank > PSI_RANK_SENSITIVE && psionic_rank < PSI_RANK_HARMONIOUS)
psi_points = 0
wipe_user_abilities()
if(!announced && owner && owner.client && !QDELETED(src))
announced = TRUE
to_chat(owner, "<hr>")
to_chat(owner, SPAN_NOTICE("<font size = 3>You are <b>psionic</b>, touched by powers beyond understanding.</font>"))
to_chat(owner, SPAN_NOTICE("<b>Left-click</b> your psionic icon to open your Psionic Point Shop, which contains information about your powers. \
You can also <b>shift-click</b> your ability icons on the top right to know more about them. \
Beware: overusing your gifts can have <b>deadly consequences</b>."))
to_chat(owner, SPAN_NOTICE("<b>Shift-left-click your Psi icon</b> on the bottom right to <b>view a summary of how to use them</b>, or <b>left click</b> it to <b>suppress or unsuppress</b> your psionics. Beware: overusing your gifts can have <b>deadly consequences</b>."))
to_chat(owner, "<hr>")
if(get_rank() >= PSI_RANK_SENSITIVE)
for(var/singleton/psionic_power/P in GET_SINGLETON_SUBTYPE_LIST(/singleton/psionic_power))
if((P.ability_flags & PSI_FLAG_FOUNDATIONAL) || (P.ability_flags & PSI_FLAG_APEX && get_rank() >= PSI_RANK_APEX) || (P.ability_flags & PSI_FLAG_LIMITLESS && get_rank() >= PSI_RANK_LIMITLESS))
if(!(P.type in psionic_powers))
P.apply(owner)
/datum/psi_complexus/proc/wipe_user_abilities()
for(var/obj/screen/ability/obj_based/psionic/P in owner.ability_master.ability_objects)
if((P.connected_power.ability_flags & PSI_FLAG_APEX) && get_rank() < PSI_RANK_APEX)
owner.ability_master.remove_ability(P)
if((P.connected_power.ability_flags & PSI_FLAG_LIMITLESS) && get_rank() < PSI_RANK_LIMITLESS)
owner.ability_master.remove_ability(P)
/datum/psi_complexus/process()
var/update_hud
if(stun)
stun--
if(stun)
@@ -79,7 +77,6 @@
update_hud = TRUE
else
to_chat(owner, SPAN_NOTICE("You have recovered your mental composure."))
suppressed = FALSE
update_hud = TRUE
return
@@ -89,11 +86,11 @@
else if(owner?.stat == UNCONSCIOUS)
stamina = min(max_stamina, stamina + rand(3,5))
if(armor_component)
spend_power(1)
if(!owner.nervous_system_failure() && owner.stat == CONSCIOUS && stamina && !suppressed && get_rank(PSI_REDACTION) >= PSI_RANK_OPERANT)
attempt_regeneration()
var/next_aura_size = max(0.1, ((stamina / max_stamina)*min(3, psionic_rank)) / 3)
var/next_aura_alpha = round(((suppressed ? max(0, psionic_rank - 2) : psionic_rank) / 5)*255)
var/next_aura_size = max(0.1,((stamina/max_stamina)*min(3,rating))/5)
var/next_aura_alpha = round(((suppressed ? max(0,rating - 2) : rating)/5)*255)
if(next_aura_alpha != last_aura_alpha || next_aura_size != last_aura_size || aura_color != last_aura_color)
last_aura_size = next_aura_size
@@ -106,3 +103,126 @@
if(update_hud)
ui.update_icon()
/datum/psi_complexus/proc/attempt_regeneration()
var/heal_general = FALSE
var/heal_poison = FALSE
var/heal_internal = FALSE
var/heal_bleeding = FALSE
var/heal_rate = 0
var/mend_prob = 0
var/use_rank = get_rank(PSI_REDACTION)
if(use_rank >= PSI_RANK_PARAMOUNT)
heal_general = TRUE
heal_poison = TRUE
heal_internal = TRUE
heal_bleeding = TRUE
mend_prob = 50
heal_rate = 7
else if(use_rank == PSI_RANK_GRANDMASTER)
heal_poison = TRUE
heal_internal = TRUE
heal_bleeding = TRUE
mend_prob = 20
heal_rate = 5
else if(use_rank == PSI_RANK_MASTER)
heal_internal = TRUE
heal_bleeding = TRUE
mend_prob = 10
heal_rate = 3
else if(use_rank == PSI_RANK_OPERANT)
heal_bleeding = TRUE
mend_prob = 5
heal_rate = 1
else
return
if(!heal_rate || stamina < heal_rate)
return // Don't backblast from trying to heal ourselves thanks.
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
// Fix some pain.
if(heal_rate > 0)
H.shock_stage = max(0, H.shock_stage - max(1, round(heal_rate/2)))
// Mend internal damage.
if(prob(mend_prob))
// Fix our heart if we're paramount.
if(heal_general && H.is_asystole() && H.should_have_organ(BP_HEART) && spend_power(heal_rate))
H.resuscitate()
// Heal organ damage.
if(heal_internal)
for(var/obj/item/organ/I in H.internal_organs)
if(BP_IS_ROBOTIC(I))
continue
if(I.damage > 0 && spend_power(heal_rate))
I.damage = max(I.damage - heal_rate, 0)
if(prob(25))
to_chat(H, SPAN_NOTICE("Your innards itch as your autoredactive faculty mends your [I.name]."))
return
// Heal broken bones.
if(H.bad_external_organs.len)
for(var/obj/item/organ/external/E in H.bad_external_organs)
if(BP_IS_ROBOTIC(E))
continue
if(heal_internal && (E.status & ORGAN_BROKEN) && E.damage < E.min_broken_damage) // So we don't mend and autobreak.
if(spend_power(heal_rate))
if(E.mend_fracture())
to_chat(H, SPAN_NOTICE("Your autoredactive faculty coaxes together the shattered bones in your [E.name]."))
return
if(heal_bleeding)
if((E.status & ORGAN_ARTERY_CUT) && spend_power(heal_rate))
to_chat(H, SPAN_NOTICE("Your autoredactive faculty mends the torn artery in your [E.name], stemming the worst of the bleeding."))
E.status &= ~ORGAN_ARTERY_CUT
return
if((E.tendon_status() & TENDON_CUT) && E.tendon.can_recover())
to_chat(H, SPAN_NOTICE("Your autoredactive faculty repairs the severed tendon in your [E.name]."))
E.tendon.rejuvenate()
return TRUE
for(var/datum/wound/W in E.wounds)
if(W.bleeding() && spend_power(heal_rate))
to_chat(H, SPAN_NOTICE("Your autoredactive faculty knits together severed veins, stemming the bleeding from \a [W.desc] on your [E.name]."))
W.bleed_timer = 0
W.clamped = TRUE
E.status &= ~ORGAN_BLEEDING
return
// Heal radiation, cloneloss and poisoning.
if(heal_poison)
if(owner.total_radiation && spend_power(heal_rate))
if(prob(25))
to_chat(owner, SPAN_NOTICE("Your autoredactive faculty repairs some of the radiation damage to your body."))
owner.total_radiation = max(0, owner.total_radiation - heal_rate)
return
if(owner.getCloneLoss() && spend_power(heal_rate))
if(prob(25))
to_chat(owner, SPAN_NOTICE("Your autoredactive faculty stitches together some of your mangled DNA."))
owner.adjustCloneLoss(-heal_rate)
return
// Heal everything left.
if(heal_general && prob(mend_prob) && (owner.getBruteLoss() || owner.getFireLoss() || owner.getOxyLoss()) && spend_power(heal_rate))
owner.adjustBruteLoss(-(heal_rate))
owner.adjustFireLoss(-(heal_rate))
owner.adjustOxyLoss(-(heal_rate))
if(prob(25))
to_chat(owner, SPAN_NOTICE("Your skin crawls as your autoredactive faculty heals your body."))