Skip to content
Draft
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
16 changes: 12 additions & 4 deletions code/__DEFINES/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,18 @@
/// Doesn't let a mob shift this atom around with move_pulled
#define TRAIT_NO_MOVE_PULL "no_move_pull"

/// Boosts the heart rate of the mob
/// Boosts the heart rate of the mob (raises blood pressure)
/// One application of the trait translates to +10 bpm, which may translate to +10 blood pressure
#define TRAIT_HEART_RATE_BOOST "heart_rate_boost"
/// Slows the heart rate of the mob
/// Slows the heart rate of the mob (lowers blood pressure)
/// One application of the trait translates to -10 bpm, which may translate to -10 blood pressure
#define TRAIT_HEART_RATE_SLOW "heart_rate_slow"
/// Constricts blood vessels (raises blood pressure)
/// One application of the trait translates to +0.2 "vasoconstriction", which is a +0.2 multiplier to blood pressure
#define TRAIT_VASOCONSTRICTED "vasoconstricted"
/// Dilates blood vessels (lowers blood pressure)
/// One application of the trait translates to -0.2 "vasodilation", which is a -0.2 multiplier to blood pressure
#define TRAIT_VASODILATED "vasodilated"

/// The trait that determines if someone has the robotic limb reattachment quirk.
#define TRAIT_ROBOTIC_LIMBATTACHMENT "trait_robotic_limbattachment"
Expand Down Expand Up @@ -179,9 +187,9 @@
#define UPDATE_SELF (UPDATE_SELF_DAMAGE | UPDATE_SELF_HEALTH)

/// Threshold that heart beat becomes "slow"
#define SLOW_HEARTBEAT_THRESHOLD 6
#define SLOW_HEARTBEAT_THRESHOLD 60
/// Threshold that heart beat becomes "fast"
#define FAST_HEARTBEAT_THRESHOLD 11
#define FAST_HEARTBEAT_THRESHOLD 110

// Used in living mob offset list for determining pixel offsets
#define PIXEL_W_OFFSET "w"
Expand Down
2 changes: 2 additions & 0 deletions code/datums/status_effects/buffs.dm
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,12 @@

/datum/status_effect/exercised/on_apply()
owner.add_mood_event("exercise", /datum/mood_event/exercise, owner.mind.get_skill_level(/datum/skill/athletics))
ADD_TRAIT(owner, TRAIT_HEART_RATE_BOOST, type)
return ..()

/datum/status_effect/exercised/on_remove()
owner.clear_mood_event("exercise")
REMOVE_TRAIT(owner, TRAIT_HEART_RATE_BOOST, type)

/atom/movable/screen/alert/status_effect/exercised
name = "Exercise"
Expand Down
33 changes: 21 additions & 12 deletions code/datums/status_effects/debuffs/grabbed.dm
Original file line number Diff line number Diff line change
Expand Up @@ -634,20 +634,16 @@
#undef CRIT_SOURCE
#undef PIN_SOURCE

#define IS_VULNERABLE(mob) (\
mob.incapacitated(IGNORE_GRAB|IGNORE_STASIS) \
|| mob.body_position == LYING_DOWN \
|| (mob.has_status_effect(/datum/status_effect/staggered) && mob.getStaminaLoss() >= 30) \
)

/**
* Checks how strong our grabs are.
*
* Returns a flat number that represents how strong our grabs are
* somewhere in the range of 0-10 for a normal human.
*/
/atom/movable/proc/get_grab_strength()
// resist strength and grab strength overlap in plenty of ways so we will re-use it for our base
. = get_grab_resist_strength()
// strength adds a bonus on top of resist strength (stacking with the strengh bonus already factored in to resistance)
if(HAS_TRAIT(src, TRAIT_STRENGTH))
. += 1

Expand Down Expand Up @@ -686,28 +682,41 @@
return 5

/mob/living/get_grab_resist_strength()
// base resistance is base on size
. += mob_size * 2
// athletics skill can give a decent boost
. += clamp(0.5 * ((mind?.get_skill_level(/datum/skill/athletics) || 1) - 2), -1, 3)
// monkey wrangling buff
if(ismonkey(src))
. -= 1
// dead people are not actively resisting, though this is not an absurdly high nubmer like -20
// because grabbing a corpse should still be cumbersome and unwieldy
if(stat == DEAD)
. -= 4
else if(IS_VULNERABLE(src))
// otherwise being in soft crit or incapacitated means you can't fight back well
else if(HAS_TRAIT(src, TRAIT_SOFT_CRIT) || incapacitated(IGNORE_GRAB|IGNORE_STASIS))
. -= 2
if(HAS_TRAIT(src, TRAIT_STRENGTH))
. += 1
// lying down or staggered represents a vulnerable position which has you disadvanteged
if(body_position == LYING_DOWN || (has_status_effect(/datum/status_effect/staggered) && getStaminaLoss() >= 30))
. -= 2
// generic grab weakness such as from quirks
if(HAS_TRAIT(src, TRAIT_GRABWEAKNESS))
. -= 2
// these two are not
// grabs you grabs you grabs you
if(HAS_TRAIT(src, TRAIT_SMALL))
. -= 2

// generic buff
if(HAS_TRAIT(src, TRAIT_STRENGTH))
. += 1
// hulks are the pinnacle of strength
if(HAS_TRAIT(src, TRAIT_HULK))
. += 3
// being large also helps considerably
// mutually exclusive with hulk as hulk's strength can be interpreted as coming from size
else if(HAS_TRAIT(src, TRAIT_GIANT) || HAS_TRAIT(src, TRAIT_HUGE))
. += 2

#undef IS_VULNERABLE

/**
* When given a base climb speed, modifies it based on how good a climber we are.
*
Expand Down
30 changes: 0 additions & 30 deletions code/datums/status_effects/drug_effects.dm
Original file line number Diff line number Diff line change
Expand Up @@ -12,36 +12,6 @@
desc = "You feel a bit slower than usual, it seems doing things with your hands takes longer than it usually does."
icon_state = "woozy"

/datum/status_effect/high_blood_pressure
id = "high_blood_pressure"
tick_interval = -1
status_type = STATUS_EFFECT_UNIQUE
alert_type = null

/datum/status_effect/high_blood_pressure/on_apply()
if(!ishuman(owner))
return FALSE

var/mob/living/carbon/human/human_owner = owner
human_owner.physiology.bleed_mod *= 1.25
RegisterSignal(owner, COMSIG_LIVING_HEALTHSCAN, PROC_REF(on_healthscan))
return TRUE

/datum/status_effect/high_blood_pressure/on_remove()
if(!ishuman(owner))
return

var/mob/living/carbon/human/human_owner = owner
human_owner.physiology.bleed_mod /= 1.25
UnregisterSignal(owner, COMSIG_LIVING_HEALTHSCAN)

/datum/status_effect/high_blood_pressure/proc/on_healthscan(datum/source, list/render_list, advanced, mob/user, mode, tochat)
SIGNAL_HANDLER

if(owner.has_status_effect(/datum/status_effect/low_blood_pressure))
return
render_list += "<span class='alert ml-1'>Hypertension detected.</span><br>"

/datum/status_effect/seizure
id = "seizure"
tick_interval = -1
Expand Down
19 changes: 13 additions & 6 deletions code/game/objects/items/devices/scanners/health_analyzer.dm
Original file line number Diff line number Diff line change
Expand Up @@ -372,18 +372,25 @@
// Blood Level
var/datum/blood_type/target_blood_type = target.get_blood_type()
if(target_blood_type)
var/bpm = target.get_bpm()
var/list/bp = target.get_bp_range()
var/needs_heart = TRUE
if(ishuman(target))
var/mob/living/carbon/human/humantarget = target
needs_heart = humantarget.needs_heart()

var/bpm_format = "[needs_heart ? bpm : "n/a"] bpm"
var/level_format = "[round_and_format_decimal(target.blood_volume, 0.1)] cl" // round to 0.1 but also print "100.0" and not "100"
var/bp_format = "[bp[1]]/[bp[2]]" + span_slightly_smaller("mmHg")
var/level_format = "[round_and_format_decimal(target.blood_volume, 0.1)]" + span_slightly_smaller("cl") // round to 0.1 but also print "100.0" and not "100"
var/blood_type_format = "[target_blood_type.name]"

if(needs_heart && (bpm < 60 || bpm > 100))
bpm_format = span_alert(bpm_format)
if(needs_heart)
if(bp[1] > 140 && bp[2] > 90) // high blood pressure
bp_format = conditional_tooltip(span_alert("[bp_format] (Warning: Hypertension)"), \
"To fix, resolve underlying causes such as pain, hypoxima, or blood loss. Side effects can be abated by \
supplying vasodilators such as [/datum/reagent/potassium::name] or [/datum/reagent/nitroglycerin::name].", tochat)
if(bp[1] < 90 && bp[2] < 60) // low blood pressure
bp_format = conditional_tooltip(span_alert("[bp_format] (Warning: Hypotension)"), \
"To fix, resolve underlying causes such as heart damage or blood loss. Side effects can be abated by \
supplying vasoconstrictors such as [/datum/reagent/medicine/epinephrine::name].", tochat)

switch(target.blood_volume)
if(BLOOD_VOLUME_EXCESS to INFINITY)
Expand All @@ -410,7 +417,7 @@
recieve_from_text += " Regenerates slowly via [target_blood_type.restoration_chem::name] reagent."
blood_type_format = span_tooltip(recieve_from_text, blood_type_format)

render_list += "<span class='info ml-1'>Heart rate: [bpm_format]</span><br>"
render_list += "<span class='info ml-1'>Blood pressure: [bp_format]</span><br>"
render_list += "<span class='info ml-1'>Blood level: [level_format]</span><br>"
render_list += "<span class='info ml-1'>Blood type: [blood_type_format]</span><br>"

Expand Down
2 changes: 1 addition & 1 deletion code/game/objects/items/robot/items/hypo.dm
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
)
#define HACKED_PEACE_REAGENTS list(\
/datum/reagent/toxin/cyanide,\
/datum/reagent/toxin/fentanyl,\
/datum/reagent/medicine/painkiller/fentanyl,\
/datum/reagent/toxin/sodium_thiopental,\
/datum/reagent/toxin/staminatoxin,\
/datum/reagent/toxin/sulfonal\
Expand Down
2 changes: 1 addition & 1 deletion code/modules/clothing/neck/_neck.dm
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@

//assess heart
if(body_part == BODY_ZONE_CHEST)//if we're listening to the chest
var/heart_rate = carbon_patient.get_heart_rate()
var/heart_rate = carbon_patient.get_bpm()
switch(heart_rate)
if(0)
render_list += "<span class='danger ml-1'>You don't hear a heartbeat!</span>\n"
Expand Down
67 changes: 37 additions & 30 deletions code/modules/mob/living/carbon/carbon.dm
Original file line number Diff line number Diff line change
Expand Up @@ -548,39 +548,46 @@
SShealth_updates.queue_update(src, UPDATE_SELF|UPDATE_MEDHUD_HEALTH)

/mob/living/carbon/proc/paincrit_check()
if(crit_percent() < 100 || HAS_TRAIT(src, TRAIT_NOSOFTCRIT)) // melbert todo
if(HAS_TRAIT_FROM(src, TRAIT_SOFT_CRIT, PAINCRIT))
Paralyze(2 SECONDS)
remove_traits(list(TRAIT_SOFT_CRIT, TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), PAINCRIT)
if(crit_percent() < 100)
remove_status_effect(/datum/status_effect/paincrit)
return

if(HAS_TRAIT_FROM(src, TRAIT_SOFT_CRIT, PAINCRIT))
return
var/is_standing = body_position == STANDING_UP
add_traits(list(TRAIT_SOFT_CRIT, TRAIT_INCAPACITATED, TRAIT_IMMOBILIZED, TRAIT_FLOORED, TRAIT_HANDS_BLOCKED), PAINCRIT)
if(stat == DEAD)
return
if(buckled)
visible_message(
span_warning("[src] slumps against [buckled]!"),
span_userdanger("You go limp, unable to move!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
apply_status_effect(/datum/status_effect/paincrit)

else if(is_standing && body_position != STANDING_UP)
visible_message(
span_warning("[src] collapses!"),
span_userdanger("You collapse, unable to stand!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else if(body_position == LYING_DOWN)
visible_message(
span_warning("[src] slumps against the ground!"),
span_userdanger("You go limp, unable to get up!"),
visible_message_flags = ALWAYS_SHOW_SELF_MESSAGE,
)
else
to_chat(src, span_userdanger("You can't will yourself to move!"))
/datum/status_effect/paincrit
id = "paincrit"
alert_type = null
tick_interval = -1
duration = -1

/datum/status_effect/paincrit/nextmove_modifier()
return 3

/datum/status_effect/paincrit/on_apply()
. = ..()
owner.add_traits(list(TRAIT_SOFT_CRIT, TRAIT_FLOORED, TRAIT_GRABWEAKNESS), id)
owner.add_movespeed_modifier(/datum/movespeed_modifier/paincrit)
owner.add_actionspeed_modifier(/datum/actionspeed_modifier/paincrit)
owner.drop_all_held_items()
RegisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOSOFTCRIT), PROC_REF(clean_up))

/datum/status_effect/paincrit/on_remove()
. = ..()
owner.remove_traits(list(TRAIT_SOFT_CRIT, TRAIT_FLOORED, TRAIT_GRABWEAKNESS), id)
owner.remove_movespeed_modifier(/datum/movespeed_modifier/paincrit)
owner.remove_actionspeed_modifier(/datum/actionspeed_modifier/paincrit)
owner.Paralyze(2 SECONDS)
UnregisterSignal(owner, SIGNAL_ADDTRAIT(TRAIT_NOSOFTCRIT))

/datum/status_effect/paincrit/clean_up()
SIGNAL_HANDLER
qdel(src)

/datum/movespeed_modifier/paincrit
multiplicative_slowdown = 9

/datum/actionspeed_modifier/paincrit
multiplicative_slowdown = 3

/mob/living/carbon/update_sight()
if(!client)
Expand Down
2 changes: 2 additions & 0 deletions code/modules/mob/living/carbon/human/death.dm
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ GLOBAL_LIST_EMPTY(dead_players_during_shift)
if(!HAS_TRAIT(src, TRAIT_NOBLOOD) && blood_volume < BLOOD_VOLUME_BAD)
return BLOOD_LOSS

return "hypoxia"

if(TOX_DAMAGE)
var/obj/item/organ/liver/liver = get_organ_slot(ORGAN_SLOT_LIVER)
if(isnull(liver) || (liver.organ_flags & ORGAN_FAILING))
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@
if(stat == HARD_CRIT && !internal && !external) // being on internals function as a ventilator + also makes anesthetic function (revisit later)
losebreath = max(losebreath, 1)
else if(HAS_TRAIT(src, TRAIT_LABOURED_BREATHING))
losebreath += (1 / next_breath)
losebreath += (1 / max(2, next_breath))

if(losebreath < 1)
var/pre_sig_return = SEND_SIGNAL(src, COMSIG_CARBON_ATTEMPT_BREATHE, seconds_per_tick, times_fired)
Expand Down
6 changes: 6 additions & 0 deletions code/modules/mob/living/life.dm
Original file line number Diff line number Diff line change
Expand Up @@ -176,9 +176,11 @@
if(feels_like > hot_threshold_high)
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3)
add_mood_event("hot", /datum/mood_event/overhot)
ADD_TRAIT(src, TRAIT_VASODILATED, "extreme_temperature")
else if(feels_like > hot_threshold_medium)
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2)
add_mood_event("hot", /datum/mood_event/hot)
ADD_TRAIT(src, TRAIT_VASODILATED, "high_temperature")
else
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1)
add_mood_event("hot", /datum/mood_event/warm)
Expand All @@ -194,9 +196,11 @@
if(feels_like < cold_threshold_high)
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3)
add_mood_event("cold", /datum/mood_event/freezing)
ADD_TRAIT(src, TRAIT_VASOCONSTRICTED, "extreme_temperature")
else if(feels_like < cold_threshold_medium)
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2)
add_mood_event("cold", /datum/mood_event/cold)
ADD_TRAIT(src, TRAIT_VASOCONSTRICTED, "high_temperature")
else
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1)
add_mood_event("cold", /datum/mood_event/chilly)
Expand All @@ -213,6 +217,8 @@
clear_mood_event("cold")
clear_mood_event("hot")
temp_alerts = FALSE
REMOVE_TRAITS_IN(src, "extreme_temperature")
REMOVE_TRAITS_IN(src, "high_temperature")

/mob/living/silicon/body_temperature_alerts()
return // Not yet
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1486,7 +1486,7 @@
if(!istype(target))
CRASH("Missing target arg for can_perform_action")

if(stat != CONSCIOUS)
if(stat >= UNCONSCIOUS)
to_chat(src, span_warning("You are not conscious enough for this action!"))
return FALSE

Expand Down
2 changes: 0 additions & 2 deletions code/modules/reagents/chemistry/reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -233,8 +233,6 @@ Primarily used in reagents/reaction_agents

/// Called when an overdose starts. Returning UPDATE_MOB_HEALTH will cause updatehealth() to be called on the holder mob by /datum/reagents/proc/metabolize.
/datum/reagent/proc/overdose_start(mob/living/affected_mob)
to_chat(affected_mob, span_userdanger("You feel like you took too much of [name]!"))
affected_mob.add_mood_event("[type]_overdose", /datum/mood_event/overdose, name)
return

/**
Expand Down
7 changes: 6 additions & 1 deletion code/modules/reagents/chemistry/reagents/drug_reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
if(trippy)
affected_mob.clear_mood_event("[type]_high")
REMOVE_TRAIT(affected_mob, TRAIT_HEART_RATE_BOOST, type)
REMOVE_TRAIT(affected_mob, TRAIT_HEART_RATE_BOOST, "[type]_overdose")

/datum/reagent/drug/overdose_start(mob/living/affected_mob)
. = ..()
affected_mob.add_mood_event("[type]_overdose", /datum/mood_event/overdose, name)
ADD_TRAIT(affected_mob, TRAIT_HEART_RATE_BOOST, "[type]_overdose")

/datum/reagent/drug/space_drugs
name = "Space Drugs"
Expand All @@ -35,7 +41,6 @@
/datum/reagent/drug/space_drugs/overdose_start(mob/living/affected_mob)
. = ..()
to_chat(affected_mob, span_userdanger("You start tripping hard!"))
affected_mob.add_mood_event("[type]_overdose", /datum/mood_event/overdose, name)

/datum/reagent/drug/space_drugs/overdose_process(mob/living/affected_mob, seconds_per_tick, times_fired)
. = ..()
Expand Down
2 changes: 2 additions & 0 deletions code/modules/reagents/chemistry/reagents/medicine_reagents.dm
Original file line number Diff line number Diff line change
Expand Up @@ -990,12 +990,14 @@
ADD_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
ADD_TRAIT(affected_mob, TRAIT_ABATES_SHOCK, type)
ADD_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
ADD_TRAIT(affected_mob, TRAIT_VASOCONSTRICTED, type)

/datum/reagent/medicine/epinephrine/on_mob_end_metabolize(mob/living/affected_mob)
. = ..()
REMOVE_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
REMOVE_TRAIT(affected_mob, TRAIT_ABATES_SHOCK, type)
REMOVE_TRAIT(affected_mob, TRAIT_NOCRITDAMAGE, type)
REMOVE_TRAIT(affected_mob, TRAIT_VASOCONSTRICTED, type)

/datum/reagent/medicine/epinephrine/on_mob_life(mob/living/carbon/affected_mob, seconds_per_tick, times_fired)
. = ..()
Expand Down
Loading