mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-25 21:19:44 +01:00
Spooky/Horror modifier & various tweaks/fixes (#17775)
* spooky Adds horror organs and reworks the redspace effect Proper organ names & tweaks - Lowers time of the internal organ surgery steps. Min&max is the same - When going to remove an organ, it now shows you the name of the organ instead of 'what it is' - Removes the inability to put dead organs in bodies...Even if it's dead, you can still physically put it back in. Fixes everyone that was missing spleens Fixes worm meat not runtime when cut Stumbled across these...Fix them to forcemove * LINT * fine you win DM * Secret~
This commit is contained in:
@@ -0,0 +1,318 @@
|
||||
// These are modifiers used for various spooky areas that are meant to be SCARY and THREATENING.
|
||||
// Outside of extreme circumstances, these should not be used.
|
||||
// For the primary effect, if someone is not in one of the below 'redspace_areas' Then they can not have the modifier
|
||||
// applied to them. This acts as a failsafe from it from accidentally being used outside of events.
|
||||
// If you DO want to use this for an event, make the event area a child of /redgate or add it to the below areas list.
|
||||
// These have some extremely spooky effects and players should know about it beforehand.
|
||||
|
||||
|
||||
// REDSPACE AREAS
|
||||
// This list needs expansion... Currently, we have very few proper redspace areas.
|
||||
// Tossing /area/redgate in here as well. Entering one of these areas (unless coded to do such) doesn't apply
|
||||
// the modifier, but if you're in one of these areas, you'll keep the modifier until you leave.
|
||||
var/static/list/redspace_areas = list (
|
||||
/area/redspace_abduction,
|
||||
/area/redgate
|
||||
)
|
||||
|
||||
/datum/modifier/redspace_drain
|
||||
name = "redspace warp"
|
||||
desc = "Your body is being slowly sapped of it's lifeforce, being used to fuel this hellish nightmare of a place."
|
||||
|
||||
on_created_text = span_cult("You feel your body slowly being drained and warped")
|
||||
on_expired_text = span_notice("Your body feels more normal.")
|
||||
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
//mob_overlay_state = "redspace_aura" //Let's be secretive~
|
||||
var/mob/living/carbon/human/unfortunate_soul //The human target of our modifier.
|
||||
|
||||
/datum/modifier/redspace_drain/can_apply(mob/living/L, suppress_output = TRUE)
|
||||
if(ishuman(L) && !L.isSynthetic() && L.lastarea && is_type_in_list(L.lastarea, redspace_areas))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/datum/modifier/redspace_drain/on_applied()
|
||||
unfortunate_soul = holder
|
||||
to_chat(unfortunate_soul, span_cult("You feel as if your lifeforce is slowly being rended from your body."))
|
||||
return
|
||||
|
||||
/datum/modifier/redspace_drain/on_expire()
|
||||
if(QDELETED(holder))
|
||||
unfortunate_soul = null
|
||||
return //Don't do anything if we got QDEL'd, such as if we were gibbed
|
||||
if(unfortunate_soul.stat == DEAD) //Only care if we're dead.
|
||||
handle_corpse()
|
||||
var/obj/effect/landmark/drop_point
|
||||
drop_point = pick(GLOB.latejoin) //Can be changed to whatever exit list you want. By default, uses GLOB.latejoin
|
||||
if(drop_point)
|
||||
unfortunate_soul.forceMove(get_turf(drop_point))
|
||||
unfortunate_soul.maxHealth = max(50, unfortunate_soul.maxHealth) //If they died, send them back with 50 maxHealth or their current maxHealth. Whatever's higher. We're evil, but not mean.
|
||||
else
|
||||
message_admins("Redspace Drain expired, but no drop point was found, leaving [unfortunate_soul] in limbo. This is a bug. Please report it with this info: redspace_drain/on_expire")
|
||||
unfortunate_soul = null
|
||||
|
||||
/datum/modifier/redspace_drain/proc/handle_corpse()
|
||||
return //Specialty stuff to do to a corpse other than teleport them.
|
||||
|
||||
/datum/modifier/redspace_drain/check_if_valid() //We don't call parent. This doesn't wear off without set conditions.
|
||||
if(holder.stat == DEAD)
|
||||
expire(silent = TRUE)
|
||||
else if(holder.lastarea && !is_type_in_list(holder.lastarea, redspace_areas))
|
||||
expire(silent = TRUE)
|
||||
|
||||
/datum/modifier/redspace_drain/tick()
|
||||
if(isbelly(holder.loc)) //If you're eaten, let's hold off on doing anything spooky.
|
||||
return
|
||||
|
||||
//The dangerous health effects.
|
||||
unfortunate_soul.nutrition = max(0, unfortunate_soul.nutrition - 5) //Your nutrition is being sapped faster than usual.
|
||||
if(unfortunate_soul.life_tick % 100 == 0)// Once every 100 ticks, we mutate some organs.
|
||||
choose_organs()
|
||||
become_drippy()
|
||||
to_chat(unfortunate_soul, span_cult("You feel as if your organs are crawling around within your body."))
|
||||
|
||||
if(unfortunate_soul.life_tick % 5 == 0) //Once every 5 ticks, we chip away at them.
|
||||
unfortunate_soul.drip(1) //Blood trail.
|
||||
unfortunate_soul.take_overall_damage(1) //Small bit of damage
|
||||
if(unfortunate_soul.bloodstr.get_reagent_amount(REAGENT_ID_NUMBENZYME) < 2) //We lose all feeling in our body. We can't tell how injured we are.
|
||||
unfortunate_soul.bloodstr.add_reagent(REAGENT_ID_NUMBENZYME,1)
|
||||
if(unfortunate_soul.life_tick % 10 == 0) //Once every 10 ticks, we permanetly cripple them.
|
||||
unfortunate_soul.maxHealth = max(10, unfortunate_soul.maxHealth - 1) //Max health is reduced by 1, but never below 10. This is PERMANENT for the rest of the round or until resleeving.
|
||||
|
||||
|
||||
//The mental effects.
|
||||
unfortunate_soul.fear = min(100, unfortunate_soul.fear + 2) //Fear is increased by 1, but never above 100. You're in a scary place.
|
||||
if(unfortunate_soul.life_tick % 20 == 0)
|
||||
var/obj/item/organ/O = pick(unfortunate_soul.internal_organs)
|
||||
if(!O) //If you don't have any internal organs, you know what? No spooky messages for you, freak.
|
||||
var/spooky_message = pick("Join us...", "Stay with us...", "Stay forever...", "Don't leave us...", \
|
||||
"Don't go...", "We can be as one...", "Become one with us...", \
|
||||
"You can feel your [O] squirming inside of you, trying to get out...", "Your [O] is trying to escape...", \
|
||||
"Your [O] itches.", "Your [O] is crawling around inside of you.")
|
||||
to_chat(unfortunate_soul, span_cult(spooky_message))
|
||||
unfortunate_soul.make_dizzy(20)
|
||||
unfortunate_soul.stuttering = min(100, unfortunate_soul.stuttering + 10) //Stuttering is increased by 1, but never above 100. You're in a scary place.
|
||||
return
|
||||
|
||||
/datum/modifier/redspace_drain/proc/choose_organs()
|
||||
var/organs_to_replace = rand(2,3)
|
||||
for(var/i = 0 to organs_to_replace)
|
||||
var/organ_choice = pick("eyes", "heart", "lungs", "liver", "kidneys", "appendix", "voicebox", "spleen", "stomach", "intestine")
|
||||
switch(organ_choice)
|
||||
if("eyes")
|
||||
var/obj/item/organ/internal/eyes/E = unfortunate_soul.internal_organs_by_name[O_EYES]
|
||||
if(E)
|
||||
replace_eyes(E)
|
||||
if("heart")
|
||||
var/obj/item/organ/internal/heart/H = unfortunate_soul.internal_organs_by_name[O_HEART]
|
||||
if(H)
|
||||
replace_heart(H)
|
||||
if("lungs")
|
||||
var/obj/item/organ/internal/lungs/L = unfortunate_soul.internal_organs_by_name[O_LUNGS]
|
||||
if(L)
|
||||
replace_lungs(L)
|
||||
if("liver")
|
||||
var/obj/item/organ/internal/liver/L = unfortunate_soul.internal_organs_by_name[O_LIVER]
|
||||
if(L)
|
||||
replace_liver(L)
|
||||
if("kidneys")
|
||||
var/obj/item/organ/internal/kidneys/K = unfortunate_soul.internal_organs_by_name[O_KIDNEYS]
|
||||
if(K)
|
||||
replace_kidneys(K)
|
||||
if("appendix")
|
||||
var/obj/item/organ/internal/appendix/A = unfortunate_soul.internal_organs_by_name[O_APPENDIX]
|
||||
if(A)
|
||||
replace_appendix(A)
|
||||
if("voicebox")
|
||||
var/obj/item/organ/internal/voicebox/V = unfortunate_soul.internal_organs_by_name[O_VOICE]
|
||||
if(V)
|
||||
replace_voicebox(V)
|
||||
if("spleen")
|
||||
var/obj/item/organ/internal/spleen/S = unfortunate_soul.internal_organs_by_name[O_SPLEEN]
|
||||
if(S)
|
||||
replace_spleen(S)
|
||||
if("stomach")
|
||||
var/obj/item/organ/internal/stomach/S = unfortunate_soul.internal_organs_by_name[O_STOMACH]
|
||||
if(S)
|
||||
replace_stomach(S)
|
||||
if("intestine")
|
||||
var/obj/item/organ/internal/intestine/E = unfortunate_soul.internal_organs_by_name[O_INTESTINE]
|
||||
if(E)
|
||||
replace_intestine(E)
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_eyes(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/eyes/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/eyes/new_organ = new /obj/item/organ/internal/eyes/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_heart(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/heart/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/heart/new_organ = new /obj/item/organ/internal/heart/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_lungs(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/lungs/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/lungs/new_organ = new /obj/item/organ/internal/lungs/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_liver(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/liver/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/liver/new_organ = new /obj/item/organ/internal/liver/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_kidneys(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/kidneys/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/kidneys/new_organ = new /obj/item/organ/internal/kidneys/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_appendix(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/appendix/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/appendix/new_organ = new /obj/item/organ/internal/appendix/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_voicebox(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/voicebox/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/voicebox/new_organ = new /obj/item/organ/internal/voicebox/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_spleen(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/spleen/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/spleen/new_organ = new /obj/item/organ/internal/spleen/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_stomach(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/stomach/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/stomach/new_organ = new /obj/item/organ/internal/stomach/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/datum/modifier/redspace_drain/proc/replace_intestine(obj/item/organ/internal/O)
|
||||
if(istype(O, /obj/item/organ/internal/intestine/horror))
|
||||
return
|
||||
var/organ_spot = O.parent_organ
|
||||
var/obj/item/organ/internal/intestine/new_organ = new /obj/item/organ/internal/intestine/horror()
|
||||
O.removed(unfortunate_soul)
|
||||
qdel(O)
|
||||
new_organ.replaced(unfortunate_soul,unfortunate_soul.get_organ(organ_spot))
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
new_organ.name = "[random_name] [initial(new_organ.name)]"
|
||||
|
||||
/*
|
||||
/datum/modifier/redspace_drain/proc/replace_organ() //Old version of doing this WITHOUT the custom organs. Preserved as an alternative version / reference
|
||||
var/obj/item/organ/O = pick(unfortunate_soul.internal_organs)
|
||||
if(O)
|
||||
var/random_name = pick("pulsating", "quivering", "throbbing", "crawling", "oozing", "melting", "gushing", "dripping", "twitching", "slimy", "gooey")
|
||||
O.name = "[random_name] [initial(O.name)]"
|
||||
O.desc = "A twisted, warped version of a [initial(O.name)] covered in thick, red, pulsating tendrils."
|
||||
O.take_damage(3)
|
||||
O.color = "#760b0b"
|
||||
O.add_autopsy_data("ANOMALOUS FLESH GROWTH", 3)
|
||||
O.decays = FALSE
|
||||
O.meat_type = /obj/item/reagent_containers/food/snacks/meat/worm //It turns into 'weird meat' with the desc of 'A chunk of pulsating meat'
|
||||
O.can_reject = FALSE
|
||||
*/
|
||||
|
||||
/datum/modifier/redspace_drain/proc/become_drippy()
|
||||
if(!(unfortunate_soul.species.flags & NO_DNA)) //Doing it as such in case drippy is ever made NOT a trait gene.
|
||||
var/datum/gene/trait/drippy_trait = get_gene_from_trait(/datum/trait/neutral/drippy)
|
||||
unfortunate_soul.dna.SetSEState(drippy_trait.block, TRUE)
|
||||
domutcheck(unfortunate_soul, null, GENE_ALWAYS_ACTIVATE)
|
||||
unfortunate_soul.UpdateAppearance()
|
||||
|
||||
/datum/modifier/redsight
|
||||
name = "redsight"
|
||||
desc = "You can see into the unknown."
|
||||
client_color = "#ce6161"
|
||||
|
||||
on_created_text = span_alien("You feel as though you can see the horrors of reality!")
|
||||
on_expired_text = span_notice("Your sight returns to what it once was.")
|
||||
stacks = MODIFIER_STACK_EXTEND
|
||||
|
||||
/datum/modifier/redsight/on_applied()
|
||||
holder.see_invisible = 60
|
||||
holder.see_invisible_default = 60
|
||||
holder.vis_enabled += VIS_GHOSTS
|
||||
holder.recalculate_vis()
|
||||
|
||||
/datum/modifier/redsight/on_expire()
|
||||
holder.see_invisible_default = initial(holder.see_invisible_default)
|
||||
holder.see_invisible = holder.see_invisible_default
|
||||
holder.vis_enabled -= VIS_GHOSTS
|
||||
holder.recalculate_vis()
|
||||
|
||||
/datum/modifier/redsight/can_apply(var/mob/living/L)
|
||||
if(L.stat)
|
||||
to_chat(L, span_warning("You can't be unconscious or dead to see the unknown."))
|
||||
return FALSE
|
||||
var/obj/item/organ/internal/eyes/E = L.internal_organs_by_name[O_EYES]
|
||||
if(E && istype(E, /obj/item/organ/internal/eyes/horror))
|
||||
return ..()
|
||||
return FALSE
|
||||
|
||||
/datum/modifier/redsight/check_if_valid() //We don't call parent. This doesn't wear off without set conditions.
|
||||
//Dead?
|
||||
if(holder.stat == DEAD)
|
||||
expire(silent = TRUE)
|
||||
//We got eyes and they're special eyes?
|
||||
var/obj/item/organ/internal/eyes/E = holder.internal_organs_by_name[O_EYES]
|
||||
if(!E)
|
||||
expire(silent = TRUE)
|
||||
else if(!istype(E, /obj/item/organ/internal/eyes/horror))
|
||||
expire(silent = TRUE)
|
||||
|
||||
/datum/modifier/redsight/tick()
|
||||
..()
|
||||
@@ -48,6 +48,10 @@
|
||||
if(holder.stat != DEAD)
|
||||
src.expire()
|
||||
|
||||
/datum/modifier/bloodpump_corpse/expire(silent)
|
||||
human_being_pumped = null
|
||||
..()
|
||||
|
||||
//This INTENTIONALLY only happens on DEAD people. Alive people are metabolizing already (and can be healed quicker through things like brute packs) meaning they don't need this extra assistance!
|
||||
//Why does it not make you bleed out? Because we'll let medical have a few benefits that don't come with innate downsides. It takes 2 seconds to resleeve someone. It takes a good amount of time to repair a corpse. Let's make the latter more appealing.
|
||||
/datum/modifier/bloodpump_corpse/tick()
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
var/desc = null // Ditto.
|
||||
var/icon_state = null // See above.
|
||||
var/mob/living/holder = null // The mob that this datum is affecting.
|
||||
var/datum/weakref/origin = null // A weak reference to whatever caused the modifier to appear. THIS NEEDS TO BE A MOB/LIVING. It's a weakref to not interfere with qdel().
|
||||
var/datum/weakref/origin = null // A weak reference to whatever caused the modifier to appear. THIS NEEDS TO BE A MOB/LIVING. It's a weakref to not interfere with qdel().
|
||||
var/expire_at = null // world.time when holder's Life() will remove the datum. If null, it lasts forever or until it gets deleted by something else.
|
||||
var/on_created_text = null // Text to show to holder upon being created.
|
||||
var/on_expired_text = null // Text to show to holder when it expires.
|
||||
@@ -20,7 +20,7 @@
|
||||
var/light_intensity = null // Ditto. Not implemented yet.
|
||||
var/mob_overlay_state = null // Icon_state for an overlay to apply to a (human) mob while this exists. This is actually implemented.
|
||||
var/client_color = null // If set, the client will have the world be shown in this color, from their perspective.
|
||||
var/wire_colors_replace = null // If set, the client will have wires replaced by the given replacement list. For colorblindness. //VOREStation Add
|
||||
var/wire_colors_replace = null // If set, the client will have wires replaced by the given replacement list. For colorblindness.
|
||||
var/list/filter_parameters = null // If set, will add a filter to the holder with the parameters in this var. Must be a list.
|
||||
var/filter_priority = 1 // Used to make filters be applied in a specific order, if that is important.
|
||||
var/filter_instance = null // Instance of a filter created with the `filter_parameters` list. This exists to make `animate()` calls easier. Don't set manually.
|
||||
|
||||
@@ -80,14 +80,6 @@
|
||||
else
|
||||
expire(silent = FALSE)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/modifier/shield_projection
|
||||
name = "Shield Projection"
|
||||
desc = "You are currently protected by a shield, rendering nigh impossible to hit you through conventional means."
|
||||
|
||||
Reference in New Issue
Block a user