mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 04:31:09 +02:00
Add a fieldmove.eligibility hook to partyKnows (#310)
Mods that widen field-move rules (use an HM without teaching it, a rental mon) had to monkey-patch partyKnows, the one function every field-move path funnels through. Wrap the vanilla check in a hook instead: next_ is the whole badge-and-knows-move check, so a wrapper that calls it first keeps vanilla answers winning and only fills the cases vanilla denies. No hook, no behavior change. Co-authored-by: johnjohto <johnjohto@users.noreply.github.com>
This commit is contained in:
@@ -1241,7 +1241,7 @@ end
|
|||||||
-- (constants.hmBadges; distinct from constants.hmMoves, the forget gate).
|
-- (constants.hmBadges; distinct from constants.hmMoves, the forget gate).
|
||||||
-- Gen 1 allows field use from fainted party members (party menu + name
|
-- Gen 1 allows field use from fainted party members (party menu + name
|
||||||
-- lookup for Cut/Surf messages); do not require mon.hp > 0 here.
|
-- lookup for Cut/Surf messages); do not require mon.hp > 0 here.
|
||||||
function OverworldState:partyKnows(moveId)
|
local function partyKnowsVanilla(moveId)
|
||||||
local gate = (FieldDefaults.constant(Game.data, "hmBadges") or {})[moveId]
|
local gate = (FieldDefaults.constant(Game.data, "hmBadges") or {})[moveId]
|
||||||
local badge = gate and gate.badge
|
local badge = gate and gate.badge
|
||||||
if badge and not Game.save.inventory[badge] then
|
if badge and not Game.save.inventory[badge] then
|
||||||
@@ -1255,6 +1255,17 @@ function OverworldState:partyKnows(moveId)
|
|||||||
return nil
|
return nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function OverworldState:partyKnows(moveId)
|
||||||
|
-- a mod may unlock a field move another way (an HM in the bag, a rental
|
||||||
|
-- mon); next_ is the whole vanilla check, so calling it first keeps
|
||||||
|
-- vanilla answers winning
|
||||||
|
if Runtime.wantsHook("fieldmove.eligibility") then
|
||||||
|
return Runtime.call("fieldmove.eligibility", partyKnowsVanilla, moveId,
|
||||||
|
{ save = Game.save, data = Game.data })
|
||||||
|
end
|
||||||
|
return partyKnowsVanilla(moveId)
|
||||||
|
end
|
||||||
|
|
||||||
-- The rejection loop shared by the Good and Super Rods
|
-- The rejection loop shared by the Good and Super Rods
|
||||||
-- (item_effects.asm ItemUseGoodRod .RandomLoop / ReadSuperRodData): an
|
-- (item_effects.asm ItemUseGoodRod .RandomLoop / ReadSuperRodData): an
|
||||||
-- odd random byte is no bite; otherwise a 2-bit pick rerolls until it
|
-- odd random byte is no bite; otherwise a 2-bit pick rerolls until it
|
||||||
|
|||||||
@@ -574,6 +574,39 @@ do
|
|||||||
check(blocked == false and why == "tile", "a walled step still reports 'tile'")
|
check(blocked == false and why == "tile", "a walled step still reports 'tile'")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
do
|
||||||
|
-- fieldmove.eligibility: next_ is the whole vanilla partyKnows check,
|
||||||
|
-- so a wrapper can widen field-move rules without forking the engine
|
||||||
|
local save = {
|
||||||
|
inventory = { SOULBADGE = 1, THUNDERBADGE = 1, CASCADEBADGE = 1 },
|
||||||
|
party = { { species = "SQUIRTLE", moves = {} },
|
||||||
|
{ species = "PIDGEY", moves = { { id = "FLY" } } } },
|
||||||
|
}
|
||||||
|
local game = { save = save, data = Data }
|
||||||
|
check(bindGame(OW.partyKnows, game), "partyKnows binds a test Game")
|
||||||
|
check(OW:partyKnows("SURF") == nil, "no hook, no surf without a knower")
|
||||||
|
check(OW:partyKnows("FLY") == save.party[2], "the knower wins unwrapped")
|
||||||
|
withBuses(function(_, hooks)
|
||||||
|
local seen
|
||||||
|
hooks:wrap("fieldmove.eligibility", function(next_, moveId, ctx)
|
||||||
|
seen = { moveId = moveId, ctx = ctx }
|
||||||
|
local mon = next_(moveId, ctx)
|
||||||
|
if mon then return mon end -- vanilla first
|
||||||
|
if moveId == "SURF" then return ctx.save.party[1] end
|
||||||
|
return nil
|
||||||
|
end, 0, "rental")
|
||||||
|
check(OW:partyKnows("SURF") == save.party[1],
|
||||||
|
"the hook can offer a field move vanilla denies")
|
||||||
|
check(OW:partyKnows("FLY") == save.party[2],
|
||||||
|
"a vanilla knower still beats the hook")
|
||||||
|
check(OW:partyKnows("CUT") == nil,
|
||||||
|
"next_ still yields nil when the hook declines")
|
||||||
|
check(seen.moveId == "CUT" and seen.ctx.save == save
|
||||||
|
and seen.ctx.data == Data,
|
||||||
|
"the hook ctx carries moveId, save, and data")
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
do
|
do
|
||||||
-- warp.destination reroutes one door without owning the warp table
|
-- warp.destination reroutes one door without owning the warp table
|
||||||
local warpDef = Data.maps.PALLET_TOWN.warps[1]
|
local warpDef = Data.maps.PALLET_TOWN.warps[1]
|
||||||
|
|||||||
Reference in New Issue
Block a user