mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
23617f43b4
CLOSES #2290, CLOSES #2338, CLOSES #2186, CLOSES #2305, CLOSES #2332, CLOSES #2320, CLOSES #2344, CLOSES #2291, CLOSES #2335, CLOSES #2340, CLOSES #2385, CLOSES #2352, CLOSES #2378, CLOSES #2403, CLOSES #2404, CLOSES #2405, CLOSES #2367, CLOSES #2037, CLOSES #2177, CLOSES #2368, CLOSES #2382, CLOSES #1951
221 lines
7.6 KiB
Lua
221 lines
7.6 KiB
Lua
-- engine/battle/effects.asm:764-789
|
|
-- engine/battle/core.asm:3481-3506
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local BattleState = require("src.battle.BattleState")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
local fails = 0
|
|
local function check(label, ok)
|
|
if ok then
|
|
print("PASS " .. label)
|
|
else
|
|
print("FAIL " .. label)
|
|
fails = fails + 1
|
|
end
|
|
return ok
|
|
end
|
|
|
|
local function flat(s) return (tostring(s or ""):gsub("[\n\v\f]", " ")) end
|
|
|
|
game.save.options = game.save.options or {}
|
|
game.save.options.animations = true
|
|
|
|
local lead = Pokemon.new(game.data, "CHARMANDER", 20)
|
|
lead.moves = { { id = "BIDE", pp = 10 } }
|
|
game.save.party = { lead }
|
|
|
|
U.teleport(game, "ROUTE_1", 5, 5, "down")
|
|
U.wait(15)
|
|
local ow = game.overworld
|
|
check("standing on ROUTE_1", ow and ow.map and ow.map.id == "ROUTE_1")
|
|
|
|
local function watcher(battle)
|
|
local w = { shown = {}, anims = {}, queued = {} }
|
|
local markQ, lastCur = {}, nil
|
|
function w.poll()
|
|
for _, row in ipairs(battle.queue) do
|
|
if not markQ[row] then
|
|
markQ[row] = true
|
|
if row.text then w.queued[#w.queued + 1] = flat(row.text) end
|
|
if row.anim then w.anims[#w.anims + 1] = row.anim end
|
|
end
|
|
end
|
|
local cur = battle.current
|
|
if cur ~= lastCur then
|
|
lastCur = cur
|
|
if cur and cur.text then
|
|
w.shown[#w.shown + 1] = flat(cur.text)
|
|
return flat(cur.text)
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
return w
|
|
end
|
|
|
|
local function has(list, needle)
|
|
for _, s in ipairs(list) do
|
|
if s:find(needle, 1, true) then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function waitPhase(battle, phase, tries, w)
|
|
for _ = 1, tries do
|
|
if battle.phase == phase then return true end
|
|
U.tap(game, "a")
|
|
for _ = 1, 6 do w.poll() U.wait(1) end
|
|
end
|
|
return battle.phase == phase
|
|
end
|
|
|
|
local function pickFirstMove(battle, w)
|
|
U.tap(game, "a")
|
|
if not waitPhase(battle, "moveSelect", 10, w) then return false end
|
|
U.tap(game, "a")
|
|
return true
|
|
end
|
|
|
|
local function settledShot(watch, path)
|
|
for _ = 1, 100 do watch.poll() U.wait(1) end
|
|
return U.shot(game, path)
|
|
end
|
|
|
|
local function leaveBattle()
|
|
for _ = 1, 10 do
|
|
if game.stack:top() == ow then break end
|
|
game.stack:pop()
|
|
end
|
|
end
|
|
|
|
local battle = BattleState.newWild(game, "RATTATA", 8)
|
|
battle.onFinish = function() end
|
|
battle.enemy.mon.moves = { { id = "TACKLE", pp = 35 } }
|
|
battle.enemy.curMoves = battle.enemy.mon.moves
|
|
ow:pushBattle(battle)
|
|
local w = watcher(battle)
|
|
check("player battle reached the menu", waitPhase(battle, "menu", 80, w))
|
|
local sinceShown, sinceQueued = #w.shown, #w.queued
|
|
check("BIDE picked", pickFirstMove(battle, w))
|
|
|
|
local tackles, unleashed = 0, false
|
|
local lockedSeen, sawSpiral = false, false
|
|
local shots = {}
|
|
for _ = 1, 3000 do
|
|
local line = w.poll()
|
|
if has(w.anims, "XSTATITEM_ANIM") then sawSpiral = true end
|
|
if line then
|
|
if line:find("TACKLE", 1, true) then
|
|
tackles = tackles + 1
|
|
if tackles == 1 and not shots.store then
|
|
shots.store = settledShot(w, DIR .. "/2338_01_store_turn_spiral_then_foe_tackle.png")
|
|
elseif tackles >= 2 and not shots.locked then
|
|
lockedSeen = true
|
|
shots.locked = settledShot(w, DIR .. "/2338_02_locked_turn_only_foe_text.png")
|
|
end
|
|
elseif line:find("unleashed energy", 1, true) then
|
|
unleashed = true
|
|
shots.release = settledShot(w, DIR .. "/2338_03_release_unleashed_energy.png")
|
|
break
|
|
end
|
|
end
|
|
if game.stack:top() ~= battle then
|
|
if not game.stack:top() or battle.player.mon.hp <= 0 then break end
|
|
end
|
|
if U.frame() % 6 == 0 then U.tap(game, "a") else U.wait(1) end
|
|
end
|
|
|
|
local pShown, pQueued = {}, {}
|
|
for i = sinceShown + 1, #w.shown do pShown[#pShown + 1] = w.shown[i] end
|
|
for i = sinceQueued + 1, #w.queued do pQueued[#pQueued + 1] = w.queued[i] end
|
|
local stray = {}
|
|
for _, s in ipairs(pShown) do
|
|
if s:find("CHARMANDER", 1, true) and not s:find("used BIDE", 1, true)
|
|
and not s:find("unleashed energy", 1, true) then
|
|
stray[#stray + 1] = s
|
|
end
|
|
if s:find("unleashed energy", 1, true) then break end
|
|
end
|
|
U.log("player battle shown: " .. table.concat(pShown, " | "))
|
|
check("storing turn played the X-item spiral", sawSpiral)
|
|
check("no storing-energy line shown on the player's side",
|
|
not has(pShown, "storing energy"))
|
|
check("no storing-energy line queued on the player's side",
|
|
not has(pQueued, "storing energy"))
|
|
check("foe acted on at least one locked turn (" .. tackles .. " TACKLE lines)",
|
|
lockedSeen)
|
|
check("no CHARMANDER line besides used BIDE before the release: "
|
|
.. (#stray > 0 and table.concat(stray, " | ") or "(none)"), #stray == 0)
|
|
check("release printed unleashed energy", unleashed)
|
|
for _ = 1, 30 do w.poll() U.wait(1) end
|
|
check("release played BIDE's own animation", has(w.anims, "BIDE"))
|
|
|
|
leaveBattle()
|
|
|
|
lead.hp = lead.stats.hp
|
|
lead.status = nil
|
|
lead.moves = { { id = "SCRATCH", pp = 35 } }
|
|
local foeBattle = BattleState.newWild(game, "RATTATA", 25)
|
|
foeBattle.onFinish = function() end
|
|
foeBattle.enemy.mon.moves = { { id = "BIDE", pp = 10 } }
|
|
foeBattle.enemy.curMoves = foeBattle.enemy.mon.moves
|
|
ow:pushBattle(foeBattle)
|
|
local fw = watcher(foeBattle)
|
|
check("foe battle reached the menu", waitPhase(foeBattle, "menu", 80, fw))
|
|
local fSince = #fw.shown
|
|
local fQSince = #fw.queued
|
|
check("SCRATCH picked", pickFirstMove(foeBattle, fw))
|
|
|
|
local scratches, foeUnleashed, foeSpiral = 0, false, false
|
|
local foeStoreShot = false
|
|
for _ = 1, 3000 do
|
|
local line = fw.poll()
|
|
if has(fw.anims, "XSTATITEM_DUPLICATE_ANIM") then foeSpiral = true end
|
|
if line then
|
|
if line:find("SCRATCH", 1, true) then
|
|
scratches = scratches + 1
|
|
if foeSpiral and not foeStoreShot then
|
|
foeStoreShot = true
|
|
settledShot(fw, DIR .. "/2338_04_foe_store_turn_then_player_move.png")
|
|
end
|
|
elseif line:find("unleashed energy", 1, true) then
|
|
foeUnleashed = true
|
|
break
|
|
end
|
|
end
|
|
if game.stack:top() ~= foeBattle then
|
|
if not game.stack:top() or foeBattle.enemy.mon.hp <= 0 then break end
|
|
end
|
|
if U.frame() % 6 == 0 then U.tap(game, "a") else U.wait(1) end
|
|
end
|
|
|
|
local fShown, fQueued = {}, {}
|
|
for i = fSince + 1, #fw.shown do fShown[#fShown + 1] = fw.shown[i] end
|
|
for i = fQSince + 1, #fw.queued do fQueued[#fQueued + 1] = fw.queued[i] end
|
|
local fStray = {}
|
|
for _, s in ipairs(fShown) do
|
|
if s:find("RATTATA", 1, true) and not s:find("used BIDE", 1, true)
|
|
and not s:find("unleashed energy", 1, true) then
|
|
fStray[#fStray + 1] = s
|
|
end
|
|
if s:find("unleashed energy", 1, true) then break end
|
|
end
|
|
U.log("foe battle shown: " .. table.concat(fShown, " | "))
|
|
check("foe's storing turn played XSTATITEM_DUPLICATE_ANIM", foeSpiral)
|
|
check("no storing-energy line shown on the foe's side",
|
|
not has(fShown, "storing energy"))
|
|
check("no storing-energy line queued on the foe's side",
|
|
not has(fQueued, "storing energy"))
|
|
check("player moved through the foe's locked turns (" .. scratches
|
|
.. " SCRATCH lines)", scratches >= 2)
|
|
check("no RATTATA line besides used BIDE before the release: "
|
|
.. (#fStray > 0 and table.concat(fStray, " | ") or "(none)"), #fStray == 0)
|
|
check("foe's release printed unleashed energy", foeUnleashed)
|
|
|
|
leaveBattle()
|
|
print(fails == 0 and "PASS bide_silent_bug2338" or "FAIL bide_silent_bug2338")
|
|
love.event.quit(fails == 0 and 0 or 1)
|
|
end
|