Files
Bubberstation/code/modules/unit_tests/mouse_bite_cable.dm
John Willard a15a1b88ed Basic mobs now use z-level turnoff instead of simple (#82469)
## About The Pull Request

On one compile of MetaStation, I saw that there's 45 basic mobs on the
station, 256 on lavaland (the number growing from tendrils), and 59 in
all other z levels combined.

While we do expect Lavaland to be visited every round, at least it won't
be running during the times when no one is there, but even more
importantly, space exploration is something not done every round, so we
don't have any reason to waste our resources on AIs that will never be
interacted with.

Simple animals had an easy solution to this:
If no one is on the Z level, their AI turns off
If someone is on the Z level, they are idle unless needed.

The last simple animals that exists right now are bots, megafauna,
geese, gondolas, and some minor ones like mimic, zombie, dark wizard,
soulscythe, etc.
Point is, we're very much nearly done going through all simple animals,
so this code is being wasted just to ensure things like cleanbots won't
work if no one is on the z level, something I doubt happens often, so I
took their code and made it work for basic mobs instead. I could've done
both but I thought it would look very bad, and maybe this is a good
incentivize to get more basic mob conversions.

There's one major change here and it's that we're missing the "Idle"
mode, some basic mobs like the Lavaland village seems to be made with
intent that they'll be running even if players aren't around, so this
sets up a future PR that makes idle AI easier to add, and I want to make
sure those cases are taken into account.

## Why It's Good For The Game

We don't need to always be processing these basic mobs, and sets us in
the future to hopefully also implement idle AIs.

## Changelog

🆑
balance: Basic mob AIs with no mobs on the Z level now stop.
/🆑

---------

Co-authored-by: san7890 <the@san7890.com>
2024-04-06 15:17:53 -06:00

57 lines
3.0 KiB
Plaintext

/// Unit Test to ensure that a mouse bites a cable, gets shocked, and dies.
/datum/unit_test/mouse_bite_cable
/datum/unit_test/mouse_bite_cable/Run()
// use dummy subtype that will bypass the probability check to bite on a cable
var/mob/living/basic/mouse/biter = allocate(/mob/living/basic/mouse/cable_lover)
var/obj/structure/cable/wire = allocate(/obj/structure/cable)
// Make sure the cable has a powernet.
wire.powernet = new()
// Make sure the powernet has a good amount of power!
// mice bites check if there is ANY power in the powernet and passes fine, but better safe than sorry
wire.powernet.avail = 100000
var/turf/open/floor/stage = get_turf(wire)
// the unit tests room has normal flooring so let's just make it be interactable for the sake of this test
stage.underfloor_accessibility = UNDERFLOOR_INTERACTABLE
// relocate the rat
biter.forceMove(stage)
// Ai controlling processes expect a seconds_per_tick, supply a real-fake dt
var/fake_dt = SSai_controllers.wait * 0.1
// Set AI - AIs by default are off in z-levels with no client, we have to force it on.
biter.ai_controller.set_ai_status(AI_STATUS_ON)
// Select behavior - this will queue finding the cable
biter.ai_controller.SelectBehaviors(fake_dt)
// Process behavior - this will execute the "locate the cable" behavior
biter.ai_controller.process(fake_dt)
// Check that the cable was found
TEST_ASSERT(biter.ai_controller.blackboard[BB_LOW_PRIORITY_HUNTING_TARGET] == wire, "Mouse, after executing find, did not set the cable as a target.")
// Select behavior - this will queue hunting
biter.ai_controller.SelectBehaviors(fake_dt)
// Process behavior - this will execute the hunt for the cable and cause a bite (as we're in the min range)
biter.ai_controller.process(fake_dt)
// Check that the cable was removed, as it was hunted correctly
TEST_ASSERT_NULL(biter.ai_controller.blackboard[BB_LOW_PRIORITY_HUNTING_TARGET], "Mouse, after executing hunt, did not clear their target blackboard.")
// Now check that the bite went through - remember we qdel mice on death
TEST_ASSERT(QDELETED(biter), "Mouse, did not die after biting a powered cable.")
TEST_ASSERT(QDELETED(wire), "Cable, was not deleted after being bitten by a mouse.")
// reset the floor to its original state, to be nice to other tests in case that matters
stage.underfloor_accessibility = initial(stage.underfloor_accessibility)
/// Dummy mouse that is guaranteed to die when biting shocked cables.
/mob/living/basic/mouse/cable_lover
cable_zap_prob = 100
ai_controller = /datum/ai_controller/basic_controller/mouse/guaranteed_to_bite
/// Dummy mouse's ai controller that is guaranteed to find and bite a cable beneath it
/datum/ai_controller/basic_controller/mouse/guaranteed_to_bite
planning_subtrees = list(/datum/ai_planning_subtree/find_and_hunt_target/look_for_cables/guaranteed)
/// Cable hunting subtree that's guarantee to hunt its target.
/datum/ai_planning_subtree/find_and_hunt_target/look_for_cables/guaranteed
hunt_chance = 100