mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-29 08:08:49 +01:00
Add a unit test to check that maploaded simple/basic mobs are in an environment they can survive in. (#82180)
## About The Pull Request I've recently noticed that the maploaded penguins from the snowdin away mission were dying from unsafe atmos/temperature. This sparked the idea of making a (focus only) unit test that would prevent this sort of issues from happening. This PR also implements the usage of the `atmos_requirements` and `body_temp_sensitive` elements for simple animals too, cutting down the copypaste. ## Why It's Good For The Game More unit tests to make sure things are done correctly. ## Changelog 🆑 fix: Made sure that mapped critters (i.e. penguins on the snow cabin away mission) can survive in the environment they're spawned in. /🆑
This commit is contained in:
@@ -2601,9 +2601,7 @@
|
||||
pixel_x = 15;
|
||||
pixel_y = 14
|
||||
},
|
||||
/mob/living/basic/frog{
|
||||
name = "Peter Jr."
|
||||
},
|
||||
/mob/living/basic/frog/icemoon_facility,
|
||||
/turf/open/floor/plating/icemoon,
|
||||
/area/ruin/plasma_facility/operations)
|
||||
"TK" = (
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
},
|
||||
/area/ruin/unpowered/buried_library)
|
||||
"aO" = (
|
||||
/mob/living/basic/pet/fox,
|
||||
/mob/living/basic/pet/fox/icemoon,
|
||||
/turf/open/floor/wood{
|
||||
initial_gas_mix = "ICEMOON_ATMOS"
|
||||
},
|
||||
@@ -327,7 +327,7 @@
|
||||
/area/ruin/unpowered/buried_library)
|
||||
"cA" = (
|
||||
/obj/effect/decal/cleanable/dirt,
|
||||
/mob/living/basic/pet/fox,
|
||||
/mob/living/basic/pet/fox/icemoon,
|
||||
/turf/open/floor/wood{
|
||||
initial_gas_mix = "ICEMOON_ATMOS"
|
||||
},
|
||||
@@ -394,7 +394,7 @@
|
||||
/obj/structure/fluff/paper{
|
||||
dir = 1
|
||||
},
|
||||
/mob/living/basic/pet/fox,
|
||||
/mob/living/basic/pet/fox/icemoon,
|
||||
/turf/open/floor/wood{
|
||||
initial_gas_mix = "ICEMOON_ATMOS"
|
||||
},
|
||||
|
||||
@@ -208,9 +208,7 @@
|
||||
"nq" = (
|
||||
/obj/effect/decal/cleanable/cobweb,
|
||||
/obj/machinery/light/small/directional/north,
|
||||
/mob/living/basic/pet/dog/bullterrier{
|
||||
name = "Saint Nick's Helpful Associate"
|
||||
},
|
||||
/mob/living/basic/pet/dog/bullterrier/lavaland_party,
|
||||
/turf/open/floor/carpet/blue/lavaland,
|
||||
/area/ruin/unpowered)
|
||||
"nI" = (
|
||||
|
||||
@@ -3002,7 +3002,7 @@
|
||||
set_luminosity = 6;
|
||||
light_color = "#9bbbff"
|
||||
},
|
||||
/mob/living/basic/pet/penguin/baby/permanent,
|
||||
/mob/living/basic/pet/penguin/baby/permanent/snowdin,
|
||||
/turf/open/misc/ice/smooth,
|
||||
/area/awaymission/cabin/snowforest)
|
||||
"sK" = (
|
||||
@@ -3725,7 +3725,7 @@
|
||||
set_luminosity = 6;
|
||||
light_color = "#9bbbff"
|
||||
},
|
||||
/mob/living/basic/pet/penguin/emperor,
|
||||
/mob/living/basic/pet/penguin/emperor/snowdin,
|
||||
/turf/open/misc/ice/smooth,
|
||||
/area/awaymission/cabin/snowforest)
|
||||
"Aa" = (
|
||||
|
||||
@@ -1260,7 +1260,7 @@
|
||||
},
|
||||
/area/awaymission/caves/bmp_asteroid/level_two)
|
||||
"kE" = (
|
||||
/mob/living/basic/spider/giant/hunter,
|
||||
/mob/living/basic/spider/giant/hunter/away_caves,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/caves/bmp_asteroid)
|
||||
"kL" = (
|
||||
@@ -1332,7 +1332,7 @@
|
||||
/area/awaymission/caves/northblock)
|
||||
"pC" = (
|
||||
/obj/item/mjollnir,
|
||||
/mob/living/basic/spider/giant/nurse,
|
||||
/mob/living/basic/spider/giant/nurse/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
@@ -1432,7 +1432,7 @@
|
||||
/obj/machinery/sleeper{
|
||||
dir = 8
|
||||
},
|
||||
/mob/living/basic/spider/giant/hunter,
|
||||
/mob/living/basic/spider/giant/hunter/away_caves,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/caves/bmp_asteroid)
|
||||
"uO" = (
|
||||
@@ -1590,7 +1590,7 @@
|
||||
},
|
||||
/area/awaymission/caves/bmp_asteroid/level_two)
|
||||
"Bz" = (
|
||||
/mob/living/basic/spider/giant/nurse,
|
||||
/mob/living/basic/spider/giant/nurse/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
@@ -1672,7 +1672,7 @@
|
||||
"FS" = (
|
||||
/obj/machinery/light/small/built/directional/north,
|
||||
/obj/structure/spider/stickyweb,
|
||||
/mob/living/basic/spider/giant/hunter,
|
||||
/mob/living/basic/spider/giant/hunter/away_caves,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/caves/bmp_asteroid)
|
||||
"FV" = (
|
||||
@@ -1856,10 +1856,7 @@
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/caves/listeningpost)
|
||||
"Qe" = (
|
||||
/mob/living/basic/bat{
|
||||
desc = "A rare breed of bat which roosts deep in caves.";
|
||||
name = "Cave Bat"
|
||||
},
|
||||
/mob/living/basic/bat/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
@@ -1871,10 +1868,7 @@
|
||||
},
|
||||
/area/awaymission/caves/bmp_asteroid/level_four)
|
||||
"Rt" = (
|
||||
/mob/living/basic/bat{
|
||||
desc = "A rare breed of bat which roosts deep in caves.";
|
||||
name = "Cave Bat"
|
||||
},
|
||||
/mob/living/basic/bat/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
@@ -1951,14 +1945,11 @@
|
||||
/turf/open/floor/iron/recharge_floor,
|
||||
/area/awaymission/caves/bmp_asteroid)
|
||||
"Xa" = (
|
||||
/mob/living/basic/bat{
|
||||
desc = "A rare breed of bat which roosts deep in caves.";
|
||||
name = "Cave Bat"
|
||||
},
|
||||
/mob/living/basic/bat/away_caves,
|
||||
/turf/open/floor/iron,
|
||||
/area/awaymission/caves/northblock)
|
||||
"Xs" = (
|
||||
/mob/living/basic/spider/giant/hunter,
|
||||
/mob/living/basic/spider/giant/hunter/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
@@ -1980,7 +1971,7 @@
|
||||
/area/awaymission/caves/bmp_asteroid/level_two)
|
||||
"XR" = (
|
||||
/obj/structure/spider/stickyweb,
|
||||
/mob/living/basic/spider/giant/hunter,
|
||||
/mob/living/basic/spider/giant/hunter/away_caves,
|
||||
/turf/open/misc/asteroid/basalt{
|
||||
initial_gas_mix = "n2=23;o2=14;TEMP=2.7"
|
||||
},
|
||||
|
||||
@@ -57,7 +57,7 @@ PROCESSING_SUBSYSTEM_DEF(dcs)
|
||||
var/datum/element/eletype = arguments[1]
|
||||
var/list/fullid = list(eletype)
|
||||
var/list/named_arguments
|
||||
for(var/i in initial(eletype.argument_hash_start_idx) to length(arguments))
|
||||
for(var/i in initial(eletype.argument_hash_start_idx) to (initial(eletype.argument_hash_end_idx) || length(arguments)))
|
||||
var/key = arguments[i]
|
||||
|
||||
if(istext(key))
|
||||
|
||||
@@ -10,14 +10,20 @@
|
||||
/**
|
||||
* The index of the first attach argument to consider for duplicate elements
|
||||
*
|
||||
* All arguments from this index onwards (1 based) are hashed into the key to determine
|
||||
* if this is a new unique element or one already exists
|
||||
* All arguments from this index onwards (1 based, until `argument_hash_end_idx` is reached, if set)
|
||||
* are hashed into the key to determine if this is a new unique element or one already exists
|
||||
*
|
||||
* Is only used when flags contains [ELEMENT_BESPOKE]
|
||||
*
|
||||
* This is infinity so you must explicitly set this
|
||||
*/
|
||||
var/argument_hash_start_idx = INFINITY
|
||||
/**
|
||||
* The index of the last attach argument to consider for duplicate elements
|
||||
* Only used when `element_flags` contains [ELEMENT_BESPOKE].
|
||||
* If not set, it'll copy every argument from `argument_hash_start_idx` onwards as normal
|
||||
*/
|
||||
var/argument_hash_end_idx = 0
|
||||
|
||||
/// Activates the functionality defined by the element on the given target datum
|
||||
/datum/element/proc/Attach(datum/target)
|
||||
|
||||
@@ -6,21 +6,29 @@
|
||||
/datum/element/atmos_requirements
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
argument_hash_end_idx = 3
|
||||
/// 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)
|
||||
/datum/element/atmos_requirements/Attach(datum/target, list/atmos_requirements, unsuitable_atmos_damage = 5, mapload = FALSE)
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
if(!atmos_requirements)
|
||||
stack_trace("[type] added to [target] without any requirements specified.")
|
||||
CRASH("[type] added to [target] without any requirements specified.")
|
||||
var/list/short = atmos_requirements
|
||||
if(!short["min_oxy"] && !short["max_oxy"] && !short["min_plas"] && !short["max_plas"] && !short["min_co2"] && !short["max_co2"] && !short["min_n2"] && !short["max_n2"])
|
||||
CRASH("[type] added to [target] with all requirements set to 0.")
|
||||
src.atmos_requirements = atmos_requirements
|
||||
src.unsuitable_atmos_damage = unsuitable_atmos_damage
|
||||
RegisterSignal(target, COMSIG_LIVING_HANDLE_BREATHING, PROC_REF(on_non_stasis_life))
|
||||
|
||||
if(!mapload || !PERFORM_ALL_TESTS(focus_only/atmos_and_temp_requirements))
|
||||
return
|
||||
check_safe_environment(target)
|
||||
|
||||
/datum/element/atmos_requirements/Detach(datum/target)
|
||||
. = ..()
|
||||
UnregisterSignal(target, COMSIG_LIVING_HANDLE_BREATHING)
|
||||
@@ -42,34 +50,45 @@
|
||||
return TRUE
|
||||
|
||||
var/turf/open/open_turf = target.loc
|
||||
if(!open_turf.air && (atmos_requirements["min_oxy"] || atmos_requirements["min_tox"] || atmos_requirements["min_n2"] || atmos_requirements["min_co2"]))
|
||||
return FALSE
|
||||
if(isnull(open_turf.air))
|
||||
if(atmos_requirements["min_oxy"] || atmos_requirements["min_plas"] || atmos_requirements["min_n2"] || atmos_requirements["min_co2"])
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
var/list/gases = get_atmos_req_list(open_turf)
|
||||
|
||||
if(!ISINRANGE(gases["oxy"], atmos_requirements["min_oxy"], (atmos_requirements["max_oxy"] || INFINITY)))
|
||||
return FALSE
|
||||
if(!ISINRANGE(gases["plas"], atmos_requirements["min_plas"], (atmos_requirements["max_plas"] || INFINITY)))
|
||||
return FALSE
|
||||
if(!ISINRANGE(gases["n2"], atmos_requirements["min_n2"], (atmos_requirements["max_n2"] || INFINITY)))
|
||||
return FALSE
|
||||
if(!ISINRANGE(gases["co2"], atmos_requirements["min_co2"], (atmos_requirements["max_co2"] || INFINITY)))
|
||||
return FALSE
|
||||
return TRUE
|
||||
|
||||
/datum/element/atmos_requirements/proc/get_atmos_req_list(turf/open/open_turf)
|
||||
var/open_turf_gases = open_turf.air.gases
|
||||
open_turf.air.assert_gases(/datum/gas/oxygen, /datum/gas/pluoxium, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)
|
||||
|
||||
var/plas = open_turf_gases[/datum/gas/plasma][MOLES]
|
||||
var/oxy = open_turf_gases[/datum/gas/oxygen][MOLES] + (open_turf_gases[/datum/gas/pluoxium][MOLES] * PLUOXIUM_PROPORTION)
|
||||
var/n2 = open_turf_gases[/datum/gas/nitrogen][MOLES]
|
||||
var/co2 = open_turf_gases[/datum/gas/carbon_dioxide][MOLES]
|
||||
var/list/return_gases = list()
|
||||
return_gases["plas"] = open_turf_gases[/datum/gas/plasma][MOLES]
|
||||
return_gases["oxy"] = open_turf_gases[/datum/gas/oxygen][MOLES] + (open_turf_gases[/datum/gas/pluoxium][MOLES] * PLUOXIUM_PROPORTION)
|
||||
return_gases["n2"] = open_turf_gases[/datum/gas/nitrogen][MOLES]
|
||||
return_gases["co2"] = open_turf_gases[/datum/gas/carbon_dioxide][MOLES]
|
||||
|
||||
open_turf.air.garbage_collect()
|
||||
|
||||
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["min_plas"] && plas < atmos_requirements["min_plas"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["max_plas"] && plas > atmos_requirements["max_plas"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["max_n2"] && n2 > atmos_requirements["max_n2"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["min_co2"] && co2 < atmos_requirements["min_co2"])
|
||||
return FALSE
|
||||
else if(atmos_requirements["max_co2"] && co2 > atmos_requirements["max_co2"])
|
||||
return FALSE
|
||||
return return_gases
|
||||
|
||||
return TRUE
|
||||
///Ensures that maploaded mobs are in a safe environment. Unit test stuff.
|
||||
/datum/element/atmos_requirements/proc/check_safe_environment(mob/living/living_mob)
|
||||
if(living_mob.stat == DEAD || is_breathable_atmos(living_mob))
|
||||
return
|
||||
var/turf/open/open_turf = living_mob.loc
|
||||
var/list/gases
|
||||
var/string_text = "No Air"
|
||||
if(open_turf.air)
|
||||
gases = get_atmos_req_list(open_turf)
|
||||
string_text = "O2: [gases["o2"]] - Plasma: [gases["plasma"]] - N2: [gases["n2"]] - CO2: [gases["co2"]]"
|
||||
stack_trace("[living_mob] loaded on a turf with unsafe atmos at \[[open_turf.x], [open_turf.y], [open_turf.z]\] (area : [open_turf.loc]). Turf gases: [string_text]. Check the mob atmos requirements again.")
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
/**
|
||||
* When attached to a basic mob, it gives it the ability to be hurt by cold/hot body temperatures
|
||||
*/
|
||||
/datum/element/basic_body_temp_sensitive
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
|
||||
///Min body temp
|
||||
var/min_body_temp = 250
|
||||
///Max body temp
|
||||
var/max_body_temp = 350
|
||||
////Damage when below min temp
|
||||
var/cold_damage = 1
|
||||
///Damage when above max temp
|
||||
var/heat_damage = 1
|
||||
|
||||
/datum/element/basic_body_temp_sensitive/Attach(datum/target, min_body_temp, max_body_temp, cold_damage, heat_damage)
|
||||
. = ..()
|
||||
if(!isbasicmob(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
if(isnum(min_body_temp))
|
||||
src.min_body_temp = min_body_temp
|
||||
|
||||
if(isnum(max_body_temp))
|
||||
src.max_body_temp = max_body_temp
|
||||
|
||||
if(isnum(cold_damage))
|
||||
src.cold_damage = cold_damage
|
||||
|
||||
if(isnum(heat_damage))
|
||||
src.heat_damage = heat_damage
|
||||
|
||||
RegisterSignal(target, COMSIG_LIVING_LIFE, PROC_REF(on_life))
|
||||
|
||||
/datum/element/basic_body_temp_sensitive/Detach(datum/source)
|
||||
if(source)
|
||||
UnregisterSignal(source, COMSIG_LIVING_LIFE)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/element/basic_body_temp_sensitive/proc/on_life(datum/target, seconds_per_tick, times_fired)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/basic/basic_mob = target
|
||||
var/gave_alert = FALSE
|
||||
|
||||
if(basic_mob.bodytemperature < min_body_temp)
|
||||
basic_mob.adjust_health(cold_damage * seconds_per_tick)
|
||||
if(!basic_mob.has_status_effect(/datum/status_effect/inebriated))
|
||||
switch(cold_damage)
|
||||
if(1 to 5)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1)
|
||||
if(5 to 10)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2)
|
||||
if(10 to INFINITY)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3)
|
||||
gave_alert = TRUE
|
||||
|
||||
else if(basic_mob.bodytemperature > max_body_temp)
|
||||
basic_mob.adjust_health(heat_damage * seconds_per_tick)
|
||||
switch(heat_damage)
|
||||
if(1 to 5)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1)
|
||||
if(5 to 10)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2)
|
||||
if(10 to INFINITY)
|
||||
basic_mob.throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3)
|
||||
gave_alert = TRUE
|
||||
|
||||
if(!gave_alert)
|
||||
basic_mob.clear_alert(ALERT_TEMPERATURE)
|
||||
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* When attached to a basic mob, it gives it the ability to be hurt by cold/hot body temperatures
|
||||
*/
|
||||
/datum/element/body_temp_sensitive
|
||||
element_flags = ELEMENT_BESPOKE
|
||||
argument_hash_start_idx = 2
|
||||
argument_hash_end_idx = 5
|
||||
|
||||
///Min body temp
|
||||
var/min_body_temp = 250
|
||||
///Max body temp
|
||||
var/max_body_temp = 350
|
||||
////Damage when below min temp
|
||||
var/cold_damage = 1
|
||||
///Damage when above max temp
|
||||
var/heat_damage = 1
|
||||
|
||||
/datum/element/body_temp_sensitive/Attach(datum/target, min_body_temp, max_body_temp, cold_damage, heat_damage, mapload = FALSE)
|
||||
. = ..()
|
||||
if(!isliving(target))
|
||||
return ELEMENT_INCOMPATIBLE
|
||||
|
||||
if(isnum(min_body_temp))
|
||||
src.min_body_temp = min_body_temp
|
||||
|
||||
if(isnum(max_body_temp))
|
||||
src.max_body_temp = max_body_temp
|
||||
|
||||
if(isnum(cold_damage))
|
||||
src.cold_damage = cold_damage
|
||||
|
||||
if(isnum(heat_damage))
|
||||
src.heat_damage = heat_damage
|
||||
|
||||
RegisterSignal(target, COMSIG_LIVING_LIFE, PROC_REF(on_life))
|
||||
|
||||
if(!mapload || !PERFORM_ALL_TESTS(focus_only/atmos_and_temp_requirements))
|
||||
return
|
||||
check_safe_environment(target)
|
||||
|
||||
/datum/element/body_temp_sensitive/Detach(datum/source)
|
||||
if(source)
|
||||
UnregisterSignal(source, COMSIG_LIVING_LIFE)
|
||||
return ..()
|
||||
|
||||
/datum/element/body_temp_sensitive/proc/on_life(datum/target, seconds_per_tick, times_fired)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/mob/living/living_mob = target
|
||||
var/gave_alert = FALSE
|
||||
|
||||
if(living_mob.bodytemperature < min_body_temp)
|
||||
living_mob.adjustFireLoss(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)
|
||||
gave_alert = TRUE
|
||||
|
||||
else if(living_mob.bodytemperature > max_body_temp)
|
||||
living_mob.adjustFireLoss(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)
|
||||
gave_alert = TRUE
|
||||
|
||||
if(!gave_alert)
|
||||
living_mob.clear_alert(ALERT_TEMPERATURE)
|
||||
|
||||
///Ensures that maploaded mobs are in a safe environment. Unit test stuff.
|
||||
/datum/element/body_temp_sensitive/proc/check_safe_environment(mob/living/living_mob)
|
||||
if(living_mob.stat == DEAD)
|
||||
return
|
||||
var/atom/location = living_mob.loc
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
var/areatemp = living_mob.get_temperature(environment)
|
||||
if(!ISINRANGE(areatemp, min_body_temp, max_body_temp))
|
||||
stack_trace("[living_mob] loaded on in a loc with unsafe temperature at \[[location.x], [location.y], [location.z]\] (area : [get_area(location)]): [areatemp]K. Acceptable Range: [min_body_temp]K - [max_body_temp]K,")
|
||||
@@ -134,6 +134,13 @@
|
||||
/obj/effect/spawner/random/trash/cigbutt = 2,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/random/trash/grime/Initialize(mapload)
|
||||
if(mapload)
|
||||
var/turf/location = get_turf(loc)
|
||||
if(location.initial_gas_mix != OPENTURF_DEFAULT_ATMOS && location.initial_gas_mix != OPENTURF_DIRTY_ATMOS)
|
||||
loot -= /mob/living/basic/cockroach
|
||||
return ..()
|
||||
|
||||
/obj/effect/spawner/random/trash/moisture
|
||||
name = "water hazard spawner"
|
||||
icon_state = "caution"
|
||||
@@ -150,6 +157,13 @@
|
||||
/mob/living/basic/axolotl = 1,
|
||||
)
|
||||
|
||||
/obj/effect/spawner/random/trash/moisture/Initialize(mapload)
|
||||
if(mapload)
|
||||
var/turf/location = get_turf(loc)
|
||||
if(location.initial_gas_mix != OPENTURF_DEFAULT_ATMOS && location.initial_gas_mix != OPENTURF_DIRTY_ATMOS)
|
||||
loot -= list(/mob/living/basic/frog, /mob/living/basic/axolotl)
|
||||
return ..()
|
||||
|
||||
/obj/effect/spawner/random/trash/graffiti
|
||||
name = "random graffiti spawner"
|
||||
icon_state = "rune"
|
||||
|
||||
@@ -172,8 +172,8 @@
|
||||
* Also used in other chat-based gas scans.
|
||||
*/
|
||||
/proc/atmos_scan(mob/user, atom/target, silent=FALSE)
|
||||
var/mixture = target.return_analyzable_air()
|
||||
if(!mixture)
|
||||
var/mixture = target.return_air()
|
||||
if(mixture)
|
||||
return FALSE
|
||||
|
||||
var/icon = target
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
speech_span = SPAN_ROBOT
|
||||
death_message = "malfunctions!"
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = TCMB
|
||||
ai_controller = /datum/ai_controller/basic_controller/netguardian
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
death_sound = 'sound/voice/hiss6.ogg'
|
||||
death_message = "lets out a waning guttural screech, green blood bubbling from its maw..."
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
unsuitable_atmos_damage = FALSE
|
||||
unsuitable_heat_damage = 20
|
||||
|
||||
|
||||
@@ -93,9 +93,9 @@
|
||||
var/minimum_survivable_temperature = NPC_DEFAULT_MIN_TEMP
|
||||
///Maximal body temperature without receiving damage
|
||||
var/maximum_survivable_temperature = NPC_DEFAULT_MAX_TEMP
|
||||
///This damage is taken when the body temp is too cold. Set both this and unsuitable_heat_damage to 0 to avoid adding the basic_body_temp_sensitive element.
|
||||
///This damage is taken when the body temp is too cold. Set both this and unsuitable_heat_damage to 0 to avoid adding the body_temp_sensitive element.
|
||||
var/unsuitable_cold_damage = 1
|
||||
///This damage is taken when the body temp is too hot. Set both this and unsuitable_cold_damage to 0 to avoid adding the basic_body_temp_sensitive element.
|
||||
///This damage is taken when the body temp is too hot. Set both this and unsuitable_cold_damage to 0 to avoid adding the body_temp_sensitive element.
|
||||
var/unsuitable_heat_damage = 1
|
||||
|
||||
/mob/living/basic/Initialize(mapload)
|
||||
@@ -115,23 +115,32 @@
|
||||
if(speak_emote)
|
||||
speak_emote = string_list(speak_emote)
|
||||
|
||||
apply_atmos_requirements()
|
||||
apply_temperature_requirements()
|
||||
///We need to wait for SSair to be initialized before we can check atmos/temp requirements.
|
||||
if(PERFORM_ALL_TESTS(focus_only/atmos_and_temp_requirements) && mapload && !SSair.initialized)
|
||||
RegisterSignal(SSair, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(on_ssair_init))
|
||||
return
|
||||
apply_atmos_requirements(mapload)
|
||||
apply_temperature_requirements(mapload)
|
||||
|
||||
/mob/living/basic/proc/on_ssair_init(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(SSair, COMSIG_SUBSYSTEM_POST_INITIALIZE)
|
||||
apply_atmos_requirements(TRUE)
|
||||
apply_temperature_requirements(TRUE)
|
||||
|
||||
/// Ensures this mob can take atmospheric damage if it's supposed to
|
||||
/mob/living/basic/proc/apply_atmos_requirements()
|
||||
if(unsuitable_atmos_damage == 0)
|
||||
/mob/living/basic/proc/apply_atmos_requirements(mapload)
|
||||
if(unsuitable_atmos_damage == 0 || isnull(habitable_atmos))
|
||||
return
|
||||
//String assoc list returns a cached list, so this is like a static list to pass into the element below.
|
||||
habitable_atmos = string_assoc_list(habitable_atmos)
|
||||
AddElement(/datum/element/atmos_requirements, habitable_atmos, unsuitable_atmos_damage)
|
||||
AddElement(/datum/element/atmos_requirements, habitable_atmos, unsuitable_atmos_damage, mapload)
|
||||
|
||||
/// Ensures this mob can take temperature damage if it's supposed to
|
||||
/mob/living/basic/proc/apply_temperature_requirements()
|
||||
if(unsuitable_cold_damage == 0 && unsuitable_heat_damage == 0)
|
||||
/mob/living/basic/proc/apply_temperature_requirements(mapload)
|
||||
if((unsuitable_cold_damage == 0 && unsuitable_heat_damage == 0) || (minimum_survivable_temperature <= 0 && maximum_survivable_temperature >= INFINITY))
|
||||
return
|
||||
AddElement(/datum/element/basic_body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage)
|
||||
|
||||
AddElement(/datum/element/body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage, mapload)
|
||||
|
||||
/mob/living/basic/Life(seconds_per_tick = SSMOBS_DT, times_fired)
|
||||
. = ..()
|
||||
@@ -219,7 +228,7 @@
|
||||
RemoveElement(/datum/element/atmos_requirements, habitable_atmos, unsuitable_atmos_damage)
|
||||
. = TRUE
|
||||
if(NAMEOF(src, minimum_survivable_temperature), NAMEOF(src, maximum_survivable_temperature), NAMEOF(src, unsuitable_cold_damage), NAMEOF(src, unsuitable_heat_damage))
|
||||
RemoveElement(/datum/element/basic_body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage)
|
||||
RemoveElement(/datum/element/body_temp_sensitive, minimum_survivable_temperature, maximum_survivable_temperature, unsuitable_cold_damage, unsuitable_heat_damage)
|
||||
. = TRUE
|
||||
|
||||
. = ..()
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
combat_mode = TRUE
|
||||
bubble_icon = "blob"
|
||||
speak_emote = null
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = INFINITY
|
||||
lighting_cutoff_red = 20
|
||||
|
||||
@@ -16,7 +16,7 @@ GLOBAL_LIST_INIT(command_strings, list(
|
||||
icon_state = "medibot0"
|
||||
base_icon_state = "medibot"
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0)
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_PATH_HUD = HUD_LIST_LIST)
|
||||
maximum_survivable_temperature = INFINITY
|
||||
minimum_survivable_temperature = 0
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
can_be_held = TRUE
|
||||
held_w_class = WEIGHT_CLASS_TINY
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
basic_mob_flags = DEL_ON_DEATH
|
||||
ai_controller = /datum/ai_controller/basic_controller/bee
|
||||
///the reagent the bee has
|
||||
|
||||
@@ -49,5 +49,5 @@
|
||||
|
||||
/// Cold resistent and doesn't need to breathe
|
||||
/mob/living/basic/deer/ice
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
|
||||
@@ -129,7 +129,7 @@
|
||||
faction = list(ROLE_SYNDICATE)
|
||||
ponycolors = list("#5d566f", COLOR_RED)
|
||||
pressure_resistance = 200
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
unique_tamer = TRUE
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
gender = NEUTER
|
||||
mob_biotypes = NONE
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0)
|
||||
speed = 0
|
||||
melee_attack_cooldown = CLICK_CD_MELEE
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
pixel_x = -16
|
||||
base_pixel_x = -16
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
faction = list(FACTION_JUNGLE)
|
||||
obj_damage = 30
|
||||
environment_smash = ENVIRONMENT_SMASH_WALLS
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
attack_sound = 'sound/creatures/venus_trap_hit.ogg'
|
||||
unsuitable_heat_damage = 5 // heat damage is different from cold damage since coldmos is significantly more common than plasmafires
|
||||
unsuitable_cold_damage = 2 // they now do take cold damage, but this should be sufficiently small that it does not cause major issues
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
unsuitable_atmos_damage = 0
|
||||
/// copied over from the code from eyeballs (the mob) to make it easier for venus human traps to see in kudzu that doesn't have the transparency mutation
|
||||
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
status_flags = CANSTUN|CANKNOCKDOWN|CANPUSH
|
||||
mouse_opacity = MOUSE_OPACITY_ICON
|
||||
combat_mode = TRUE
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
health = 125
|
||||
maxHealth = 125
|
||||
|
||||
@@ -38,6 +38,13 @@
|
||||
collar_icon_state = "bullterrier"
|
||||
held_state = "bullterrier"
|
||||
|
||||
/mob/living/basic/pet/dog/bullterrier/lavaland_party
|
||||
name = "Saint Nick's Helpful Associate"
|
||||
desc = "Undergraduate in 'Being a Good Boy'."
|
||||
habitable_atmos = null
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
unique_pet = TRUE
|
||||
|
||||
/mob/living/basic/pet/dog/breaddog //Most of the code originates from Cak
|
||||
name = "Kobun"
|
||||
real_name = "Kobun"
|
||||
|
||||
@@ -72,3 +72,10 @@
|
||||
// A more docile subtype that won't attack other animals.
|
||||
/mob/living/basic/pet/fox/docile
|
||||
ai_controller = /datum/ai_controller/basic_controller/fox/docile
|
||||
|
||||
/mob/living/basic/pet/fox/icemoon
|
||||
name = "icemoon fox"
|
||||
desc = "A fox, scraping by the icemoon hostile atmosphere."
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = ICEBOX_MIN_TEMPERATURE
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
light_range = 6
|
||||
light_color = "#64bee1"
|
||||
health = 100
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
unsuitable_atmos_damage = 0
|
||||
can_buckle_to = FALSE
|
||||
density = FALSE
|
||||
|
||||
@@ -196,4 +196,10 @@
|
||||
/mob/living/basic/pet/penguin/baby/permanent
|
||||
can_grow_up = FALSE
|
||||
|
||||
/mob/living/basic/pet/penguin/emperor/snowdin
|
||||
minimum_survivable_temperature = ICEBOX_MIN_TEMPERATURE
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/mob/living/basic/pet/penguin/baby/permanent/snowdin
|
||||
minimum_survivable_temperature = ICEBOX_MIN_TEMPERATURE
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
faction = list(FACTION_RUSSIAN)
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = TCMB
|
||||
maximum_survivable_temperature = T0C + 1500
|
||||
ai_controller = /datum/ai_controller/basic_controller/bear
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
butcher_results = list(/obj/item/food/fishmeat/carp = 2, /obj/item/stack/sheet/animalhide/carp = 1)
|
||||
greyscale_config = /datum/greyscale_config/carp
|
||||
ai_controller = /datum/ai_controller/basic_controller/carp
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
death_message = "screams in agony as it sublimates into a sulfurous smoke."
|
||||
death_sound = 'sound/magic/demon_dies.ogg'
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = T0C - 25 //Weak to cold
|
||||
maximum_survivable_temperature = INFINITY
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
faction = list(FACTION_SPOOKY)
|
||||
speak_emote = list("telepathically cries")
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = T0C
|
||||
maximum_survivable_temperature = T0C + 1500
|
||||
sight = SEE_SELF|SEE_MOBS|SEE_OBJS|SEE_TURFS
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
speech_span = SPAN_ROBOT
|
||||
death_message = "blows apart!"
|
||||
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = TCMB
|
||||
ai_controller = /datum/ai_controller/basic_controller/hivebot
|
||||
///does this type do range attacks?
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
response_disarm_simple = "gently push"
|
||||
faction = list()
|
||||
ai_controller = /datum/ai_controller/basic_controller/meteor_heart
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
combat_mode = TRUE
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = TCMB
|
||||
|
||||
obj_damage = 50
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
response_harm_simple = "punch through"
|
||||
unsuitable_atmos_damage = 0
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0) //I don't know how you'd apply those, but revenants no-sell them anyway.
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = INFINITY
|
||||
|
||||
|
||||
@@ -109,6 +109,11 @@
|
||||
. = ..()
|
||||
AddElement(/datum/element/web_walker, /datum/movespeed_modifier/fast_web)
|
||||
|
||||
///Used in the caves away mission.
|
||||
/mob/living/basic/spider/giant/hunter/away_caves
|
||||
minimum_survivable_temperature = 0
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/**
|
||||
* ### Scout Spider
|
||||
* A subtype of the giant spider which is faster, has thermal vision, but less health and damage.
|
||||
@@ -166,6 +171,11 @@
|
||||
///The health HUD applied to the mob.
|
||||
var/health_hud = DATA_HUD_MEDICAL_ADVANCED
|
||||
|
||||
///Used in the caves away mission.
|
||||
/mob/living/basic/spider/giant/nurse/away_caves
|
||||
minimum_survivable_temperature = 0
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/mob/living/basic/spider/giant/nurse/Initialize(mapload)
|
||||
. = ..()
|
||||
var/datum/atom_hud/datahud = GLOB.huds[health_hud]
|
||||
@@ -464,7 +474,7 @@
|
||||
*/
|
||||
/mob/living/basic/spider/giant/ice
|
||||
name = "giant ice spider"
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
color = rgb(114,228,250)
|
||||
@@ -478,7 +488,7 @@
|
||||
*/
|
||||
/mob/living/basic/spider/giant/nurse/ice
|
||||
name = "giant ice spider"
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
poison_type = /datum/reagent/consumable/frostoil
|
||||
@@ -492,7 +502,7 @@
|
||||
*/
|
||||
/mob/living/basic/spider/giant/hunter/ice
|
||||
name = "giant ice spider"
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = 1500
|
||||
poison_type = /datum/reagent/consumable/frostoil
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
health = 10
|
||||
minimum_survivable_temperature = TCMB
|
||||
maximum_survivable_temperature = T0C + 1250
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
death_message = "falls to the ground, its shard dulling to a miserable grey!"
|
||||
|
||||
faction = list(FACTION_HOSTILE)
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
lighting_cutoff_red = 20
|
||||
lighting_cutoff_green = 10
|
||||
lighting_cutoff_blue = 40
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
minimum_survivable_temperature = 0
|
||||
maximum_survivable_temperature = INFINITY
|
||||
ai_controller = /datum/ai_controller/basic_controller/wumborian_fugu
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
desc = "Pray for your life, syndicate. Run while you can."
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
habitable_atmos = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
habitable_atmos = null
|
||||
unsuitable_cold_damage = 0
|
||||
casingtype = /obj/item/ammo_casing/energy/laser
|
||||
burst_shots = 3
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
var/static/list/roach_drops = list(/obj/effect/decal/cleanable/insectguts)
|
||||
AddElement(/datum/element/death_drops, roach_drops)
|
||||
AddElement(/datum/element/swabable, cockroach_cell_line, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 7)
|
||||
AddElement(/datum/element/basic_body_temp_sensitive, 270, INFINITY)
|
||||
AddComponent( \
|
||||
/datum/component/squashable, \
|
||||
squash_chance = 50, \
|
||||
|
||||
@@ -52,13 +52,7 @@
|
||||
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
|
||||
|
||||
if(prob(1))
|
||||
name = "rare frog"
|
||||
desc = "They seem a little smug."
|
||||
icon_state = "rare_frog"
|
||||
icon_living = "rare_frog"
|
||||
icon_dead = "rare_frog_dead"
|
||||
butcher_results = list(/obj/item/food/nugget = 5)
|
||||
poison_type = /datum/reagent/drug/mushroomhallucinogen
|
||||
make_rare()
|
||||
|
||||
var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
||||
@@ -68,6 +62,15 @@
|
||||
AddElement(/datum/element/ai_retaliate)
|
||||
AddElement(/datum/element/swabable, CELL_LINE_TABLE_FROG, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
|
||||
|
||||
/mob/living/basic/frog/proc/make_rare()
|
||||
name = "rare frog"
|
||||
desc = "They seem a little smug."
|
||||
icon_state = "rare_[icon_state]"
|
||||
icon_living = "rare_[icon_living]"
|
||||
icon_dead = "rare_[icon_dead]"
|
||||
butcher_results = list(/obj/item/food/nugget = 5)
|
||||
poison_type = /datum/reagent/drug/mushroomhallucinogen
|
||||
|
||||
/mob/living/basic/frog/proc/on_entered(datum/source, AM as mob|obj)
|
||||
SIGNAL_HANDLER
|
||||
if(!stat && isliving(AM))
|
||||
@@ -75,6 +78,17 @@
|
||||
if(L.mob_size > MOB_SIZE_TINY)
|
||||
playsound(src, stepped_sound, 50, TRUE)
|
||||
|
||||
/mob/living/basic/frog/icemoon_facility
|
||||
name = "Peter Jr."
|
||||
desc = "They seem a little cold."
|
||||
minimum_survivable_temperature = ICEBOX_MIN_TEMPERATURE
|
||||
habitable_atmos = null
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
/mob/living/basic/frog/icemoon_facility/make_rare()
|
||||
. = ..()
|
||||
name = "Peter Sr." //make him senior.
|
||||
|
||||
/mob/living/basic/frog/frog_suicide
|
||||
name = "suicide frog"
|
||||
desc = "Driven by sheer will."
|
||||
|
||||
@@ -53,3 +53,10 @@
|
||||
/datum/ai_planning_subtree/target_retaliate,
|
||||
/datum/ai_planning_subtree/basic_melee_attack_subtree,
|
||||
)
|
||||
|
||||
///Subtype used in the caves away mission
|
||||
/mob/living/basic/bat/away_caves
|
||||
name = "cave bat"
|
||||
desc = "A rare breed of bat which roosts deep in caves."
|
||||
minimum_survivable_temperature = 0
|
||||
gold_core_spawnable = NO_SPAWN
|
||||
|
||||
@@ -7,7 +7,8 @@
|
||||
stop_automated_movement = TRUE
|
||||
wander = FALSE
|
||||
damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 0, STAMINA = 0, OXY = 0)
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
unsuitable_atmos_damage = 0
|
||||
hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_BATT_HUD, DIAG_PATH_HUD = HUD_LIST_LIST)
|
||||
maxbodytemp = INFINITY
|
||||
minbodytemp = 0
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
icon_living = "gondola"
|
||||
loot = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/stack/sheet/animalhide/gondola = 1, /obj/item/food/meat/slab/gondola = 1)
|
||||
//Gondolas aren't affected by cold.
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
minbodytemp = 0
|
||||
maxbodytemp = 1500
|
||||
maxHealth = 200
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
weather_immunities = list(TRAIT_LAVA_IMMUNE, TRAIT_ASHSTORM_IMMUNE)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
loot = list(/obj/effect/decal/remains/human)
|
||||
del_on_death = TRUE
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
robust_searching = TRUE
|
||||
ranged_ignores_vision = TRUE
|
||||
stat_attack = DEAD
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
damage_coeff = list(BRUTE = 1, BURN = 0.5, TOX = 1, STAMINA = 0, OXY = 1)
|
||||
minbodytemp = 0
|
||||
maxbodytemp = INFINITY
|
||||
|
||||
@@ -32,7 +32,7 @@ GLOBAL_LIST_INIT(animatable_blacklist, typecacheof(list(
|
||||
speak_emote = list("creaks")
|
||||
taunt_chance = 30
|
||||
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
minbodytemp = 0
|
||||
|
||||
faction = list(FACTION_MIMIC)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
//the base mining mob
|
||||
/mob/living/simple_animal/hostile/asteroid
|
||||
vision_range = 2
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
faction = list(FACTION_MINING)
|
||||
weather_immunities = list(TRAIT_LAVA_IMMUNE,TRAIT_ASHSTORM_IMMUNE)
|
||||
obj_damage = 30
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
gender = NEUTER
|
||||
emote_see = list("jiggles", "bounces in place")
|
||||
speak_emote = list("blorbles")
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
hud_type = /datum/hud/ooze
|
||||
minbodytemp = 250
|
||||
maxbodytemp = INFINITY
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
gender = NEUTER
|
||||
environment_smash = ENVIRONMENT_SMASH_STRUCTURES
|
||||
speak_emote = list("roars")
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
health = 250
|
||||
maxHealth = 250
|
||||
damage_coeff = list(BRUTE = 0.7, BURN = 0.7, TOX = 1, STAMINA = 0, OXY = 1)
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
attack_sound = 'sound/hallucinations/growl1.ogg'
|
||||
attack_vis_effect = ATTACK_EFFECT_BITE
|
||||
combat_mode = TRUE
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
minbodytemp = 0
|
||||
status_flags = CANPUSH
|
||||
death_message = "collapses, flesh gone in a pile of bones!"
|
||||
|
||||
@@ -176,7 +176,6 @@
|
||||
add_traits(weather_immunities, ROUNDSTART_TRAIT)
|
||||
if (environment_smash >= ENVIRONMENT_SMASH_WALLS)
|
||||
AddElement(/datum/element/wall_smasher, strength_flag = environment_smash)
|
||||
|
||||
if(speak)
|
||||
speak = string_list(speak)
|
||||
if(speak_emote)
|
||||
@@ -185,8 +184,6 @@
|
||||
emote_hear = string_list(emote_hear)
|
||||
if(emote_see)
|
||||
emote_see = string_list(emote_hear)
|
||||
if(atmos_requirements)
|
||||
atmos_requirements = string_assoc_list(atmos_requirements)
|
||||
if(damage_coeff)
|
||||
damage_coeff = string_assoc_list(damage_coeff)
|
||||
if(footstep_type)
|
||||
@@ -196,6 +193,24 @@
|
||||
if(isnull(unsuitable_heat_damage))
|
||||
unsuitable_heat_damage = unsuitable_atmos_damage
|
||||
|
||||
///We need to wait for SSair to be initialized before we can check atmos/temp requirements.
|
||||
if(PERFORM_ALL_TESTS(focus_only/atmos_and_temp_requirements) && mapload && !SSair.initialized)
|
||||
RegisterSignal(SSair, COMSIG_SUBSYSTEM_POST_INITIALIZE, PROC_REF(on_ssair_init))
|
||||
return
|
||||
init_atmos_temp_requirement(mapload)
|
||||
|
||||
/mob/living/simple_animal/proc/on_ssair_init(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
UnregisterSignal(SSair, COMSIG_SUBSYSTEM_POST_INITIALIZE)
|
||||
init_atmos_temp_requirement(TRUE)
|
||||
|
||||
/mob/living/simple_animal/proc/init_atmos_temp_requirement(mapload)
|
||||
if(atmos_requirements && unsuitable_atmos_damage)
|
||||
atmos_requirements = string_assoc_list(atmos_requirements)
|
||||
AddElement(/datum/element/atmos_requirements, atmos_requirements, unsuitable_atmos_damage, mapload)
|
||||
if((unsuitable_cold_damage || unsuitable_heat_damage) && (minbodytemp > 0 || maxbodytemp < INFINITY))
|
||||
AddElement(/datum/element/body_temp_sensitive, minbodytemp, maxbodytemp, unsuitable_cold_damage, unsuitable_heat_damage, mapload)
|
||||
|
||||
/mob/living/simple_animal/Life(seconds_per_tick = SSMOBS_DT, times_fired)
|
||||
. = ..()
|
||||
if(staminaloss > 0)
|
||||
@@ -302,51 +317,6 @@
|
||||
else
|
||||
manual_emote(pick(emote_hear))
|
||||
|
||||
/mob/living/simple_animal/proc/environment_air_is_safe()
|
||||
. = TRUE
|
||||
|
||||
if(pulledby && pulledby.grab_state >= GRAB_KILL && atmos_requirements["min_oxy"])
|
||||
. = FALSE //getting choked
|
||||
|
||||
if(isturf(loc) && isopenturf(loc))
|
||||
var/turf/open/ST = loc
|
||||
if(ST.air)
|
||||
var/ST_gases = ST.air.gases
|
||||
ST.air.assert_gases(/datum/gas/oxygen, /datum/gas/pluoxium, /datum/gas/nitrogen, /datum/gas/carbon_dioxide, /datum/gas/plasma)
|
||||
|
||||
var/plas = ST_gases[/datum/gas/plasma][MOLES]
|
||||
var/oxy = ST_gases[/datum/gas/oxygen][MOLES] + (ST_gases[/datum/gas/pluoxium][MOLES] * PLUOXIUM_PROPORTION)
|
||||
var/n2 = ST_gases[/datum/gas/nitrogen][MOLES]
|
||||
var/co2 = ST_gases[/datum/gas/carbon_dioxide][MOLES]
|
||||
|
||||
ST.air.garbage_collect()
|
||||
|
||||
if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["min_plas"] && plas < atmos_requirements["min_plas"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["max_plas"] && plas > atmos_requirements["max_plas"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["max_n2"] && n2 > atmos_requirements["max_n2"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["min_co2"] && co2 < atmos_requirements["min_co2"])
|
||||
. = FALSE
|
||||
else if(atmos_requirements["max_co2"] && co2 > atmos_requirements["max_co2"])
|
||||
. = FALSE
|
||||
else
|
||||
if(atmos_requirements["min_oxy"] || atmos_requirements["min_plas"] || atmos_requirements["min_n2"] || atmos_requirements["min_co2"])
|
||||
. = FALSE
|
||||
|
||||
/mob/living/simple_animal/proc/environment_temperature_is_safe(datum/gas_mixture/environment)
|
||||
. = TRUE
|
||||
var/areatemp = get_temperature(environment)
|
||||
if((areatemp < minbodytemp) || (areatemp > maxbodytemp))
|
||||
. = FALSE
|
||||
|
||||
/mob/living/simple_animal/handle_environment(datum/gas_mixture/environment, seconds_per_tick, times_fired)
|
||||
var/atom/A = loc
|
||||
if(isturf(A))
|
||||
@@ -359,42 +329,6 @@
|
||||
else
|
||||
adjust_bodytemperature(clamp(temp_delta * seconds_per_tick / temperature_normalization_speed, 0, temp_delta))
|
||||
|
||||
if(!environment_air_is_safe() && unsuitable_atmos_damage)
|
||||
adjustHealth(unsuitable_atmos_damage * seconds_per_tick)
|
||||
if(unsuitable_atmos_damage > 0)
|
||||
throw_alert(ALERT_NOT_ENOUGH_OXYGEN, /atom/movable/screen/alert/not_enough_oxy)
|
||||
else
|
||||
clear_alert(ALERT_NOT_ENOUGH_OXYGEN)
|
||||
|
||||
handle_temperature_damage(seconds_per_tick, times_fired)
|
||||
|
||||
/mob/living/simple_animal/proc/handle_temperature_damage(seconds_per_tick, times_fired)
|
||||
. = FALSE
|
||||
if((bodytemperature < minbodytemp) && unsuitable_cold_damage)
|
||||
adjustHealth(unsuitable_cold_damage * seconds_per_tick)
|
||||
switch(unsuitable_cold_damage)
|
||||
if(1 to 5)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 1)
|
||||
if(5 to 10)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 2)
|
||||
if(10 to INFINITY)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/cold, 3)
|
||||
. = TRUE
|
||||
|
||||
if((bodytemperature > maxbodytemp) && unsuitable_heat_damage)
|
||||
adjustHealth(unsuitable_heat_damage * seconds_per_tick)
|
||||
switch(unsuitable_heat_damage)
|
||||
if(1 to 5)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 1)
|
||||
if(5 to 10)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 2)
|
||||
if(10 to INFINITY)
|
||||
throw_alert(ALERT_TEMPERATURE, /atom/movable/screen/alert/hot, 3)
|
||||
. = TRUE
|
||||
|
||||
if(!.)
|
||||
clear_alert(ALERT_TEMPERATURE)
|
||||
|
||||
/mob/living/simple_animal/gib()
|
||||
if(butcher_results || guaranteed_butcher_results)
|
||||
var/list/butcher = list()
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
bubble_icon = "slime"
|
||||
initial_language_holder = /datum/language_holder/slime
|
||||
|
||||
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
|
||||
atmos_requirements = null
|
||||
|
||||
maxHealth = 150
|
||||
health = 150
|
||||
|
||||
@@ -44,3 +44,6 @@
|
||||
|
||||
/// Checks that the contents of the fish_counts list are also present in fish_table
|
||||
/datum/unit_test/focus_only/fish_sources_tables
|
||||
|
||||
/// Checks that maploaded mobs with either the `atmos_requirements` or `body_temp_sensitive`
|
||||
/datum/unit_test/focus_only/atmos_and_temp_requirements
|
||||
|
||||
+1
-1
@@ -1360,12 +1360,12 @@
|
||||
#include "code\datums\elements\attack_equip.dm"
|
||||
#include "code\datums\elements\backblast.dm"
|
||||
#include "code\datums\elements\bane.dm"
|
||||
#include "code\datums\elements\basic_body_temp_sensitive.dm"
|
||||
#include "code\datums\elements\basic_eating.dm"
|
||||
#include "code\datums\elements\beauty.dm"
|
||||
#include "code\datums\elements\bed_tucking.dm"
|
||||
#include "code\datums\elements\befriend_petting.dm"
|
||||
#include "code\datums\elements\blocks_explosives.dm"
|
||||
#include "code\datums\elements\body_temp_sensitive.dm"
|
||||
#include "code\datums\elements\bombable_turf.dm"
|
||||
#include "code\datums\elements\bonus_damage.dm"
|
||||
#include "code\datums\elements\bsa_blocker.dm"
|
||||
|
||||
Reference in New Issue
Block a user