test: cover tests.curseAtRangeHurtsAndWeakens
This commit is contained in:
1 parent
40369e5a09
commit
c3f3bc3c4f
1 file changed
+173
+173
@@ -1665,6 +1665,179 @@ function tests.summonRespectsPopulationCap()
|
|||||||
local minionB = Monsters.create(Monsters.byKey.zombie, 3, 6, 7, 4)
|
local minionB = Monsters.create(Monsters.byKey.zombie, 3, 6, 7, 4)
|
||||||
minionA.summonedBy = necro.id
|
minionA.summonedBy = necro.id
|
||||||
minionB.summonedBy = necro.id
|
minionB.summonedBy = necro.id
|
||||||
|
game.level.entities = { necro, minionA, minionB }
|
||||||
|
local acted = Abilities.tryAct(game, necro)
|
||||||
|
eq(acted, false, "a necromancer already at its summon cap does not summon a third")
|
||||||
|
eq(#game.level.entities, 3, "the level still has exactly the two existing minions")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.curseAtRangeHurtsAndWeakens()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 7, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
local hpBefore = game.player.hp
|
||||||
|
local acted = Abilities.tryAct(game, shaman)
|
||||||
|
eq(acted, true, "a shaman with a clear shot curses instead of moving")
|
||||||
|
eq(game.player.hp, hpBefore - 1, "the curse bolt runs through Combat.damage (shaman attack 2 minus the player's base defense 1)")
|
||||||
|
eq(Status.has(game.player, Status.WEAKEN), true, "the curse also weakens the player")
|
||||||
|
eq(shaman.cooldown, 4, "casting the curse starts its cooldown")
|
||||||
|
ok(contains(game.log:last(), "curses you for 1"), "the logged amount matches the mitigated damage, not a flat number")
|
||||||
|
end
|
||||||
|
|
||||||
|
-- The curse bolt used to bypass Combat.damage entirely (a flat, unmitigated
|
||||||
|
-- subtraction from hp), so a shaman hit for the same 3 no matter how armored
|
||||||
|
-- the player was, never broke a melee combo, and never wore armor - every
|
||||||
|
-- other monster-on-player attack (monsterMelee, monsterShoot, mimic/grave
|
||||||
|
-- ambush) already ran through Combat.damage + Momentum.onDamaged +
|
||||||
|
-- Durability.wearArmor. These three lock in the fix.
|
||||||
|
function tests.curseDamageIsMitigatedByThePlayersDefenseLikeAnyOtherAttack()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 7, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
game.player.defense = game.player.defense + 10
|
||||||
|
local hpBefore = game.player.hp
|
||||||
|
Abilities.tryAct(game, shaman)
|
||||||
|
eq(game.player.hp, hpBefore - 1, "a shaman's attack (2) minus a heavily-defended player floors at Combat.damage's minimum of 1, not a flat 3")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.curseBreaksThePlayersMeleeMomentumStack()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 7, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
game.player.combo = 4
|
||||||
|
Abilities.tryAct(game, shaman)
|
||||||
|
eq(Momentum.stacks(game.player), 0, "a landed curse bolt snaps momentum to zero exactly like a melee hit or a breath attack")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.curseWearsThePlayersEquippedArmor()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 7, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
game.player.armor = { name = "chainmail", kind = Items.ARMOR, power = 2, defense = 2 }
|
||||||
|
Durability.ensure(game.player.armor)
|
||||||
|
local durabilityBefore = game.player.armor.durability
|
||||||
|
Abilities.tryAct(game, shaman)
|
||||||
|
eq(game.player.armor.durability, durabilityBefore - 1, "the curse wears equipped armor exactly like a landed melee or breath hit does")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.curseWithheldWhenAdjacent()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 4, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
local acted = Abilities.tryAct(game, shaman)
|
||||||
|
eq(acted, false, "a shaman standing next to the player withholds its curse")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.shriekAtRangeBlindsThePlayer()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local banshee = Monsters.create(Monsters.byKey.banshee, 1, 7, 6, 5)
|
||||||
|
game.level.entities = { banshee }
|
||||||
|
eq(Status.has(game.player, Status.BLIND), false, "the player starts able to see")
|
||||||
|
local acted = Abilities.tryAct(game, banshee)
|
||||||
|
eq(acted, true, "a banshee with a clear shot shrieks instead of moving")
|
||||||
|
eq(Status.has(game.player, Status.BLIND), true, "the shriek blinds the player")
|
||||||
|
eq(banshee.cooldown, 6, "shrieking starts its cooldown")
|
||||||
|
ok(contains(game.log:last(), "blinds you"), "the shriek is logged")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.shriekWithheldWhenAdjacent()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local banshee = Monsters.create(Monsters.byKey.banshee, 1, 4, 6, 5)
|
||||||
|
game.level.entities = { banshee }
|
||||||
|
local acted = Abilities.tryAct(game, banshee)
|
||||||
|
eq(acted, false, "a banshee standing next to the player withholds its shriek")
|
||||||
|
eq(Status.has(game.player, Status.BLIND), false, "no shriek means no blindness")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.shriekIsUnavailableOutOfRange()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local banshee = Monsters.create(Monsters.byKey.banshee, 1, 20, 6, 5)
|
||||||
|
game.level.entities = { banshee }
|
||||||
|
local acted = Abilities.tryAct(game, banshee)
|
||||||
|
eq(acted, false, "a banshee out of shriek range falls through to its base ai")
|
||||||
|
eq(Status.has(game.player, Status.BLIND), false, "no shriek means no blindness")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.shriekBlindnessReducesTheVictimsEffectiveSightRadius()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local banshee = Monsters.create(Monsters.byKey.banshee, 1, 7, 6, 5)
|
||||||
|
game.level.entities = { banshee }
|
||||||
|
Abilities.tryAct(game, banshee)
|
||||||
|
eq(game:effectiveRadius(), 1, "blind (also inflicted by a banshee) still narrows sight to game.lua's own radius")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.abilityCooldownBlocksImmediateReuse()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local shaman = Monsters.create(Monsters.byKey.shaman, 1, 7, 6, 4)
|
||||||
|
game.level.entities = { shaman }
|
||||||
|
Abilities.tryAct(game, shaman)
|
||||||
|
local hpAfterFirst = game.player.hp
|
||||||
|
local acted = Abilities.tryAct(game, shaman)
|
||||||
|
eq(acted, false, "an ability on cooldown does not fire again")
|
||||||
|
eq(game.player.hp, hpAfterFirst, "no further damage is dealt while on cooldown")
|
||||||
|
for _ = 1, 4 do Abilities.tickCooldown(shaman) end
|
||||||
|
eq(shaman.cooldown, 0, "four ticks fully drains a four-turn cooldown")
|
||||||
|
local actedAgain = Abilities.tryAct(game, shaman)
|
||||||
|
eq(actedAgain, true, "the ability is usable again once its cooldown has ticked down")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.healerMendsNeediestAlly()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local cleric = Monsters.create(Monsters.byKey.cleric, 1, 6, 6, 5)
|
||||||
|
local hurt = Monsters.create(Monsters.byKey.rat, 2, 8, 6, 5)
|
||||||
|
hurt.hp = 1
|
||||||
|
game.level.entities = { cleric, hurt }
|
||||||
|
local acted = Abilities.tryAct(game, cleric)
|
||||||
|
eq(acted, true, "a cleric with a hurt ally in sight heals instead of moving")
|
||||||
|
eq(hurt.hp, 7, "healing restores the fixed amount, capped at max hp")
|
||||||
|
eq(cleric.cooldown, 5, "healing starts its cooldown")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.healerSkipsWhenAlliesAreHealthy()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local cleric = Monsters.create(Monsters.byKey.cleric, 1, 6, 6, 5)
|
||||||
|
local ally = Monsters.create(Monsters.byKey.rat, 2, 8, 6, 5)
|
||||||
|
game.level.entities = { cleric, ally }
|
||||||
|
local acted = Abilities.tryAct(game, cleric)
|
||||||
|
eq(acted, false, "a cleric with no hurt allies falls through to its base ai")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.rallyBuffsAdjacentAllies()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local chieftain = Monsters.create(Monsters.byKey.chieftain, 1, 10, 6, 6)
|
||||||
|
local grunt = Monsters.create(Monsters.byKey.goblin, 2, 11, 6, 6)
|
||||||
|
game.level.entities = { chieftain, grunt }
|
||||||
|
eq(Status.has(grunt, Status.STRENGTH), false, "the grunt starts unbuffed")
|
||||||
|
local acted = Abilities.tryAct(game, chieftain)
|
||||||
|
eq(acted, true, "a chieftain next to an unbuffed ally rallies instead of moving")
|
||||||
|
eq(Status.has(grunt, Status.STRENGTH), true, "rallying buffs the adjacent ally")
|
||||||
|
eq(Status.has(chieftain, Status.STRENGTH), true, "rallying also buffs the chieftain itself")
|
||||||
|
eq(chieftain.cooldown, 8, "rallying starts its cooldown")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.rallySkipsWhenNoUnbuffedAlliesAdjacent()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local chieftain = Monsters.create(Monsters.byKey.chieftain, 1, 10, 6, 6)
|
||||||
|
game.level.entities = { chieftain }
|
||||||
|
local acted = Abilities.tryAct(game, chieftain)
|
||||||
|
eq(acted, false, "a chieftain with no adjacent allies falls through to its base ai")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.healerNeverMendsThePlayersOwnCompanionHirelingOrThrall()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local cleric = Monsters.create(Monsters.byKey.cleric, 1, 6, 6, 5)
|
||||||
|
local companion = Companions.summon(game, "hound")
|
||||||
|
companion.x, companion.y = 8, 6
|
||||||
|
companion.hp = 1
|
||||||
|
game.level.entities = { cleric, companion }
|
||||||
|
local acted = Abilities.tryAct(game, cleric)
|
||||||
|
eq(acted, false, "a hurt companion is not a valid heal target, so the cleric falls through instead")
|
||||||
|
eq(companion.hp, 1, "the player's own companion is left exactly as hurt as it was")
|
||||||
|
end
|
||||||
|
|
||||||
|
function tests.rallyNeverBuffsThePlayersOwnCompanionHirelingOrThrall()
|
||||||
|
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||||
|
local chieftain = Monsters.create(Monsters.byKey.chieftain, 1, 10, 6, 6)
|
||||||
end
|
end
|
||||||
|
|
||||||
function tests.saveLoadRoundTrip()
|
function tests.saveLoadRoundTrip()
|
||||||
|
|||||||
Reference in new issue
Block a user