mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
163 lines
6.1 KiB
Lua
163 lines
6.1 KiB
Lua
-- Driver: regression coverage for #219 "Early Blue Battle".
|
|
--
|
|
-- TEXT_OAKSLAB_RIVAL (data/scripts/oaks_lab.lua) is the rival's *talk*
|
|
-- handler. In pret/pokered scripts/OaksLab.asm OaksLabText8, talking to
|
|
-- the rival after you have a starter but before the lab battle only prints
|
|
-- _OaksLabRivalMyPokemonLooksStrongerText: the battle itself is a
|
|
-- coordinate trigger (OaksLabRivalChallengesPlayerScript, wYCoord == 6),
|
|
-- never a talk action. The buggy handler fell through from that line
|
|
-- straight into start_battle OPP_RIVAL1, so talking to Blue at the table
|
|
-- immediately launched the rival fight.
|
|
--
|
|
-- Scenario A (the #219 regression): talk to the rival with a starter but
|
|
-- no lab battle yet. Correct: the "looks stronger" line shows and NO
|
|
-- battle starts. Fails before the fix (start_battle fires on talk).
|
|
-- Scenario B (guard against over-correction): step onto the coordinate
|
|
-- trigger (y >= 6). Correct: the onStep challenge still starts the
|
|
-- battle. Passes both before and after the fix.
|
|
--
|
|
-- start_battle is stubbed to record the call and return "end" (halts the
|
|
-- script cleanly, no BattleState push, no yield) so the run never hangs
|
|
-- and needs no full party. We also read the raw text handed to
|
|
-- TextBox.new (before {PLAYER}/{RIVAL} substitution) so "stronger" is
|
|
-- detectable.
|
|
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
|
|
-- Capture the raw text the next TextBox is built with.
|
|
local TextBox = require("src.render.TextBox")
|
|
local origNew = TextBox.new
|
|
local lastText
|
|
TextBox.new = function(g, text, ...)
|
|
lastText = text
|
|
return origNew(g, text, ...)
|
|
end
|
|
|
|
-- Stub start_battle: record it and halt the script instead of pushing a
|
|
-- BattleState (which would need a real party) or yielding (which would
|
|
-- hang the driver). ScriptRunner resolves the live Commands.start_battle
|
|
-- when no mod overrides it, so this monkeypatch intercepts both the talk
|
|
-- handler and the onStep challenge.
|
|
local Commands = require("src.script.Commands")
|
|
local origStartBattle = Commands.start_battle
|
|
local battleStarted = false
|
|
Commands.start_battle = function(_ctx, _kind, _a, _b)
|
|
battleStarted = true
|
|
return "end"
|
|
end
|
|
|
|
local function restore()
|
|
TextBox.new = origNew
|
|
Commands.start_battle = origStartBattle
|
|
end
|
|
|
|
local function setFlags()
|
|
local flags = game.save.flags or {}
|
|
game.save.flags = flags
|
|
flags.EVENT_FOLLOWED_OAK_INTO_LAB = true
|
|
flags.EVENT_GOT_STARTER = true
|
|
flags.EVENT_CHOSE_SQUIRTLE = true
|
|
flags.EVENT_BATTLED_RIVAL_IN_OAKS_LAB = nil
|
|
end
|
|
|
|
-- ---- Scenario A: talk to the rival at the table.
|
|
-- fresh overworld in Oak's lab, player one cell right of the rival
|
|
-- (object 1 at cell 4,3) and facing him.
|
|
U.teleport(game, "OAKS_LAB", 5, 3, "left")
|
|
setFlags()
|
|
U.wait(6)
|
|
battleStarted = false
|
|
lastText = nil
|
|
|
|
U.shot(game, DIR .. "/a_before.png")
|
|
|
|
-- open the rival's textbox
|
|
U.tap(game, "left"); U.wait(2)
|
|
for _ = 1, 8 do
|
|
U.tap(game, "a")
|
|
for _ = 1, 30 do
|
|
if lastText then break end
|
|
U.wait(1)
|
|
end
|
|
if lastText then break end
|
|
end
|
|
local strongerSeen = lastText ~= nil and lastText:find("stronger") ~= nil
|
|
-- let the typewriter reveal the line, then shoot the box: the "looks
|
|
-- stronger" taunt, still overworld, no battle intro
|
|
U.wait(30)
|
|
U.shot(game, DIR .. "/a_after.png")
|
|
|
|
-- dismiss the taunt box. Before the fix, closing it drops the script
|
|
-- into the buggy start_battle rows (battleStarted flips true); after the
|
|
-- fix it hits jump "end" and the stack settles back to the overworld.
|
|
-- Stop the moment either happens so we never re-open the box by talking
|
|
-- again (which would leave a stray TextBox on top and false-fail the
|
|
-- overworld check).
|
|
for _ = 1, 20 do
|
|
if battleStarted then break end
|
|
if game.stack:top() == game.overworld then break end
|
|
U.tap(game, "a")
|
|
U.wait(3)
|
|
end
|
|
U.wait(10) -- let any fall-through start_battle fire
|
|
|
|
local aBattleStarted = battleStarted
|
|
local aOverworld = (game.stack:top() == game.overworld)
|
|
local aText = lastText or "<none>"
|
|
local aPass = strongerSeen and (aBattleStarted == false) and aOverworld
|
|
U.log("SCENARIO A text:", aText)
|
|
U.log("SCENARIO A strongerSeen:", tostring(strongerSeen),
|
|
"battleStarted:", tostring(aBattleStarted),
|
|
"overworld:", tostring(aOverworld))
|
|
U.log("SCENARIO A", aPass and "PASS" or "FAIL")
|
|
|
|
-- close any open box before scenario B
|
|
for _ = 1, 10 do U.tap(game, "a"); U.wait(2) end
|
|
|
|
-- ---- Scenario B: step onto the coordinate trigger (y >= 6).
|
|
-- Guards the real challenge path so the fix doesn't kill the lab battle.
|
|
U.teleport(game, "OAKS_LAB", 4, 5, "down")
|
|
setFlags()
|
|
U.wait(6)
|
|
battleStarted = false
|
|
do
|
|
local p = game.overworld.player
|
|
U.log("SCENARIO B start cell:", tostring(p.cellX), tostring(p.cellY),
|
|
"rival:", tostring(game.overworld:npcByIndex(1) ~= nil))
|
|
end
|
|
-- walk down until the player crosses y == 6 (OaksLabRivalChallenges),
|
|
-- pausing to mash A so the "I'll take you on" box + rival walk advance
|
|
for _ = 1, 6 do
|
|
U.hold(game, "down", 8)
|
|
for _ = 1, 12 do
|
|
U.tap(game, "a")
|
|
U.wait(3)
|
|
if battleStarted then break end
|
|
end
|
|
if battleStarted then break end
|
|
end
|
|
do
|
|
local p = game.overworld.player
|
|
U.log("SCENARIO B end cell:", tostring(p.cellX), tostring(p.cellY),
|
|
"lastText:", tostring(lastText))
|
|
end
|
|
U.shot(game, DIR .. "/b_after.png")
|
|
local bPass = (battleStarted == true)
|
|
U.log("SCENARIO B battleStarted:", tostring(battleStarted))
|
|
U.log("SCENARIO B", bPass and "PASS" or "FAIL")
|
|
|
|
-- restore hooks before any assert so a failure can't leave them installed
|
|
restore()
|
|
|
|
U.log("RESULT bug219", (aPass and bPass) and "PASS" or "FAIL")
|
|
assert(aPass,
|
|
"Scenario A: talking to the rival must only show the 'looks stronger' "
|
|
.. "line and start no battle (strongerSeen/battleStarted=false/overworld); "
|
|
.. "text=" .. aText .. " battleStarted=" .. tostring(aBattleStarted))
|
|
assert(bPass,
|
|
"Scenario B: stepping onto the coordinate trigger must still start the "
|
|
.. "lab battle")
|
|
end
|