diff --git a/code/datums/elements/body_temp_sensitive.dm b/code/datums/elements/body_temp_sensitive.dm index b48136185ff..139a321e84c 100644 --- a/code/datums/elements/body_temp_sensitive.dm +++ b/code/datums/elements/body_temp_sensitive.dm @@ -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) diff --git a/code/datums/elements/pressure_sensitive.dm b/code/datums/elements/pressure_sensitive.dm new file mode 100644 index 00000000000..744a5cddab5 --- /dev/null +++ b/code/datums/elements/pressure_sensitive.dm @@ -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,") diff --git a/code/modules/antagonists/blood_worm/blood_worm_mob.dm b/code/modules/antagonists/blood_worm/blood_worm_mob.dm index 44b5f662f84..4d647d7740a 100644 --- a/code/modules/antagonists/blood_worm/blood_worm_mob.dm +++ b/code/modules/antagonists/blood_worm/blood_worm_mob.dm @@ -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 diff --git a/tgstation.dme b/tgstation.dme index 101a530db89..6088eb5ac60 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -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" diff --git a/tgui/packages/tgui/interfaces/AntagInfoBloodWorm.tsx b/tgui/packages/tgui/interfaces/AntagInfoBloodWorm.tsx index 349f209d3a2..ac668399a19 100644 --- a/tgui/packages/tgui/interfaces/AntagInfoBloodWorm.tsx +++ b/tgui/packages/tgui/interfaces/AntagInfoBloodWorm.tsx @@ -40,9 +40,8 @@ export const AntagInfoBloodWorm = (props) => {
- - 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. + + You don't need to breathe. This extends to your hosts as well. You can grow by using Leech Blood or Invade Corpse to consume blood, @@ -89,6 +88,10 @@ export const AntagInfoBloodWorm = (props) => {
+ + 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. + 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. - 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.