mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 08:21:02 +02:00
Skip the gym leader TM hand-over when the bag is full
The originals run GiveItem before printing the received texts, and when the bag can't hold the TM they print a make-room line instead and leave EVENT_GOT_TM* unset, so talking to the leader again retries the give. The victory reward path added the TM straight into the inventory, so a full bag went to 21/20. Route the gym TM give through Bag.add, split the TM lines out of the victory dialogue table into tmPre/tmDialogue/noRoom, and port the beaten-leader middle branch that re-runs the ReceiveTM script. Saves that already hold the TM without the flag count as received so they don't collect a second copy. Refs #797
This commit is contained in:
+37
-14
@@ -18,6 +18,26 @@ local M = {
|
|||||||
VIRIDIAN_GYM = { city = "VIRIDIAN CITY", leader = "GIOVANNI", badge = "EARTHBADGE" },
|
VIRIDIAN_GYM = { city = "VIRIDIAN CITY", leader = "GIOVANNI", badge = "EARTHBADGE" },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- The originals' middle branch shared by every leader's text_asm: beaten
|
||||||
|
-- but EVENT_GOT_TM* unset means the bag was full when the victory script
|
||||||
|
-- ran GiveItem, so talking to the leader re-runs the ReceiveTM script.
|
||||||
|
-- Returns true when the retry took over the talk. A save from before
|
||||||
|
-- #797 already holds the TM without the flag; treat the owned TM as
|
||||||
|
-- received so those saves fall through to the advice text instead of
|
||||||
|
-- collecting a second copy.
|
||||||
|
local function retryTmGive(game, ow, victoryKey, done)
|
||||||
|
local reward = require("data.scripts.victories")[victoryKey]
|
||||||
|
if not (reward and reward.gotFlag) then return false end
|
||||||
|
if game.save.flags[reward.gotFlag] then return false end
|
||||||
|
local owned = game.save.inventory and game.save.inventory[reward.item] or 0
|
||||||
|
if owned > 0 then
|
||||||
|
game.save.flags[reward.gotFlag] = true
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
ow:offerGymTm(reward, done)
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- scripts/PewterGym.asm PewterGymBrockText (text_asm): CheckEvent
|
-- scripts/PewterGym.asm PewterGymBrockText (text_asm): CheckEvent
|
||||||
-- EVENT_BEAT_BROCK branches his dialogue. Before the badge he prints
|
-- EVENT_BEAT_BROCK branches his dialogue. Before the badge he prints
|
||||||
-- _PewterGymBrockPreBattleText and engages the leader battle
|
-- _PewterGymBrockPreBattleText and engages the leader battle
|
||||||
@@ -25,12 +45,14 @@ local M = {
|
|||||||
-- badge/TM34 rewards and EVENT_BEAT_BROCK come from
|
-- badge/TM34 rewards and EVENT_BEAT_BROCK come from
|
||||||
-- data/scripts/victories.lua OPP_BROCK#1). After the badge his
|
-- data/scripts/victories.lua OPP_BROCK#1). After the badge his
|
||||||
-- .afterBeat branch prints _PewterGymBrockPostBattleAdviceText ("Go to
|
-- .afterBeat branch prints _PewterGymBrockPostBattleAdviceText ("Go to
|
||||||
-- the GYM in CERULEAN..."). The original's middle branch (beat but
|
-- the GYM in CERULEAN..."). The middle branch (beat but TM34 not yet
|
||||||
-- TM34 not yet handed over, CheckEventReuseA EVENT_GOT_TM34) is
|
-- handed over, CheckEventReuseA EVENT_GOT_TM34 -> call
|
||||||
-- unreachable in the port: the TM is granted with the victory.
|
-- PewterGymScriptReceiveTM34) retries the TM give when the bag was full
|
||||||
|
-- at the victory (#797).
|
||||||
M.PEWTER_GYM.talk = {
|
M.PEWTER_GYM.talk = {
|
||||||
TEXT_PEWTERGYM_BROCK = function(game, ow, npc, done)
|
TEXT_PEWTERGYM_BROCK = function(game, ow, npc, done)
|
||||||
if game.save.flags.EVENT_BEAT_BROCK then
|
if game.save.flags.EVENT_BEAT_BROCK then
|
||||||
|
if retryTmGive(game, ow, "OPP_BROCK#1", done) then return end
|
||||||
local TextBox = require("src.render.TextBox")
|
local TextBox = require("src.render.TextBox")
|
||||||
game.stack:push(TextBox.new(game,
|
game.stack:push(TextBox.new(game,
|
||||||
game.data.text._PewterGymBrockPostBattleAdviceText
|
game.data.text._PewterGymBrockPostBattleAdviceText
|
||||||
@@ -48,16 +70,17 @@ M.PEWTER_GYM.talk = {
|
|||||||
-- (engageTrainer shows that same pre-battle text via resolveText; the
|
-- (engageTrainer shows that same pre-battle text via resolveText; the
|
||||||
-- badge/TM rewards and the beat flag come from data/scripts/victories.lua)
|
-- badge/TM rewards and the beat flag come from data/scripts/victories.lua)
|
||||||
-- -- and once beaten print the post-battle advice text. As with Brock,
|
-- -- and once beaten print the post-battle advice text. As with Brock,
|
||||||
-- the originals' middle branch (beaten but the TM not yet handed over,
|
-- the middle branch (beaten but the TM not yet handed over,
|
||||||
-- CheckEventReuseA EVENT_GOT_TM*) is unreachable in the port: the TM is
|
-- CheckEventReuseA EVENT_GOT_TM*) retries the TM give when the bag was
|
||||||
-- granted with the victory.
|
-- full at the victory.
|
||||||
-- afterAdvice, when given, takes over `done`: it is handed (game, ow, npc,
|
-- afterAdvice, when given, takes over `done`: it is handed (game, ow, npc,
|
||||||
-- done) and must call done() itself once whatever it's doing (e.g. a fade
|
-- done) and must call done() itself once whatever it's doing (e.g. a fade
|
||||||
-- around a HideObject) finishes, rather than having it invoked
|
-- around a HideObject) finishes, rather than having it invoked
|
||||||
-- automatically. Only Giovanni's farewell uses this.
|
-- automatically. Only Giovanni's farewell uses this.
|
||||||
local function leaderTalk(beatFlag, adviceLabel, fallback, afterAdvice)
|
local function leaderTalk(beatFlag, adviceLabel, fallback, afterAdvice, victoryKey)
|
||||||
return function(game, ow, npc, done)
|
return function(game, ow, npc, done)
|
||||||
if game.save.flags[beatFlag] then
|
if game.save.flags[beatFlag] then
|
||||||
|
if victoryKey and retryTmGive(game, ow, victoryKey, done) then return end
|
||||||
local TextBox = require("src.render.TextBox")
|
local TextBox = require("src.render.TextBox")
|
||||||
local finish = done
|
local finish = done
|
||||||
if afterAdvice then
|
if afterAdvice then
|
||||||
@@ -79,42 +102,42 @@ end
|
|||||||
M.CERULEAN_GYM.talk = {
|
M.CERULEAN_GYM.talk = {
|
||||||
TEXT_CERULEANGYM_MISTY = leaderTalk("EVENT_BEAT_MISTY",
|
TEXT_CERULEANGYM_MISTY = leaderTalk("EVENT_BEAT_MISTY",
|
||||||
"_CeruleanGymMistyTM11ExplanationText",
|
"_CeruleanGymMistyTM11ExplanationText",
|
||||||
"TM11 teaches\nBUBBLEBEAM!"),
|
"TM11 teaches\nBUBBLEBEAM!", nil, "OPP_MISTY#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/VermilionGym.asm VermilionGymLTSurgeText .got_tm24_already
|
-- scripts/VermilionGym.asm VermilionGymLTSurgeText .got_tm24_already
|
||||||
M.VERMILION_GYM.talk = {
|
M.VERMILION_GYM.talk = {
|
||||||
TEXT_VERMILIONGYM_LT_SURGE = leaderTalk("EVENT_BEAT_LT_SURGE",
|
TEXT_VERMILIONGYM_LT_SURGE = leaderTalk("EVENT_BEAT_LT_SURGE",
|
||||||
"_VermilionGymLTSurgePostBattleAdviceText",
|
"_VermilionGymLTSurgePostBattleAdviceText",
|
||||||
"A little word of\nadvice, kid!"),
|
"A little word of\nadvice, kid!", nil, "OPP_LT_SURGE#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/CeladonGym.asm CeladonGymErikaText .afterBeat
|
-- scripts/CeladonGym.asm CeladonGymErikaText .afterBeat
|
||||||
M.CELADON_GYM.talk = {
|
M.CELADON_GYM.talk = {
|
||||||
TEXT_CELADONGYM_ERIKA = leaderTalk("EVENT_BEAT_ERIKA",
|
TEXT_CELADONGYM_ERIKA = leaderTalk("EVENT_BEAT_ERIKA",
|
||||||
"_CeladonGymErikaPostBattleAdviceText",
|
"_CeladonGymErikaPostBattleAdviceText",
|
||||||
"You are cataloging\nPOKéMON? I must\nsay I'm impressed."),
|
"You are cataloging\nPOKéMON? I must\nsay I'm impressed.", nil, "OPP_ERIKA#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/FuchsiaGym.asm FuchsiaGymKogaText .afterBeat
|
-- scripts/FuchsiaGym.asm FuchsiaGymKogaText .afterBeat
|
||||||
M.FUCHSIA_GYM.talk = {
|
M.FUCHSIA_GYM.talk = {
|
||||||
TEXT_FUCHSIAGYM_KOGA = leaderTalk("EVENT_BEAT_KOGA",
|
TEXT_FUCHSIAGYM_KOGA = leaderTalk("EVENT_BEAT_KOGA",
|
||||||
"_FuchsiaGymKogaPostBattleAdviceText",
|
"_FuchsiaGymKogaPostBattleAdviceText",
|
||||||
"When afflicted by\nTOXIC, POKéMON\nsuffer more and\nmore as battle\nprogresses!"),
|
"When afflicted by\nTOXIC, POKéMON\nsuffer more and\nmore as battle\nprogresses!", nil, "OPP_KOGA#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/SaffronGym.asm SaffronGymSabrinaText .afterBeat
|
-- scripts/SaffronGym.asm SaffronGymSabrinaText .afterBeat
|
||||||
M.SAFFRON_GYM.talk = {
|
M.SAFFRON_GYM.talk = {
|
||||||
TEXT_SAFFRONGYM_SABRINA = leaderTalk("EVENT_BEAT_SABRINA",
|
TEXT_SAFFRONGYM_SABRINA = leaderTalk("EVENT_BEAT_SABRINA",
|
||||||
"_SaffronGymSabrinaPostBattleAdviceText",
|
"_SaffronGymSabrinaPostBattleAdviceText",
|
||||||
"Everyone has\npsychic power!\nPeople just don't\nrealize it!"),
|
"Everyone has\npsychic power!\nPeople just don't\nrealize it!", nil, "OPP_SABRINA#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/CinnabarGym.asm CinnabarGymBlaineText .afterBeat
|
-- scripts/CinnabarGym.asm CinnabarGymBlaineText .afterBeat
|
||||||
M.CINNABAR_GYM.talk = {
|
M.CINNABAR_GYM.talk = {
|
||||||
TEXT_CINNABARGYM_BLAINE = leaderTalk("EVENT_BEAT_BLAINE",
|
TEXT_CINNABARGYM_BLAINE = leaderTalk("EVENT_BEAT_BLAINE",
|
||||||
"_CinnabarGymBlainePostBattleAdviceText",
|
"_CinnabarGymBlainePostBattleAdviceText",
|
||||||
"FIRE BLAST is the\nultimate fire\ntechnique!"),
|
"FIRE BLAST is the\nultimate fire\ntechnique!", nil, "OPP_BLAINE#1"),
|
||||||
}
|
}
|
||||||
|
|
||||||
-- scripts/ViridianGym.asm ViridianGymGiovanniText .afterBeat: after the
|
-- scripts/ViridianGym.asm ViridianGymGiovanniText .afterBeat: after the
|
||||||
@@ -142,7 +165,7 @@ M.VIRIDIAN_GYM.talk = {
|
|||||||
"VIRIDIAN_GYM", "VIRIDIANGYM_GIOVANNI")
|
"VIRIDIAN_GYM", "VIRIDIANGYM_GIOVANNI")
|
||||||
end
|
end
|
||||||
end, done))
|
end, done))
|
||||||
end),
|
end, "OPP_GIOVANNI#3"),
|
||||||
}
|
}
|
||||||
|
|
||||||
return M
|
return M
|
||||||
|
|||||||
@@ -18,6 +18,16 @@
|
|||||||
-- script). Leaders are not def_trainers entries, so engageTrainer has
|
-- script). Leaders are not def_trainers entries, so engageTrainer has
|
||||||
-- no header.won -- checkVictoryRewards shows this chain instead of a
|
-- no header.won -- checkVictoryRewards shows this chain instead of a
|
||||||
-- synthetic "received badge/TM" stub.
|
-- synthetic "received badge/TM" stub.
|
||||||
|
--
|
||||||
|
-- Gym entries split the TM hand-over out of `dialogue`, mirroring the
|
||||||
|
-- originals' GiveItem check (`call GiveItem` / `jr nc, .BagFull`):
|
||||||
|
-- `tmPre` is the ReceiveTM script's lead-in (badge info / "Wait! Take
|
||||||
|
-- this!"), shown at the victory and again when a beaten leader retries
|
||||||
|
-- the hand-over; `tmDialogue` shows only when the TM actually goes in
|
||||||
|
-- the bag; `noRoom` is the "make room" line shown instead when the bag
|
||||||
|
-- is full; `gotFlag` (pokered's EVENT_GOT_TM*) is set only on a
|
||||||
|
-- successful give, which is what makes the leader's talk script retry
|
||||||
|
-- later (gyms.lua).
|
||||||
|
|
||||||
local function range(prefix, first, last)
|
local function range(prefix, first, last)
|
||||||
local t = {}
|
local t = {}
|
||||||
@@ -33,6 +43,8 @@ return {
|
|||||||
-- escort NPC and the first Route 22 rival stay gone after the badge.
|
-- escort NPC and the first Route 22 rival stay gone after the badge.
|
||||||
["OPP_BROCK#1"] = { badge = "BOULDERBADGE", flag = "EVENT_BEAT_BROCK",
|
["OPP_BROCK#1"] = { badge = "BOULDERBADGE", flag = "EVENT_BEAT_BROCK",
|
||||||
item = "TM_BIDE",
|
item = "TM_BIDE",
|
||||||
|
gotFlag = "EVENT_GOT_TM34",
|
||||||
|
noRoom = "_PewterGymTM34NoRoomText",
|
||||||
deactivate = { "EVENT_BEAT_PEWTER_GYM_TRAINER_0" },
|
deactivate = { "EVENT_BEAT_PEWTER_GYM_TRAINER_0" },
|
||||||
hide = {
|
hide = {
|
||||||
{ "PEWTER_CITY", "PEWTERCITY_YOUNGSTER" },
|
{ "PEWTER_CITY", "PEWTERCITY_YOUNGSTER" },
|
||||||
@@ -41,69 +53,99 @@ return {
|
|||||||
dialogue = {
|
dialogue = {
|
||||||
"_PewterGymBrockReceivedBoulderBadgeText",
|
"_PewterGymBrockReceivedBoulderBadgeText",
|
||||||
"_PewterGymBrockBoulderBadgeInfoText",
|
"_PewterGymBrockBoulderBadgeInfoText",
|
||||||
"_PewterGymBrockWaitTakeThisText",
|
},
|
||||||
|
tmPre = { "_PewterGymBrockWaitTakeThisText" },
|
||||||
|
tmDialogue = {
|
||||||
"_PewterGymReceivedTM34Text",
|
"_PewterGymReceivedTM34Text",
|
||||||
"_TM34ExplanationText",
|
"_TM34ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_MISTY#1"] = { badge = "CASCADEBADGE", flag = "EVENT_BEAT_MISTY",
|
["OPP_MISTY#1"] = { badge = "CASCADEBADGE", flag = "EVENT_BEAT_MISTY",
|
||||||
item = "TM_BUBBLEBEAM",
|
item = "TM_BUBBLEBEAM",
|
||||||
|
gotFlag = "EVENT_GOT_TM11",
|
||||||
|
noRoom = "_CeruleanGymMistyTM11NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_CERULEAN_GYM_TRAINER_", 0, 1),
|
deactivate = range("EVENT_BEAT_CERULEAN_GYM_TRAINER_", 0, 1),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_CeruleanGymMistyReceivedCascadeBadgeText",
|
"_CeruleanGymMistyReceivedCascadeBadgeText",
|
||||||
"_CeruleanGymMistyCascadeBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_CeruleanGymMistyCascadeBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_CeruleanGymMistyReceivedTM11Text",
|
"_CeruleanGymMistyReceivedTM11Text",
|
||||||
} },
|
} },
|
||||||
["OPP_LT_SURGE#1"] = { badge = "THUNDERBADGE", flag = "EVENT_BEAT_LT_SURGE",
|
["OPP_LT_SURGE#1"] = { badge = "THUNDERBADGE", flag = "EVENT_BEAT_LT_SURGE",
|
||||||
item = "TM_THUNDERBOLT",
|
item = "TM_THUNDERBOLT",
|
||||||
|
gotFlag = "EVENT_GOT_TM24",
|
||||||
|
noRoom = "_VermilionGymLTSurgeTM24NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_VERMILION_GYM_TRAINER_", 0, 2),
|
deactivate = range("EVENT_BEAT_VERMILION_GYM_TRAINER_", 0, 2),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_VermilionGymLTSurgeReceivedThunderBadgeText",
|
"_VermilionGymLTSurgeReceivedThunderBadgeText",
|
||||||
"_VermilionGymLTSurgeThunderBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_VermilionGymLTSurgeThunderBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_VermilionGymLTSurgeReceivedTM24Text",
|
"_VermilionGymLTSurgeReceivedTM24Text",
|
||||||
"_TM24ExplanationText",
|
"_TM24ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_ERIKA#1"] = { badge = "RAINBOWBADGE", flag = "EVENT_BEAT_ERIKA",
|
["OPP_ERIKA#1"] = { badge = "RAINBOWBADGE", flag = "EVENT_BEAT_ERIKA",
|
||||||
item = "TM_MEGA_DRAIN",
|
item = "TM_MEGA_DRAIN",
|
||||||
|
gotFlag = "EVENT_GOT_TM21",
|
||||||
|
noRoom = "_CeladonGymTM21NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_CELADON_GYM_TRAINER_", 0, 6),
|
deactivate = range("EVENT_BEAT_CELADON_GYM_TRAINER_", 0, 6),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_CeladonGymErikaReceivedRainbowBadgeText",
|
"_CeladonGymErikaReceivedRainbowBadgeText",
|
||||||
"_CeladonGymRainbowBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_CeladonGymRainbowBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_CeladonGymReceivedTM21Text",
|
"_CeladonGymReceivedTM21Text",
|
||||||
"_TM21ExplanationText",
|
"_TM21ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_KOGA#1"] = { badge = "SOULBADGE", flag = "EVENT_BEAT_KOGA",
|
["OPP_KOGA#1"] = { badge = "SOULBADGE", flag = "EVENT_BEAT_KOGA",
|
||||||
item = "TM_TOXIC",
|
item = "TM_TOXIC",
|
||||||
|
gotFlag = "EVENT_GOT_TM06",
|
||||||
|
noRoom = "_FuchsiaGymKogaTM06NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_FUCHSIA_GYM_TRAINER_", 0, 5),
|
deactivate = range("EVENT_BEAT_FUCHSIA_GYM_TRAINER_", 0, 5),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_FuchsiaGymKogaReceivedSoulBadgeText",
|
"_FuchsiaGymKogaReceivedSoulBadgeText",
|
||||||
"_FuchsiaGymKogaSoulBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_FuchsiaGymKogaSoulBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_FuchsiaGymKogaReceivedTM06Text",
|
"_FuchsiaGymKogaReceivedTM06Text",
|
||||||
"_FuchsiaGymKogaTM06ExplanationText",
|
"_FuchsiaGymKogaTM06ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_SABRINA#1"] = { badge = "MARSHBADGE", flag = "EVENT_BEAT_SABRINA",
|
["OPP_SABRINA#1"] = { badge = "MARSHBADGE", flag = "EVENT_BEAT_SABRINA",
|
||||||
item = "TM_PSYWAVE",
|
item = "TM_PSYWAVE",
|
||||||
|
gotFlag = "EVENT_GOT_TM46",
|
||||||
|
noRoom = "_SaffronGymSabrinaTM46NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_SAFFRON_GYM_TRAINER_", 0, 6),
|
deactivate = range("EVENT_BEAT_SAFFRON_GYM_TRAINER_", 0, 6),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_SaffronGymSabrinaReceivedMarshBadgeText",
|
"_SaffronGymSabrinaReceivedMarshBadgeText",
|
||||||
"_SaffronGymSabrinaMarshBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_SaffronGymSabrinaMarshBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_SaffronGymSabrinaReceivedTM46Text",
|
"_SaffronGymSabrinaReceivedTM46Text",
|
||||||
"_TM46ExplanationText",
|
"_TM46ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_BLAINE#1"] = { badge = "VOLCANOBADGE", flag = "EVENT_BEAT_BLAINE",
|
["OPP_BLAINE#1"] = { badge = "VOLCANOBADGE", flag = "EVENT_BEAT_BLAINE",
|
||||||
item = "TM_FIRE_BLAST",
|
item = "TM_FIRE_BLAST",
|
||||||
|
gotFlag = "EVENT_GOT_TM38",
|
||||||
|
noRoom = "_CinnabarGymBlaineTM38NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_CINNABAR_GYM_TRAINER_", 0, 6),
|
deactivate = range("EVENT_BEAT_CINNABAR_GYM_TRAINER_", 0, 6),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_CinnabarGymBlaineReceivedVolcanoBadgeText",
|
"_CinnabarGymBlaineReceivedVolcanoBadgeText",
|
||||||
"_CinnabarGymBlaineVolcanoBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_CinnabarGymBlaineVolcanoBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_CinnabarGymBlaineReceivedTM38Text",
|
"_CinnabarGymBlaineReceivedTM38Text",
|
||||||
"_CinnabarGymBlaineTM38ExplanationText",
|
"_CinnabarGymBlaineTM38ExplanationText",
|
||||||
} },
|
} },
|
||||||
["OPP_GIOVANNI#3"] = { badge = "EARTHBADGE", flag = "EVENT_BEAT_GIOVANNI",
|
["OPP_GIOVANNI#3"] = { badge = "EARTHBADGE", flag = "EVENT_BEAT_GIOVANNI",
|
||||||
item = "TM_FISSURE",
|
item = "TM_FISSURE",
|
||||||
|
gotFlag = "EVENT_GOT_TM27",
|
||||||
|
noRoom = "_ViridianGymGiovanniTM27NoRoomText",
|
||||||
deactivate = range("EVENT_BEAT_VIRIDIAN_GYM_TRAINER_", 0, 7),
|
deactivate = range("EVENT_BEAT_VIRIDIAN_GYM_TRAINER_", 0, 7),
|
||||||
dialogue = {
|
dialogue = {
|
||||||
"_ViridianGymGiovanniReceivedEarthBadgeText",
|
"_ViridianGymGiovanniReceivedEarthBadgeText",
|
||||||
"_ViridianGymGiovanniEarthBadgeInfoText",
|
},
|
||||||
|
tmPre = { "_ViridianGymGiovanniEarthBadgeInfoText" },
|
||||||
|
tmDialogue = {
|
||||||
"_ViridianGymGiovanniReceivedTM27Text",
|
"_ViridianGymGiovanniReceivedTM27Text",
|
||||||
"_ViridianGymGiovanniTM27ExplanationText",
|
"_ViridianGymGiovanniTM27ExplanationText",
|
||||||
} },
|
} },
|
||||||
|
|||||||
@@ -234,8 +234,12 @@ What was ported from pokered's engine code and where it came from.
|
|||||||
pre-battle text and engages the leader battle (badge/TM via
|
pre-battle text and engages the leader battle (badge/TM via
|
||||||
data/scripts/victories.lua); post-badge talk prints the leader's
|
data/scripts/victories.lua); post-badge talk prints the leader's
|
||||||
post-battle advice text (Misty's is her TM11 explanation). The
|
post-battle advice text (Misty's is her TM11 explanation). The
|
||||||
originals' middle branch (beaten but TM not handed over) is
|
originals' middle branch (beaten but TM not handed over,
|
||||||
unreachable since the TM is granted with the victory. Giovanni's
|
CheckEventReuseA EVENT_GOT_TM*) is ported too: the victory's GiveItem
|
||||||
|
goes through the bag's capacity check, a full bag shows the leader's
|
||||||
|
"make room" text instead of the received lines and leaves
|
||||||
|
EVENT_GOT_TM* unset, and talking to the leader re-runs the ReceiveTM
|
||||||
|
script until the TM goes in (#797). Giovanni's
|
||||||
farewell (`ViridianGymGiovanniText` .afterBeat) hides him inside a
|
farewell (`ViridianGymGiovanniText` .afterBeat) hides him inside a
|
||||||
fade-to-black/fade-in Transition matching ViridianGym.asm's
|
fade-to-black/fade-in Transition matching ViridianGym.asm's
|
||||||
GBFadeOutToBlack → HideObject → GBFadeInFromBlack, persisted
|
GBFadeOutToBlack → HideObject → GBFadeInFromBlack, persisted
|
||||||
|
|||||||
@@ -3003,6 +3003,22 @@ function OverworldState:engageTrainer(npc, onDone)
|
|||||||
end))
|
end))
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- Shared GiveItem step for the victory rewards (pokered home/give.asm):
|
||||||
|
-- the item goes through the bag's capacity check, and only a successful
|
||||||
|
-- add sets the reward's gotFlag (EVENT_GOT_TM*) and copies the item name
|
||||||
|
-- into wStringBuffer for the "{RAM:wStringBuffer}" received texts.
|
||||||
|
local function giveVictoryItem(reward)
|
||||||
|
if not require("src.inventory.Bag").add(Game.save, reward.item, 1, Game.data) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
if reward.gotFlag then
|
||||||
|
Game.save.flags[reward.gotFlag] = true
|
||||||
|
end
|
||||||
|
local idef = Game.data.items[reward.item]
|
||||||
|
Game.stringBuffer = idef and idef.name or reward.item
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
-- Badges/items awarded after specific battles (data/scripts/victories.lua).
|
-- Badges/items awarded after specific battles (data/scripts/victories.lua).
|
||||||
-- `deactivate` retires unfought gym/dojo trainers the way the originals'
|
-- `deactivate` retires unfought gym/dojo trainers the way the originals'
|
||||||
-- SetEvent / SetEventRange do after the leader victory.
|
-- SetEvent / SetEventRange do after the leader victory.
|
||||||
@@ -3031,12 +3047,13 @@ function OverworldState:checkVictoryRewards(trainerClass, partyIndex)
|
|||||||
if reward.badge then
|
if reward.badge then
|
||||||
Game.save.inventory[reward.badge] = 1
|
Game.save.inventory[reward.badge] = 1
|
||||||
end
|
end
|
||||||
|
local tmGiven = false
|
||||||
if reward.item then
|
if reward.item then
|
||||||
local inv = Game.save.inventory
|
-- pokered GiveItem (home/give.asm): AddItemToInventory first, and a
|
||||||
inv[reward.item] = (inv[reward.item] or 0) + 1
|
-- full bag (jr nc, .BagFull) skips the received lines for the "make
|
||||||
local idef = Game.data.items[reward.item]
|
-- room" text, leaving EVENT_GOT_TM* unset so the leader's talk script
|
||||||
-- GiveItem -> CopyToStringBuffer for "{RAM:wStringBuffer}" received texts
|
-- retries the hand-over later (offerGymTm via gyms.lua)
|
||||||
Game.stringBuffer = idef and idef.name or reward.item
|
tmGiven = giveVictoryItem(reward)
|
||||||
end
|
end
|
||||||
local lines = {}
|
local lines = {}
|
||||||
if reward.dialogue then
|
if reward.dialogue then
|
||||||
@@ -3046,13 +3063,29 @@ function OverworldState:checkVictoryRewards(trainerClass, partyIndex)
|
|||||||
table.insert(lines, text[label])
|
table.insert(lines, text[label])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
if reward.item then
|
||||||
|
for _, label in ipairs(reward.tmPre or {}) do
|
||||||
|
if text[label] and text[label] ~= "" then
|
||||||
|
table.insert(lines, text[label])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if tmGiven then
|
||||||
|
for _, label in ipairs(reward.tmDialogue or {}) do
|
||||||
|
if text[label] and text[label] ~= "" then
|
||||||
|
table.insert(lines, text[label])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif reward.noRoom and text[reward.noRoom] and text[reward.noRoom] ~= "" then
|
||||||
|
table.insert(lines, text[reward.noRoom])
|
||||||
|
end
|
||||||
|
end
|
||||||
elseif reward.badge or reward.item then
|
elseif reward.badge or reward.item then
|
||||||
if reward.badge then
|
if reward.badge then
|
||||||
local name = Game.data.items[reward.badge] and Game.data.items[reward.badge].name
|
local name = Game.data.items[reward.badge] and Game.data.items[reward.badge].name
|
||||||
or reward.badge
|
or reward.badge
|
||||||
table.insert(lines, Strings("%s received\nthe %s!", Game.save.player.name, name))
|
table.insert(lines, Strings("%s received\nthe %s!", Game.save.player.name, name))
|
||||||
end
|
end
|
||||||
if reward.item then
|
if tmGiven then
|
||||||
local name = Game.stringBuffer or reward.item
|
local name = Game.stringBuffer or reward.item
|
||||||
table.insert(lines, Strings("%s received\n%s!", Game.save.player.name, name))
|
table.insert(lines, Strings("%s received\n%s!", Game.save.player.name, name))
|
||||||
end
|
end
|
||||||
@@ -3063,6 +3096,33 @@ function OverworldState:checkVictoryRewards(trainerClass, partyIndex)
|
|||||||
self:runVictoryHook()
|
self:runVictoryHook()
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- A beaten leader re-running their ReceiveTM script when the bag was full
|
||||||
|
-- at the victory (pokered's middle branch, e.g. PewterGymBrockText
|
||||||
|
-- CheckEventReuseA EVENT_GOT_TM34 -> call PewterGymScriptReceiveTM34).
|
||||||
|
-- The script's lead-in lines (tmPre: badge info / "Wait! Take this!")
|
||||||
|
-- show again, then the same GiveItem check decides between the received
|
||||||
|
-- lines and the "make room" text.
|
||||||
|
function OverworldState:offerGymTm(reward, done)
|
||||||
|
local text = Game.data.text or {}
|
||||||
|
local lines = {}
|
||||||
|
local function addLine(label)
|
||||||
|
if label and text[label] and text[label] ~= "" then
|
||||||
|
table.insert(lines, text[label])
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for _, label in ipairs(reward.tmPre or {}) do addLine(label) end
|
||||||
|
if giveVictoryItem(reward) then
|
||||||
|
for _, label in ipairs(reward.tmDialogue or {}) do addLine(label) end
|
||||||
|
else
|
||||||
|
addLine(reward.noRoom)
|
||||||
|
end
|
||||||
|
if #lines > 0 then
|
||||||
|
Game.stack:push(TextBox.new(Game, table.concat(lines, "\f"), done))
|
||||||
|
elseif done then
|
||||||
|
done()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
-- pokered reloads the map after every battle, re-running the map
|
-- pokered reloads the map after every battle, re-running the map
|
||||||
-- script (e.g. LoreleiShowOrHideExitBlock); this hook is the port's
|
-- script (e.g. LoreleiShowOrHideExitBlock); this hook is the port's
|
||||||
-- equivalent so seals/toggles refresh without leaving the map
|
-- equivalent so seals/toggles refresh without leaving the map
|
||||||
|
|||||||
+60
-4
@@ -183,7 +183,7 @@ do
|
|||||||
new = function(game, text, done) return { text = text, onDone = done } end,
|
new = function(game, text, done) return { text = text, onDone = done } end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local function driveLeader(mapId, textConst, beatFlag)
|
local function driveLeader(mapId, textConst, beatFlag, gotFlag)
|
||||||
local pushed, engaged
|
local pushed, engaged
|
||||||
local game = {
|
local game = {
|
||||||
save = { flags = {} },
|
save = { flags = {} },
|
||||||
@@ -198,6 +198,9 @@ do
|
|||||||
mapId .. " leader talk (no badge) engages the leader battle")
|
mapId .. " leader talk (no badge) engages the leader battle")
|
||||||
engaged, pushed = nil, nil
|
engaged, pushed = nil, nil
|
||||||
game.save.flags[beatFlag] = true
|
game.save.flags[beatFlag] = true
|
||||||
|
-- the advice/farewell branch is pokered's .afterBeat, reached only
|
||||||
|
-- once EVENT_GOT_TM* is set (the TM went into the bag)
|
||||||
|
if gotFlag then game.save.flags[gotFlag] = true end
|
||||||
local state = {}
|
local state = {}
|
||||||
script(game, ow, { def = {} }, function() state.doneCalled = true end)
|
script(game, ow, { def = {} }, function() state.doneCalled = true end)
|
||||||
check(pushed and not engaged,
|
check(pushed and not engaged,
|
||||||
@@ -206,17 +209,17 @@ do
|
|||||||
end
|
end
|
||||||
|
|
||||||
local _, box = driveLeader("CERULEAN_GYM", "TEXT_CERULEANGYM_MISTY",
|
local _, box = driveLeader("CERULEAN_GYM", "TEXT_CERULEANGYM_MISTY",
|
||||||
"EVENT_BEAT_MISTY")
|
"EVENT_BEAT_MISTY", "EVENT_GOT_TM11")
|
||||||
eq(box and box.text, Data.text._CeruleanGymMistyTM11ExplanationText,
|
eq(box and box.text, Data.text._CeruleanGymMistyTM11ExplanationText,
|
||||||
"Misty (beaten) shows the TM11 explanation text")
|
"Misty (beaten) shows the TM11 explanation text")
|
||||||
|
|
||||||
_, box = driveLeader("CINNABAR_GYM", "TEXT_CINNABARGYM_BLAINE",
|
_, box = driveLeader("CINNABAR_GYM", "TEXT_CINNABARGYM_BLAINE",
|
||||||
"EVENT_BEAT_BLAINE")
|
"EVENT_BEAT_BLAINE", "EVENT_GOT_TM38")
|
||||||
eq(box and box.text, Data.text._CinnabarGymBlainePostBattleAdviceText,
|
eq(box and box.text, Data.text._CinnabarGymBlainePostBattleAdviceText,
|
||||||
"Blaine (beaten) shows his post-battle advice text")
|
"Blaine (beaten) shows his post-battle advice text")
|
||||||
|
|
||||||
local game, gbox, state = driveLeader("VIRIDIAN_GYM", "TEXT_VIRIDIANGYM_GIOVANNI",
|
local game, gbox, state = driveLeader("VIRIDIAN_GYM", "TEXT_VIRIDIANGYM_GIOVANNI",
|
||||||
"EVENT_BEAT_GIOVANNI")
|
"EVENT_BEAT_GIOVANNI", "EVENT_GOT_TM27")
|
||||||
eq(gbox and gbox.text, Data.text._ViridianGymGiovanniPostBattleAdviceText,
|
eq(gbox and gbox.text, Data.text._ViridianGymGiovanniPostBattleAdviceText,
|
||||||
"Giovanni (beaten) shows his farewell text")
|
"Giovanni (beaten) shows his farewell text")
|
||||||
|
|
||||||
@@ -392,6 +395,59 @@ do
|
|||||||
check(cinnabarNpc and ow:trainerDefeated(cinnabarNpc),
|
check(cinnabarNpc and ow:trainerDefeated(cinnabarNpc),
|
||||||
"unfought Cinnabar trainer is defeated via seeded header event")
|
"unfought Cinnabar trainer is defeated via seeded header event")
|
||||||
|
|
||||||
|
-- #797: a full bag at the victory skips the TM hand-over (pokered's
|
||||||
|
-- `call GiveItem` / `jr nc, .BagFull`): badge and beat flag still land,
|
||||||
|
-- but EVENT_GOT_TM34 stays unset and the "make room" line replaces the
|
||||||
|
-- received/explanation texts. Talking to Brock afterwards re-runs the
|
||||||
|
-- ReceiveTM script and grants the TM once there is room.
|
||||||
|
while Game.stack:top() do Game.stack:pop() end
|
||||||
|
Game.save = SaveData.newGame()
|
||||||
|
Game.save.flags = {}
|
||||||
|
Game.save.inventory = {}
|
||||||
|
Game.save.defeatedTrainers = {}
|
||||||
|
local Bag = require("src.inventory.Bag")
|
||||||
|
for i = 1, Bag.capacity(Data) do
|
||||||
|
Bag.add(Game.save, "FULLBAG_" .. i, 1, Data)
|
||||||
|
end
|
||||||
|
eq(Bag.slots(Game.save), Bag.capacity(Data), "bag is full before Brock")
|
||||||
|
Game.stack:push(OW, "PEWTER_GYM", 4, 13, "up")
|
||||||
|
ow = Game.stack:top()
|
||||||
|
ow:checkVictoryRewards("OPP_BROCK", 1)
|
||||||
|
local fullBagText = stackedDialogue()
|
||||||
|
check(Game.save.flags.EVENT_BEAT_BROCK,
|
||||||
|
"full bag: Brock victory still sets EVENT_BEAT_BROCK")
|
||||||
|
check(Game.save.inventory.BOULDERBADGE == 1,
|
||||||
|
"full bag: Brock victory still awards BOULDERBADGE")
|
||||||
|
check(not Game.save.flags.EVENT_GOT_TM34,
|
||||||
|
"full bag: EVENT_GOT_TM34 stays unset (bag_full branch)")
|
||||||
|
check(Game.save.inventory.TM_BIDE == nil,
|
||||||
|
"full bag: TM34 is not forced into the bag")
|
||||||
|
check(fullBagText:find("room", 1, true) ~= nil,
|
||||||
|
"full bag: victory dialogue shows Brock's make-room line")
|
||||||
|
check(fullBagText:find("BIDE", 1, true) == nil,
|
||||||
|
"full bag: received/explanation texts are skipped")
|
||||||
|
|
||||||
|
-- make room, then talk to Brock: the middle branch re-runs ReceiveTM34
|
||||||
|
while Game.stack:top() do Game.stack:pop() end
|
||||||
|
Bag.remove(Game.save, "FULLBAG_1", 1)
|
||||||
|
local brockTalk = init.talkScript("PEWTER_GYM", "TEXT_PEWTERGYM_BROCK")
|
||||||
|
check(brockTalk ~= nil, "Brock's talk script is registered")
|
||||||
|
brockTalk(Game, ow, { def = {} }, function() end)
|
||||||
|
local retryText = stackedDialogue()
|
||||||
|
check(retryText:find("Wait!", 1, true) ~= nil,
|
||||||
|
"retry: ReceiveTM34 lead-in (Wait! Take this!) shows again")
|
||||||
|
check(retryText:find("BIDE", 1, true) ~= nil,
|
||||||
|
"retry: received/explanation texts show once the TM fits")
|
||||||
|
eq(Game.save.inventory.TM_BIDE, 1, "retry: TM34 goes into the bag")
|
||||||
|
check(Game.save.flags.EVENT_GOT_TM34, "retry: EVENT_GOT_TM34 is set")
|
||||||
|
|
||||||
|
-- once the TM is handed over, Brock falls back to his advice text
|
||||||
|
while Game.stack:top() do Game.stack:pop() end
|
||||||
|
brockTalk(Game, ow, { def = {} }, function() end)
|
||||||
|
local adviceText = stackedDialogue()
|
||||||
|
check(adviceText:find("CERULEAN", 1, true) ~= nil,
|
||||||
|
"after the TM: Brock shows his post-battle advice text")
|
||||||
|
|
||||||
while Game.stack:top() do Game.stack:pop() end
|
while Game.stack:top() do Game.stack:pop() end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user