test: extend coverage of testBoss

This commit is contained in:
dualfroz committed 2026-09-10 21:16:45 +02:00
1 parent 41e4b6f89f
commit e61823788a
1 file changed
+160
+160
View File
@@ -314,3 +314,163 @@ VF_TEST(theWitherIsCalledOutOfASoulSandPatternInEitherOrientation) {
CHECK(findWitherPattern(alongZ, base, orientation)); CHECK(findWitherPattern(alongZ, base, orientation));
CHECK(!orientation); CHECK(!orientation);
WitherFight fight(11u);
CHECK(fight.state().phase == BossPhase::Dormant);
CHECK(!fight.state().bar.visible);
CHECK(fight.summonFromWorld(alongX, base));
CHECK(fight.state().phase == BossPhase::Summoning);
CHECK(fight.state().bar.visible);
CHECK(fight.state().bar.style == BossBarStyle::Notched6);
CHECK_NEAR(fight.state().position.y, static_cast<float>(base.y + 1), 1e-6f);
// The pattern is consumed, so the same altar cannot be reused.
CHECK(alongX.blockAt(base.x, base.y, base.z) == Block::Air);
CHECK(alongX.blockAt(base.x, base.y + 2, base.z) == Block::Air);
WitherFight second(12u);
CHECK(!second.summonFromWorld(alongX, base));
CHECK(second.state().phase == BossPhase::Dormant);
World broken = witherAltar(base, true);
broken.setBlock(base.x, base.y + 2, base.z, Block::Stone);
CHECK(!findWitherPattern(broken, base, orientation));
}
VF_TEST(theWitherIsUntouchableWhileItChargesAndBlastsOnArrival) {
WitherFight fight(5u, quickSummon(6));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});
std::vector<WitherTarget> targets;
targets.push_back(WitherTarget{Vec3{4.0f, 64.0f, 0.0f}, 20.0f, true});
targets.push_back(WitherTarget{Vec3{40.0f, 64.0f, 0.0f}, 20.0f, true});
std::vector<WitherHit> heavy;
heavy.push_back(WitherHit{100.0f, false});
for (int step = 0; step < 5; ++step) {
BossTickReport report = fight.tick(heavy, targets);
CHECK(report.phase == BossPhase::Summoning);
CHECK_NEAR(report.bossHealth, fight.settings().maxHealth, 1e-4f);
}
BossTickReport blast = fight.tick(heavy, targets);
CHECK(blast.phase == BossPhase::Explosive);
CHECK(blast.phaseChanged);
CHECK_NEAR(blast.damageToTargets, fight.settings().summonBlastDamage, 1e-4f);
CHECK_NEAR(targets[0].health, 20.0f - fight.settings().summonBlastDamage, 1e-4f);
CHECK_NEAR(targets[1].health, 20.0f, 1e-4f);
BossTickReport settle = fight.tick(std::vector<WitherHit>{}, targets);
CHECK(settle.phase == BossPhase::Ranged);
}
VF_TEST(theWitherArmoursUpExactlyAtHalfHealth) {
WitherFight fight(21u, quickSummon(3));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});
std::vector<WitherTarget> targets;
targets.push_back(WitherTarget{Vec3{10.0f, 64.0f, 0.0f}, 200.0f, true});
runUpToRangedPhase(fight, targets);
CHECK(fight.state().phase == BossPhase::Ranged);
CHECK(!fight.armored());
float maxHealth = fight.settings().maxHealth;
std::vector<WitherHit> nearlyHalf;
nearlyHalf.push_back(WitherHit{maxHealth * 0.5f - 1.0f, false});
BossTickReport stillBare = fight.tick(nearlyHalf, targets);
CHECK(stillBare.phase == BossPhase::Ranged);
CHECK_NEAR(stillBare.bossHealth, maxHealth * 0.5f + 1.0f, 1e-4f);
CHECK(!fight.armored());
std::vector<WitherHit> theLastPoint;
theLastPoint.push_back(WitherHit{1.0f, false});
BossTickReport onTheLine = fight.tick(theLastPoint, targets);
CHECK_NEAR(onTheLine.bossHealth, maxHealth * 0.5f, 1e-4f);
CHECK(onTheLine.phase == BossPhase::Armored);
CHECK(onTheLine.phaseChanged);
CHECK(fight.armored());
}
VF_TEST(armourStopsProjectilesButNotABladeAndTheWitherRegenerates) {
WitherFight fight(33u, quickSummon(3));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});
std::vector<WitherTarget> targets;
targets.push_back(WitherTarget{Vec3{10.0f, 64.0f, 0.0f}, 400.0f, true});
runUpToRangedPhase(fight, targets);
std::vector<WitherHit> half;
half.push_back(WitherHit{fight.settings().maxHealth * 0.5f, false});
fight.tick(half, targets);
CHECK(fight.armored());
float before = fight.state().health;
std::vector<WitherHit> arrows;
arrows.push_back(WitherHit{60.0f, true});
BossTickReport shrugged = fight.tick(arrows, targets);
CHECK(shrugged.bossHealth >= before);
CHECK(shrugged.healedThisTick > 0.0f);
before = fight.state().health;
std::vector<WitherHit> blade;
blade.push_back(WitherHit{60.0f, false});
BossTickReport cut = fight.tick(blade, targets);
CHECK(cut.bossHealth < before - 50.0f);
CHECK(fight.armored());
}
VF_TEST(theArmouredWitherCallsMinionsUpToItsLimitAndKeepsShooting) {
WitherFight fight(44u, quickSummon(3));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});
std::vector<WitherTarget> targets;
targets.push_back(WitherTarget{Vec3{12.0f, 64.0f, 0.0f}, 100000.0f, true});
runUpToRangedPhase(fight, targets);
std::vector<WitherHit> half;
half.push_back(WitherHit{fight.settings().maxHealth * 0.5f, false});
fight.tick(half, targets);
CHECK(fight.armored());
std::vector<WitherHit> nothing;
float targetHealthBefore = targets[0].health;
for (int step = 0; step < 600; ++step) fight.tick(nothing, targets);
CHECK_EQ(fight.aliveMinionCount(), fight.settings().maxMinions);
CHECK_EQ(fight.state().minionsSummoned, fight.settings().maxMinions);
CHECK(targets[0].health < targetHealthBefore);
CHECK(fight.state().attacksLaunched > 10);
for (const BossMinion& minion : fight.minions()) {
CHECK(minion.alive);
CHECK(behaviorHorizontalDistance(minion.position, fight.state().position) > 0.0f);
}
}
VF_TEST(theWitherAlwaysSwitchesToTheNearestLivingTarget) {
WitherFight fight(55u, quickSummon(3));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});
std::vector<WitherTarget> targets;
targets.push_back(WitherTarget{Vec3{60.0f, 64.0f, 0.0f}, 500.0f, true});
targets.push_back(WitherTarget{Vec3{12.0f, 64.0f, 0.0f}, 500.0f, true});
targets.push_back(WitherTarget{Vec3{90.0f, 64.0f, 0.0f}, 500.0f, true});
runUpToRangedPhase(fight, targets);
std::vector<WitherHit> nothing;
fight.tick(nothing, targets);
CHECK_EQ(fight.state().targetIndex, 1);
targets[1].alive = false;
fight.tick(nothing, targets);
CHECK_EQ(fight.state().targetIndex, 0);
targets[0].alive = false;
targets[2].alive = false;
BossTickReport alone = fight.tick(nothing, targets);
CHECK_EQ(fight.state().targetIndex, -1);
CHECK_NEAR(alone.damageToTargets, 0.0f, 1e-6f);
}
VF_TEST(theWitherDiesWhenItsHealthRunsOutAndStopsTicking) {
WitherFight fight(66u, quickSummon(3));
fight.begin(Vec3{0.0f, 64.0f, 0.0f});