mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-23 14:07:34 +02:00
feat(gen2): read applyShare's announce argument in battle.exp_award
battle.exp_award hands a mod ctx.applyShare(mon, split, announce) on both
generations, and on Gen 1 the third argument decides whether the mon's
GainedText box is printed -- which is how a mod paying the whole party
prints ONE summary line instead of a box per recipient. Gold accepted
the argument and ignored it, so the same mod source printed one line on
Red and one per party member on Gold.
The Exp Share mod is the live case: it declares games gen1+gen2 and its
description promises "a single shared-exp line instead of one message per
Pokemon", passing true for the fighters and nil for the bench exactly as
the Gen 1 seam asks. On Gold every nil call announced anyway, so a
five-mon party turned every KO into six boxes. There was no mod-side
fix: the emit sits behind no hook, and the argument meaning "quietly" was
discarded.
Gold now reads it, and ONLY when it is actually passed -- by argument
count, not by value. select("#", ...) counts an explicit nil, so
applyShare(mon, split) is distinguishable from applyShare(mon, split,
nil); the first is a Gen 2-era call written against a seam that always
announced and keeps announcing, the second is a deliberate "pay this one
quietly" and is now silent on both games. No mod that exists today
changes behaviour, and a mod that passes the argument gets parity.
Only the { kind = "experience" } event is affected. A silent award is
still a whole award: exp, stat exp, battle.exp_gained, "grew to level",
learned moves and the forget prompt are untouched, in the same order.
giveExperiencePass takes a sixth `silent` parameter that defaults to
announcing, so both of the cart's own passes are unchanged.
RFC: docs/rfcs/0012-gen2-exp-award-announce.md
Docs: docs/mod-api-gen2-compat.md gains the reading and the residual
omitted-argument difference beside the existing payload note.
Tests: tests/gen2_exp_share_test.lua grows the two Route B tests -- the
no-mod parity case and the seam driven through hooks:wrap -- and
its 23 existing checks are unchanged.
This commit is contained in:
+39
-12
@@ -3272,7 +3272,16 @@ end
|
||||
-- `count` is the pass's own divisor -- the participant count for the first
|
||||
-- pass, the holder count for the EXP.SHARE pass -- and `halved` is whether
|
||||
-- any Share holder taxed the whole pool.
|
||||
function Battle:giveExperiencePass(loser, def, recipients, count, halved)
|
||||
--
|
||||
-- `silent` suppresses only the GainedText line. It exists for the
|
||||
-- battle.exp_award seam below, where a mod paying the bench wants one summary
|
||||
-- line rather than a box per mon; the cart's own two passes never pass it, so
|
||||
-- vanilla prints exactly what it always did. Everything else about the pass
|
||||
-- -- the exp, the stat exp, battle.exp_gained, "grew to level", learned moves
|
||||
-- and the forget prompt -- is unaffected, because a silent award is still an
|
||||
-- award.
|
||||
function Battle:giveExperiencePass(loser, def, recipients, count, halved,
|
||||
silent)
|
||||
for _, index in ipairs(recipients) do
|
||||
local mon = self.party[index]
|
||||
if mon and (mon.hp or 0) > 0 and not mon.isEgg then
|
||||
@@ -3323,10 +3332,12 @@ function Battle:giveExperiencePass(loser, def, recipients, count, halved)
|
||||
index = index,
|
||||
})
|
||||
end
|
||||
self:emit({ kind = "experience", index = index, amount = amount,
|
||||
-- BoostedExpPointsText, keyed on the traded arm alone.
|
||||
text = self:monName(mon) .. " gained "
|
||||
.. (traded and "a boosted " or "") .. amount .. " EXP. Points!" })
|
||||
if not silent then
|
||||
self:emit({ kind = "experience", index = index, amount = amount,
|
||||
-- BoostedExpPointsText, keyed on the traded arm alone.
|
||||
text = self:monName(mon) .. " gained "
|
||||
.. (traded and "a boosted " or "") .. amount .. " EXP. Points!" })
|
||||
end
|
||||
if result.levels > 0 then
|
||||
-- "level up happiness mod", the cart's own comment, sitting right
|
||||
-- after the stat recalc and before the "grew to level" text. It fires
|
||||
@@ -3420,22 +3431,38 @@ function Battle:awardExperience(loser)
|
||||
|
||||
-- battle.exp_award, the same hook BattleState:awardExp calls on Gen 1 and
|
||||
-- with the same ctx: the participant COUNT, the live participants, and an
|
||||
-- applyShare(mon, split) a mod can call to pay one mon its own share. The
|
||||
-- third applyShare argument is Gen 1's EXP.ALL announcement variant; Gen 2
|
||||
-- has no EXP.ALL (the EXP.SHARE pass below is its replacement), so it is
|
||||
-- accepted and ignored rather than changing what is printed. `recipients`,
|
||||
-- `holders` and `halved` are the Gen 2 additions.
|
||||
-- applyShare(mon, split, announce) a mod can call to pay one mon its own
|
||||
-- share. `recipients`, `holders` and `halved` are the Gen 2 additions.
|
||||
--
|
||||
-- `announce` is Gen 1's third argument (src/battle/BattleState.lua
|
||||
-- applyShare) and means the same thing here: truthy prints the mon's
|
||||
-- GainedText, falsy pays it silently. That is what lets one mod source
|
||||
-- print ONE summary line for a party-wide award on both generations instead
|
||||
-- of a box per mon -- which is what the Exp Share mod documents and could
|
||||
-- not do on Gold, because this argument used to be accepted and ignored.
|
||||
--
|
||||
-- It is honoured only when it is actually PASSED, by argument count rather
|
||||
-- than by value. A Gen 2-era mod calling applyShare(mon, split) was written
|
||||
-- against a seam that always announced and keeps announcing; a caller that
|
||||
-- passes the argument -- including an explicit nil, which is what a "pay
|
||||
-- this one quietly" call looks like -- gets Gen 1's reading. So no existing
|
||||
-- mod changes behaviour, and a mod that opts in gets parity.
|
||||
if Runtime.wantsHook("battle.exp_award") then
|
||||
local alive = {}
|
||||
for _, index in ipairs(participants) do
|
||||
local mon = self.party[index]
|
||||
if mon and (mon.hp or 0) > 0 then alive[#alive + 1] = mon end
|
||||
end
|
||||
local function applyShare(mon, split)
|
||||
local function applyShare(mon, split, ...)
|
||||
local announce = ...
|
||||
-- select("#") counts an explicit nil; `announce == nil` alone could not
|
||||
-- tell applyShare(mon, split) from applyShare(mon, split, nil), and
|
||||
-- those two have to mean different things here.
|
||||
local silent = select("#", ...) > 0 and not announce
|
||||
for index, candidate in ipairs(self.party) do
|
||||
if candidate == mon then
|
||||
return self:giveExperiencePass(loser, def, { index },
|
||||
math.max(1, split or 1), halved)
|
||||
math.max(1, split or 1), halved, silent)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user