mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 00:10:56 +02:00
190 lines
7.4 KiB
Lua
190 lines
7.4 KiB
Lua
-- Yellow starts Bill's House with Pikachu's confused reaction. The map
|
|
-- script owns that one-shot, while PikachuFollower owns the movement.
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
local S = require("tests.harness").suite("parity Yellow Bill's Pikachu")
|
|
local check = S.check
|
|
|
|
local entered = 0
|
|
local originalFollower = package.loaded["src.world.PikachuFollower"]
|
|
package.loaded["src.world.PikachuFollower"] = {
|
|
onBillsHouseEnter = function()
|
|
entered = entered + 1
|
|
end,
|
|
}
|
|
|
|
local story = dofile("data/scripts/story.lua")
|
|
local game = { save = { flags = {} } }
|
|
story.BILLS_HOUSE.onEnter(game, {})
|
|
check(entered == 1,
|
|
"entering Bill's House before meeting Bill starts Pikachu's reaction")
|
|
|
|
entered = 0
|
|
game.save.flags.EVENT_MET_BILL_2 = true
|
|
story.BILLS_HOUSE.onEnter(game, {})
|
|
check(entered == 0,
|
|
"Pikachu's Bill reaction does not replay after Bill is met")
|
|
|
|
package.loaded["src.world.PikachuFollower"] = originalFollower
|
|
|
|
local GameVersion = require("src.core.GameVersion")
|
|
local PikachuFollower = require("src.world.PikachuFollower")
|
|
GameVersion.set("yellow")
|
|
|
|
local npc = {
|
|
pikachuFollower = true, cellX = 3, cellY = 8, px = 48, py = 128,
|
|
facing = "up",
|
|
}
|
|
local moves = {}
|
|
local yellowGame = {
|
|
save = { flags = {} },
|
|
data = {
|
|
pokemon = { PIKACHU = { spriteFront = "pikachu.png" } },
|
|
field = { emotionBubbles = {
|
|
bubbles = {
|
|
{ name = "QUESTION_BUBBLE" }, { name = "EXCLAMATION_BUBBLE" },
|
|
},
|
|
} },
|
|
},
|
|
}
|
|
local ow = {
|
|
map = { id = "BILLS_HOUSE" }, npcs = { npc }, entities = { npc },
|
|
player = { cellX = 3, cellY = 7 },
|
|
scriptMove = function(_, entity, dir, tiles, onDone)
|
|
moves[#moves + 1] = { entity = entity, dir = dir, tiles = tiles,
|
|
onDone = onDone }
|
|
end,
|
|
}
|
|
|
|
PikachuFollower.onBillsHouseEnter(yellowGame, ow)
|
|
check(ow.pikachuBillsScene and #moves == 1
|
|
and moves[1].entity == npc and moves[1].dir == "right"
|
|
and moves[1].tiles == 3,
|
|
"Bill's House entry parks Pikachu and walks it to Bill")
|
|
moves[1].onDone()
|
|
check(#moves == 2 and moves[2].dir == "up" and moves[2].tiles == 1,
|
|
"Pikachu finishes its cartridge entry route beside Bill")
|
|
moves[2].onDone()
|
|
check(ow.emote and ow.emote.bubble == 1,
|
|
"Pikachu shows its confused reaction after reaching Bill")
|
|
|
|
-- BillsHouseScript3 seeds hl with ..._EnterCellSeparatorDown and only swaps
|
|
-- in ..._EnterCellSeparatorNotDown on the facing-down fallthrough, so the
|
|
-- table names are inverted relative to the branch that picks them: facing
|
|
-- down takes the five-step detour, every other facing walks straight up
|
|
-- (pokeyellow scripts/BillsHouse.asm:100-133) (#455).
|
|
ow.player.facing = "down"
|
|
PikachuFollower.onBillEnteredMachine(yellowGame, ow)
|
|
check(#moves == 3 and moves[3].dir == "up" and moves[3].tiles == 1,
|
|
"facing down, Pikachu starts the long way round the cell separator")
|
|
moves[3].onDone()
|
|
check(#moves == 4 and moves[4].dir == "left" and moves[4].tiles == 1,
|
|
"the detour steps aside before climbing")
|
|
moves[4].onDone()
|
|
check(#moves == 5 and moves[5].dir == "up" and moves[5].tiles == 2,
|
|
"the detour climbs past the separator")
|
|
moves[5].onDone()
|
|
check(#moves == 6 and moves[6].dir == "right" and moves[6].tiles == 1,
|
|
"the detour steps back in beside it")
|
|
moves[6].onDone()
|
|
check(ow.emote and ow.emote.bubble == 1 and npc.facing == "up",
|
|
"Pikachu looks up and wonders at the cell separator")
|
|
|
|
-- the other branch: any non-down facing takes the straight three-step route
|
|
local before = #moves
|
|
ow.player.facing = "up"
|
|
PikachuFollower.onBillEnteredMachine(yellowGame, ow)
|
|
check(#moves == before + 1 and moves[before + 1].dir == "up"
|
|
and moves[before + 1].tiles == 3,
|
|
"facing up, Pikachu walks straight to the cell separator")
|
|
moves[before + 1].onDone()
|
|
|
|
npc.goalX, npc.goalY = 9, 9
|
|
PikachuFollower.update(yellowGame, ow)
|
|
check(npc.goalX == 9 and npc.goalY == 9,
|
|
"Pikachu stays parked in Bill's House during the scene")
|
|
|
|
PikachuFollower.onBillExitedMachine(yellowGame, ow)
|
|
check(ow.emote and ow.emote.bubble == 2 and npc.facing == "left",
|
|
"Pikachu reacts when Bill comes back out")
|
|
|
|
-- BillsHousePikachuWatchPlayer (scripts/BillsHouse_2.asm:133-156) is the
|
|
-- other side of BillsHouseScript2: it only runs while Pikachu still follows
|
|
-- the player, and TryApplyPikachuMovementData keys each table on
|
|
-- GetPikachuFacingDirectionAndReturnToE, which is Pikachu's position
|
|
-- relative to the player rather than its facing byte, so WatchPlayer1 wants
|
|
-- Pikachu above the player and WatchPlayer2 wants it level and east (#455).
|
|
local function placePikachu(cx, cy)
|
|
npc.cellX, npc.cellY, npc.facing = cx, cy, "down"
|
|
end
|
|
|
|
ow.pikachuBillsScene = nil
|
|
moves = {}
|
|
placePikachu(ow.player.cellX, ow.player.cellY - 1)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 1 and moves[1].dir == "left" and moves[1].tiles == 1,
|
|
"a Pikachu standing above the player steps aside for Bill's detour")
|
|
moves[1].onDone()
|
|
check(#moves == 2 and moves[2].dir == "down" and moves[2].tiles == 1,
|
|
"the watch route drops clear of Bill's detour")
|
|
moves[2].onDone()
|
|
check(npc.facing == "right", "PIKAMOVEMENT_LOOK_RIGHT watches the player")
|
|
|
|
moves = {}
|
|
placePikachu(ow.player.cellX + 1, ow.player.cellY)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 1 and moves[1].dir == "up" and moves[1].tiles == 1,
|
|
"level with and east of the player takes the longer WatchPlayer2 route")
|
|
moves[1].onDone()
|
|
check(#moves == 2 and moves[2].dir == "left" and moves[2].tiles == 2,
|
|
"WatchPlayer2 crosses two cells west")
|
|
moves[2].onDone()
|
|
check(#moves == 3 and moves[3].dir == "down" and moves[3].tiles == 1,
|
|
"WatchPlayer2 drops back level with the player")
|
|
moves[3].onDone()
|
|
check(npc.facing == "right", "WatchPlayer2 ends watching the player too")
|
|
|
|
-- below the player is SPRITE_FACING_DOWN and west of it is
|
|
-- SPRITE_FACING_LEFT, and neither call asks for those
|
|
moves = {}
|
|
placePikachu(ow.player.cellX, ow.player.cellY + 1)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 0, "a Pikachu trailing from the south has no watch route")
|
|
|
|
placePikachu(ow.player.cellX - 1, ow.player.cellY)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 0, "nor does one already standing west of the player")
|
|
|
|
-- ApplyPikachuMovementData_ finishes a table before the second
|
|
-- TryApplyPikachuMovementData reads the geometry again, but WatchPlayer1
|
|
-- lands on (playerX - 1, playerY), so WatchPlayer2 can never chain onto it
|
|
moves = {}
|
|
placePikachu(ow.player.cellX, ow.player.cellY - 1)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
moves[1].onDone()
|
|
moves[2].onDone()
|
|
placePikachu(ow.player.cellX - 1, ow.player.cellY)
|
|
moves = {}
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 0, "the two tables stay mutually exclusive by geometry")
|
|
|
|
-- the parked Pikachu of the confused beat is the not-following side of
|
|
-- CheckPikachuFollowingPlayer, so it never watches
|
|
ow.pikachuBillsScene = true
|
|
placePikachu(ow.player.cellX, ow.player.cellY - 1)
|
|
PikachuFollower.onBillWalksAroundPlayer(yellowGame, ow)
|
|
check(#moves == 0, "the parked Pikachu of the confused beat stays put")
|
|
|
|
-- BillsHouseScript0 skips the whole entry beat for a statused starter
|
|
-- (CheckPikachuStatusCondition, scripts/BillsHouse.asm:45-46)
|
|
ow.pikachuBillsScene = nil
|
|
moves = {}
|
|
yellowGame.save.party = { { species = "PIKACHU", hp = 12, status = "PAR" } }
|
|
PikachuFollower.onBillsHouseEnter(yellowGame, ow)
|
|
check(not ow.pikachuBillsScene and #moves == 0,
|
|
"a statused starter keeps following instead of walking over to Bill")
|
|
yellowGame.save.party = nil
|
|
|
|
GameVersion.set("red")
|
|
S.finish()
|