mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-28 23:00:21 -04:00
234 lines
8.7 KiB
Lua
234 lines
8.7 KiB
Lua
local U = require("tests.drivers.util")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/em_first_battle"
|
|
|
|
return function(game)
|
|
local fails = 0
|
|
local function result(ok, label)
|
|
print((ok and "PASS " or "FAIL ") .. label)
|
|
if not ok then fails = fails + 1 end
|
|
end
|
|
local function finish()
|
|
print(string.format("[driver] em_first_battle: %d failure(s)", fails))
|
|
love.event.quit(fails == 0 and 0 or 1)
|
|
U.wait(10)
|
|
end
|
|
|
|
for _ = 1, 900 do
|
|
if game.phase == "boot" and game.boot then break end
|
|
U.wait(1)
|
|
end
|
|
game:_handleBootAction({ action = "new_game", name = "NICK", gender = 0 })
|
|
U.wait(240)
|
|
|
|
local Runtime = require("src.core.game3.runtime")
|
|
local Party = require("src.core.game3.party")
|
|
local BattleBridge = require("src.core.game3.battle_bridge")
|
|
local Battle = require("src.core.game3.battle")
|
|
local Ui = require("src.core.game3.battle.ui")
|
|
local ExpSeq = require("src.core.game3.battle.exp_seq")
|
|
local BattleTransition = require("src.core.game3.battle_transition")
|
|
local Audio = require("src.core.game3.audio")
|
|
local Map = require("src.core.game3.map")
|
|
local Field = require("src.core.game3.field")
|
|
local C = require("src.core.game3.constants").of("emerald")
|
|
local session = Runtime.getSession()
|
|
result(session ~= nil, "field session exists")
|
|
if not session then return finish() end
|
|
|
|
local ok, err = pcall(function() Map.load(nil, game, "EM_ROUTE101", { x = 7, y = 13, facing = "down" }) end)
|
|
result(ok, "Route 101 loads " .. tostring(err or ""))
|
|
U.wait(40)
|
|
|
|
session.party = {}
|
|
-- pokeemerald/src/battle_setup.c:923
|
|
Party.giveMon(session, C.species.byName.SPECIES_TREECKO, 5, "TREECKO")
|
|
local mon = session.party[1]
|
|
result(mon ~= nil and mon.level == 5, "starter Treecko lv5 in the party")
|
|
if not mon then return finish() end
|
|
local exp0 = tonumber(mon.exp) or 0
|
|
local moveNames = {}
|
|
for i, m in ipairs(mon.moves or {}) do moveNames[i] = C:name("moves", m, "MOVE_") or tostring(m) end
|
|
print("[driver] starter moves " .. table.concat(moveNames, ","))
|
|
|
|
local outcome
|
|
local started, serr = BattleBridge.startFirstBattle(Runtime._mod, game, {
|
|
done = function(r) outcome = r end,
|
|
})
|
|
result(started == true, "first battle started " .. tostring(serr or ""))
|
|
if not started then return finish() end
|
|
local tid = BattleTransition._transitionId
|
|
result(tid == C.battle.byName.B_TRANSITION_BLUR, "transition is B_TRANSITION_BLUR (" .. tostring(tid) .. ")")
|
|
local song = Audio._currentSong and Audio._currentSong.id
|
|
result(song == C.songs.byName.MUS_VS_WILD, "battle music MUS_VS_WILD (" .. tostring(song) .. ")")
|
|
|
|
for _ = 1, 3000 do
|
|
if Battle.isActive() then break end
|
|
U.wait(1)
|
|
end
|
|
result(Battle.isActive(), "battle active after the transition")
|
|
local st = Battle.getState()
|
|
if not st then return finish() end
|
|
local foe = st.enemy and st.enemy.mon
|
|
result(foe and foe.species == C.species.byName.SPECIES_ZIGZAGOON and foe.level == 2, "foe is Zigzagoon lv2")
|
|
result(st.wild and st.kinds and st.kinds.firstBattle == "birch", "battle kind firstBattle=birch")
|
|
result(st.aiFlags == 0x80000000, "AI flags AI_SCRIPT_FIRST_BATTLE (" .. string.format("0x%X", st.aiFlags or 0) .. ")")
|
|
result(not st.firstBattle, "Oak first-battle path stays off")
|
|
|
|
local lastTap, f = 0, 0
|
|
local function pump_text()
|
|
f = f + 1
|
|
if Ui.dialogPending and Ui.dialogPending() and f - lastTap >= 14 then
|
|
lastTap = f
|
|
U.tap(game, "a")
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
local function at_command()
|
|
return Battle.isActive() and Battle._phase == "command" and Ui._mode == "menu"
|
|
end
|
|
local function wait_command(limit)
|
|
for _ = 1, limit or 6000 do
|
|
if at_command() or not Battle.isActive() then break end
|
|
if not pump_text() then U.wait(1) end
|
|
end
|
|
return at_command()
|
|
end
|
|
local function logged(pattern)
|
|
for _, t in ipairs(Ui.log()) do
|
|
if type(t) == "string" and t:find(pattern) then return true end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local introShot = false
|
|
for _ = 1, 600 do
|
|
if Ui.dialogPending and Ui.dialogPending() then
|
|
U.wait(20)
|
|
introShot = U.still(game, DIR .. "/01_intro_wild_zigzagoon.png")
|
|
break
|
|
end
|
|
U.wait(1)
|
|
end
|
|
result(introShot, "intro shot")
|
|
result(logged("ZIGZAGOON"), "intro text names Wild ZIGZAGOON")
|
|
|
|
result(wait_command(), "reached the action menu")
|
|
U.wait(20)
|
|
result(U.still(game, DIR .. "/02_action_menu.png"), "action menu shot")
|
|
|
|
U.tap(game, "right")
|
|
U.wait(4)
|
|
U.tap(game, "down")
|
|
U.wait(4)
|
|
U.tap(game, "a")
|
|
U.wait(30)
|
|
result(logged("Don't leave me"), "RUN is refused with STRINGID_DONTLEAVEBIRCH")
|
|
result(U.still(game, DIR .. "/03_dont_leave_birch.png"), "run refused shot")
|
|
result(wait_command(), "back at the action menu")
|
|
U.tap(game, "up")
|
|
U.wait(4)
|
|
U.tap(game, "left")
|
|
U.wait(4)
|
|
|
|
local moveShot, faintShot, expShot = false, false, false
|
|
local turns = 0
|
|
local expSeen = false
|
|
for _ = 1, 20 do
|
|
if not Battle.isActive() then break end
|
|
if not wait_command() then break end
|
|
turns = turns + 1
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
if not moveShot and Ui._mode == "moves" then
|
|
moveShot = U.still(game, DIR .. "/04_move_select.png")
|
|
end
|
|
U.tap(game, "a")
|
|
for _ = 1, 4000 do
|
|
if at_command() or not Battle.isActive() then break end
|
|
local e = Battle.getState() and Battle.getState().enemy
|
|
if not faintShot and e and e.mon and (tonumber(e.mon.hp) or 1) <= 0 then
|
|
U.wait(24)
|
|
faintShot = U.still(game, DIR .. "/05_zigzagoon_faints.png")
|
|
end
|
|
if not expShot and ExpSeq.busy() then
|
|
expSeen = true
|
|
U.wait(30)
|
|
expShot = U.still(game, DIR .. "/06_exp_gain.png")
|
|
end
|
|
if Battle._phase == "awarding" then expSeen = true end
|
|
if not pump_text() then U.wait(1) end
|
|
end
|
|
end
|
|
print("[driver] turns " .. turns .. " outcome " .. tostring(outcome) .. " endReason " .. tostring(st.endReason))
|
|
result(moveShot, "move select shot")
|
|
result(faintShot, "faint shot")
|
|
result(expSeen, "exp award sequence ran")
|
|
result(expShot, "exp gain shot")
|
|
result(logged("gained"), "STRINGID_PKMNGAINEDEXP printed")
|
|
|
|
for _ = 1, 3000 do
|
|
if outcome ~= nil then break end
|
|
if not pump_text() then U.wait(1) end
|
|
end
|
|
result(outcome == "win", "battle outcome win (" .. tostring(outcome) .. ")")
|
|
local exp1 = tonumber(session.party[1] and session.party[1].exp) or 0
|
|
result(exp1 > exp0, string.format("starter exp %d -> %d", exp0, exp1))
|
|
for _ = 1, 300 do
|
|
if not Field.locked then break end
|
|
U.wait(1)
|
|
end
|
|
U.wait(60)
|
|
result(Map.current == "EM_ROUTE101", "back on the field at Route 101 (" .. tostring(Map.current) .. ")")
|
|
result(not Battle.isActive(), "battle closed")
|
|
result(U.still(game, DIR .. "/07_back_on_field.png"), "field shot")
|
|
|
|
local Trainers = require("src.core.game3.scripting.trainers")
|
|
local Prize = require("src.core.game3.battle.prize")
|
|
local calvin = C.trainers.byName.TRAINER_CALVIN_1
|
|
local foeRow = Trainers.foeFromId(calvin)
|
|
result(foeRow ~= nil, "Calvin trainer row")
|
|
if not foeRow then return finish() end
|
|
session.party = {}
|
|
Party.giveMon(session, C.species.byName.SPECIES_GROVYLE, 30, "GROVYLE")
|
|
session.money = 1000
|
|
local want = Prize.calcRse(calvin, {})
|
|
outcome = nil
|
|
Ui._log = {}
|
|
local ok2, err2 = BattleBridge.start(Runtime._mod, game, foeRow, {
|
|
wild = false, trainerId = calvin, done = function(r) outcome = r end,
|
|
})
|
|
result(ok2 == true, "Calvin battle started " .. tostring(err2 or ""))
|
|
for _ = 1, 3000 do
|
|
if Battle.isActive() then break end
|
|
U.wait(1)
|
|
end
|
|
local tsong = Audio._currentSong and Audio._currentSong.id
|
|
result(tsong == C.songs.byName.MUS_VS_TRAINER, "trainer battle music MUS_VS_TRAINER (" .. tostring(tsong) .. ")")
|
|
local victoryHeard = false
|
|
for _ = 1, 20 do
|
|
if not Battle.isActive() then break end
|
|
if not wait_command() then break end
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
U.tap(game, "a")
|
|
for _ = 1, 4000 do
|
|
if at_command() or not Battle.isActive() then break end
|
|
local s = Audio._currentSong and Audio._currentSong.id
|
|
if s == C.songs.byName.MUS_VICTORY_TRAINER then victoryHeard = true end
|
|
if not pump_text() then U.wait(1) end
|
|
end
|
|
end
|
|
for _ = 1, 3000 do
|
|
if outcome ~= nil then break end
|
|
if not pump_text() then U.wait(1) end
|
|
end
|
|
result(outcome == "win", "Calvin battle won (" .. tostring(outcome) .. ")")
|
|
result(victoryHeard, "MUS_VICTORY_TRAINER played on the win")
|
|
result(session.money == 1000 + want, string.format("prize money %d (+%d from gTrainerMoneyTable)", session.money, want))
|
|
result(logged("got %$" .. want) or logged(tostring(want)), "STRINGID_PLAYERGOTMONEY shows " .. want)
|
|
U.wait(60)
|
|
result(U.still(game, DIR .. "/08_after_calvin.png"), "after trainer battle shot")
|
|
return finish()
|
|
end
|