mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-27 15:17:01 +01:00
[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:
co-authored by
MrMelbert
Tom
parent
513aaff5b2
commit
6f8b19cfa6
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user