From 4dfbc5a82836897ff6384d4bf9445210231502b0 Mon Sep 17 00:00:00 2001 From: johnjohto Date: Mon, 3 Aug 2026 11:52:48 -0400 Subject: [PATCH] Wire up Yellow's Route 18 gate trade cook (#651) --- data/scripts/story5.lua | 14 ++++++ tests/engine/save_convert_extra_flags.lua | 9 +++- tests/parity_yellow_route18_gate_trade.lua | 58 ++++++++++++++++++++++ 3 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 tests/parity_yellow_route18_gate_trade.lua diff --git a/data/scripts/story5.lua b/data/scripts/story5.lua index 1dc376d4..89324f90 100644 --- a/data/scripts/story5.lua +++ b/data/scripts/story5.lua @@ -176,6 +176,20 @@ M.ROUTE_18_GATE_2F = { { "face_player" }, { "trade", 6, "EVENT_TRADED_SLOWBRO_FOR_LICKITUNG" }, -- MARC }, + -- Yellow replaces the youngster with a cook trading SPIKE + -- (TANGELA -> PARASECT): pokeyellow/scripts/Route18Gate2F.asm + -- Route18Gate2FCookText runs TRADE_FOR_SPIKE, index 6 in the Yellow + -- TradeMons table that Data:applyVersionedFieldData swaps in. Red + -- maps have no COOK object here and Yellow maps have no YOUNGSTER, + -- so each version only ever fires its own row (#651). Both rows + -- share the Red-flavoured done flag on purpose: a .sav tracks + -- "trade slot 6 completed" in one wCompletedInGameTradeFlags bit + -- either version reads, and the save codec maps that bit to this + -- flag name (src/save_convert/GenSave.lua EXTRA_FLAG_BITS). + TEXT_ROUTE18GATE2F_COOK = { + { "face_player" }, + { "trade", 6, "EVENT_TRADED_SLOWBRO_FOR_LICKITUNG" }, -- SPIKE (Yellow) + }, }, } diff --git a/tests/engine/save_convert_extra_flags.lua b/tests/engine/save_convert_extra_flags.lua index a5eb3b35..24fd846f 100644 --- a/tests/engine/save_convert_extra_flags.lua +++ b/tests/engine/save_convert_extra_flags.lua @@ -105,7 +105,14 @@ for path in scripts:lines() do end end scripts:close() -check(#TRADE_ROWS == 7, "the nine-row trade table's seven reachable trades are scripted") +check(#TRADE_ROWS == 8, "all eight scripted trade rows are found") +-- trade slot 6 is scripted twice: Red's youngster and Yellow's gate cook +-- share the index and its done flag, one row per version (#651) +local slot6 = 0 +for _, row in ipairs(TRADE_ROWS) do + if row.index == 6 then slot6 = slot6 + 1 end +end +eq(slot6, 2, "trade slot 6 has a row for each version") -- ------------------------------------------------------------------ -- round trips diff --git a/tests/parity_yellow_route18_gate_trade.lua b/tests/parity_yellow_route18_gate_trade.lua new file mode 100644 index 00000000..af508cd4 --- /dev/null +++ b/tests/parity_yellow_route18_gate_trade.lua @@ -0,0 +1,58 @@ +-- Parity: Yellow's Route 18 Gate 2F trader is a cook offering SPIKE +-- (TANGELA -> PARASECT), not Red's youngster (pokeyellow/scripts/ +-- Route18Gate2F.asm Route18Gate2FCookText, TRADE_FOR_SPIKE). The port +-- only wired TEXT_ROUTE18GATE2F_YOUNGSTER, so on Yellow the cook had no +-- talk script at all and never answered (#651). +package.path = "./?.lua;./?/init.lua;" .. package.path +if not _G.love then _G.love = require("tests.love_stub") end + +local S = require("tests.harness").suite("parity Yellow route 18 gate trade") +local check, eq = S.check, S.eq + +local scripts = require("data.scripts.init") + +local cook = scripts.talkScript("ROUTE_18_GATE_2F", "TEXT_ROUTE18GATE2F_COOK") +check(cook ~= nil, "the Yellow cook has a talk script") +if cook then + eq(cook[2][1], "trade", "the cook runs a trade") + eq(cook[2][2], 6, "the cook's trade is TRADE_FOR_SPIKE (index 6)") + eq(cook[2][3], "EVENT_TRADED_SLOWBRO_FOR_LICKITUNG", + "the cook shares slot 6's done flag, so a converted .sav stays done") +end + +-- Red's youngster row stays put: trade 6 is MARC on Red's table and the +-- two rows share the index across versions. +local youngster = scripts.talkScript("ROUTE_18_GATE_2F", "TEXT_ROUTE18GATE2F_YOUNGSTER") +check(youngster ~= nil, "Red's youngster keeps his talk script") +if youngster then + eq(youngster[2][1], "trade", "the youngster runs a trade") + eq(youngster[2][2], 6, "the youngster's trade stays index 6") +end + +-- Yellow's map only has the cook, so the new key is the one that fires. +local manifestFile = assert(io.open("tools/rom_manifest_yellow.json", "r")) +local manifest = manifestFile:read("*a") +manifestFile:close() +check(manifest:find('"name": "ROUTE18GATE2F_COOK"', 1, true) ~= nil, + "Yellow's Route18Gate2F object is the cook") +check(manifest:find('"TEXT_ROUTE18GATE2F_COOK"', 1, true) ~= nil, + "the cook carries TEXT_ROUTE18GATE2F_COOK") +check(manifest:find("ROUTE18GATE2F_YOUNGSTER", 1, true) == nil, + "Yellow's Route18Gate2F has no youngster") + +-- The Yellow table makes index 6 the SPIKE row (TANGELA -> PARASECT). +local Data = require("src.core.Data") +if not (Data.field and Data.field.trades) then Data:load() end +local GameVersion = require("src.core.GameVersion") +local oldVersion = GameVersion.get() +local oldTrades = Data.field.trades +GameVersion.set("yellow") +Data:applyVersionedFieldData() +local spike = Data.field.trades[6] +check(spike.give == "TANGELA" and spike.get == "PARASECT" + and spike.nickname == "SPIKE", + "on Yellow trade 6 is SPIKE (TANGELA -> PARASECT)") +Data.field.trades = oldTrades +GameVersion.set(oldVersion) + +S.finish()