Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] [SEMI-MODULAR] Resonance degradation disorder: The quirk that makes you fear death #840

Merged
merged 1 commit into from
Nov 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions code/__DEFINES/~skyrat_defines/quirks.dm
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#define DEATH_CONSEQUENCES_QUIRK_NAME "Death Degradation Disorder"
#define DEATH_CONSEQUENCES_QUIRK_DESC "Patient is unusually susceptable to mortality."
#define DEATH_CONSEQUENCES_BASE_DEGRADATION_ON_DEATH 50

/// The victim's crit threshold cannot go below this.
#define DEATH_CONSEQUENCES_MINIMUM_VICTIM_CRIT_THRESHOLD (MAX_LIVING_HEALTH) - 1

#define DEATH_CONSEQUENCES_REAGENT_FLAT_AMOUNT "dc_flat_reagent_amount"
#define DEATH_CONSEQUENCES_REAGENT_MULT_AMOUNT "dc_mult_reagent_amount"
#define DEATH_CONSEQUENCES_REAGENT_METABOLIZE "dc_reagent_should_be_metabolizing"
/// If true, we will check to see if this can process. Ex. things like synths wont process formaldehyde
#define DEATH_CONSEQUENCES_REAGENT_CHECK_PROCESSING_FLAGS "dc_check_reagent_processing_flags"

/// Absolute maximum for preferences.
#define DEATH_CONSEQUENCES_MAXIMUM_THEORETICAL_DEGRADATION 10000
#define DEATH_CONSEQUENCES_DEFAULT_MAX_DEGRADATION 500 // arbitrary
#define DEATH_CONSEQUENCES_DEFAULT_LIVING_DEGRADATION_RECOVERY 0.01
#define DEATH_CONSEQUENCES_DEFAULT_DEGRADATION_ON_DEATH 50

#define DEATH_CONSEQUENCES_DEFAULT_REZADONE_DEGRADATION_REDUCTION 0.4
#define DEATH_CONSEQUENCES_DEFAULT_STRANGE_REAGENT_DEGRADATION_REDUCTION 0.25
#define DEATH_CONSEQUENCES_DEFAULT_EIGENSTASIUM_DEGRADATION_REDUCTION 5 // for such a rare chem, you fucking bet
#define DEATH_CONSEQUENCES_DEFAULT_SANSUFENTANYL_DEGRADATION_REDUCTION 1

#define DEATH_CONSEQUENCES_SHOW_HEALTH_ANALYZER_DATA "dc_show_health_analyzer_data"

#define DEATH_CONSEQUENCES_TIME_BETWEEN_REMINDERS 5 MINUTES
11 changes: 11 additions & 0 deletions code/game/objects/items/devices/scanners/health_analyzer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@
if (!target.get_organ_slot(ORGAN_SLOT_BRAIN)) // kept exclusively for soul purposes
render_list += "<span class='alert ml-1'>Subject lacks a brain.</span>\n"

var/death_consequences_status_text // SKYRAT EDIT ADDITION: Death consequences quirk
if(iscarbon(target))
var/mob/living/carbon/carbontarget = target
if(LAZYLEN(carbontarget.get_traumas()))
Expand All @@ -199,6 +200,11 @@
trauma_desc += "permanent "
trauma_desc += trauma.scan_desc
trauma_text += trauma_desc
// SKYRAT EDIT ADDITION START: Death Consequences Quirk
if (istype(trauma, /datum/brain_trauma/severe/death_consequences))
var/datum/brain_trauma/severe/death_consequences/consequences_trauma = trauma
death_consequences_status_text = consequences_trauma.get_health_analyzer_link_text(user)
// SKYRAT EDIT ADDITION END: Death Consequences Quirk
render_list += "<span class='alert ml-1'>Cerebral traumas detected: subject appears to be suffering from [english_list(trauma_text)].</span>\n"
if(carbontarget.quirks.len)
render_list += "<span class='info ml-1'>Subject Major Disabilities: [carbontarget.get_quirk_string(FALSE, CAT_QUIRK_MAJOR_DISABILITY, from_scan = TRUE)].</span>\n"
Expand Down Expand Up @@ -401,6 +407,11 @@
render_list += span_userdanger("UNKNOWN PROTO-VIRAL INFECTION DETECTED. ISOLATE IMMEDIATELY.")
// SKYRAT EDIT END

// SKYRAT EDIT ADDITION - DEATH CONSEQUENCES QUIRK
if(death_consequences_status_text)
render_list += death_consequences_status_text
// SKYRAT EDIT END

if(tochat)
to_chat(user, examine_block(jointext(render_list, "")), trailing_newline = FALSE, type = MESSAGE_TYPE_INFO)
else
Expand Down
1 change: 1 addition & 0 deletions code/modules/client/preferences.dm
Original file line number Diff line number Diff line change
Expand Up @@ -331,6 +331,7 @@ GLOBAL_LIST_EMPTY(preferences_datums)
var/datum/loadout_manager/tgui = new(usr)
tgui.ui_interact(usr)
return TRUE

if ("set_tricolor_preference")
var/requested_preference_key = params["preference"]
var/index_key = params["value"]
Expand Down
27 changes: 6 additions & 21 deletions code/modules/reagents/chemistry/holder/mob_life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -58,28 +58,13 @@
owner = reagent.holder.my_atom

//SKYRAT EDIT ADDITION BEGIN - CUSTOMIZATION
if(ishuman(owner))
var/mob/living/carbon/human/H = owner
//Check if this mob's species is set and can process this type of reagent
var/can_process = FALSE
//If we somehow avoided getting a species or reagent_flags set, we'll assume we aren't meant to process ANY reagents
if(H.dna && H.dna.species.reagent_flags)
var/owner_flags = H.dna.species.reagent_flags
if((reagent.process_flags & REAGENT_SYNTHETIC) && (owner_flags & PROCESS_SYNTHETIC)) //SYNTHETIC-oriented reagents require PROCESS_SYNTHETIC
can_process = TRUE
if((reagent.process_flags & REAGENT_ORGANIC) && (owner_flags & PROCESS_ORGANIC)) //ORGANIC-oriented reagents require PROCESS_ORGANIC
can_process = TRUE

//If the mob can't process it, remove the reagent at it's normal rate without doing any addictions, overdoses, or on_mob_life() for the reagent
if(!can_process)
reagent.holder.remove_reagent(reagent.type, reagent.metabolization_rate)
return
//We'll assume that non-human mobs lack the ability to process synthetic-oriented reagents (adjust this if we need to change that assumption)
else
if(reagent.process_flags == REAGENT_SYNTHETIC)
reagent.holder.remove_reagent(reagent.type, reagent.metabolization_rate)
return
var/can_process = reagent_process_flags_valid(owner, reagent)
//If the mob can't process it, remove the reagent at it's normal rate without doing any addictions, overdoses, or on_mob_life() for the reagent
if(!can_process)
reagent.holder.remove_reagent(reagent.type, reagent.metabolization_rate)
return
//SKYRAT EDIT ADDITION END

if(owner && reagent && (!dead || (reagent.chemical_flags & REAGENT_DEAD_PROCESS)))
if(owner.reagent_check(reagent, seconds_per_tick, times_fired))
return
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/datum/preference/numeric/death_consequences
abstract_type = /datum/preference/numeric/death_consequences
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_identifier = PREFERENCE_CHARACTER

step = 0.01

/datum/preference/numeric/death_consequences/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
return FALSE

/datum/preference/numeric/death_consequences/starting_degradation
savefile_key = "dc_starting_degradation"

minimum = 0
maximum = DEATH_CONSEQUENCES_MAXIMUM_THEORETICAL_DEGRADATION

/datum/preference/numeric/death_consequences/starting_degradation/create_default_value()
return minimum

/datum/preference/numeric/death_consequences/max_degradation
savefile_key = "dc_max_degradation"

minimum = 0
maximum = DEATH_CONSEQUENCES_MAXIMUM_THEORETICAL_DEGRADATION

/datum/preference/numeric/death_consequences/max_degradation/create_default_value()
return DEATH_CONSEQUENCES_DEFAULT_MAX_DEGRADATION

/datum/preference/numeric/death_consequences/living_degradation_recovery_per_second
savefile_key = "dc_living_degradation_recovery_per_second"

minimum = -100 // if you want, you can just die slowly
maximum = 1000

/datum/preference/numeric/death_consequences/living_degradation_recovery_per_second/create_default_value()
return DEATH_CONSEQUENCES_DEFAULT_LIVING_DEGRADATION_RECOVERY

/datum/preference/numeric/death_consequences/dead_degradation_per_second
savefile_key = "dc_dead_degradation_per_second"

minimum = 0
maximum = 1000

/datum/preference/numeric/death_consequences/dead_degradation_per_second/create_default_value()
return 0

/datum/preference/numeric/death_consequences/degradation_on_death
savefile_key = "dc_degradation_on_death"

minimum = 0
maximum = 1000

/datum/preference/numeric/death_consequences/degradation_on_death/create_default_value()
return DEATH_CONSEQUENCES_DEFAULT_DEGRADATION_ON_DEATH

/datum/preference/numeric/death_consequences/formeldahyde_dead_degradation_mult
savefile_key = "dc_formeldahyde_dead_degradation_mult"

minimum = 0
maximum = 1

/datum/preference/numeric/death_consequences/formeldahyde_dead_degradation_mult/create_default_value()
return 0

/datum/preference/numeric/death_consequences/stasis_dead_degradation_mult
savefile_key = "dc_stasis_dead_degradation_mult"

minimum = 0
maximum = 1

/datum/preference/numeric/death_consequences/stasis_dead_degradation_mult/create_default_value()
return 0

/datum/preference/numeric/death_consequences/rezadone_living_degradation_reduction
savefile_key = "dc_rezadone_living_degradation_reduction"

minimum = 0
maximum = 500

/datum/preference/numeric/death_consequences/rezadone_living_degradation_reduction/create_default_value()
return DEATH_CONSEQUENCES_DEFAULT_REZADONE_DEGRADATION_REDUCTION

/datum/preference/numeric/death_consequences/eigenstasium_degradation_reduction
savefile_key = "dc_eigenstasium_degradation_reduction"

minimum = 0
maximum = 5000

/datum/preference/numeric/death_consequences/eigenstasium_degradation_reduction/create_default_value()
return DEATH_CONSEQUENCES_DEFAULT_EIGENSTASIUM_DEGRADATION_REDUCTION

/datum/preference/numeric/death_consequences/crit_threshold_reduction_min_percent_of_max
savefile_key = "dc_crit_threshold_reduction_min_percent_of_max"

minimum = 0
maximum = 100

/datum/preference/numeric/death_consequences/crit_threshold_reduction_min_percent_of_max/create_default_value()
return 0 // percent

/datum/preference/numeric/death_consequences/crit_threshold_reduction_percent_of_max
savefile_key = "dc_crit_threshold_reduction_percent_of_max"

minimum = 0
maximum = 100

/datum/preference/numeric/death_consequences/crit_threshold_reduction_percent_of_max/create_default_value()
return 100 // percent

/datum/preference/numeric/death_consequences/max_crit_threshold_reduction
savefile_key = "dc_max_crit_threshold_reduction"

minimum = 0
maximum = MAX_LIVING_HEALTH

/datum/preference/numeric/death_consequences/max_crit_threshold_reduction/create_default_value()
return 30

/datum/preference/numeric/death_consequences/stamina_damage_min_percent_of_max
savefile_key = "dc_stamina_damage_min_percent_of_max"

minimum = 0
maximum = 100

/datum/preference/numeric/death_consequences/stamina_damage_min_percent_of_max/create_default_value()
return 20 // percent

/datum/preference/numeric/death_consequences/stamina_damage_percent_of_max
savefile_key = "dc_stamina_damage_percent_of_max"

minimum = 0
maximum = 100

/datum/preference/numeric/death_consequences/stamina_damage_percent_of_max/create_default_value()
return 100 // percent

/datum/preference/numeric/death_consequences/max_stamina_damage
savefile_key = "dc_max_stamina_damage"

minimum = 0
maximum = 150

/datum/preference/numeric/death_consequences/max_stamina_damage/create_default_value()
return 80

// BOOLEANS

/datum/preference/toggle/death_consequences
abstract_type = /datum/preference/toggle/death_consequences
category = PREFERENCE_CATEGORY_MANUALLY_RENDERED
savefile_identifier = PREFERENCE_CHARACTER

/datum/preference/toggle/death_consequences/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences)
return FALSE

/datum/preference/toggle/death_consequences/permakill_at_max
savefile_key = "dc_permakill_at_max"

default_value = FALSE // lets not be too cruel here

/datum/preference/toggle/death_consequences/force_death_if_permakilled
savefile_key = "dc_force_death_if_permakilled"

default_value = FALSE

Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/datum/quirk/death_consequences
name = DEATH_CONSEQUENCES_QUIRK_NAME
desc = "Every time you die, your body suffers long-term damage that can't easily be repaired."
medical_record_text = DEATH_CONSEQUENCES_QUIRK_DESC
icon = FA_ICON_DNA
value = 0 // due to its high customization, you can make it really inconsequential

/datum/quirk_constant_data/death_consequences
associated_typepath = /datum/quirk/death_consequences

/datum/quirk_constant_data/death_consequences/New()
customization_options = (subtypesof(/datum/preference/numeric/death_consequences) + subtypesof(/datum/preference/toggle/death_consequences))

return ..()

/datum/quirk/death_consequences/add(client/client_source)
var/mob/living/carbon/human/human_holder = quirk_holder
human_holder.gain_trauma(/datum/brain_trauma/severe/death_consequences, TRAUMA_RESILIENCE_ABSOLUTE)
var/datum/brain_trauma/severe/death_consequences/added_trauma = human_holder.get_death_consequences_trauma()
if (!isnull(added_trauma))
added_trauma.update_variables(client_source)

to_chat(human_holder, span_danger("You suffer from [src]. By default, you will \
degrade every time you die, and recover very slowly while alive. This may be expedited by resting, sleeping, being buckled \
to something cozy, or using rezadone.\n\
As your degradation rises, so too will negative effects, such as stamina damage or a worsened crit threshold.\n\
You can alter your degradation on the fly via the Adjust death degradation verb, and change your settings via the Refresh death consequence variables verb."))

/datum/quirk/death_consequences/remove()
var/mob/living/carbon/human/human_holder = quirk_holder
human_holder.cure_trauma_type(/datum/brain_trauma/severe/death_consequences, TRAUMA_RESILIENCE_ABSOLUTE)

/// Adjusts the mob's linked death consequences trauma (see get_death_consequences_trauma())'s degradation by increment.
/mob/verb/adjust_degradation(increment as num)
set name = "Adjust death degradation"
set category = "IC"
set instant = TRUE

if (isnull(mind))
to_chat(usr, span_warning("You have no mind!"))
return

var/datum/brain_trauma/severe/death_consequences/linked_trauma = get_death_consequences_trauma()
var/mob/living/carbon/trauma_holder = linked_trauma?.owner
if (isnull(linked_trauma) || isnull(trauma_holder) || trauma_holder != mind.current) // sanity
to_chat(usr, span_warning("You don't have a body with death consequences!"))
return

if (!isnum(increment))
to_chat(usr, span_warning("You can artificially change the current level of your death degradation with this verb. \
You can use this to cause degradation in ways the customization cannot. <b>You need to enter a number to use this verb.</b>"))
return

if (linked_trauma.permakill_if_at_max_degradation && ((linked_trauma.current_degradation + increment) >= linked_trauma.max_degradation))
if (tgui_alert(usr, "This will put you over/at your maximum degradation threshold and PERMANENTLY KILL YOU!!! Are you SURE you want to do this?", "WARNING", list("Yes", "No"), timeout = 7 SECONDS) != "Yes")
return

linked_trauma.adjust_degradation(increment)
to_chat(usr, span_notice("Degradation successfully adjusted!"))

/// Calls update_variables() on this mob's linked death consequences trauma. See that proc for further info.
/mob/verb/refresh_death_consequences()
set name = "Refresh death consequence variables"
set category = "IC"
set instant = TRUE

if (isnull(mind))
to_chat(usr, span_warning("You have no mind!"))
return

var/datum/brain_trauma/severe/death_consequences/linked_trauma = get_death_consequences_trauma()
var/mob/living/carbon/trauma_holder = linked_trauma?.owner
if (isnull(linked_trauma) || isnull(trauma_holder) || trauma_holder != mind.current) // sanity
to_chat(usr, span_warning("You don't have a body with death consequences!"))
return

linked_trauma.update_variables(client)
to_chat(usr, span_notice("Variables successfully updated!"))

/// Searches mind.current for a death_consequences trauma. Allows this proc to be used on both ghosts and living beings to find their linked trauma.
/mob/proc/get_death_consequences_trauma()
RETURN_TYPE(/datum/brain_trauma/severe/death_consequences)

if (isnull(mind))
return

if (iscarbon(mind.current))
var/mob/living/carbon/carbon_body = mind.current
for (var/datum/brain_trauma/trauma as anything in carbon_body.get_traumas())
if (istype(trauma, /datum/brain_trauma/severe/death_consequences))
return trauma
// else, return null
Loading
Loading