test: cover tests.setsDoNotCrossTalkBetweenDifferentSets
This commit is contained in:
1 parent
50131d3e41
commit
6dc9d144d2
1 file changed
+173
+173
@@ -7049,6 +7049,179 @@ end
|
||||
function tests.setsBonusDropsBackWhenAPieceIsUnequipped()
|
||||
local player = {
|
||||
weapon = Sets.create("ironclad", "weapon"),
|
||||
armor = Sets.create("ironclad", "armor"),
|
||||
ring = Sets.create("ironclad", "ring"),
|
||||
}
|
||||
eq(Sets.attackBonus(player), 2, "the full set starts active")
|
||||
player.ring = Items.ring("plain band", 0, 0)
|
||||
eq(Sets.attackBonus(player), 1, "losing a piece drops the bonus back to the 2-piece tier")
|
||||
player.armor = Items.armor("plain mail", 2)
|
||||
eq(Sets.attackBonus(player), 0, "a single remaining piece grants no bonus at all")
|
||||
end
|
||||
|
||||
function tests.setsDoNotCrossTalkBetweenDifferentSets()
|
||||
local player = { weapon = Sets.create("ironclad", "weapon"), bow = Sets.create("duskrunner", "bow") }
|
||||
eq(Sets.attackBonus(player), 0, "one piece from each of two different sets completes neither")
|
||||
end
|
||||
|
||||
function tests.gameEquippingASetPieceAppliesItsBonusInActualCombat()
|
||||
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||
Items.equipWeapon(Items.weapon("sword", 4), game.player)
|
||||
local orc = Monsters.create(Monsters.byKey.orc, 1, 4, 6, 1)
|
||||
orc.defense, orc.baseDefense, orc.hp, orc.maxHp = 0, 0, 40, 40
|
||||
game.level.entities = { orc }
|
||||
local before = orc.hp
|
||||
game:playerAttack(orc)
|
||||
local plainDamage = before - orc.hp
|
||||
|
||||
local game2 = stagedGame(1, arena(21, 11), 3, 6)
|
||||
Items.equipWeapon(Sets.create("ironclad", "weapon"), game2.player)
|
||||
Items.equipArmor(Sets.create("ironclad", "armor"), game2.player)
|
||||
local orc2 = Monsters.create(Monsters.byKey.orc, 1, 4, 6, 1)
|
||||
orc2.defense, orc2.baseDefense, orc2.hp, orc2.maxHp = 0, 0, 40, 40
|
||||
game2.level.entities = { orc2 }
|
||||
local before2 = orc2.hp
|
||||
game2:playerAttack(orc2)
|
||||
local setDamage = before2 - orc2.hp
|
||||
-- The ironclad weapon's own power (3) is one below the plain sword's (4),
|
||||
-- but the completed 2-piece bonus adds back exactly +1 attack, landing on
|
||||
-- the same total damage - proof the bonus reads live in actual combat.
|
||||
eq(setDamage, plainDamage, "a 2-piece Ironclad bonus makes up for the set piece's own weaker power")
|
||||
end
|
||||
|
||||
function tests.gameEquippingTheSecondSetPieceLogsTheSetAwakening()
|
||||
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||
game.player.inventory = { Sets.create("ironclad", "weapon"), Sets.create("ironclad", "armor") }
|
||||
ok(game:useItem(1), "equipping the first ironclad piece succeeds")
|
||||
ok(not contains(game.log:last(), "awakens"), "a lone set piece does not announce a bonus")
|
||||
ok(game:useItem(1), "equipping the second ironclad piece succeeds")
|
||||
ok(contains(game.log:last(), "Ironclad") and contains(game.log:last(), "awakens"),
|
||||
"completing the 2-piece threshold announces the set by name")
|
||||
end
|
||||
|
||||
function tests.setsRegenerationAppliesEachTurnAtTheFullIroncladSet()
|
||||
local game = Game.new(1)
|
||||
Items.equipWeapon(Sets.create("ironclad", "weapon"), game.player)
|
||||
Items.equipArmor(Sets.create("ironclad", "armor"), game.player)
|
||||
Items.equipRing(Sets.create("ironclad", "ring"), game.player)
|
||||
game.player.hp = game.player.maxHp - 10
|
||||
local before = game.player.hp
|
||||
game:hungerTorchTick()
|
||||
eq(game.player.hp, before + 1, "the full ironclad set regenerates its fixed amount each turn")
|
||||
end
|
||||
|
||||
function tests.builderOccasionallyPlacesASetPieceFromDepthThree()
|
||||
local found
|
||||
for seed = 1, 20 do
|
||||
local level = Builder.build(3, Rng.new(seed), {})
|
||||
for _, ground in ipairs(level.floorItems) do
|
||||
if ground.item.set then found = ground.item end
|
||||
end
|
||||
if found then break end
|
||||
end
|
||||
ok(found ~= nil, "a depth-3 floor eventually places a set piece across a handful of seeds")
|
||||
ok(Sets.byKey[found.set] ~= nil, "the placed piece names a real catalog set")
|
||||
end
|
||||
|
||||
function tests.setPiecesStayOffTheShallowestTwoFloors()
|
||||
for seed = 1, 6 do
|
||||
for depth = 1, 2 do
|
||||
local level = Builder.build(depth, Rng.new(seed), {})
|
||||
for _, ground in ipairs(level.floorItems) do
|
||||
ok(not ground.item.set, "no set piece appears on depth 1 or 2")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function tests.setFieldsSurviveSerialization()
|
||||
local game = Game.new(3)
|
||||
Items.equipWeapon(Sets.create("ironclad", "weapon"), game.player)
|
||||
local path = os.tmpname()
|
||||
game:save(path)
|
||||
local restored = Game.load(path)
|
||||
os.remove(path)
|
||||
eq(restored.player.weapon.set, "ironclad", "an equipped set piece's set key survives a save/load round trip")
|
||||
end
|
||||
|
||||
function tests.gamePickupTracksSetPiecesFoundForMetaStats()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
game.level.floorItems = { { x = 5, y = 5, item = Sets.create("ironclad", "ring") } }
|
||||
game:pickupHere()
|
||||
eq(game.stats.setPiecesFound, 1, "picking up a set piece counts toward set pieces found")
|
||||
ok(game.player.ring == nil, "picking up a set piece only stashes it in inventory, it is not auto-equipped")
|
||||
end
|
||||
|
||||
function tests.metaRenownForScalesWithSetPiecesFound()
|
||||
local base = Meta.renownFor({ deepestDepth = 3, bossKills = 0, questsCompleted = 0, setPiecesFound = 0, won = false })
|
||||
local withPieces = Meta.renownFor({ deepestDepth = 3, bossKills = 0, questsCompleted = 0, setPiecesFound = 2, won = false })
|
||||
eq(withPieces, base + 6, "each set piece found adds a fixed renown bonus")
|
||||
end
|
||||
|
||||
function tests.metaRecordRunUnlocksSetCollectorOnceThreePiecesFound()
|
||||
local meta = Meta.new()
|
||||
local stats = {
|
||||
deepestDepth = 1, kills = 0, bossKills = 0, questsCompleted = 0,
|
||||
artifactsFound = 0, vaultsOpened = 0, setPiecesFound = 3, won = false,
|
||||
}
|
||||
local unlocked = Meta.recordRun(meta, stats)
|
||||
eq(unlocked[1], "Set Collector", "finding three set pieces in a run unlocks Set Collector")
|
||||
eq(meta.achievements.set_collector, true, "set_collector is marked unlocked")
|
||||
local again = Meta.recordRun(meta, stats)
|
||||
eq(#again, 0, "an already-unlocked Set Collector is not re-announced on a later run")
|
||||
end
|
||||
|
||||
function tests.renderPanelShowsTheActiveSetBonusWhenOneApplies()
|
||||
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||
ok(not contains(Render.panel(game), "set "), "the panel omits the set line without an active bonus")
|
||||
Items.equipWeapon(Sets.create("ironclad", "weapon"), game.player)
|
||||
Items.equipArmor(Sets.create("ironclad", "armor"), game.player)
|
||||
ok(contains(Render.panel(game), "Ironclad 2pc"), "the panel names the active set and its piece count")
|
||||
end
|
||||
|
||||
function tests.mimicsFloorItemBuildsADisguisedLootShape()
|
||||
local item = Mimics.floorItem(Rng.new(1))
|
||||
eq(item.kind, "mimic", "a mimic's floor item is its own kind, not a real item kind")
|
||||
eq(item.mimic, true, "a mimic's floor item is tagged so pickupHere knows to unmask it")
|
||||
local matched
|
||||
for _, disguise in ipairs(Mimics.DISGUISES) do
|
||||
if disguise.name == item.name and disguise.glyph == item.glyph then matched = true end
|
||||
end
|
||||
ok(matched, "the rolled disguise's name and glyph both come from the catalog")
|
||||
end
|
||||
|
||||
function tests.mimicsRevealBuildsAHostileMonsterScaledByDepth()
|
||||
local shallow = Mimics.reveal(1, 4, 6, 1)
|
||||
eq(shallow.kind, "monster", "a revealed mimic is a genuine monster entity")
|
||||
eq(shallow.glyph, "M", "a revealed mimic shows its own glyph, not a disguise")
|
||||
eq(shallow.mimic, true, "a revealed mimic stays tagged as a mimic")
|
||||
eq(shallow.hp, 12, "a depth-1 mimic has its base hp with no bonus")
|
||||
local deep = Mimics.reveal(2, 4, 6, 5)
|
||||
eq(deep.hp, 16, "a mimic's hp scales with depth the same way Monsters.create scales a wild species")
|
||||
end
|
||||
|
||||
function tests.gamePickupHereRevealsAMimicAndAmbushesThePlayer()
|
||||
local game = stagedGame(1, arena(21, 11), 5, 5)
|
||||
game.player.defense, game.player.baseDefense = 0, 0
|
||||
game.level.floorItems = { { x = 5, y = 5, item = Mimics.floorItem(Rng.new(1)) } }
|
||||
local hpBefore = game.player.hp
|
||||
game:pickupHere()
|
||||
eq(#game.level.floorItems, 0, "the disguised item leaves the floor the instant it is disturbed")
|
||||
eq(#game.level.entities, 1, "a revealed mimic joins the level as a real hostile monster")
|
||||
eq(game.level.entities[1].mimic, true, "the spawned monster is tagged as a mimic")
|
||||
eq(game.player.hp, hpBefore - 5, "the mimic lands one free ambush hit for its full attack")
|
||||
ok(contains(game.log:last(), "damage"), "the ambush hit is logged")
|
||||
end
|
||||
|
||||
function tests.gameKillingARevealedMimicGrantsItsFixedEssenceReward()
|
||||
local game = stagedGame(1, arena(21, 11), 3, 6)
|
||||
local mimic = Mimics.reveal(1, 4, 6, 1)
|
||||
mimic.hp = 1
|
||||
game.level.entities = { mimic }
|
||||
local essenceBefore = game.player.essence
|
||||
game:playerAttack(mimic)
|
||||
eq(game.player.essence, essenceBefore + Crafting.essenceFor(Mimics.xpFor()),
|
||||
"felling a mimic grants essence scaled to its own fixed xp reward, not a plain monster's")
|
||||
end
|
||||
|
||||
local order = {
|
||||
|
||||
Reference in new issue
Block a user