Files
Bubberstation/code/modules/unit_tests/strange_reagent.dm
John Willard 8442124bcd Gondolas are now basic mobs (#83451)
## About The Pull Request

This PR turns gondolas into basic mobs and does some fiddling with
gondola pods
Their verbs are now action buttons which they lose upon delivering. If
set to stay, they won't have their abilities afterwards (or wont get
them in the first place if the delivery is already done).
Lets them survive without a pod requirement in case admins want to spawn
one for their own stuff, so I also removed it from the snowflake checks
to exclude them from stuff.

Also replaced the hardcoded "cant speak" with simply giving the mute
trait, so admins can make gondolas speak if they want to for any reason.

## Why It's Good For The Game

The pet level of simple animals can finally be killed off, also gives
admins more control over gondola-related stuff if they so wish.

## Changelog

🆑
refactor: Gondolas (including gondola pods) are now basic mobs.
/🆑

---------

Co-authored-by: san7890 <the@san7890.com>
2024-05-31 16:48:31 -06:00

159 lines
6.3 KiB
Plaintext

/// Checks to ensure strange reagent works as expected
/datum/unit_test/strange_reagent
priority = TEST_LONGER
var/datum/reagent/medicine/strange_reagent/instant/strange_reagent
var/target_max_health
var/amount_needed_to_full_heal
var/amount_needed_to_revive
/datum/unit_test/strange_reagent/Run()
strange_reagent = new
var/list/types_to_check = typecacheof(list(
/mob/living/carbon/human/consistent,
/mob/living/simple_animal,
/mob/living/basic,
))
types_to_check -= typesof(/mob/living/simple_animal/hostile/megafauna) // no
types_to_check -= typesof(/mob/living/basic/mouse) // qdel themselves on death; why dont they use DEL_ON_DEATH you might ask. I-unno
types_to_check -= typesof(/mob/living/basic/slime) // if they roll the 50% chance to spawn as an adult, they can just at random split and qdel themselves
for(var/mob/living/type as anything in types_to_check)
var/mob/living/target = allocate_new_target(type)
var/is_basic = istype(target, /mob/living/basic)
var/is_simple = istype(target, /mob/living/simple_animal)
// check some basic stuff
if(target.status_flags & GODMODE)
continue
if(!(target.mob_biotypes & MOB_ORGANIC))
continue
if(is_simple)
var/mob/living/simple_animal/simple_animal = target
if(simple_animal.del_on_death)
continue
simple_animal.loot?.Cut()
if(is_basic)
var/mob/living/basic/basic = target
if(basic.basic_mob_flags & DEL_ON_DEATH)
continue
test_damage_but_no_death(type)
test_death_no_damage(type)
test_death_with_damage(type)
test_death_with_damage_but_not_enough_reagent(type)
if(!is_basic && !is_simple) // simple/basic mobs cannot have negative health
test_death_with_full_heal(type)
test_death_from_damage(type)
test_death_from_too_much_damage(type)
// cleanup our vars
QDEL_NULL(strange_reagent)
allocate_new_target(null)
/datum/unit_test/strange_reagent/proc/allocate_new_target(type)
// cache the last one created so that we don't create N instances of the exact same mob
var/static/mob/living/pre_allocated
if(!type)
pre_allocated = null
return
if(pre_allocated?.type == type)
pre_allocated.revive(ALL) // for some reason HEAL_ADMIN doesn't work?
return pre_allocated
pre_allocated = allocate(type)
target_max_health = pre_allocated.getMaxHealth()
update_amounts(pre_allocated)
return pre_allocated
/datum/unit_test/strange_reagent/proc/update_amounts(mob/living/target)
amount_needed_to_full_heal = strange_reagent.calculate_amount_needed_to_full_heal(target)
amount_needed_to_revive = strange_reagent.calculate_amount_needed_to_revive(target)
/datum/unit_test/strange_reagent/proc/damage_target_to_percentage(mob/living/target, percent)
var/damage = target_max_health * percent * 0.5
target.setBruteLoss(damage, updating_health=FALSE) // no point running health update logic here
target.setFireLoss(damage, updating_health=TRUE) // since we do it here
update_amounts(target)
if(percent >= 1)
target.death()
return TRUE
/datum/unit_test/strange_reagent/proc/get_target_organic_health_manual(mob/living/target)
return target.getMaxHealth() - (target.getBruteLoss() + target.getFireLoss())
/datum/unit_test/strange_reagent/proc/test_damage_but_no_death(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, 0.8))
return
var/health = get_target_organic_health_manual(target)
strange_reagent.expose_mob(target, INGEST, 20)
TEST_ASSERT_EQUAL(health, get_target_organic_health_manual(target), "Strange Reagent healed a target type [target.type] that was not dead.")
/datum/unit_test/strange_reagent/proc/test_death_no_damage(target_type)
var/mob/living/target = allocate_new_target(target_type)
target.death()
if(QDELETED(target))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive)
TEST_ASSERT_NOTEQUAL(target.stat, DEAD, "Strange Reagent did not revive a dead target type [target.type].")
/datum/unit_test/strange_reagent/proc/test_death_with_damage(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, 0.8))
return
target.death()
if(QDELETED(target))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive)
TEST_ASSERT_NOTEQUAL(target.stat, DEAD, "Strange Reagent did not revive a dead target type [target.type].")
/datum/unit_test/strange_reagent/proc/test_death_with_damage_but_not_enough_reagent(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, 1.2))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive - 1)
TEST_ASSERT_EQUAL(target.stat, DEAD, "Strange Reagent revived a dead target type [target.type] without enough reagent.")
/datum/unit_test/strange_reagent/proc/test_death_with_full_heal(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, 0.8))
return
target.death()
if(QDELETED(target))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_full_heal)
TEST_ASSERT_EQUAL(target_max_health, get_target_organic_health_manual(target), "Strange Reagent did not fully heal a dead target type [target.type] with the expected amount.")
/datum/unit_test/strange_reagent/proc/test_death_from_damage(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, strange_reagent.max_revive_damage_ratio * 0.9)) // 10% under the damage cap
return
if(QDELETED(target))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive)
TEST_ASSERT_NOTEQUAL(target.stat, DEAD, "Strange Reagent did not revive a target type [target.type] who died from damage.")
/datum/unit_test/strange_reagent/proc/test_death_from_too_much_damage(target_type)
var/mob/living/target = allocate_new_target(target_type)
if(!damage_target_to_percentage(target, strange_reagent.max_revive_damage_ratio * 1.1)) // 10% over the damage cap
return
if(QDELETED(target))
return
update_amounts(target)
strange_reagent.expose_mob(target, INGEST, amount_needed_to_revive)
TEST_ASSERT_EQUAL(target.stat, DEAD, "Strange Reagent revived a target type [target.type] with more than double their max health in damage.")