mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
123feef3a1
CLOSES #2425, CLOSES #2428, CLOSES #2431, CLOSES #2432, CLOSES #2433, CLOSES #2435, CLOSES #2436, CLOSES #2437, CLOSES #2440
194 lines
6.7 KiB
Lua
194 lines
6.7 KiB
Lua
local U = require("tests.drivers.util")
|
|
local DIR = os.getenv("POKEPORT_SHOT_DIR") or "/tmp/game3_teleport_in_lock"
|
|
|
|
local PALLET = "FR_PALLET_TOWN"
|
|
local FLAG_BADGE03_GET = 0x822
|
|
local FLAG_SYS_POKEMON_GET = 0x828
|
|
|
|
local failures = 0
|
|
|
|
local function say(line)
|
|
print(line)
|
|
end
|
|
|
|
local function result(ok, label)
|
|
say((ok and "PASS " or "FAIL ") .. label)
|
|
if not ok then failures = failures + 1 end
|
|
return ok
|
|
end
|
|
|
|
local function finish()
|
|
if failures == 0 then
|
|
say("PASS game3_teleport_in_lock")
|
|
love.event.quit(0)
|
|
else
|
|
say("FAIL game3_teleport_in_lock failures=" .. failures)
|
|
love.event.quit(1)
|
|
end
|
|
end
|
|
|
|
local function run(game)
|
|
for _ = 1, 900 do
|
|
if game.phase == "boot" and game.boot then break end
|
|
U.wait(1)
|
|
end
|
|
game:_handleBootAction({ action = "new_game", name = "RED" })
|
|
U.wait(240)
|
|
|
|
local Runtime = require("src.core.game3.runtime")
|
|
local Map = require("src.core.game3.map")
|
|
local Space = require("src.core.game3.scripting.space")
|
|
local Flags = require("src.core.game3.scripting.flags")
|
|
local Player = require("src.core.game3.player")
|
|
local Party = require("src.core.game3.party")
|
|
local PartyMenu = require("src.ui.game3.party_menu")
|
|
local StartMenu = require("src.ui.game3.start_menu")
|
|
local Field = require("src.core.game3.field")
|
|
local Fade = require("src.ui.game3.fade")
|
|
local FieldEffects = require("src.core.game3.field_effects")
|
|
|
|
local session = Runtime.getSession()
|
|
if not result(session ~= nil, "new game reached the game3 field") then return finish() end
|
|
|
|
Flags.setFlag(Space.store, Space.vm and Space.vm.ctx, FLAG_BADGE03_GET, true)
|
|
Flags.setFlag(Space.store, nil, FLAG_SYS_POKEMON_GET, true)
|
|
session.party = {}
|
|
Party.giveMon(session, 6, 40)
|
|
local mon = session.party[1]
|
|
mon.moves = { "TELEPORT", "EMBER", "FLY", "DIG" }
|
|
mon.pp = { 20, 25, 15, 10 }
|
|
|
|
Map.load(nil, game, PALLET, { x = 10, y = 6, facing = "down" })
|
|
session.x, session.y, session.facing = 10, 6, "down"
|
|
Player.cellX, Player.cellY = 10, 6
|
|
Player.px, Player.py = 160, 96
|
|
Player.targetX, Player.targetY = 10, 6
|
|
Player.facing = "down"
|
|
U.wait(90)
|
|
|
|
local function openParty()
|
|
for _ = 1, 40 do
|
|
if PartyMenu.isOpen and PartyMenu.isOpen() then return true end
|
|
if StartMenu.isOpen and StartMenu.isOpen() then break end
|
|
U.tap(game, "start")
|
|
U.wait(8)
|
|
end
|
|
for _ = 1, 20 do
|
|
local e = StartMenu.ENTRIES and StartMenu.ENTRIES[StartMenu.cursor]
|
|
if e and e.id == "pokemon" then break end
|
|
U.tap(game, "down")
|
|
U.wait(6)
|
|
end
|
|
U.tap(game, "a")
|
|
for _ = 1, 60 do
|
|
if PartyMenu.isOpen and PartyMenu.isOpen() then return true end
|
|
U.wait(4)
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function chooseAction(label)
|
|
U.tap(game, "a")
|
|
U.wait(12)
|
|
local target = nil
|
|
for i, name in ipairs(PartyMenu.ACTIONS or {}) do
|
|
if name == label then target = i end
|
|
end
|
|
if not target then return false end
|
|
for _ = 1, 12 do
|
|
if PartyMenu.actionCursor == target then break end
|
|
U.tap(game, "down")
|
|
U.wait(6)
|
|
end
|
|
return PartyMenu.actionCursor == target
|
|
end
|
|
|
|
local function fxAnim(kind)
|
|
for _, a in ipairs(FieldEffects._anims or {}) do
|
|
if a.kind == kind then return a end
|
|
end
|
|
end
|
|
|
|
local function waitFor(pred, frames)
|
|
for _ = 1, frames do
|
|
if pred() then return true end
|
|
U.wait(1)
|
|
end
|
|
return pred() and true or false
|
|
end
|
|
|
|
if not result(openParty(), "party menu opens in Pallet Town") then return finish() end
|
|
if not result(chooseAction("TELEPORT"), "TELEPORT is on the action list") then return finish() end
|
|
U.tap(game, "a")
|
|
U.wait(20)
|
|
U.tap(game, "a")
|
|
U.wait(6)
|
|
waitFor(function() return fxAnim("teleport_out") ~= nil end, 400)
|
|
if not result(fxAnim("teleport_out") ~= nil, "teleport_out started") then return finish() end
|
|
waitFor(function() return session.map ~= PALLET end, 900)
|
|
if not result(session.map ~= PALLET, "the heal map loaded (map=" .. tostring(session.map) .. ")") then
|
|
return finish()
|
|
end
|
|
|
|
local dirs = { "left", "down", "right", "up" }
|
|
local startCell = { Player.cellX, Player.cellY }
|
|
local st = {
|
|
f = 0, firstUnlock = nil, firstFadeDone = nil, firstIn = nil, inDone = nil,
|
|
movedDuringFade = false, movedDuringIn = false, claimEarly = false,
|
|
}
|
|
|
|
local function step()
|
|
st.f = st.f + 1
|
|
local f = st.f
|
|
local btn = dirs[(math.floor((f - 1) / 12) % #dirs) + 1]
|
|
table.insert(game.input.pressQueue, btn)
|
|
game.input.state[btn] = true
|
|
U.wait(1)
|
|
game.input.state[btn] = false
|
|
local tin = fxAnim("teleport_in")
|
|
if not st.firstUnlock and Field.locked == false then st.firstUnlock = f end
|
|
if not st.firstFadeDone and not Fade.active then st.firstFadeDone = f end
|
|
if not st.firstIn and tin then st.firstIn = f end
|
|
if st.firstIn and not st.inDone and not tin then st.inDone = f end
|
|
if not st.inDone and Space._pendingOnFrame ~= true then st.claimEarly = true end
|
|
local moved = Player.moving or Player.cellX ~= startCell[1] or Player.cellY ~= startCell[2]
|
|
if moved then
|
|
if tin then st.movedDuringIn = true end
|
|
if Fade.active then st.movedDuringFade = true end
|
|
end
|
|
return tin
|
|
end
|
|
|
|
for _ = 1, 300 do
|
|
local tin = step()
|
|
if tin and tin.y2 >= -40 then break end
|
|
end
|
|
local mid = fxAnim("teleport_in")
|
|
result(mid ~= nil and Field.locked == true,
|
|
"the field is locked mid teleport-in spin (y2=" .. tostring(mid and mid.y2) .. ")")
|
|
U.still(game, DIR .. "/teleport_in_locked_mid_spin.png")
|
|
|
|
for _ = 1, 300 do
|
|
step()
|
|
if st.inDone and st.f > st.inDone + 30 then break end
|
|
end
|
|
say(string.format("[driver] firstUnlock=%s firstFadeDone=%s firstIn=%s inDone=%s",
|
|
tostring(st.firstUnlock), tostring(st.firstFadeDone), tostring(st.firstIn), tostring(st.inDone)))
|
|
result(st.firstIn ~= nil and st.inDone ~= nil, "the heal map ran the teleport-in effect")
|
|
result(not (st.firstUnlock and st.firstFadeDone and st.firstUnlock < st.firstFadeDone),
|
|
"the field stays locked through the fade-in (unlock f=" .. tostring(st.firstUnlock)
|
|
.. ", fade done f=" .. tostring(st.firstFadeDone) .. ")")
|
|
result(st.firstUnlock ~= nil and st.inDone ~= nil and st.firstUnlock >= st.inDone,
|
|
"the field stays locked until TeleportInFieldEffectTask3 unlocks it (unlock f=" .. tostring(st.firstUnlock)
|
|
.. ", spin done f=" .. tostring(st.inDone) .. ")")
|
|
result(not st.movedDuringFade, "the player cannot walk during the fade-in")
|
|
result(not st.movedDuringIn, "the player cannot walk during the teleport-in spin")
|
|
result(not st.claimEarly, "the heal map ON_FRAME claim waits for the teleport-in spin")
|
|
result(Space._pendingOnFrame ~= true and Field.locked == false,
|
|
"after the spin the ON_FRAME claim runs and the field unlocks")
|
|
U.still(game, DIR .. "/teleport_in_after_spin.png")
|
|
finish()
|
|
end
|
|
|
|
return run
|