[MIRROR] Buffs Heretic Curses, Living Heart, Leeching Walk, and technically Entropic Plume by fixing some bugs [MDB IGNORE] (#15986)

* Buffs Heretic Curses, Living Heart, Leeching Walk, and technically Entropic Plume by fixing some bugs

* resolve conflicts

Co-authored-by: MrMelbert <51863163+MrMelbert@users.noreply.github.com>
Co-authored-by: Tom <8881105+tf-4@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-09-04 19:28:17 +01:00
committed by GitHub
co-authored by MrMelbert Tom
parent 513aaff5b2
commit 6f8b19cfa6
11 changed files with 320 additions and 166 deletions
+8 -2
View File
@@ -1,11 +1,17 @@
//Prevents calling anything in update_icon() like update_icon_state() or update_overlays()
/// Prevents calling anything in update_icon() like update_icon_state() or update_overlays()
/datum/element/update_icon_blocker
/datum/element/update_icon_blocker/Attach(datum/target)
. = ..()
if(!istype(target, /atom))
if(!isatom(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON, .proc/block_update_icon)
/datum/element/update_icon_blocker/Detach(datum/source, ...)
UnregisterSignal(source, COMSIG_ATOM_UPDATE_ICON)
return ..()
/datum/element/update_icon_blocker/proc/block_update_icon()
SIGNAL_HANDLER
@@ -777,78 +777,6 @@
msg_stage++
/datum/status_effect/corrosion_curse
id = "corrosion_curse"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
tick_interval = 1 SECONDS
/datum/status_effect/corrosion_curse/on_creation(mob/living/new_owner, ...)
. = ..()
to_chat(owner, span_userdanger("Your body starts to break apart!"))
/datum/status_effect/corrosion_curse/tick()
. = ..()
if(!ishuman(owner))
return
var/mob/living/carbon/human/human_owner = owner
var/chance = rand(0, 100)
switch(chance)
if(0 to 10)
human_owner.vomit()
if(20 to 30)
human_owner.set_timed_status_effect(100 SECONDS, /datum/status_effect/dizziness, only_if_higher = TRUE)
human_owner.set_timed_status_effect(100 SECONDS, /datum/status_effect/jitter, only_if_higher = TRUE)
if(30 to 40)
human_owner.adjustOrganLoss(ORGAN_SLOT_LIVER, 5)
if(40 to 50)
human_owner.adjustOrganLoss(ORGAN_SLOT_HEART, 5, 90)
if(50 to 60)
human_owner.adjustOrganLoss(ORGAN_SLOT_STOMACH, 5)
if(60 to 70)
human_owner.adjustOrganLoss(ORGAN_SLOT_EYES, 10)
if(70 to 80)
human_owner.adjustOrganLoss(ORGAN_SLOT_EARS, 10)
if(80 to 90)
human_owner.adjustOrganLoss(ORGAN_SLOT_LUNGS, 10)
if(90 to 95)
human_owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20, 190)
if(95 to 100)
human_owner.adjust_timed_status_effect(12 SECONDS, /datum/status_effect/confusion)
/datum/status_effect/cloudstruck
id = "cloudstruck"
status_type = STATUS_EFFECT_REPLACE
duration = 3 SECONDS
on_remove_on_mob_delete = TRUE
///This overlay is applied to the owner for the duration of the effect.
var/mutable_appearance/mob_overlay
/datum/status_effect/cloudstruck/on_creation(mob/living/new_owner, set_duration)
if(isnum(set_duration))
duration = set_duration
. = ..()
/datum/status_effect/cloudstruck/on_apply()
mob_overlay = mutable_appearance('icons/effects/eldritch.dmi', "cloud_swirl", ABOVE_MOB_LAYER)
owner.overlays += mob_overlay
owner.update_appearance()
ADD_TRAIT(owner, TRAIT_BLIND, STATUS_EFFECT_TRAIT)
return TRUE
/datum/status_effect/cloudstruck/on_remove()
. = ..()
if(QDELETED(owner))
return
REMOVE_TRAIT(owner, TRAIT_BLIND, STATUS_EFFECT_TRAIT)
if(owner)
owner.overlays -= mob_overlay
owner.update_appearance()
/datum/status_effect/cloudstruck/Destroy()
. = ..()
QDEL_NULL(mob_overlay)
//Deals with ants covering someone.
/datum/status_effect/ants
id = "ants"
@@ -29,7 +29,7 @@
var/ascended = FALSE
/// The path our heretic has chosen. Mostly used for flavor.
var/heretic_path = PATH_START
/// A list of how many knowledge points this heretic CURRENTLY has. Used to research.
/// A sum of how many knowledge points this heretic CURRENTLY has. Used to research.
var/knowledge_points = 2 //SKYRAT EDIT - ORIGINAL 1
/// The time between gaining influence passively. The heretic gain +1 knowledge points every this duration of time.
var/passive_gain_timer = 20 MINUTES
@@ -39,9 +39,9 @@
var/living_heart_organ_slot = ORGAN_SLOT_HEART
/// A list of TOTAL how many sacrifices completed. (Includes high value sacrifices)
var/total_sacrifices = 0
/// A list of TOTAL how many high value sacrifices completed.
/// A list of TOTAL how many high value sacrifices completed. (Heads of staff)
var/high_value_sacrifices = 0
/// Lazy assoc list of [weakrefs to humans] to [image previews of the human]. Humans that we have as sacrifice targets.
/// Lazy assoc list of [refs to humans] to [image previews of the human]. Humans that we have as sacrifice targets.
var/list/mob/living/carbon/human/sac_targets
/// Whether we're drawing a rune or not
var/drawing_rune = FALSE
@@ -181,7 +181,6 @@
return ..()
/datum/antagonist/heretic/on_removal()
for(var/knowledge_index in researched_knowledge)
var/datum/heretic_knowledge/knowledge = researched_knowledge[knowledge_index]
knowledge.on_lose(owner.current)
@@ -194,15 +193,24 @@
var/mob/living/our_mob = mob_override || owner.current
handle_clown_mutation(our_mob, "Ancient knowledge described to you has allowed you to overcome your clownish nature, allowing you to wield weapons without harming yourself.")
our_mob.faction |= FACTION_HERETIC
RegisterSignal(our_mob, list(COMSIG_MOB_BEFORE_SPELL_CAST, COMSIG_MOB_SPELL_ACTIVATED), .proc/on_spell_cast)
RegisterSignal(our_mob, COMSIG_MOB_ITEM_AFTERATTACK, .proc/on_item_afterattack)
RegisterSignal(our_mob, COMSIG_MOB_LOGIN, .proc/fix_influence_network)
RegisterSignal(our_mob, COMSIG_LIVING_POST_FULLY_HEAL, .proc/after_fully_healed)
/datum/antagonist/heretic/remove_innate_effects(mob/living/mob_override)
var/mob/living/our_mob = mob_override || owner.current
handle_clown_mutation(our_mob, removing = FALSE)
our_mob.faction -= FACTION_HERETIC
UnregisterSignal(our_mob, list(COMSIG_MOB_BEFORE_SPELL_CAST, COMSIG_MOB_SPELL_ACTIVATED, COMSIG_MOB_ITEM_AFTERATTACK, COMSIG_MOB_LOGIN))
UnregisterSignal(our_mob, list(
COMSIG_MOB_BEFORE_SPELL_CAST,
COMSIG_MOB_SPELL_ACTIVATED,
COMSIG_MOB_ITEM_AFTERATTACK,
COMSIG_MOB_LOGIN,
COMSIG_LIVING_POST_FULLY_HEAL,
))
/datum/antagonist/heretic/on_body_transfer(mob/living/old_body, mob/living/new_body)
. = ..()
@@ -327,6 +335,17 @@
GLOB.reality_smash_track.rework_network()
/// Signal proc for [COMSIG_LIVING_POST_FULLY_HEAL], when we get fullhealed / ahealed,
/// all of our organs are "deleted" and regenerated (cause it's a full heal)
/// which unfortunately means we lose our living heart.
/// So, we'll give them some lee-way and give them back the living heart afterwards
/// (Maybe put this behind only admin_revives only? Not sure.)
/datum/antagonist/heretic/proc/after_fully_healed(mob/living/source, admin_revive)
SIGNAL_HANDLER
var/datum/heretic_knowledge/living_heart/heart_knowledge = get_knowledge(/datum/heretic_knowledge/living_heart)
heart_knowledge.on_research(source)
/**
* Create our objectives for our heretic.
*/
@@ -374,64 +374,123 @@
*/
/datum/heretic_knowledge/curse
abstract_parent_type = /datum/heretic_knowledge/curse
/// How far can we curse people?
var/max_range = 64
/// The duration of the curse
var/duration = 5 MINUTES
/// Cache list of fingerprints (actual fingerprint strings) we have from our current ritual
var/duration = 1 MINUTES
/// The duration of the curse on people which have a fingerprint or blood sample present
var/duration_modifier = 2
/// What color do we outline cursed folk with?
var/curse_color = "#dadada"
/// A list of all the fingerprints that were found on our atoms, in our last go at the ritual
var/list/fingerprints
/// A list of all the blood samples that were found on our atoms, in our last go at the ritual
var/list/blood_samples
/datum/heretic_knowledge/curse/recipe_snowflake_check(mob/living/user, list/atoms, list/selected_atoms, turf/loc)
fingerprints = list()
for(var/atom/requirements as anything in atoms)
fingerprints |= GET_ATOM_FINGERPRINTS(requirements)
list_clear_nulls(fingerprints)
blood_samples = list()
for(var/atom/requirement as anything in atoms)
for(var/print in GET_ATOM_FINGERPRINTS(requirement))
fingerprints[print] = 1
// No fingerprints? No ritual
if(!length(fingerprints))
loc.balloon_alert(user, "ritual failed, no fingerprints!")
return FALSE
for(var/blood in GET_ATOM_BLOOD_DNA(requirement))
blood_samples[blood] = 1
return TRUE
/datum/heretic_knowledge/curse/on_finished_recipe(mob/living/user, list/selected_atoms, turf/loc)
var/list/compiled_list = list()
// Potential targets is an assoc list of [names] to [human mob ref].
var/list/potential_targets = list()
// Boosted targets is a list of human mob references.
var/list/boosted_targets = list()
for(var/mob/living/carbon/human/human_to_check as anything in GLOB.human_list)
if(fingerprints[md5(human_to_check.dna.unique_identity)])
compiled_list |= human_to_check.real_name
compiled_list[human_to_check.real_name] = human_to_check
for(var/datum/mind/crewmember as anything in get_crewmember_minds())
var/mob/living/carbon/human/human_to_check = crewmember.current
if(!istype(human_to_check) || human_to_check.stat == DEAD || !human_to_check.dna)
continue
var/their_prints = md5(human_to_check.dna.unique_identity)
var/their_blood = human_to_check.dna.unique_enzymes
// Having their fingerprints or blood present will boost the curse
// and also not run any z or dist checks, as a bonus for those going beyond
if(fingerprints[their_prints] || blood_samples[their_blood])
boosted_targets += human_to_check
potential_targets["[human_to_check.real_name] (Boosted)"] = human_to_check
continue
if(!length(compiled_list))
loc.balloon_alert(user, "ritual failed, no fingerprints!")
return FALSE
// No boost present, so we should be a little stricter moving forward
var/turf/check_turf = get_turf(human_to_check)
// We have to match z-levels.
// Otherwise, you could probably hard own miners, which is funny but mean.
// Multi-z stations technically work though.
if(!is_valid_z_level(check_turf, loc))
continue
// Also has to abide by our max range.
if(get_dist(check_turf, loc) > max_range)
continue
var/chosen_mob = tgui_input_list(user, "Select the person you wish to curse", "Eldritch Curse", sort_list(compiled_list))
potential_targets[human_to_check.real_name] = human_to_check
var/chosen_mob = tgui_input_list(user, "Select the victim you wish to curse.", name, sort_list(potential_targets, /proc/cmp_text_asc))
if(isnull(chosen_mob))
return FALSE
var/mob/living/carbon/human/to_curse = compiled_list[chosen_mob]
var/mob/living/carbon/human/to_curse = potential_targets[chosen_mob]
if(QDELETED(to_curse))
loc.balloon_alert(user, "ritual failed, invalid choice!")
return FALSE
log_combat(user, to_curse, "cursed via heretic ritual", addition = "([name])")
curse(to_curse)
addtimer(CALLBACK(src, .proc/uncurse, to_curse), duration)
// Yes, you COULD curse yourself, not sure why but you could
if(to_curse == user)
var/are_you_sure = tgui_alert(user, "Are you sure you want to curse yourself?", name, list("Yes", "No"))
if(are_you_sure != "Yes")
return FALSE
var/boosted = (to_curse in boosted_targets)
var/turf/curse_turf = get_turf(to_curse)
if(!boosted && (!is_valid_z_level(curse_turf, loc) || get_dist(curse_turf, loc) > max_range * 1.5)) // Give a bit of leeway on max range for people moving around
loc.balloon_alert(user, "ritual failed, too far!")
return FALSE
if(to_curse.can_block_magic(MAGIC_RESISTANCE|MAGIC_RESISTANCE_HOLY, charge_cost = 0))
to_chat(to_curse, span_warning("You feel a ghastly chill, but the feeling passes shortly."))
return TRUE
log_combat(user, to_curse, "cursed via heretic ritual", addition = "([boosted ? "Boosted" : ""] [name])")
curse(to_curse, boosted)
to_chat(user, span_hierophant("You cast a[boosted ? "n empowered":""] [name] upon [to_curse.real_name]."))
fingerprints = null
blood_samples = null
return TRUE
/**
* Calls a curse onto [chosen_mob].
*/
/datum/heretic_knowledge/curse/proc/curse(mob/living/carbon/human/chosen_mob)
SHOULD_CALL_PARENT(FALSE)
CRASH("[type] did not implement curse()!")
/datum/heretic_knowledge/curse/proc/curse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
SHOULD_CALL_PARENT(TRUE)
addtimer(CALLBACK(src, .proc/uncurse, chosen_mob, boosted), duration * (boosted ? duration_modifier : 1))
if(!curse_color)
return
chosen_mob.add_filter(name, 2, list("type" = "outline", "color" = curse_color, "size" = 1))
/**
* Removes a curse from [chosen_mob]. Used in timers / callbacks.
*/
/datum/heretic_knowledge/curse/proc/uncurse(mob/living/carbon/human/chosen_mob)
SHOULD_CALL_PARENT(FALSE)
CRASH("[type] did not implement uncurse()!")
/datum/heretic_knowledge/curse/proc/uncurse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
SHOULD_CALL_PARENT(TRUE)
if(QDELETED(chosen_mob))
return
if(!curse_color)
return
chosen_mob.remove_filter(name)
/*
* A knowledge subtype lets the heretic summon a monster with the ritual.
@@ -14,14 +14,13 @@
var/datum/action/item_action/organ_action/track_target/action
/// The icon of the heart before we made it a living heart.
var/old_icon
/// The icon_state of the heart before we made it a living heart.
var/old_icon_state
/datum/component/living_heart/Initialize()
if(!isorgan(parent))
return COMPONENT_INCOMPATIBLE
var/obj/item/organ/organ_parent = parent
// These are incompatible for "balance" reasons, not due to code limitations.
if(organ_parent.status != ORGAN_ORGANIC || (organ_parent.organ_flags & ORGAN_SYNTHETIC))
return COMPONENT_INCOMPATIBLE
@@ -34,12 +33,10 @@
ADD_TRAIT(parent, TRAIT_LIVING_HEART, REF(src))
RegisterSignal(parent, COMSIG_ORGAN_REMOVED, .proc/on_organ_removed)
// It's not technically visible,
// but the organ sprite shows up in the action
// So we'll do this anyways
// The heart's not technically visible (and is never visible to anyone besides the heretic),
// but the organ sprite shows up in the organ action - so we'll do this anyways
parent.AddElement(/datum/element/update_icon_blocker)
old_icon = organ_parent.icon
old_icon_state = organ_parent.icon_state
organ_parent.icon = 'icons/obj/eldritch.dmi'
organ_parent.icon_state = "living_heart"
@@ -50,10 +47,14 @@
REMOVE_TRAIT(parent, TRAIT_LIVING_HEART, REF(src))
UnregisterSignal(parent, COMSIG_ORGAN_REMOVED)
// Restore the heart to look normal
parent.RemoveElement(/datum/element/update_icon_blocker)
var/obj/item/organ/organ_parent = parent
organ_parent.icon = old_icon
organ_parent.icon_state = old_icon_state
organ_parent.icon_state = initial(organ_parent.icon_state)
// Sets the icon state to be the correct state
organ_parent.update_appearance(UPDATE_ICON_STATE)
return ..()
@@ -82,7 +83,7 @@
/// Whether the target radial is currently opened.
var/radial_open = FALSE
/// How long we have to wait between tracking uses.
var/track_cooldown_lenth = 8 SECONDS
var/track_cooldown_lenth = 4 SECONDS
/// The cooldown between button uses.
COOLDOWN_DECLARE(track_cooldown)
@@ -106,12 +107,15 @@
if(radial_open)
return FALSE
return TRUE
/datum/action/item_action/organ_action/track_target/Trigger(trigger_flags)
. = ..()
if(!.)
return
var/datum/antagonist/heretic/heretic_datum = IS_HERETIC(owner)
var/datum/heretic_knowledge/sac_knowledge = heretic_datum.get_knowledge(/datum/heretic_knowledge/hunt_and_sacrifice)
if(!LAZYLEN(heretic_datum.sac_targets))
owner.balloon_alert(owner, "no targets, visit a rune!")
return TRUE
@@ -147,14 +151,71 @@
return FALSE
COOLDOWN_START(src, track_cooldown, track_cooldown_lenth)
var/balloon_message = "error text!"
UpdateButtons()
addtimer(CALLBACK(src, .proc/UpdateButtons), track_cooldown_lenth + 1)
playsound(owner, 'sound/effects/singlebeat.ogg', 50, TRUE, SILENCED_SOUND_EXTRARANGE)
if(isturf(tracked_mob.loc) && owner.z != tracked_mob.z)
owner.balloon_alert(owner, get_balloon_message(tracked_mob))
// Let them know how to sacrifice people if they're able to be sac'd
if(tracked_mob.stat == DEAD)
to_chat(owner, span_hierophant("[tracked_mob] is dead. Bring them to a transmutation rune \
and invoke \"[sac_knowledge.name]\" to sacrifice them!"))
return TRUE
/// Callback for the radial to ensure it's closed when not allowed.
/datum/action/item_action/organ_action/track_target/proc/check_menu()
if(QDELETED(src))
return FALSE
if(!IS_HERETIC(owner))
return FALSE
if(!HAS_TRAIT(target, TRAIT_LIVING_HEART))
return FALSE
return TRUE
/// Gets the balloon message for who we're tracking.
/datum/action/item_action/organ_action/track_target/proc/get_balloon_message(mob/living/carbon/human/tracked_mob)
var/balloon_message = "error text!"
var/turf/their_turf = get_turf(tracked_mob)
var/turf/our_turf = get_turf(owner)
var/their_z = their_turf?.z
var/our_z = our_turf?.z
// One of us is in somewhere we shouldn't be
if(!our_z || !their_z)
// "Hell if I know"
balloon_message = "on another plane!"
// They're not on the same z-level as us
else if(our_z != their_z)
// They're on the station
if(is_station_level(their_z))
// We're on a multi-z station
if(is_station_level(our_z))
if(our_z > their_z)
balloon_message = "below you!"
else
balloon_message = "above you!"
// We're off station, they're not
else
balloon_message = "on station!"
// Mining
else if(is_mining_level(their_z))
balloon_message = "on lavaland!"
// In the gateway
else if(is_away_level(their_z) || is_secret_level(their_z))
balloon_message = "beyond the gateway!"
// They're somewhere we probably can't get too - sacrifice z-level, centcom, etc
else
balloon_message = "on another plane!"
// They're on the same z-level as us!
else
var/dist = get_dist(get_turf(owner), get_turf(tracked_mob))
var/dir = get_dir(get_turf(owner), get_turf(tracked_mob))
var/dist = get_dist(our_turf, their_turf)
var/dir = get_dir(our_turf, their_turf)
switch(dist)
if(0 to 15)
@@ -169,15 +230,4 @@
if(tracked_mob.stat == DEAD)
balloon_message = "they're dead, " + balloon_message
owner.balloon_alert(owner, balloon_message)
return TRUE
/// Callback for the radial to ensure it's closed when not allowed.
/datum/action/item_action/organ_action/track_target/proc/check_menu()
if(QDELETED(src))
return FALSE
if(!IS_HERETIC(owner))
return FALSE
if(!HAS_TRAIT(target, TRAIT_LIVING_HEART))
return FALSE
return TRUE
return balloon_message
@@ -122,12 +122,17 @@
if(!HAS_TRAIT(our_turf, TRAIT_RUSTY))
return
// Heals all damage + Stamina
source.adjustBruteLoss(-2, FALSE)
source.adjustFireLoss(-2, FALSE)
source.adjustToxLoss(-2, FALSE, forced = TRUE)
source.adjustToxLoss(-2, FALSE, forced = TRUE) // Slimes are people to
source.adjustOxyLoss(-0.5, FALSE)
source.adjustStaminaLoss(-2)
source.AdjustAllImmobility(-5)
// Reduces duration of stuns/etc
source.AdjustAllImmobility(-0.5 SECONDS)
// Heals blood loss
if(source.blood_volume < BLOOD_VOLUME_NORMAL)
source.blood_volume += 2.5 * delta_time
/datum/heretic_knowledge/mark/rust_mark
name = "Mark of Rust"
@@ -19,10 +19,9 @@
/datum/heretic_knowledge/curse/paralysis
name = "Curse of Paralysis"
desc = "Allows you to transmute a hatchet, a left and right leg, \
and an item containing fingerprints to cast a curse of immobility \
on one of the fingerprint's owners for five minutes. While cursed, \
the victim will be unable to walk."
desc = "Allows you to transmute a hatchet and both a left and right leg to cast a curse of immobility on a crew member. \
While cursed, the victim will be unable to walk. You can additionally supply an item that a victim has touched \
or is covered in the victim's blood to empower the curse."
gain_text = "The flesh of humanity is weak. Make them bleed. Show them their fragility."
next_knowledge = list(
/datum/heretic_knowledge/mad_mask,
@@ -33,27 +32,31 @@
/obj/item/bodypart/r_leg = 1,
/obj/item/hatchet = 1,
)
duration = 5 MINUTES
duration = 3 MINUTES
duration_modifier = 2
curse_color = "#f19a9a"
cost = 1
route = PATH_SIDE
/datum/heretic_knowledge/curse/paralysis/curse(mob/living/carbon/human/chosen_mob)
/datum/heretic_knowledge/curse/paralysis/curse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
if(chosen_mob.usable_legs <= 0) // What're you gonna do, curse someone who already can't walk?
to_chat(chosen_mob, span_notice("You feel a slight pain for a moment, but it passes shortly. Odd."))
else
to_chat(chosen_mob, span_danger("You suddenly lose feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
return
to_chat(chosen_mob, span_danger("You suddenly lose feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type)
ADD_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type)
return ..()
/datum/heretic_knowledge/curse/paralysis/uncurse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
if(QDELETED(chosen_mob))
return
/datum/heretic_knowledge/curse/paralysis/uncurse(mob/living/carbon/human/chosen_mob)
REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_L_LEG, type)
REMOVE_TRAIT(chosen_mob, TRAIT_PARALYSIS_R_LEG, type)
if(chosen_mob.usable_legs <= 0) // What're you gonna do, curse someone who already can't walk?
to_chat(chosen_mob, span_notice("The slight pain returns, but disperses shortly."))
else
to_chat(chosen_mob, span_notice("You regain feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
if(chosen_mob.usable_legs > 1)
to_chat(chosen_mob, span_green("You regain feeling in your leg[chosen_mob.usable_legs == 1 ? "":"s"]!"))
return ..()
/datum/heretic_knowledge/summon/ashy
name = "Ashen Ritual"
@@ -20,10 +20,9 @@
/datum/heretic_knowledge/curse/corrosion
name = "Curse of Corrosion"
desc = "Allows you to transmute wirecutters, a pool of vomit, a heart, \
and an item containing fingerprints to cast a curse of plague \
on one of the fingerprint's owners for two minutes. While cursed, \
the victim will repeatedly vomit while their organs will take constant damage."
desc = "Allows you to transmute wirecutters, a pool of vomit, and a heart to cast a curse of sickness on a crew member.\
While cursed, the victim will repeatedly vomit while their organs will take constant damage. You can additionally supply an item \
that a victim has touched or is covered in the victim's blood to empower the curse."
gain_text = "The body of humanity is temporary. Their weaknesses cannot be stopped, like iron falling to rust. Show them all."
next_knowledge = list(
/datum/heretic_knowledge/mad_mask,
@@ -34,17 +33,24 @@
/obj/effect/decal/cleanable/vomit = 1,
/obj/item/organ/internal/heart = 1,
)
duration = 2 MINUTES
duration = 0.5 MINUTES
duration_modifier = 4
curse_color = "#c1ffc9"
cost = 1
route = PATH_SIDE
/datum/heretic_knowledge/curse/corrosion/curse(mob/living/carbon/human/chosen_mob)
to_chat(chosen_mob, span_danger("You feel very ill."))
/datum/heretic_knowledge/curse/corrosion/curse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
to_chat(chosen_mob, span_danger("You feel very ill..."))
chosen_mob.apply_status_effect(/datum/status_effect/corrosion_curse)
return ..()
/datum/heretic_knowledge/curse/corrosion/uncurse(mob/living/carbon/human/chosen_mob, boosted = FALSE)
if(QDELETED(chosen_mob))
return
/datum/heretic_knowledge/curse/corrosion/uncurse(mob/living/carbon/human/chosen_mob)
chosen_mob.remove_status_effect(/datum/status_effect/corrosion_curse)
to_chat(chosen_mob, span_notice("You start to feel better."))
to_chat(chosen_mob, span_green("You start to feel better."))
return ..()
/datum/heretic_knowledge/summon/rusty
name = "Rusted Ritual"
@@ -5,6 +5,7 @@
background_icon_state = "bg_ecult"
icon_icon = 'icons/mob/actions/actions_ecult.dmi'
button_icon_state = "entropic_plume"
sound = 'sound/magic/forcewall.ogg'
school = SCHOOL_FORBIDDEN
cooldown_time = 30 SECONDS
@@ -27,10 +28,8 @@
if(victim.can_block_magic(antimagic_flags) || IS_HERETIC_OR_MONSTER(victim))
return
victim.apply_status_effect(/datum/status_effect/amok)
victim.apply_status_effect(/datum/status_effect/cloudstruck, (level * 1 SECONDS))
if(iscarbon(victim))
var/mob/living/carbon/carbon_victim = victim
carbon_victim.reagents?.add_reagent(/datum/reagent/eldritch, min(1, 6 - level))
victim.apply_status_effect(/datum/status_effect/cloudstruck, level * 1 SECONDS)
victim.reagents?.add_reagent(/datum/reagent/eldritch, max(1, 6 - level))
/datum/action/cooldown/spell/cone/staggered/entropic_plume/calculate_cone_shape(current_level)
if(current_level == cone_levels)
@@ -39,20 +39,99 @@
tick_interval = 1 SECONDS
/datum/status_effect/amok/on_apply(mob/living/afflicted)
. = ..()
to_chat(owner, span_boldwarning("You feel filled with a rage that is not your own!"))
return TRUE
/datum/status_effect/amok/tick()
. = ..()
var/prev_combat_mode = owner.combat_mode
owner.set_combat_mode(TRUE)
// If we're holding a gun, expand the range a bit.
// Otherwise, just look for adjacent targets
var/search_radius = isgun(owner.get_active_held_item()) ? 3 : 1
var/list/mob/living/targets = list()
for(var/mob/living/potential_target in oview(owner, 1))
for(var/mob/living/potential_target in oview(owner, search_radius))
if(IS_HERETIC_OR_MONSTER(potential_target))
continue
targets += potential_target
if(LAZYLEN(targets))
owner.log_message(" attacked someone due to the amok debuff.", LOG_ATTACK) //the following attack will log itself
owner.ClickOn(pick(targets))
owner.set_combat_mode(prev_combat_mode)
/datum/status_effect/cloudstruck
id = "cloudstruck"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
duration = 3 SECONDS
on_remove_on_mob_delete = TRUE
///This overlay is applied to the owner for the duration of the effect.
var/static/mutable_appearance/mob_overlay
/datum/status_effect/cloudstruck/on_creation(mob/living/new_owner, duration = 10 SECONDS)
src.duration = duration
if(!mob_overlay)
mob_overlay = mutable_appearance('icons/effects/eldritch.dmi', "cloud_swirl", ABOVE_MOB_LAYER)
return ..()
/datum/status_effect/cloudstruck/on_apply()
owner.add_overlay(mob_overlay)
owner.become_blind(STATUS_EFFECT_TRAIT)
owner.update_blindness() // become_blind is supposed to call this but it doesn't work for some reason because blindness is a fuck
return TRUE
/datum/status_effect/cloudstruck/on_remove()
if(QDELETED(owner))
return
owner.cure_blind(STATUS_EFFECT_TRAIT)
owner.update_blindness()
owner.cut_overlay(mob_overlay)
/datum/status_effect/corrosion_curse
id = "corrosion_curse"
status_type = STATUS_EFFECT_REPLACE
alert_type = null
tick_interval = 1 SECONDS
/datum/status_effect/corrosion_curse/on_apply()
to_chat(owner, span_userdanger("Your body starts to break apart!"))
return TRUE
/datum/status_effect/corrosion_curse/tick()
. = ..()
if(!ishuman(owner))
return
var/mob/living/carbon/human/human_owner = owner
var/chance = rand(0, 100)
switch(chance)
if(0 to 10)
human_owner.vomit()
if(20 to 30)
human_owner.set_timed_status_effect(100 SECONDS, /datum/status_effect/dizziness, only_if_higher = TRUE)
human_owner.set_timed_status_effect(100 SECONDS, /datum/status_effect/jitter, only_if_higher = TRUE)
if(30 to 40)
// Don't fully kill liver that's important
human_owner.adjustOrganLoss(ORGAN_SLOT_LIVER, 10, 90)
if(40 to 50)
// Don't fully kill heart that's important
human_owner.adjustOrganLoss(ORGAN_SLOT_HEART, 10, 90)
if(50 to 60)
// You can fully kill the stomach that's not crucial
human_owner.adjustOrganLoss(ORGAN_SLOT_STOMACH, 10)
if(60 to 70)
// Same with eyes
human_owner.adjustOrganLoss(ORGAN_SLOT_EYES, 5)
if(70 to 80)
// And same with ears
human_owner.adjustOrganLoss(ORGAN_SLOT_EARS, 10)
if(80 to 90)
// But don't fully kill lungs that's usually important
human_owner.adjustOrganLoss(ORGAN_SLOT_LUNGS, 10, 90)
if(90 to 95)
// And definitely don't fully kil brains
human_owner.adjustOrganLoss(ORGAN_SLOT_BRAIN, 20, 190)
if(95 to 100)
human_owner.adjust_timed_status_effect(12 SECONDS, /datum/status_effect/confusion, max_duration = 24 SECONDS)
@@ -32,9 +32,9 @@
for(var/atom/movable/movable_content as anything in target_turf)
if(isobj(movable_content))
do_obj_cone_effect(movable_content, level)
do_obj_cone_effect(movable_content, caster, level)
else if(isliving(movable_content))
do_mob_cone_effect(movable_content, level)
do_mob_cone_effect(movable_content, caster, level)
///This proc deterimines how the spell will affect turfs.
/datum/action/cooldown/spell/cone/proc/do_turf_cone_effect(turf/target_turf, atom/caster, level)