mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-01-06 06:52:39 +00:00
* QoL improvements to the mob damage unit tests (#78748) ## About The Pull Request This is something that I meant to do because it was a minor annoyance as I was creating the tests but I never got around to it. Because many of the failures occurred in procs it could be difficult to pinpoint the exact line of the test where they were failing. It would just be the line within the proc, and not the line where the proc was called. So you'd have to sort of infer which one it was from the values of `x` and `y` in `Expected x to be equal to y`. Now each test failure will have a brief description and a line number where `apply_damage()` / `verify_damage()` actually got called to make it clearer. Like shown below.  ## Why It's Good For The Game Just a small QoL update for coders. Some typos fixed, too. ## Changelog Nothing player facing though. * QoL improvements to the mob damage unit tests --------- Co-authored-by: Bloop <13398309+vinylspiders@users.noreply.github.com>
623 lines
33 KiB
Plaintext
623 lines
33 KiB
Plaintext
/// Tests to make sure mob damage procs are working correctly
|
|
/datum/unit_test/mob_damage
|
|
priority = TEST_LONGER
|
|
|
|
/datum/unit_test/mob_damage/Destroy()
|
|
SSmobs.ignite()
|
|
return ..()
|
|
|
|
/datum/unit_test/mob_damage/Run()
|
|
SSmobs.pause()
|
|
var/mob/living/carbon/human/dummy = allocate(/mob/living/carbon/human/consistent)
|
|
dummy.maxHealth = 200 // tank mode
|
|
|
|
/* The sanity tests: here we make sure that:
|
|
1) That damage procs are returning the expected values. They should be returning the actual amount of damage taken/healed.
|
|
(Negative values mean damage was taken, positive mean healing)
|
|
2) Verifying that the damage has been accurately applied to the mob afterwards. */
|
|
|
|
test_sanity_simple(dummy)
|
|
test_sanity_complex(dummy)
|
|
|
|
// Testing if biotypes are working as intended
|
|
test_biotypes(dummy)
|
|
|
|
// Testing whether or not TRAIT_NOBREATH is working as intended
|
|
test_nobreath(dummy)
|
|
|
|
// Testing whether or not TRAIT_TOXINLOVER and TRAIT_TOXIMMUNE are working as intended
|
|
test_toxintraits(dummy)
|
|
|
|
// Testing whether or not TRAIT_NOCLONELOSS is working as intended
|
|
test_nocloneloss(dummy)
|
|
|
|
// Testing the proc ordered_healing()
|
|
test_ordered_healing(dummy)
|
|
|
|
// testing with godmode enabled
|
|
test_godmode(dummy)
|
|
|
|
/**
|
|
* Test whether the adjust damage procs return the correct values and that the mob's health is the expected value afterwards.
|
|
*
|
|
* By default this calls apply_damage(amount) followed by verify_damage(amount_after) and returns TRUE if both succeeded.
|
|
* amount_after defaults to the mob's current stamina loss but can be overridden as needed.
|
|
*
|
|
* Arguments:
|
|
* * testing_mob - the mob to apply the damage to
|
|
* * amount - the amount of damage to apply to the mob
|
|
* * expected - what the expected return value of the damage proc is
|
|
* * amount_after - in case you want to specify what the damage amount on the mob should be afterwards
|
|
* * included_types - Bitflag of damage types to apply
|
|
* * biotypes - the biotypes of damage to apply
|
|
* * bodytypes - the bodytypes of damage to apply
|
|
* * forced - whether or not this is forced damage
|
|
*/
|
|
/datum/unit_test/mob_damage/proc/test_apply_damage(mob/living/testing_mob, amount, expected = -amount, amount_after, included_types, biotypes, bodytypes, forced)
|
|
if(isnull(amount_after))
|
|
amount_after = testing_mob.getStaminaLoss() - expected // stamina loss applies to both carbon and basic mobs the same way, so that's why we're using it here
|
|
if(!apply_damage(testing_mob, amount, expected, included_types, biotypes, bodytypes, forced))
|
|
return FALSE
|
|
if(!verify_damage(testing_mob, amount_after, included_types))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/**
|
|
* Test whether the set damage procs return the correct values and that the mob's health is the expected value afterwards.
|
|
*
|
|
* By default this calls set_damage(amount) followed by verify_damage(amount_after) and returns TRUE if both succeeded.
|
|
* amount_after defaults to the mob's current stamina loss but can be overridden as needed.
|
|
*
|
|
* Arguments:
|
|
* * testing_mob - the mob to apply the damage to
|
|
* * amount - the amount of damage to apply to the mob
|
|
* * expected - what the expected return value of the damage proc is
|
|
* * amount_after - in case you want to specify what the damage amount on the mob should be afterwards
|
|
* * included_types - Bitflag of damage types to apply
|
|
* * biotypes - the biotypes of damage to apply
|
|
* * bodytypes - the bodytypes of damage to apply
|
|
* * forced - whether or not this is forced damage
|
|
*/
|
|
/datum/unit_test/mob_damage/proc/test_set_damage(mob/living/testing_mob, amount, expected, amount_after, included_types, biotypes, bodytypes, forced)
|
|
if(isnull(amount_after))
|
|
amount_after = testing_mob.getStaminaLoss() - expected
|
|
if(!set_damage(testing_mob, amount, expected, included_types, biotypes, bodytypes, forced))
|
|
return FALSE
|
|
if(!verify_damage(testing_mob, amount_after, included_types))
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/**
|
|
* Check that the mob has a specific amount of damage
|
|
*
|
|
* By default this checks that the mob has <amount> of every type of damage.
|
|
* Arguments:
|
|
* * testing_mob - the mob to check the damage of
|
|
* * amount - the amount of damage to verify that the mob has
|
|
* * included_types - Bitflag of damage types to check.
|
|
*/
|
|
/datum/unit_test/mob_damage/proc/verify_damage(mob/living/testing_mob, amount, included_types = ALL)
|
|
if(included_types & TOXLOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getToxLoss(), amount, \
|
|
"[testing_mob] should have [amount] toxin damage, instead they have [testing_mob.getToxLoss()]!")
|
|
if(included_types & CLONELOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getCloneLoss(), amount, \
|
|
"[testing_mob] should have [amount] clone damage, instead they have [testing_mob.getCloneLoss()]!")
|
|
if(included_types & BRUTELOSS)
|
|
TEST_ASSERT_EQUAL(round(testing_mob.getBruteLoss(), 1), amount, \
|
|
"[testing_mob] should have [amount] brute damage, instead they have [testing_mob.getBruteLoss()]!")
|
|
if(included_types & FIRELOSS)
|
|
TEST_ASSERT_EQUAL(round(testing_mob.getFireLoss(), 1), amount, \
|
|
"[testing_mob] should have [amount] burn damage, instead they have [testing_mob.getFireLoss()]!")
|
|
if(included_types & OXYLOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getOxyLoss(), amount, \
|
|
"[testing_mob] should have [amount] oxy damage, instead they have [testing_mob.getOxyLoss()]!")
|
|
if(included_types & STAMINALOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getStaminaLoss(), amount, \
|
|
"[testing_mob] should have [amount] stamina damage, instead they have [testing_mob.getStaminaLoss()]!")
|
|
return TRUE
|
|
|
|
/**
|
|
* Apply a specific amount of damage to the mob using adjustBruteLoss(), adjustToxLoss(), etc.
|
|
*
|
|
* By default this applies <amount> damage of every type to the mob, and checks that the damage procs return the <expected> value
|
|
* Arguments:
|
|
* * testing_mob - the mob to apply the damage to
|
|
* * amount - the amount of damage to apply to the mob
|
|
* * expected - what the expected return value of the damage proc is
|
|
* * included_types - Bitflag of damage types to apply
|
|
* * biotypes - the biotypes of damage to apply
|
|
* * bodytypes - the bodytypes of damage to apply
|
|
* * forced - whether or not this is forced damage
|
|
*/
|
|
/datum/unit_test/mob_damage/proc/apply_damage(mob/living/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE)
|
|
var/damage_returned
|
|
if(included_types & TOXLOSS)
|
|
damage_returned = testing_mob.adjustToxLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustToxLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & CLONELOSS)
|
|
damage_returned = testing_mob.adjustCloneLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustCloneLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & BRUTELOSS)
|
|
damage_returned = round(testing_mob.adjustBruteLoss(amount, updating_health = FALSE, forced = forced, required_bodytype = bodytypes), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustBruteLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & FIRELOSS)
|
|
damage_returned = round(testing_mob.adjustFireLoss(amount, updating_health = FALSE, forced = forced, required_bodytype = bodytypes), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustFireLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & OXYLOSS)
|
|
damage_returned = testing_mob.adjustOxyLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustOxyLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & STAMINALOSS)
|
|
damage_returned = testing_mob.adjustStaminaLoss(amount, updating_stamina = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"adjustStaminaLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
return TRUE
|
|
|
|
/**
|
|
* Set a specific amount of damage for the mob using setBruteLoss(), setToxLoss(), etc.
|
|
*
|
|
* By default this sets every type of damage to <amount> for the mob, and checks that the damage procs return the <expected> value
|
|
* Arguments:
|
|
* * testing_mob - the mob to apply the damage to
|
|
* * amount - the amount of damage to apply to the mob
|
|
* * expected - what the expected return value of the damage proc is
|
|
* * included_types - Bitflag of damage types to apply
|
|
* * biotypes - the biotypes of damage to apply
|
|
* * bodytypes - the bodytypes of damage to apply
|
|
* * forced - whether or not this is forced damage
|
|
*/
|
|
/datum/unit_test/mob_damage/proc/set_damage(mob/living/testing_mob, amount, expected = -amount, included_types = ALL, biotypes = ALL, bodytypes = ALL, forced = FALSE)
|
|
var/damage_returned
|
|
if(included_types & TOXLOSS)
|
|
damage_returned = testing_mob.setToxLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setToxLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & CLONELOSS)
|
|
damage_returned = testing_mob.setCloneLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setCloneLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & BRUTELOSS)
|
|
damage_returned = round(testing_mob.setBruteLoss(amount, updating_health = FALSE, forced = forced), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setBruteLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & FIRELOSS)
|
|
damage_returned = round(testing_mob.setFireLoss(amount, updating_health = FALSE, forced = forced), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setFireLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & OXYLOSS)
|
|
damage_returned = testing_mob.setOxyLoss(amount, updating_health = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setOxyLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
if(included_types & STAMINALOSS)
|
|
damage_returned = testing_mob.setStaminaLoss(amount, updating_stamina = FALSE, forced = forced, required_biotype = biotypes)
|
|
TEST_ASSERT_EQUAL(damage_returned, expected, \
|
|
"setStaminaLoss() should have returned [expected], but returned [damage_returned] instead!")
|
|
return TRUE
|
|
|
|
/// Sanity tests damage and healing using adjustToxLoss, adjustBruteLoss, etc
|
|
/datum/unit_test/mob_damage/proc/test_sanity_simple(mob/living/carbon/human/consistent/dummy)
|
|
// Apply 5 damage and then heal it
|
|
if(!test_apply_damage(dummy, amount = 5))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly")
|
|
|
|
if(!test_apply_damage(dummy, amount = -5))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly")
|
|
|
|
// Apply 15 damage and heal 3
|
|
if(!test_apply_damage(dummy, amount = 15))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly")
|
|
|
|
if(!test_apply_damage(dummy, amount = -3))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! underhealing was not applied correctly")
|
|
|
|
// Now overheal by 666. It should heal for 12.
|
|
|
|
if(!test_apply_damage(dummy, amount = -666, expected = 12))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! overhealing was not applied correctly")
|
|
|
|
// Now test the damage setter procs
|
|
|
|
// set all types of damage to 5
|
|
if(!test_set_damage(dummy, amount = 5, expected = -5))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to set damage to 5")
|
|
// now try healing 5
|
|
if(!test_set_damage(dummy, amount = 0, expected = 5))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to set damage to 0")
|
|
|
|
/// Sanity tests damage and healing using the more complex procs like take_overall_damage(), heal_overall_damage(), etc
|
|
/datum/unit_test/mob_damage/proc/test_sanity_complex(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
|
|
var/damage_returned
|
|
// take 5 brute, 2 burn
|
|
damage_returned = round(dummy.take_bodypart_damage(5, 2, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, -7, \
|
|
"take_bodypart_damage() should have returned -7, but returned [damage_returned] instead!")
|
|
|
|
TEST_ASSERT_EQUAL(round(dummy.getBruteLoss(), 1), 5, \
|
|
"Dummy should have 5 brute damage, instead they have [dummy.getBruteLoss()]!")
|
|
TEST_ASSERT_EQUAL(round(dummy.getFireLoss(), 1), 2, \
|
|
"Dummy should have 2 burn damage, instead they have [dummy.getFireLoss()]!")
|
|
|
|
// heal 4 brute, 1 burn
|
|
damage_returned = round(dummy.heal_bodypart_damage(4, 1, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 5, \
|
|
"heal_bodypart_damage() should have returned 5, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(dummy, 1, included_types = BRUTELOSS|FIRELOSS))
|
|
TEST_FAIL("heal_bodypart_damage did not apply its healing correctly on the mob!")
|
|
|
|
// heal 1 brute, 1 burn
|
|
damage_returned = round(dummy.heal_overall_damage(1, 1, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 2, \
|
|
"heal_overall_damage() should have returned 2, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS))
|
|
TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mob!")
|
|
|
|
// take 50 brute, 50 burn
|
|
damage_returned = round(dummy.take_overall_damage(50, 50, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, -100, \
|
|
"take_overall_damage() should have returned -100, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS))
|
|
TEST_FAIL("take_overall_damage did not apply its damage correctly on the mob!")
|
|
|
|
// testing negative damage amount args with the overall damage procs - the sign should be ignored for these procs
|
|
|
|
damage_returned = round(dummy.take_bodypart_damage(-5, -5, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, -10, \
|
|
"take_bodypart_damage() should have returned -10, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = round(dummy.heal_bodypart_damage(-5, -5, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 10, \
|
|
"heal_bodypart_damage() should have returned 10, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = round(dummy.take_overall_damage(-5, -5, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, -10, \
|
|
"take_overall_damage() should have returned -10, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = round(dummy.heal_overall_damage(-5, -5, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 10, \
|
|
"heal_overall_damage() should have returned 10, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(dummy, 50, included_types = BRUTELOSS|FIRELOSS))
|
|
TEST_FAIL("heal_overall_damage did not apply its healingcorrectly on the mob!")
|
|
|
|
// testing overhealing
|
|
|
|
damage_returned = round(dummy.heal_overall_damage(75, 99, updating_health = FALSE), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 100, \
|
|
"heal_overall_damage() should have returned 100, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(dummy, 0, included_types = BRUTELOSS|FIRELOSS))
|
|
TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mob!")
|
|
|
|
/// Tests damage procs with godmode on
|
|
/datum/unit_test/mob_damage/proc/test_godmode(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
// flip godmode bit to 1
|
|
dummy.status_flags ^= GODMODE
|
|
|
|
// Apply 9 damage and then heal it
|
|
if(!test_apply_damage(dummy, amount = 9, expected = 0))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_godmode! mob took damage despite having godmode enabled.")
|
|
|
|
if(!test_apply_damage(dummy, amount = -9, expected = 0))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_godmode! mob healed when they should've been at full health.")
|
|
|
|
// Apply 11 damage and then heal it, this time with forced enabled. The damage should go through regardless of godmode.
|
|
if(!test_apply_damage(dummy, amount = 11, forced = TRUE))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_godmode! godmode did not respect forced = TRUE")
|
|
|
|
if(!test_apply_damage(dummy, amount = -11, forced = TRUE))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_godmode! godmode did not respect forced = TRUE")
|
|
|
|
// flip godmode bit back to 0
|
|
dummy.status_flags ^= GODMODE
|
|
|
|
/// Testing biotypes
|
|
/datum/unit_test/mob_damage/proc/test_biotypes(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
// Testing biotypes using a plasmaman, who is MOB_MINERAL and MOB_HUMANOID
|
|
dummy.set_species(/datum/species/plasmaman)
|
|
|
|
// argumentless default: should default to required_biotype = ALL. The damage should be applied in that case.
|
|
if(!test_apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS))
|
|
TEST_FAIL("ABOVE FAILURE: plasmaman did not take damage with biotypes = ALL")
|
|
|
|
// If we specify MOB_ORGANIC, the damage should not get applied because plasmamen lack that biotype.
|
|
if(!test_apply_damage(dummy, 1, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC))
|
|
TEST_FAIL("ABOVE FAILURE: plasmaman took damage with biotypes = MOB_ORGANIC")
|
|
|
|
// Now if we specify MOB_MINERAL the damage should get applied.
|
|
if(!test_apply_damage(dummy, 1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL))
|
|
TEST_FAIL("ABOVE FAILURE: plasmaman did not take damage with biotypes = MOB_MINERAL")
|
|
|
|
// Transform back to human
|
|
dummy.set_species(/datum/species/human)
|
|
|
|
// We have 2 damage presently.
|
|
// Try to heal it; let's specify MOB_MINERAL, which should no longer work because we have changed back to a human.
|
|
if(!test_apply_damage(dummy, -2, expected = 0, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL))
|
|
TEST_FAIL("ABOVE FAILURE: human took damage with biotypes = MOB_MINERAL")
|
|
|
|
// Force heal some of the damage. When forced = TRUE the damage/healing gets applied no matter what.
|
|
if(!test_apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_MINERAL, forced = TRUE))
|
|
TEST_FAIL("ABOVE FAILURE: human did not get healed when biotypes = MOB_MINERAL and forced = TRUE")
|
|
|
|
// Now heal the rest of it with the correct biotype. Make sure that this works. We should have 0 damage afterwards.
|
|
if(!test_apply_damage(dummy, -1, included_types = TOXLOSS|CLONELOSS|STAMINALOSS, biotypes = MOB_ORGANIC))
|
|
TEST_FAIL("ABOVE FAILURE: human did not get healed with biotypes = MOB_ORGANIC")
|
|
|
|
/// Testing oxyloss with the TRAIT_NOBREATH
|
|
/datum/unit_test/mob_damage/proc/test_nobreath(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
|
|
// TRAIT_NOBREATH is supposed to prevent oxyloss damage (but not healing). Let's make sure that's the case.
|
|
ADD_TRAIT(dummy, TRAIT_NOBREATH, TRAIT_SOURCE_UNIT_TESTS)
|
|
// force some oxyloss here
|
|
dummy.setOxyLoss(2, updating_health = FALSE, forced = TRUE)
|
|
|
|
// Try to take more oxyloss damage with TRAIT_NOBREATH. It should not work.
|
|
if(!test_apply_damage(dummy, 2, expected = 0, amount_after = dummy.getOxyLoss(), included_types = OXYLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_nobreath! mob took oxyloss damage while having TRAIT_NOBREATH")
|
|
|
|
// Make sure we are still be able to heal the oxyloss. This should work.
|
|
if(!test_apply_damage(dummy, -2, amount_after = dummy.getOxyLoss()-2, included_types = OXYLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_nobreath! mob could not heal oxyloss damage while having TRAIT_NOBREATH")
|
|
|
|
REMOVE_TRAIT(dummy, TRAIT_NOBREATH, TRAIT_SOURCE_UNIT_TESTS)
|
|
|
|
/// Testing toxloss with TRAIT_TOXINLOVER and TRAIT_TOXIMMUNE
|
|
/datum/unit_test/mob_damage/proc/test_toxintraits(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
|
|
// TRAIT_TOXINLOVER is supposed to invert toxin damage and healing. Things that would normally cause toxloss now heal it, and vice versa.
|
|
ADD_TRAIT(dummy, TRAIT_TOXINLOVER, TRAIT_SOURCE_UNIT_TESTS)
|
|
// force some toxloss here
|
|
dummy.setToxLoss(2, updating_health = FALSE, forced = TRUE)
|
|
|
|
// Try to take more toxloss damage with TRAIT_TOXINLOVER. It should heal instead.
|
|
if(!test_apply_damage(dummy, 2, expected = 2, amount_after = dummy.getToxLoss()-2, included_types = TOXLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not heal from toxin damage with TRAIT_TOXINLOVER")
|
|
|
|
// If we try to heal the toxloss we should take damage instead
|
|
if(!test_apply_damage(dummy, -2, expected = -2, amount_after = dummy.getToxLoss()+2, included_types = TOXLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not take damage from toxin healing with TRAIT_TOXINLOVER")
|
|
|
|
// TOXIMMUNE trait should prevent the damage you get from being healed by toxins medicines while having TRAIT_TOXINLOVER
|
|
ADD_TRAIT(dummy, TRAIT_TOXIMMUNE, TRAIT_SOURCE_UNIT_TESTS)
|
|
|
|
// need to force apply some toxin damage since the TOXIMUNNE trait sets toxloss to 0 upon being added
|
|
dummy.setToxLoss(2, updating_health = FALSE, forced = TRUE)
|
|
|
|
// try to 'heal' again - this time it should just do nothing because we should be immune to any sort of toxin damage - including from inverted healing
|
|
if(!test_apply_damage(dummy, -2, expected = 0, amount_after = dummy.getToxLoss(), included_types = TOXLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob should not have taken any damage or healing with TRAIT_TOXINLOVER + TRAIT_TOXIMMUNE")
|
|
|
|
// ok, let's try taking 'damage'. The inverted damage should still heal mobs with the TOXIMMUNE trait.
|
|
if(!test_apply_damage(dummy, 2, expected = 2, amount_after = dummy.getToxLoss()-2, included_types = TOXLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_toxintraits! mob did not heal from taking toxin damage with TRAIT_TOXINLOVER + TRAIT_TOXIMMUNE")
|
|
|
|
REMOVE_TRAIT(dummy, TRAIT_TOXINLOVER, TRAIT_SOURCE_UNIT_TESTS)
|
|
REMOVE_TRAIT(dummy, TRAIT_TOXIMMUNE, TRAIT_SOURCE_UNIT_TESTS)
|
|
|
|
/// Testing cloneloss with TRAIT_NOCLONELOSS
|
|
/datum/unit_test/mob_damage/proc/test_nocloneloss(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
|
|
// TRAIT_TRAIT_NOCLONELOSS is supposed to prevent cloneloss damage and healing. Let's make sure that's the case.
|
|
ADD_TRAIT(dummy, TRAIT_NOCLONELOSS, TRAIT_SOURCE_UNIT_TESTS)
|
|
// force some cloneloss here
|
|
dummy.setCloneLoss(2, updating_health = FALSE, forced = TRUE)
|
|
|
|
// Try to take more cloneloss damage with TRAIT_NOCLONELOSS. It should not work.
|
|
if(!test_apply_damage(dummy, 2, expected = 0, amount_after = dummy.getCloneLoss(), included_types = CLONELOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob took cloneloss damage with TRAIT_NOCLONELOSS")
|
|
|
|
// Healing the cloneloss should not work either, unless we force it
|
|
if(!test_apply_damage(dummy, -2, expected = 0, amount_after = dummy.getCloneLoss(), included_types = CLONELOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob healed cloneloss damage with TRAIT_NOCLONELOSS")
|
|
// so let's force it
|
|
if(!test_apply_damage(dummy, -2, expected = 2, amount_after = dummy.getCloneLoss()-2, included_types = CLONELOSS, forced = TRUE))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_nocloneloss! mob could not heal cloneloss damage with forced = TRUE and TRAIT_NOCLONELOSS")
|
|
|
|
REMOVE_TRAIT(dummy, TRAIT_NOCLONELOSS, TRAIT_SOURCE_UNIT_TESTS)
|
|
|
|
/// Testing heal_ordered_damage()
|
|
/datum/unit_test/mob_damage/proc/test_ordered_healing(mob/living/carbon/human/consistent/dummy)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
dummy.fully_heal(HEAL_DAMAGE)
|
|
var/damage_returned
|
|
|
|
// We apply 20 brute, 20 burn, and 20 toxin damage. 60 damage total
|
|
apply_damage(dummy, 20, included_types = TOXLOSS|BRUTELOSS|FIRELOSS)
|
|
|
|
// Heal 30 damage of that, starting from brute
|
|
damage_returned = round(dummy.heal_ordered_damage(30, list(BRUTE, BURN, TOX)), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 30, \
|
|
"heal_ordered_damage() should have returned 30, but returned [damage_returned] instead!")
|
|
|
|
// Should have 10 burn damage and 20 toxins damage remaining, let's check
|
|
TEST_ASSERT_EQUAL(dummy.getBruteLoss(), 0, \
|
|
"[src] should have 0 brute damage, but has [dummy.getBruteLoss()] instead!")
|
|
TEST_ASSERT_EQUAL(dummy.getFireLoss(), 10, \
|
|
"[src] should have 10 burn damage, but has [dummy.getFireLoss()] instead!")
|
|
TEST_ASSERT_EQUAL(dummy.getToxLoss(), 20, \
|
|
"[src] should have 20 toxin damage, but has [dummy.getToxLoss()] instead!")
|
|
|
|
// Now heal the remaining 30, overhealing by 5.
|
|
damage_returned = round(dummy.heal_ordered_damage(35, list(BRUTE, BURN, TOX)), 1)
|
|
TEST_ASSERT_EQUAL(damage_returned, 30, \
|
|
"heal_ordered_damage() should have returned 30, but returned [damage_returned] instead!")
|
|
|
|
// Should have no damage remaining
|
|
TEST_ASSERT_EQUAL(dummy.getBruteLoss(), 0, \
|
|
"[src] should have 0 brute damage, but has [dummy.getBruteLoss()] instead!")
|
|
TEST_ASSERT_EQUAL(dummy.getFireLoss(), 0, \
|
|
"[src] should have 0 burn damage, but has [dummy.getFireLoss()] instead!")
|
|
TEST_ASSERT_EQUAL(dummy.getToxLoss(), 0, \
|
|
"[src] should have 0 toxin damage, but has [dummy.getToxLoss()] instead!")
|
|
|
|
/// Tests that mob damage procs are working as intended for basic mobs
|
|
/datum/unit_test/mob_damage/basic
|
|
|
|
/datum/unit_test/mob_damage/basic/Run()
|
|
SSmobs.pause()
|
|
var/mob/living/basic/mouse/gray/gusgus = allocate(/mob/living/basic/mouse/gray)
|
|
// give gusgus a damage_coeff of 1 for this test
|
|
gusgus.damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 1, OXY = 1)
|
|
// tank mouse
|
|
gusgus.maxHealth = 200
|
|
|
|
test_sanity_simple(gusgus)
|
|
test_sanity_complex(gusgus)
|
|
|
|
/**
|
|
* Check that the mob has a specific amount of damage. Note: basic mobs have all incoming damage types besides stam converted into brute damage.
|
|
*
|
|
* By default this checks that the mob has <amount> of every type of damage.
|
|
* Arguments:
|
|
* * testing_mob - the mob to check the damage of
|
|
* * amount - the amount of damage to verify that the mob has
|
|
* * expected - the expected return value of the damage procs, if it differs from the default of (amount * 5)
|
|
* * included_types - Bitflag of damage types to check.
|
|
*/
|
|
/datum/unit_test/mob_damage/basic/verify_damage(mob/living/testing_mob, amount, expected, included_types = ALL)
|
|
if(included_types & TOXLOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getToxLoss(), 0, \
|
|
"[testing_mob] should have [0] toxin damage, instead they have [testing_mob.getToxLoss()]!")
|
|
if(included_types & CLONELOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getCloneLoss(), 0, \
|
|
"[testing_mob] should have [0] clone damage, instead they have [testing_mob.getCloneLoss()]!")
|
|
if(included_types & BRUTELOSS)
|
|
TEST_ASSERT_EQUAL(round(testing_mob.getBruteLoss(), 1), expected || amount * 5, \
|
|
"[testing_mob] should have [expected || amount * 5] brute damage, instead they have [testing_mob.getBruteLoss()]!")
|
|
if(included_types & FIRELOSS)
|
|
TEST_ASSERT_EQUAL(round(testing_mob.getFireLoss(), 1), 0, \
|
|
"[testing_mob] should have [0] burn damage, instead they have [testing_mob.getFireLoss()]!")
|
|
if(included_types & OXYLOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getOxyLoss(), 0, \
|
|
"[testing_mob] should have [0] oxy damage, instead they have [testing_mob.getOxyLoss()]!")
|
|
if(included_types & STAMINALOSS)
|
|
TEST_ASSERT_EQUAL(testing_mob.getStaminaLoss(), amount, \
|
|
"[testing_mob] should have [amount] stamina damage, instead they have [testing_mob.getStaminaLoss()]!")
|
|
return TRUE
|
|
|
|
/datum/unit_test/mob_damage/basic/test_sanity_simple(mob/living/basic/mouse/gray/gusgus)
|
|
// check to see if basic mob damage works
|
|
|
|
// Simple damage and healing
|
|
// Take 1 damage, heal for 1
|
|
if(!test_apply_damage(gusgus, amount = 1))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly")
|
|
|
|
if(!test_apply_damage(gusgus, amount = -1))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly")
|
|
|
|
// Give 2 damage of every time (translates to 10 brute, 2 staminaloss)
|
|
if(!test_apply_damage(gusgus, amount = 2))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! damage was not applied correctly")
|
|
|
|
// underhealing: heal 1 damage of every type (translates to 5 brute, 1 staminaloss)
|
|
if(!test_apply_damage(gusgus, amount = -1))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! healing was not applied correctly")
|
|
|
|
// overhealing
|
|
|
|
// heal 11 points of toxloss (should take care of all 5 brute damage remaining)
|
|
if(!apply_damage(gusgus, -11, expected = 5, included_types = TOXLOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! toxloss was not applied correctly")
|
|
// heal the remaining point of staminaloss
|
|
if(!apply_damage(gusgus, -11, expected = 1, included_types = STAMINALOSS))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! failed to heal staminaloss correctly")
|
|
// heal 35 points of each type, we should already be at full health so nothing should happen
|
|
if(!test_apply_damage(gusgus, amount = -35, expected = 0))
|
|
TEST_FAIL("ABOVE FAILURE: failed test_sanity_simple! overhealing was not applied correctly")
|
|
|
|
/datum/unit_test/mob_damage/basic/test_sanity_complex(mob/living/basic/mouse/gray/gusgus)
|
|
// Heal up, so that errors from the previous tests we won't cause this one to fail
|
|
gusgus.fully_heal(HEAL_DAMAGE)
|
|
var/damage_returned
|
|
// overall damage procs
|
|
|
|
// take 5 brute, 2 burn
|
|
damage_returned = gusgus.take_bodypart_damage(5, 2, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, -7, \
|
|
"take_bodypart_damage() should have returned -7, but returned [damage_returned] instead!")
|
|
|
|
TEST_ASSERT_EQUAL(gusgus.bruteloss, 7, \
|
|
"Mouse should have 7 brute damage, instead they have [gusgus.bruteloss]!")
|
|
TEST_ASSERT_EQUAL(gusgus.fireloss, 0, \
|
|
"Mouse should have 0 burn damage, instead they have [gusgus.fireloss]!")
|
|
|
|
// heal 4 brute, 1 burn
|
|
damage_returned = gusgus.heal_bodypart_damage(4, 1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, 5, \
|
|
"heal_bodypart_damage() should have returned 5, but returned [damage_returned] instead!")
|
|
|
|
TEST_ASSERT_EQUAL(gusgus.bruteloss, 2, \
|
|
"Mouse should have 2 brute damage, instead they have [gusgus.bruteloss]!")
|
|
TEST_ASSERT_EQUAL(gusgus.fireloss, 0, \
|
|
"Mouse should have 0 burn damage, instead they have [gusgus.fireloss]!")
|
|
|
|
// heal 1 brute, 1 burn
|
|
damage_returned = gusgus.heal_overall_damage(1, 1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, 2, \
|
|
"heal_overall_damage() should have returned 2, but returned [damage_returned] instead!")
|
|
|
|
TEST_ASSERT_EQUAL(gusgus.bruteloss, 0, \
|
|
"Mouse should have 0 brute damage, instead they have [gusgus.bruteloss]!")
|
|
TEST_ASSERT_EQUAL(gusgus.fireloss, 0, \
|
|
"Mouse should have 0 burn damage, instead they have [gusgus.fireloss]!")
|
|
|
|
// take 50 brute, 50 burn
|
|
damage_returned = gusgus.take_overall_damage(3, 3, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, -6, \
|
|
"take_overall_damage() should have returned -6, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS))
|
|
TEST_FAIL("take_overall_damage did not apply its damage correctly on the mouse!")
|
|
|
|
// testing negative args with the overall damage procs
|
|
|
|
damage_returned = gusgus.take_bodypart_damage(-1, -1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, -2, \
|
|
"take_bodypart_damage() should have returned -2, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = gusgus.heal_bodypart_damage(-1, -1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, 2, \
|
|
"heal_bodypart_damage() should have returned 2, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = gusgus.take_overall_damage(-1, -1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, -2, \
|
|
"take_overall_damage() should have returned -2, but returned [damage_returned] instead!")
|
|
|
|
damage_returned = gusgus.heal_overall_damage(-1, -1, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, 2, \
|
|
"heal_overall_damage() should have returned 2, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(gusgus, 1, expected = 6, included_types = BRUTELOSS))
|
|
TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!")
|
|
|
|
// testing overhealing
|
|
|
|
damage_returned = gusgus.heal_overall_damage(75, 99, updating_health = FALSE)
|
|
TEST_ASSERT_EQUAL(damage_returned, 6, \
|
|
"heal_overall_damage() should have returned 6, but returned [damage_returned] instead!")
|
|
|
|
if(!verify_damage(gusgus, 0, included_types = BRUTELOSS))
|
|
TEST_FAIL("heal_overall_damage did not apply its healing correctly on the mouse!")
|