mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 21:18:37 +01:00
Buffs Heretic Curses, Living Heart, Leeching Walk, and technically Entropic Plume by fixing some bugs (#69181)
About The Pull Request
Heretic curses have been buffed / reworked.
Curses can be cast on any crewmember, not just those who you have fingerprints to.
Having an item present in the ritual that contains fingerprints OR blood dna of a crewmember who you are cursing will boost the curse, causing it to last longer (and be stronger? Still undecided, but there's support for it)
Curses have a max range (64 by default) and don't work on people on a different z-level (Do not BTFO miners so easily)
Corrosion curse's numbers have been tweaked due to this, and it can no longer cause vital organ failure
Living Heart has been buffed
Cooldown cut in half, and it provides a bit more thorough instructions
Closes
Living heart targets who are located in non-turf locs and are off z-level will show as on the same z #67256
Leeching Walk has been buffed
Rust will also restore lost blood.
Technically buffs Entropic Plume by fixing some bugs
"Cloudstruck" has always meant to blind, but they used the wrong method, so I fixed that.
Also it was meant to inject multiple units of poison, but used "min" instead of "max" so it always did the lowest.
I also fixed the stink cloud lasting forever on people.
Amok also makes people holding guns to shoot people further away.
Closes
Admin healing removes heretic living heart #69167 while I'm here
Why It's Good For The Game
Heretic curses have pretty much always been bad, getting fingerprints is damn near impossible considering everyone uses gloves. Not only that but their requirements were very high. This should hopefully bring curses to the limelight, as they can be applied to any potential targets. It also rewards heretics who go out of their way to collect fingerprints and blood samples with even stronger curses.
The Living Heart was often hard to pinpoint people exactly, partially cause of an oversight. I improved the text to be clearer about potential locations of your targets.
Leeching Walk's healing was nice, but blood wounds were still a major threat. Some blood restoration should help.
Entropic Plume I think has never worked correctly, so that was a bummer. Fixes that.
Changelog
cl Melbert
balance: Heretic: Curses have been reworked. You can now curse any member of the crew, granted they're not too far away. If you additionally provide an item in the ritual containing a sample of the target's blood or fingerprints, the curse's duration will be increased and have its range uncapped.
balance: Heretic: The Curse of Corrosion has been nerfed slightly due to this rework, and can no longer cause vital organs to fail.
balance: Heretic: The Living Heart should now provide better directions, and had its cooldown halved to 4 seconds.
balance: Heretic: Leeching Walk (rust healing) now restores lost blood.
balance: Heretic: If you apply Amok (Entropic Plume) to someone holding a gun, they'll try to shoot it at people nearby.
fix: Entropic Plume's effect now blinds, as it should.
fix: Entropic Plume no longer sometimes applies the stink effect forever.
fix: Entropic Plume no longer always applies the lowest amount of poison, and properly scales on distance.
fix: Fixed an exploit which allowed people to figure out if a Heretic's heart was a previously a Living Heart after being removed.
fix: If a heretic is fully healed by something (such as ahealed), they'll not lose their living heart
/cl
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -770,78 +770,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 = 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)
|
||||
|
||||
Reference in New Issue
Block a user