Make blood worms take damage from pressure instead of lack of oxygen and tweak their environmental damage values (#96607)

<!-- Write **BELOW** The Headers and **ABOVE** The comments else it may
not be viewable. -->
<!-- You can view Contributing.MD for a detailed description of the pull
request process. -->

## About The Pull Request

Extension to #96385

I added `/datum/element/pressure_sensitive` for making mobs sensitive to
low/high pressure limits, then implemented it for blood worms so they
take damage from low pressure. The element also has the same
`/proc/check_safe_environment` setup that
`/datum/element/body_temp_sensitive` has, for future-proofing in case
pressure sensitivity is expanded to all basic mobs.

I also did some message fixes for the pressure and temperature alerts.
The temperature alert no longer breaks if the damage being dealt is
below 1 but above 0. Also, the check for more severe alerts is now
effectively `>=` instead of `>`, meaning that 5 damage is now considered
high severity.

Hatchlings take 0.5 DPS from low pressure and 0.5 DPS from cold
temperatures. All blood worms have low absolute values for minimum
pressure and minimum temperature, but they're still reliably screwed
over by space which is what I want.

Lastly, I made blood worms breathless again.

EDIT: I also updated the antag info panel to match #95920.

<!-- Describe The Pull Request. Please be sure every change is
documented or this can delay review and even discourage maintainers from
merging your PR! -->

## Why It's Good For The Game

Blood worm hatchlings are highly dependent on vents for being able to
play the game. I don't want distro losing pressure or an atmos tech
optimizing distro density with low temperature to be a gotcha for blood
worms. Those happen coincidentally pretty often with no intention to
kill blood worms behind them and losing to something like that right
after you spawn just feels bad.

The pressure and cold damage in general is meant to prevent blood worms
from spacewalking and breaking every window in sight to expand their
effective domain. They can still get hosts with space suits to
circumvent this.

<!-- Argue for the merits of your changes and how they benefit the game,
especially if they are controversial and/or far reaching. If you can't
actually explain WHY what you are doing will improve the game, then it
probably isn't good for the game in the first place. -->

## Changelog

<!-- If your PR modifies aspects of the game that can be concretely
observed by players or admins you should add a changelog. If your change
does NOT meet this description, remove this section. Be sure to properly
mark your PRs to prevent unnecessary GBP loss. You can read up on GBP
and its effects on PRs in the tgstation guides for contributors. Please
note that maintainers freely reserve the right to remove and add tags
should they deem it appropriate. You can attempt to finagle the system
all you want, but it's best to shoot for clear communication right off
the bat. -->

🆑
fix: Low temperature alerts now appear for basic mobs when the damage
being dealt is below 1 but above 0 (e.g. 0.5 DPS).
balance: Blood worms are now breathless again.
balance: Blood worms take damage from low pressures now (increases with
growth stage).
/🆑

<!-- Both 🆑's are required for the changelog to work! You can put
your name to the right of the first 🆑 if you want to overwrite your
GitHub username as author ingame. -->
<!-- You can use multiple of the same prefix (they're only used for the
icon ingame) and delete the unneeded ones. Despite some of the tags,
changelogs should generally represent how a player might be affected by
the changes rather than a summary of the PR's contents. -->
This commit is contained in:
RikuTheKiller
2026-07-05 17:38:28 -07:00
committed by GitHub
parent da75ec822a
commit 7fe431dee2
5 changed files with 118 additions and 18 deletions
+10 -10
View File
@@ -49,27 +49,27 @@
var/mob/living/living_mob = target
var/gave_alert = FALSE
if(living_mob.bodytemperature < min_body_temp && !HAS_TRAIT(living_mob, TRAIT_RESISTCOLD))
if(living_mob.bodytemperature < min_body_temp && cold_damage > 0 && !HAS_TRAIT(living_mob, TRAIT_RESISTCOLD))
living_mob.adjust_fire_loss(cold_damage * seconds_per_tick, forced = TRUE)
if(!living_mob.has_status_effect(/datum/status_effect/inebriated))
switch(cold_damage)
if(1 to 5)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1)
if(5 to 10)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2)
if(10 to INFINITY)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3)
if(5 to 10)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2)
if(-INFINITY to 5)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1)
gave_alert = TRUE
else if(living_mob.bodytemperature > max_body_temp && !HAS_TRAIT(living_mob, TRAIT_RESISTHEAT))
else if(living_mob.bodytemperature > max_body_temp && heat_damage > 0 && !HAS_TRAIT(living_mob, TRAIT_RESISTHEAT))
living_mob.adjust_fire_loss(heat_damage * seconds_per_tick, forced = TRUE)
switch(heat_damage)
if(1 to 5)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1)
if(5 to 10)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2)
if(10 to INFINITY)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3)
if(5 to 10)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2)
if(-INFINITY to 5)
living_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1)
gave_alert = TRUE
if(!gave_alert)
@@ -0,0 +1,85 @@
/// When attached to a living mob, causes it to take damage over time when pressure is too low or too high as defined by the element's arguments.
/datum/element/pressure_sensitive
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
argument_hash_end_idx = 5
/// The pressure (in kilopascals) below which low_pressure_damage is taken.
var/min_pressure = WARNING_LOW_PRESSURE
/// The pressure (in kilopascals) above which high_pressure_damage is taken.
var/max_pressure = HAZARD_HIGH_PRESSURE
/// The damage taken when pressure is below min_pressure. 0 or below disables low pressure damage.
var/low_pressure_damage = 1
/// The damage taken when pressure is above max_pressure. 0 or below disables high pressure damage.
var/high_pressure_damage = 1
/datum/element/pressure_sensitive/Attach(datum/target, min_pressure, max_pressure, low_pressure_damage, high_pressure_damage, mapload = FALSE)
. = ..()
if (!isliving(target))
return ELEMENT_INCOMPATIBLE
if (isnum(min_pressure))
src.min_pressure = min_pressure
if (isnum(max_pressure))
src.max_pressure = max_pressure
if (isnum(low_pressure_damage))
src.low_pressure_damage = low_pressure_damage
if (isnum(high_pressure_damage))
src.high_pressure_damage = high_pressure_damage
RegisterSignal(target, COMSIG_LIVING_LIFE, PROC_REF(on_life))
if(mapload && PERFORM_ALL_TESTS(focus_only/atmos_and_temp_requirements))
check_safe_environment(target)
/datum/element/pressure_sensitive/Detach(datum/target)
if(target)
UnregisterSignal(target, COMSIG_LIVING_LIFE)
return ..()
/datum/element/pressure_sensitive/proc/on_life(mob/living/target, seconds_per_tick)
SIGNAL_HANDLER
if (HAS_TRAIT(target, TRAIT_STASIS))
return
var/gave_alert = FALSE
var/datum/gas_mixture/environment = target.loc.return_air()
var/pressure = target.calculate_affecting_pressure(environment.return_pressure())
if(pressure < min_pressure && low_pressure_damage > 0 && !HAS_TRAIT(target, TRAIT_RESISTLOWPRESSURE))
target.adjust_brute_loss(low_pressure_damage * seconds_per_tick)
switch(low_pressure_damage)
if(5 to INFINITY)
target.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 2)
if(-INFINITY to 5)
target.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/lowpressure, 1)
gave_alert = TRUE
else if(pressure > max_pressure && high_pressure_damage > 0 && !HAS_TRAIT(target, TRAIT_RESISTHIGHPRESSURE))
target.adjust_brute_loss(high_pressure_damage * seconds_per_tick)
switch(high_pressure_damage)
if(5 to INFINITY)
target.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 2)
if(-INFINITY to 5)
target.throw_alert(ALERT_PRESSURE, /atom/movable/screen/alert/highpressure, 1)
gave_alert = TRUE
if(!gave_alert)
target.clear_alert(ALERT_PRESSURE)
/// Ensures that the given mob is in a safe environment.
/datum/element/pressure_sensitive/proc/check_safe_environment(mob/living/target)
if(target.stat == DEAD || isnull(target.loc))
return
var/atom/loc = target.loc
var/datum/gas_mixture/environment = loc.return_air()
var/pressure = target.calculate_affecting_pressure(environment.return_pressure())
if(!ISINRANGE(pressure, min_pressure, max_pressure))
stack_trace("[target] loaded on in a loc with unsafe pressure at \[[loc.x], [loc.y], [loc.z]\] (area : [get_area(loc)]): [pressure]kPa. Acceptable Range: [min_pressure]kPa - [max_pressure]kPa,")
@@ -24,12 +24,11 @@
attack_verb_continuous = "bites"
attack_verb_simple = "bite"
minimum_survivable_temperature = ICEBOX_MIN_TEMPERATURE
minimum_survivable_temperature = T0C - 100
maximum_survivable_temperature = T0C + 100
unsuitable_cold_damage = 1
unsuitable_atmos_damage = 2
unsuitable_atmos_damage = 0
habitable_atmos = list("min_oxy" = 5, "max_oxy" = 0)
habitable_atmos = null // Breathless
// A vivid red.
lighting_cutoff_red = 40
@@ -286,6 +285,9 @@
maxHealth = 80 // In practice, escaping into a vent from someone who could 3 hit you with a basic bitch welder was really hard. This used to be 50, and was buffed to 80, but speed was slowed a bit.
health = 80
// Hatchlings need to be space resistant
// Otherwise, if distro loses pressure or is made cold for increased density, all blood worm hatchlings will die
unsuitable_cold_damage = 0.5
unsuitable_heat_damage = 1
obj_damage = 15 // 10 -> 15, in testing 10 proved to be way too slow at breaking morgue trays and such. Make sure that this doesn't go above airlock damage deflection.
@@ -311,6 +313,7 @@
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
AddComponent(/datum/component/slide_under_doors, slide_in_delay = 3 SECONDS)
AddElement(/datum/element/pressure_sensitive, min_pressure = 20, max_pressure = 0, low_pressure_damage = 0.5, high_pressure_damage = 0)
/mob/living/basic/blood_worm/juvenile
name = "juvenile blood worm"
@@ -327,6 +330,7 @@
maxHealth = 120 // Note that the juveniles are bigger and slower than hatchlings, making them far easier to hit by comparison.
health = 120
unsuitable_cold_damage = 1
unsuitable_heat_damage = 1.5
obj_damage = 35 // Able to break most obstacles, such as airlocks. This is mandatory since they can't ventcrawl anymore.
@@ -354,6 +358,7 @@
. = ..()
AddComponent(/datum/component/slide_under_doors, slide_in_delay = 5 SECONDS)
AddElement(/datum/element/pressure_sensitive, min_pressure = 20, max_pressure = 0, low_pressure_damage = 1, high_pressure_damage = 0)
/mob/living/basic/blood_worm/adult
name = "adult blood worm"
@@ -374,6 +379,7 @@
maxHealth = 180 // Used to be 150, turns out their lack of armor and weakness to burn made them too squishy. People kited them using lasguns, leaving them with no way to fight back at all.
health = 180
unsuitable_cold_damage = 1
unsuitable_heat_damage = 2
obj_damage = 50 // You are not getting away.
@@ -400,6 +406,11 @@
regen_rate = 0.5 // 360 seconds to recover from 0 to 180, or exactly 6 minutes.
/mob/living/basic/blood_worm/adult/Initialize(mapload)
. = ..()
AddElement(/datum/element/pressure_sensitive, min_pressure = 20, max_pressure = 0, low_pressure_damage = 2, high_pressure_damage = 0)
/mob/living/basic/blood_worm/hatchling/polymorph
cocoon_action = /datum/action/cooldown/mob_cooldown/blood_worm/cocoon/hatchling/polymorph
+1
View File
@@ -1685,6 +1685,7 @@
#include "code\datums\elements\plant_backfire.dm"
#include "code\datums\elements\point_of_interest.dm"
#include "code\datums\elements\poster_tearer.dm"
#include "code\datums\elements\pressure_sensitive.dm"
#include "code\datums\elements\prevent_attacking_of_types.dm"
#include "code\datums\elements\projectile_drop.dm"
#include "code\datums\elements\projectile_shield.dm"
@@ -40,9 +40,8 @@ export const AntagInfoBloodWorm = (props) => {
<Stack.Item>
<Section fill title="Powers">
<LabeledList>
<LabeledList.Item label="Space Immunity">
You are immune to low temperature, low pressure and don't need to breathe.
Your hosts don't have to breathe either, but their bodies remain vulnerable to space.
<LabeledList.Item label="Breathless">
You don't need to breathe. This extends to your hosts as well.
</LabeledList.Item>
<LabeledList.Item label="Blood Consumption">
You can grow by using Leech Blood or Invade Corpse to consume blood,
@@ -89,6 +88,10 @@ export const AntagInfoBloodWorm = (props) => {
<Stack.Item>
<Section fill title="Weaknesses">
<LabeledList>
<LabeledList.Item label="Extreme Cold">
Your species is highly pressure and cold resistant, but extremely low pressures and temperatures can still harm you.
This doesn't apply to you while in a host and you can equip your host with a space suit to protect it too.
</LabeledList.Item>
<LabeledList.Item label="High Heat">
Your species is averse to heat and will rapidly burn up in hot environments. Your body is also flammable, so stay away from fires.
This weakness applies even while in a host, but can be covered by equipping your host with fire-resistant gear.
@@ -132,7 +135,7 @@ export const AntagInfoBloodWorm = (props) => {
You can use this as insurance to get a last ditch escape attempt.
</LabeledList.Item>
<LabeledList.Item label="Medbay Buffet">
Medbay's blood freezers are all-you-can-eat buffets for you! They are only half synthetic and their high volumes grant you a lot of growth.
Medbay's blood freezers can be a decent source of synthetic blood if you can't find any monkeys.
Be careful of nearby crew, as the sounds of breaking freezers can travel through walls.
</LabeledList.Item>
<LabeledList.Item label="Fast Food">