Files
gen1recomp/tests/drivers/em_steven_multi.lua
T
bryanthaboi 690f0cd9a1 TOUCHDOWN
2026-09-27 16:07:31 -04:00

178 lines
7.4 KiB
Lua

local U = require("tests.drivers.util")
local L = require("tests.drivers.em_battle_loop")
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/em_steven_multi"
local failures = 0
local function result(ok, label)
print((ok and "PASS " or "FAIL ") .. label)
if not ok then failures = failures + 1 end
return ok
end
local function finish()
print((failures == 0 and "PASS" or "FAIL") .. " em_steven_multi failures=" .. failures)
love.event.quit(failures == 0 and 0 or 1)
U.wait(10)
end
return function(game)
io.stdout:setvbuf("line")
for _ = 1, 900 do
if game.phase == "boot" and game.boot then break end
U.wait(1)
end
game:_handleBootAction({ action = "new_game", name = "BRENDAN", gender = 0 })
U.wait(240)
local Runtime = require("src.core.game3.runtime")
local Map = require("src.core.game3.map")
local Party = require("src.core.game3.party")
local Space = require("src.core.game3.scripting.space")
local Rse = require("src.core.game3.rse.init")
local Encounters = require("src.core.game3.encounters")
local Message = require("src.ui.game3.message")
local Choice = require("src.ui.game3.choice")
local PartyMenu = require("src.ui.game3.party_menu")
local Battle = require("src.core.game3.battle")
local Kinds = require("src.core.game3.battle.kinds")
local Anim = require("src.core.game3.battle.anim")
local Ui = require("src.core.game3.battle.ui")
local Natives = require("src.core.game3.scripting.natives")
local C = require("src.core.game3.constants").of("emerald")
local session = Runtime.getSession()
if not result(session ~= nil, "field session exists") then return finish() end
Encounters.onStep = function() return nil end
Natives.ensureBound(session)
result(Natives.handlerFor("DoSpecialTrainerBattle") ~= nil, "DoSpecialTrainerBattle is bound on Emerald")
session.party = {}
Party.giveMon(session, C.species.byName.SPECIES_SWAMPERT, 60, "")
Party.giveMon(session, C.species.byName.SPECIES_ZIGZAGOON, 5, "")
Party.giveMon(session, C.species.byName.SPECIES_BLAZIKEN, 60, "")
Party.giveMon(session, C.species.byName.SPECIES_SCEPTILE, 60, "")
local zigPersonality = session.party[2].personality
local swampertExp = session.party[1].exp
Rse.setVar("VAR_MOSSDEEP_CITY_STATE", 2)
Rse.setVar("VAR_MOSSDEEP_SPACE_CENTER_STATE", 2)
Rse.setFlag("FLAG_HIDE_MOSSDEEP_CITY_SPACE_CENTER_2F_STEVEN", false)
Rse.setFlag("FLAG_HIDE_MOSSDEEP_CITY_SPACE_CENTER_2F_TEAM_MAGMA", false)
Rse.setFlag("FLAG_INTERACTED_WITH_STEVEN_SPACE_CENTER", false)
local ok, err = pcall(function()
Map.load(nil, game, "EM_MOSSDEEP_CITY_SPACE_CENTER_2F", { x = 2, y = 8, facing = "left" })
end)
if not result(ok, "Space Center 2F loads " .. tostring(err or "")) then return finish() end
U.wait(40)
U.still(game, DIR .. "/01_space_center.png")
local function pump_field(limit, stop)
for _ = 1, limit do
if stop() then return true end
if Choice.isOpen and Choice.isOpen() then
U.wait(4)
U.tap(game, "a")
elseif Message.isOpen and Message.isOpen() then
U.tap(game, "a")
end
U.wait(2)
end
return stop()
end
U.tap(game, "a")
pump_field(1200, function() return not (Space.vm and Space.vm:isRunning()) end)
result(Rse.flag("FLAG_INTERACTED_WITH_STEVEN_SPACE_CENTER"), "first talk runs Steven's intro scene")
U.wait(20)
local sawParty = false
U.tap(game, "a")
for _ = 1, 1500 do
if PartyMenu.isOpen and PartyMenu.isOpen() then sawParty = true break end
if Choice.isOpen and Choice.isOpen() then
U.wait(4)
U.tap(game, "a")
elseif Message.isOpen and Message.isOpen() then
U.tap(game, "a")
end
U.wait(2)
end
if not result(sawParty, "YES opens ChooseHalfPartyForBattle") then return finish() end
U.wait(20)
U.still(game, DIR .. "/02_choose_half_party.png")
for _, slot in ipairs({ 1, 3, 4 }) do
PartyMenu.enterChosenMon(slot)
U.wait(6)
end
U.still(game, DIR .. "/03_three_entered.png")
PartyMenu.confirmChosenMons()
for _ = 1, 1500 do
if Battle.isActive() then break end
if Message.isOpen and Message.isOpen() then U.tap(game, "a") end
U.wait(2)
end
if not result(Battle.isActive(), "DoSpecialTrainerBattle SPECIAL_BATTLE_STEVEN starts the battle") then
return finish()
end
local st = Battle._st
result(st.double and st.kinds.partner and st.kinds.twoOpponents, "double, partner and two opponents")
result(st.playerHalf == 3, "player brings the three chosen mons (" .. tostring(st.playerHalf) .. ")")
result(#st.playerParty == 6, "battle party is 3 chosen + 3 Steven")
result(st.battlers[2] and st.battlers[2].mon.species == C.species.byName.SPECIES_METANG,
"Steven leads with Metang on the right")
result(st.player.mon.species == C.species.byName.SPECIES_SWAMPERT, "player leads with the first chosen mon")
result(Kinds.controllerOf(st, 2) == "aiPartner", "battler 2 runs the partner controller")
result(st.trainerId == C.trainers.byName.TRAINER_MAXIE_MOSSDEEP and st.trainerIdB == C.trainers.byName.TRAINER_TABITHA_MOSSDEEP,
"opponents are Maxie and Tabitha")
result(st.partner and st.partner.backPic == 7, "Steven back pic (TRAINER_BACK_PIC_STEVEN)")
local shots = {}
local done, why = L.run(game, {
turnCap = 40,
onFrame = function(s, phase)
local stage = Anim.stage()
if phase == "intro" and not shots.intro and stage.trainer.player.visible and (stage.trainer.player.ox or 0) == 0 then
shots.intro = true
U.still(game, DIR .. "/04_intro_steven_and_player.png")
end
if phase == "command" and not shots.cmd and Ui._mode == "menu" then
shots.cmd = true
U.wait(10)
U.still(game, DIR .. "/05_command.png")
end
if phase == "animating" and not shots.anim and s.turn >= 2 then
shots.anim = true
U.wait(12)
U.still(game, DIR .. "/06_mid_turn.png")
end
end,
})
result(done, "battle finished " .. tostring(why or ""))
local sentOut = L.logIndex("sent out METANG") or L.logIndex("sent\nout METANG")
result(sentOut ~= nil, "intro uses sText_InGamePartnerSentOutZGoN (STEVEN sent out METANG)")
result(L.logHas("want to battle"), "intro uses sText_TwoTrainersWantToBattle")
result(st.result == "win", "the multi battle is won (" .. tostring(st.result) .. ")")
local partnerMoves = 0
for _, t in ipairs(Ui.log and Ui.log() or {}) do
local s = tostring(t):gsub("\n", " ")
if s:find("METANG used", 1, true) or s:find("SKARMORY used", 1, true) or s:find("AGGRON used", 1, true) then
partnerMoves = partnerMoves + 1
end
end
result(partnerMoves > 0, "Steven's mons act on their own (" .. partnerMoves .. " moves)")
local restored = pump_field(3000, function()
return not (Space.vm and Space.vm:isRunning()) and #session.party == 4
end)
result(restored, "LoadPlayerParty restores the four-mon party")
local stevenLeft = false
for _, m in ipairs(session.party) do if m.stevenPartner then stevenLeft = true end end
result(not stevenLeft, "none of Steven's mons stay in the party")
result(session.party[2].personality == zigPersonality, "the unchosen Zigzagoon keeps its slot")
result((session.party[1].exp or 0) > (swampertExp or 0), "the chosen Swampert keeps the exp it earned (frontier_saveparty)")
result(Rse.var("VAR_MOSSDEEP_SPACE_CENTER_STATE") == 3, "defeat script sets VAR_MOSSDEEP_SPACE_CENTER_STATE = 3")
result(Rse.flag("FLAG_DEFEATED_MAGMA_SPACE_CENTER"), "FLAG_DEFEATED_MAGMA_SPACE_CENTER set")
U.wait(30)
U.still(game, DIR .. "/07_after.png")
return finish()
end