refactor: Moves simplemob atmos and temperature requirements to DCS elements. (#25619)

* refactor: elementize simplemob homeostasis

* undef these bad boys

* ugh

* Fix up comments

Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Signed-off-by: warriorstar-orion <orion@snowfrost.garden>

* update element var name

* Update code/modules/mob/living/simple_animal/simple_animal.dm

Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com>

---------

Signed-off-by: warriorstar-orion <orion@snowfrost.garden>
Signed-off-by: Burzah <116982774+Burzah@users.noreply.github.com>
Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
warriorstar-orion
2024-08-15 23:07:43 +00:00
committed by GitHub
co-authored by Luc Burzah
parent bd91a1b962
commit 90e52f70e8
6 changed files with 170 additions and 58 deletions
+4
View File
@@ -550,6 +550,10 @@
#define COMSIG_LIVING_WRITE_MEMORY "living_write_memory"
#define COMPONENT_DONT_WRITE_MEMORY (1<<0)
// /mob/living/simple_animal signals
///from /mob/living/simple_animal/handle_environment()
#define COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT "simpleanimal_handle_environment"
// /mob/living/carbon signals
///from base of mob/living/carbon/soundbang_act(): (list(intensity))
@@ -0,0 +1,73 @@
/**
* Bespoke element that deals damage to the attached mob when the atmos requirements aren't satisfied
*/
/datum/element/atmos_requirements
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// An assoc list of "what atmos does this mob require to survive in".
var/list/atmos_requirements
/// How much (brute) damage we take from being in unsuitable atmos.
var/unsuitable_atmos_damage
/datum/element/atmos_requirements/Attach(datum/target, list/atmos_requirements_, unsuitable_atmos_damage_ = 5)
. = ..()
if(!issimple_animal(target))
return ELEMENT_INCOMPATIBLE
if(!atmos_requirements_)
stack_trace("[type] added to [target] without any requirements specified.")
atmos_requirements = atmos_requirements_
unsuitable_atmos_damage = unsuitable_atmos_damage_
RegisterSignal(target, COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT, PROC_REF(handle_environment))
/datum/element/atmos_requirements/Detach(datum/target)
UnregisterSignal(target, COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT)
return ..()
/datum/element/atmos_requirements/proc/handle_environment(mob/living/simple_animal/target, datum/gas_mixture/readonly_environment)
SIGNAL_HANDLER // COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT
if(!readonly_environment)
return
var/atmos_suitable = TRUE
var/tox = readonly_environment.toxins()
var/oxy = readonly_environment.oxygen()
var/n2 = readonly_environment.nitrogen()
var/co2 = readonly_environment.carbon_dioxide()
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
atmos_suitable = FALSE
target.throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"])
atmos_suitable = FALSE
target.throw_alert("too_much_oxy", /atom/movable/screen/alert/too_much_oxy)
else
target.clear_alert("not_enough_oxy")
target.clear_alert("too_much_oxy")
if(atmos_requirements["min_tox"] && tox < atmos_requirements["min_tox"])
atmos_suitable = FALSE
target.throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox)
else if(atmos_requirements["max_tox"] && tox > atmos_requirements["max_tox"])
atmos_suitable = FALSE
target.throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox)
else
target.clear_alert("too_much_tox")
target.clear_alert("not_enough_tox")
if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"])
atmos_suitable = FALSE
else if(atmos_requirements["max_n2"] && n2 > atmos_requirements["max_n2"])
atmos_suitable = FALSE
if(atmos_requirements["min_co2"] && co2 < atmos_requirements["min_co2"])
atmos_suitable = FALSE
else if(atmos_requirements["max_co2"] && co2 > atmos_requirements["max_co2"])
atmos_suitable = FALSE
if(!atmos_suitable)
target.adjustHealth(unsuitable_atmos_damage)
+68
View File
@@ -0,0 +1,68 @@
#define NONCARBON_DEFAULT_MIN_BODY_TEMP 250
#define NONCARBON_DEFAULT_MAX_BODY_TEMP 350
#define NONCARBON_DEFAULT_COLD_DAMAGE 2
#define NONCARBON_DEFAULT_HEAT_DAMAGE 2
/**
* Bespoke element that deals damage to the attached mob when the ambient temperature is unsuitable.
*/
/datum/element/body_temperature
element_flags = ELEMENT_BESPOKE
argument_hash_start_idx = 2
/// Min body temp
var/min_body_temp = NONCARBON_DEFAULT_MIN_BODY_TEMP
/// Max body temp
var/max_body_temp = NONCARBON_DEFAULT_MAX_BODY_TEMP
//// Damage when below min temp
var/cold_damage_per_tick = NONCARBON_DEFAULT_COLD_DAMAGE
/// Damage when above max temp
var/heat_damage_per_tick = NONCARBON_DEFAULT_HEAT_DAMAGE
/datum/element/body_temperature/Attach(datum/target, min_body_temp_, max_body_temp_, cold_damage_per_tick_, heat_damage_per_tick_)
. = ..()
if(!issimple_animal(target))
return ELEMENT_INCOMPATIBLE
if(isnum(min_body_temp))
min_body_temp = min_body_temp_
if(isnum(max_body_temp))
max_body_temp = max_body_temp_
if(isnum(cold_damage_per_tick))
cold_damage_per_tick = cold_damage_per_tick_
if(isnum(heat_damage_per_tick))
heat_damage_per_tick = heat_damage_per_tick_
RegisterSignal(target, COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT, PROC_REF(handle_temperature))
/datum/element/body_temperature/Detach(datum/target)
UnregisterSignal(target, COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT)
return ..()
/datum/element/body_temperature/proc/handle_temperature(mob/living/simple_animal/target, datum/gas_mixture/readonly_environment)
SIGNAL_HANDLER // COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT
if(!readonly_environment)
return
var/areatemp = target.get_temperature(readonly_environment)
if(abs(areatemp - target.bodytemperature) > 5 && !HAS_TRAIT(src, TRAIT_NOBREATH))
var/diff = areatemp - target.bodytemperature
diff = diff / 5
target.bodytemperature += diff
if(target.bodytemperature < min_body_temp)
target.adjustHealth(cold_damage_per_tick)
else if(target.bodytemperature > max_body_temp)
target.adjustHealth(heat_damage_per_tick)
#undef NONCARBON_DEFAULT_MIN_BODY_TEMP
#undef NONCARBON_DEFAULT_MAX_BODY_TEMP
#undef NONCARBON_DEFAULT_COLD_DAMAGE
#undef NONCARBON_DEFAULT_HEAT_DAMAGE
+2 -1
View File
@@ -116,7 +116,8 @@
/mob/living/proc/handle_random_events()
return
/mob/living/proc/handle_environment(datum/gas_mixture/environment)
/// Handle temperature/pressure differences between body and environment
/mob/living/proc/handle_environment()
return
/mob/living/proc/update_pulling()
@@ -162,6 +162,9 @@
AddComponent(/datum/component/footstep, footstep_type)
add_strippable_element()
apply_atmos_requirements()
AddElement(/datum/element/body_temperature, minbodytemp, maxbodytemp, cold_damage_per_tick, heat_damage_per_tick)
/mob/living/simple_animal/Destroy()
/// We need to clear the reference to where we're walking to properly GC
walk_to(src, 0)
@@ -181,8 +184,25 @@
if(T && AIStatus == AI_Z_OFF)
SSidlenpcpool.idle_mobs_by_zlevel[T.z] -= src
remove_atmos_requirements()
RemoveElement(/datum/element/body_temperature)
return ..()
/mob/living/simple_animal/proc/apply_atmos_requirements()
if(unsuitable_atmos_damage == 0)
return
/*
* String associated list returns a cached list.
* This is like a static list to pass into the element below.
*/
atmos_requirements = string_assoc_list(atmos_requirements)
AddElement(/datum/element/atmos_requirements, atmos_requirements, unsuitable_atmos_damage)
/mob/living/simple_animal/proc/remove_atmos_requirements()
RemoveElement(/datum/element/atmos_requirements)
/mob/living/simple_animal/handle_atom_del(atom/A)
if(A == pcollar)
pcollar = null
@@ -288,64 +308,8 @@
else
custom_emote(EMOTE_AUDIBLE, pick(emote_hear))
/mob/living/simple_animal/handle_environment(datum/gas_mixture/readonly_environment)
if(!readonly_environment)
return
var/atmos_suitable = 1
var/areatemp = get_temperature(readonly_environment)
if(abs(areatemp - bodytemperature) > 5 && !HAS_TRAIT(src, TRAIT_NOBREATH))
var/diff = areatemp - bodytemperature
diff = diff / 5
bodytemperature += diff
var/tox = readonly_environment.toxins()
var/oxy = readonly_environment.oxygen()
var/n2 = readonly_environment.nitrogen()
var/co2 = readonly_environment.carbon_dioxide()
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
atmos_suitable = 0
throw_alert("not_enough_oxy", /atom/movable/screen/alert/not_enough_oxy)
else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"])
atmos_suitable = 0
throw_alert("too_much_oxy", /atom/movable/screen/alert/too_much_oxy)
else
clear_alert("not_enough_oxy")
clear_alert("too_much_oxy")
if(atmos_requirements["min_tox"] && tox < atmos_requirements["min_tox"])
atmos_suitable = 0
throw_alert("not_enough_tox", /atom/movable/screen/alert/not_enough_tox)
else if(atmos_requirements["max_tox"] && tox > atmos_requirements["max_tox"])
atmos_suitable = 0
throw_alert("too_much_tox", /atom/movable/screen/alert/too_much_tox)
else
clear_alert("too_much_tox")
clear_alert("not_enough_tox")
if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"])
atmos_suitable = 0
else if(atmos_requirements["max_n2"] && n2 > atmos_requirements["max_n2"])
atmos_suitable = 0
if(atmos_requirements["min_co2"] && co2 < atmos_requirements["min_co2"])
atmos_suitable = 0
else if(atmos_requirements["max_co2"] && co2 > atmos_requirements["max_co2"])
atmos_suitable = 0
if(!atmos_suitable)
adjustHealth(unsuitable_atmos_damage)
handle_temperature_damage()
/mob/living/simple_animal/proc/handle_temperature_damage()
if(bodytemperature < minbodytemp)
adjustHealth(cold_damage_per_tick)
else if(bodytemperature > maxbodytemp)
adjustHealth(heat_damage_per_tick)
SEND_SIGNAL(src, COMSIG_SIMPLEANIMAL_HANDLE_ENVIRONMENT, readonly_environment)
/mob/living/simple_animal/gib()
if(icon_gib)