mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-10 09:42:29 +00:00
## About The Pull Request This PR kills the abstract internal and external typepaths for organs, now replaced by an EXTERNAL_ORGAN flag to distinguish the two kinds. This PR also fixes fox ears (from #87162, no tail is added) and mushpeople's caps (they should be red, the screenshot is a tad outdated). And yes, you can now use a hair dye spray to recolor body parts like most tails, podpeople hair, mushpeople caps and cat ears. The process can be reversed by using the spray again. ## Why It's Good For The Game Time-Green put some effort during the last few months to untie functions and mechanics from external/internal organ pathing. Now, all that this pathing is good for are a few typechecks, easily replaceable with bitflags. Also podpeople and mushpeople need a way to recolor their "hair". This kind of applies to fish tails from the fish infusion, which colors can't be selected right now. The rest is just there if you ever want to recolor your lizard tail for some reason. Proof of testing btw (screenshot taken before mushpeople cap fix, right side has dyed body parts, moth can't be dyed, they're already fabolous):  ## Changelog 🆑 code: Removed internal/external pathing from organs in favor of a bit flag. Hopefully this shouldn't break anything about organs. fix: Fixed invisible fox ears. fix: Fixed mushpeople caps not being colored red by default. add: You can now dye most tails, podpeople hair, mushpeople caps etc. with a hair dye spray. /🆑
203 lines
11 KiB
Plaintext
203 lines
11 KiB
Plaintext
#define TEST_CHECK_BREATH_MESSAGE(lungs_organ, message) "[lungs_organ.type]/check_breath() [message]"
|
|
#define TEST_ALERT_THROW_MESSAGE(lungs_organ, alert_name) TEST_CHECK_BREATH_MESSAGE(lungs_organ, "failed to throw alert [alert_name] when expected.")
|
|
#define TEST_ALERT_INHIBIT_MESSAGE(lungs_organ, alert_name) TEST_CHECK_BREATH_MESSAGE(lungs_organ, "threw alert [alert_name] when it wasn't expected.")
|
|
#define GET_MOLES(gas_mixture, gas_type) (gas_mixture.gases[gas_type] ? gas_mixture.gases[gas_type][MOLES] : 0)
|
|
|
|
/// Tests the standard, plasmaman, and lavaland lungs organ to ensure breathing and suffocation behave as expected.
|
|
/// Performs a check on each main (can be life-sustaining) gas, and ensures gas alerts are only thrown when expected.
|
|
/datum/unit_test/lungs
|
|
abstract_type = /datum/unit_test/lungs
|
|
|
|
/datum/unit_test/lungs/lungs_sanity/Run()
|
|
// "Standard" form of breathing.
|
|
// 2500 Litres of O2/N2 gas mix, ideal for life.
|
|
var/datum/gas_mixture/test_mix = create_standard_mix()
|
|
var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
var/obj/item/organ/lungs/test_lungs = allocate(/obj/item/organ/lungs)
|
|
// Test one breath of O2/N2 mix.
|
|
lungs_test_check_breath("standard gas mixture", lab_rat, test_lungs, test_mix)
|
|
|
|
// Suffocation with an empty gas mix.
|
|
var/datum/gas_mixture/empty_test_mix = allocate(/datum/gas_mixture)
|
|
lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
test_lungs = allocate(/obj/item/organ/lungs)
|
|
// Test one breath of nothing. Suffocate due to the breath being empty.
|
|
lungs_test_check_breath("empty gas mixture", lab_rat, test_lungs, empty_test_mix, expect_failure = TRUE)
|
|
|
|
// Suffocation with null. This does indeed happen normally.
|
|
lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
test_lungs = allocate(/obj/item/organ/lungs)
|
|
// Test one breath of nothing. Suffocate due to the breath being null.
|
|
lungs_test_check_breath("null", lab_rat, test_lungs, null, expect_failure = TRUE)
|
|
|
|
// Suffocation with Nitrogen.
|
|
var/datum/gas_mixture/nitro_test_mix = create_nitrogen_mix()
|
|
lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
test_lungs = allocate(/obj/item/organ/lungs)
|
|
// Test one breath of Nitrogen. Suffocate due to the breath being 100% N2.
|
|
lungs_test_check_breath("pure Nitrogen", lab_rat, test_lungs, nitro_test_mix, expect_failure = TRUE)
|
|
|
|
/// Tests the Plasmaman lungs organ to ensure Plasma breathing and suffocation behave as expected.
|
|
/datum/unit_test/lungs/lungs_sanity_plasmaman
|
|
|
|
/datum/unit_test/lungs/lungs_sanity_plasmaman/Run()
|
|
// 2500 Litres of pure Plasma.
|
|
var/datum/gas_mixture/plasma_test_mix = create_plasma_mix()
|
|
var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
var/obj/item/organ/lungs/plasmaman/test_lungs = allocate(/obj/item/organ/lungs/plasmaman)
|
|
// Test one breath of Plasma on Plasmaman lungs.
|
|
lungs_test_check_breath("pure Plasma", lab_rat, test_lungs, plasma_test_mix)
|
|
|
|
// Tests suffocation with Nitrogen.
|
|
var/datum/gas_mixture/nitro_test_mix = create_nitrogen_mix()
|
|
lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
test_lungs = allocate(/obj/item/organ/lungs/plasmaman)
|
|
// Test one breath of Nitrogen on Plasmaman lungs.
|
|
lungs_test_check_breath("pure Nitrogen", lab_rat, test_lungs, nitro_test_mix, expect_failure = TRUE)
|
|
|
|
/// Tests the lavaland/Ashwalker lungs organ.
|
|
/// Ensures they can breathe from the lavaland air mixture properly, and suffocate on inadequate mixture.
|
|
/datum/unit_test/lungs/lungs_sanity_ashwalker
|
|
|
|
/datum/unit_test/lungs/lungs_sanity_ashwalker/Run()
|
|
// Gas mix resembling one cell of lavaland's atmosphere.
|
|
var/datum/gas_mixture/lavaland_test_mix = create_lavaland_mix()
|
|
var/obj/item/organ/lungs/lavaland/test_lungs = allocate(/obj/item/organ/lungs/lavaland)
|
|
var/mob/living/carbon/human/lab_rat = allocate(/mob/living/carbon/human/consistent)
|
|
// Test one breath of Lavaland gas mix on Ashwalker lungs.
|
|
lungs_test_check_breath("Lavaland air mixture", lab_rat, test_lungs, lavaland_test_mix)
|
|
|
|
/// Comprehensive unit test for [/obj/item/organ/lungs/proc/check_breath()]
|
|
/// If "expect_failure" is set to TRUE, the test ensures the given Human suffocated.
|
|
/// A "test_name" string is required to contextualize test logs. Describe the gas you're testing.
|
|
/datum/unit_test/lungs/proc/lungs_test_check_breath(test_name, mob/living/carbon/human/lab_rat, obj/item/organ/lungs/test_lungs, datum/gas_mixture/test_mix, expect_failure = FALSE)
|
|
// Setup a small volume of gas which represents one "breath" from test_mix.
|
|
var/datum/gas_mixture/test_breath
|
|
|
|
if(!isnull(test_mix))
|
|
var/total_moles = test_mix.total_moles()
|
|
if(total_moles > 0)
|
|
test_breath = test_mix.remove(total_moles * BREATH_PERCENTAGE)
|
|
|
|
if(isnull(test_breath))
|
|
test_breath = allocate(/datum/gas_mixture, BREATH_VOLUME)
|
|
|
|
// Backup of the breath mixture, to compare against after testing check_breath().
|
|
var/datum/gas_mixture/test_breath_backup = test_breath.copy()
|
|
|
|
// Get partial pressures for each "main" gas.
|
|
var/oxygen_pp = 0
|
|
var/nitro_pp = 0
|
|
var/co2_pp = 0
|
|
var/plasma_pp = 0
|
|
if(test_breath.total_moles() > 0)
|
|
oxygen_pp = test_breath.get_breath_partial_pressure(GET_MOLES(test_breath, /datum/gas/oxygen))
|
|
nitro_pp = test_breath.get_breath_partial_pressure(GET_MOLES(test_breath, /datum/gas/nitrogen))
|
|
co2_pp = test_breath.get_breath_partial_pressure(GET_MOLES(test_breath, /datum/gas/carbon_dioxide))
|
|
plasma_pp = test_breath.get_breath_partial_pressure(GET_MOLES(test_breath, /datum/gas/plasma))
|
|
|
|
// Minimum and maximum gas tolerances for the 4 main life-sustaining gases.
|
|
var/min_oxygen = test_lungs.safe_oxygen_min
|
|
var/min_nitro = test_lungs.safe_nitro_min
|
|
var/min_plasma = test_lungs.safe_plasma_min
|
|
var/max_oxygen = test_lungs.safe_oxygen_max
|
|
var/max_co2 = test_lungs.safe_co2_max
|
|
var/max_plasma = test_lungs.safe_plasma_max
|
|
|
|
// Test a single "breath" of air.
|
|
var/status_code = test_lungs.check_breath(test_breath, lab_rat)
|
|
|
|
// Ensures failed_last_breath is set as we expect, and that check_breath returns a corollary status code.
|
|
if(expect_failure)
|
|
TEST_ASSERT(!status_code, TEST_CHECK_BREATH_MESSAGE(test_lungs, "returned truthy / status code 1 (success) when it wasn't expected."))
|
|
TEST_ASSERT(lab_rat.failed_last_breath, TEST_CHECK_BREATH_MESSAGE(test_lungs, "should suffocate from [test_name]."))
|
|
else
|
|
TEST_ASSERT(status_code, TEST_CHECK_BREATH_MESSAGE(test_lungs, "returned falsy / status code 0 (failure) when it wasn't expected."))
|
|
TEST_ASSERT(!lab_rat.failed_last_breath, TEST_CHECK_BREATH_MESSAGE(test_lungs, "can't get a full breath from [test_name]."))
|
|
|
|
// Checks each "main" gas to ensure gas alerts are thrown/inhibited when expected.
|
|
lungs_test_alert_min(lab_rat, test_lungs, ALERT_NOT_ENOUGH_OXYGEN, min_oxygen, oxygen_pp)
|
|
lungs_test_alert_max(lab_rat, test_lungs, ALERT_TOO_MUCH_OXYGEN, max_oxygen, oxygen_pp)
|
|
|
|
lungs_test_alert_min(lab_rat, test_lungs, ALERT_NOT_ENOUGH_NITRO, min_nitro, nitro_pp)
|
|
|
|
lungs_test_alert_max(lab_rat, test_lungs, ALERT_TOO_MUCH_CO2, max_co2, co2_pp)
|
|
|
|
lungs_test_alert_min(lab_rat, test_lungs, ALERT_NOT_ENOUGH_PLASMA, min_plasma, plasma_pp)
|
|
lungs_test_alert_max(lab_rat, test_lungs, ALERT_TOO_MUCH_PLASMA, max_plasma, plasma_pp)
|
|
|
|
// Track the volumes of O2 and CO2 which are expected to be exhaled.
|
|
var/expected_oxygen = GET_MOLES(test_breath_backup, /datum/gas/oxygen)
|
|
var/expected_nitro = GET_MOLES(test_breath_backup, /datum/gas/nitrogen)
|
|
var/expected_co2 = GET_MOLES(test_breath_backup, /datum/gas/carbon_dioxide)
|
|
var/expected_plasma = GET_MOLES(test_breath_backup, /datum/gas/plasma)
|
|
|
|
// Setup expectations for main gas exchange tests.
|
|
if(min_oxygen)
|
|
expected_co2 += expected_oxygen
|
|
expected_oxygen = 0
|
|
if(min_nitro)
|
|
expected_co2 += GET_MOLES(test_breath_backup, /datum/gas/nitrogen)
|
|
expected_nitro = 0
|
|
if(min_plasma)
|
|
expected_co2 += GET_MOLES(test_breath_backup, /datum/gas/plasma)
|
|
expected_plasma = 0
|
|
|
|
// Validate conversion of inhaled gas to exhaled gas.
|
|
if(min_oxygen)
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/oxygen), expected_oxygen), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should consume all Oxygen initially present in the breath."))
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/carbon_dioxide), expected_co2), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should convert Oxygen into an equivalent volume of CO2."))
|
|
if(min_nitro)
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/nitrogen), expected_nitro), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should consume all Nitrogen initially present in the breath."))
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/carbon_dioxide), expected_co2), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should convert Nitrogen into an equivalent volume of CO2."))
|
|
if(min_plasma)
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/plasma), expected_plasma), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should consume all Plasma initially present in the breath."))
|
|
TEST_ASSERT(molar_cmp_equals(GET_MOLES(test_breath, /datum/gas/carbon_dioxide), expected_co2), TEST_CHECK_BREATH_MESSAGE(test_lungs, "should convert Plasma into an equivalent volume of CO2."))
|
|
|
|
/// Tests minimum gas alerts by comparing gas pressure.
|
|
/datum/unit_test/lungs/proc/lungs_test_alert_min(mob/living/carbon/human/lab_rat, obj/item/organ/lungs/test_lungs, alert_name, min_pressure, pressure)
|
|
var/alert_thrown = lab_rat.has_alert(alert_name)
|
|
var/pressure_safe = (pressure >= min_pressure) || (min_pressure == 0)
|
|
TEST_ASSERT(!pressure_safe && alert_thrown || pressure_safe, TEST_ALERT_THROW_MESSAGE(test_lungs, alert_name))
|
|
TEST_ASSERT(pressure_safe && !alert_thrown || !pressure_safe, TEST_ALERT_INHIBIT_MESSAGE(test_lungs, alert_name))
|
|
|
|
/// Tests maximum gas alerts by comparing gas pressure.
|
|
/datum/unit_test/lungs/proc/lungs_test_alert_max(mob/living/carbon/human/lab_rat, obj/item/organ/lungs/test_lungs, alert_name, max_pressure, pressure)
|
|
var/alert_thrown = lab_rat.has_alert(alert_name)
|
|
var/pressure_safe = (pressure <= max_pressure) || (max_pressure == 0)
|
|
TEST_ASSERT(!pressure_safe && alert_thrown || pressure_safe, TEST_ALERT_THROW_MESSAGE(test_lungs, alert_name))
|
|
TEST_ASSERT(pressure_safe && !alert_thrown || !pressure_safe, TEST_ALERT_INHIBIT_MESSAGE(test_lungs, alert_name))
|
|
|
|
/// Set up a 2500-Litre gas mixture with the given gases and percentages.
|
|
/datum/unit_test/lungs/proc/create_gas_mix(list/gas_to_percent)
|
|
var/datum/gas_mixture/test_mix = allocate(/datum/gas_mixture, 2500)
|
|
test_mix.temperature = T20C
|
|
for(var/datum/gas/gas_type as anything in gas_to_percent)
|
|
test_mix.add_gas(gas_type)
|
|
test_mix.gases[gas_type][MOLES] = (ONE_ATMOSPHERE * 2500 / (R_IDEAL_GAS_EQUATION * T20C) * gas_to_percent[gas_type])
|
|
return test_mix
|
|
|
|
/// Set up an O2/N2 gas mix which is "ideal" for organic life.
|
|
/datum/unit_test/lungs/proc/create_standard_mix()
|
|
return create_gas_mix(list(/datum/gas/oxygen = O2STANDARD, /datum/gas/nitrogen = N2STANDARD))
|
|
|
|
/// Set up a pure Nitrogen gas mix.
|
|
/datum/unit_test/lungs/proc/create_nitrogen_mix()
|
|
return create_gas_mix(list(/datum/gas/nitrogen = 1))
|
|
|
|
/// Set up an O2/N2 gas mix which is "ideal" for plasmamen.
|
|
/datum/unit_test/lungs/proc/create_plasma_mix()
|
|
return create_gas_mix(list(/datum/gas/plasma = 1))
|
|
|
|
/// Set up an Lavaland gas mix which is "ideal" for Ashwalker life.
|
|
/datum/unit_test/lungs/proc/create_lavaland_mix()
|
|
var/datum/gas_mixture/immutable/planetary/lavaland_mix = SSair.planetary[LAVALAND_DEFAULT_ATMOS]
|
|
var/datum/gas_mixture/test_mix = allocate(/datum/gas_mixture, 2500)
|
|
test_mix.copy_from(lavaland_mix)
|
|
return test_mix
|
|
|
|
#undef TEST_CHECK_BREATH_MESSAGE
|
|
#undef TEST_ALERT_THROW_MESSAGE
|
|
#undef TEST_ALERT_INHIBIT_MESSAGE
|
|
#undef GET_MOLES
|