mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
96 lines
4.4 KiB
Lua
96 lines
4.4 KiB
Lua
-- Driver (#215): a link-traded mon must keep its ORIGINAL trainer's OT
|
|
-- name and ID on the receiving game, not adopt the receiver's identity.
|
|
--
|
|
-- pokered engine/link/cable_club.asm + home/serial.asm: a trade transmits
|
|
-- the whole party data block, which carries each mon's OT ID (party_struct
|
|
-- MON_OTID offset) and the OT-names block (wPartyMonOT). The receiving game
|
|
-- copies both verbatim and never overwrites -- a differing OT/ID is exactly
|
|
-- what marks a mon as traded (boosted EXP, high-level disobedience).
|
|
--
|
|
-- The bug: Protocol.packMon/unpackMon dropped mon.ot/mon.otId on the wire,
|
|
-- so a received mon arrived ot=nil/otId=nil and SummaryMenu (status_screen.asm
|
|
-- StatusScreen) fell back to the local player's name/ID -- the reporter saw
|
|
-- the sender's CULLEN/16012 mon show up on the receiver as RED/60368. This
|
|
-- drives the receiver side headlessly: pack a CULLEN-owned mon and unpack it,
|
|
-- then read exactly what SummaryMenu draws in the IDNo/OT slots.
|
|
return function(game)
|
|
local U = dofile("tests/drivers/util.lua")
|
|
local DIR = os.getenv("SHOT_DIR") or "/tmp/shots"
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local Protocol = require("src.link.Protocol")
|
|
local SummaryMenu = require("src.ui.SummaryMenu")
|
|
local BattleState = require("src.battle.BattleState")
|
|
local Font = require("src.render.Font")
|
|
|
|
-- This install is the RECEIVER: player RED, ID 60368 (from the report's
|
|
-- Blue window). A correctly preserved OT must NOT match these.
|
|
game.save.player.name = "RED"
|
|
game.save.player.id = 60368
|
|
|
|
-- Capture exactly the strings SummaryMenu draws in the IDNo value slot
|
|
-- (x=96, y=112) and the OT value slot (x=96, y=128) on page 1. Monkeypatch
|
|
-- the Font table field so SummaryMenu's own `local Font` reference resolves
|
|
-- to our wrapper at call time -- this reads the real rendered strings, not
|
|
-- Protocol in isolation, so it fails while the received mon carries no OT.
|
|
local realDraw = Font.draw
|
|
local function recordShot(mon, path)
|
|
local summary = SummaryMenu.new(game, mon)
|
|
game.stack:push(summary)
|
|
U.wait(4)
|
|
local capturedId, capturedOt = nil, nil
|
|
Font.draw = function(text, x, y)
|
|
if x == 96 and y == 112 then capturedId = text end
|
|
if x == 96 and y == 128 then capturedOt = text end
|
|
return realDraw(text, x, y)
|
|
end
|
|
U.shot(game, path)
|
|
Font.draw = realDraw
|
|
game.stack:pop()
|
|
U.wait(2)
|
|
return capturedId, capturedOt
|
|
end
|
|
|
|
-- The bug case: a RATTATA caught by trainer CULLEN (id 16012), sent across
|
|
-- the wire. pack -> unpack is exactly what the trade session does to the
|
|
-- mon before it lands in the receiver's party (Protocol.TradeSession).
|
|
local sender = Pokemon.new(game.data, "RATTATA", 8)
|
|
sender.ot = "CULLEN"
|
|
sender.otId = 16012
|
|
local received = Protocol.unpackMon(game.data, Protocol.packMon(sender))
|
|
local recvId, recvOt =
|
|
recordShot(received, DIR .. "/trade_ot_215_received_p1.png")
|
|
U.log("received mon: IDNo=", tostring(recvId), " OT=", tostring(recvOt))
|
|
|
|
-- Control: a mon caught locally on THIS game gets the player stamped as OT
|
|
-- (BattleState.stampOT, engine/battle/core.asm on catch), so its summary
|
|
-- correctly reads RED / 60368. This proves the player-fallback path itself
|
|
-- is fine and it is only the received mon that was wrong.
|
|
local mine = Pokemon.new(game.data, "PIDGEY", 8)
|
|
BattleState.stampOT(game.save, mine)
|
|
local mineId, mineOt =
|
|
recordShot(mine, DIR .. "/trade_ot_215_control_p1.png")
|
|
U.log("self-caught mon: IDNo=", tostring(mineId), " OT=", tostring(mineOt))
|
|
|
|
U.log("shots under", DIR)
|
|
|
|
-- The received mon must show the ORIGINAL trainer, not the receiver.
|
|
assert(recvOt == "CULLEN",
|
|
"#215: received mon OT must render CULLEN (the original trainer), drew "
|
|
.. tostring(recvOt))
|
|
assert(recvId == "16012",
|
|
"#215: received mon IDNo must render 16012 (the original trainer ID), drew "
|
|
.. tostring(recvId))
|
|
assert(recvOt ~= game.save.player.name,
|
|
"#215: received mon must not adopt the receiver's OT name")
|
|
assert(recvId ~= ("%05d"):format(game.save.player.id),
|
|
"#215: received mon must not adopt the receiver's ID")
|
|
|
|
-- Control must still show the local player (self-caught mon is unaffected).
|
|
assert(mineOt == "RED",
|
|
"control: self-caught mon OT must render RED, drew " .. tostring(mineOt))
|
|
assert(mineId == "60368",
|
|
"control: self-caught mon IDNo must render 60368, drew " .. tostring(mineId))
|
|
|
|
U.log("#215 PASS: link-traded mon keeps the original trainer's OT/ID")
|
|
end
|