mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 16:31:05 +02:00
73 lines
3.2 KiB
Lua
73 lines
3.2 KiB
Lua
-- Parity test: Self-Destruct/Explosion against a mid-Fly/Dig
|
|
-- (semi-invulnerable) target still faints the user (#528).
|
|
--
|
|
-- EffectRegistry.runDamaging's target.invulnerable branch prints the miss
|
|
-- text and returned without ever calling record.onMiss, while the
|
|
-- accuracy-roll, type-immunity and floored-damage miss branches all did.
|
|
-- EXPLODE_EFFECT (src/battle/MoveEffects.lua) relies on onMiss to run
|
|
-- battle:selfDestruct(user); skipping it left the user at full HP.
|
|
--
|
|
-- pokered engine/battle/core.asm MoveHitTest: "bit INVULNERABLE, [hl] /
|
|
-- jp nz, .moveMissed" sets the same wMoveMissed as a failed accuracy roll,
|
|
-- and the shared miss handler runs the explode effect regardless of which
|
|
-- branch set it ("even if Explosion or Selfdestruct missed, its effect
|
|
-- still needs to be activated"). JUMP_KICK_EFFECT's onMiss filters on
|
|
-- reason == "accuracy", so a crash-damage kick must NOT also fire here.
|
|
--
|
|
-- Self-contained; run via `luajit tests/parity_explode_invulnerable.lua`.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
if not _G.love then _G.love = require("tests.love_stub") end
|
|
local S = require("tests.harness").suite("parity explode invulnerable")
|
|
local check, eq = S.check, S.eq
|
|
|
|
local Data = require("src.core.Data")
|
|
Data:load()
|
|
|
|
local Game = require("src.core.Game")
|
|
local Input = require("src.core.Input")
|
|
local StateStack = require("src.core.StateStack")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local BattleState = require("src.battle.BattleState")
|
|
|
|
Game.data = Data
|
|
Game.input = Input; Input:init()
|
|
Game.stack = StateStack; StateStack:init()
|
|
Game.save = require("src.core.SaveData").newGame()
|
|
|
|
-- Self-Destruct against a target mid-Fly (invulnerable, never-miss moves
|
|
-- aside): the move never rolls accuracy at all, it just hits the
|
|
-- invulnerable branch in EffectRegistry.runDamaging.
|
|
local function selfDestructVsInvulnerable(moveId)
|
|
Game.save.party = { Pokemon.new(Data, "GEODUDE", 30) }
|
|
local b = BattleState.newWild(Game, "PIDGEY", 20)
|
|
b.enemy.invulnerable = true -- mid-Fly/Dig, set by ChargeEffect on turn 1
|
|
local hpBefore = b.enemy.mon.hp
|
|
b:performMove(b.player, b.enemy, { id = moveId, pp = 5 })
|
|
return b, hpBefore
|
|
end
|
|
|
|
for _, moveId in ipairs({ "SELFDESTRUCT", "EXPLOSION" }) do
|
|
local b, enemyHpBefore = selfDestructVsInvulnerable(moveId)
|
|
eq(b.player.mon.hp, 0, moveId .. " vs an invulnerable target still faints the user")
|
|
eq(b.enemy.mon.hp, enemyHpBefore,
|
|
moveId .. " vs an invulnerable target deals the target no damage")
|
|
local sawMiss = false
|
|
for _, r in ipairs(b.queue) do
|
|
if r.text and r.text:find("attack missed", 1, true) then sawMiss = true end
|
|
end
|
|
check(sawMiss, moveId .. " still prints the miss text against an invulnerable target")
|
|
end
|
|
|
|
-- Companion: JUMP_KICK's onMiss must reject the "invulnerable" reason, so
|
|
-- a mid-Fly target does not also take Jump Kick's crash damage (its
|
|
-- onMiss guard only fires for reason == "accuracy").
|
|
Game.save.party = { Pokemon.new(Data, "GEODUDE", 30) }
|
|
local jk = BattleState.newWild(Game, "PIDGEY", 20)
|
|
jk.enemy.invulnerable = true
|
|
local jkHpBefore = jk.player.mon.hp
|
|
jk:performMove(jk.player, jk.enemy, { id = "JUMP_KICK", pp = 5 })
|
|
eq(jk.player.mon.hp, jkHpBefore,
|
|
"JUMP KICK vs an invulnerable target takes no crash damage (reason filter holds)")
|
|
|
|
S.finish()
|