From dc9d5c74c7efadeb582654dc0f1b3fdc2a899ee4 Mon Sep 17 00:00:00 2001 From: 1jamie Date: Fri, 11 Sep 2026 16:50:56 -0500 Subject: [PATCH] fix(game3): fix level-up move learn soft lock when mon has free move slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit LearnMove.begin's free-slot path called say(text, cb) expecting pushMsg to invoke the callback once the message is dismissed. The battle UI's hooks.pushMsg is Ui.push which only accepts (text) and silently drops the callback, so finish(ok) was never called, LearnMove._active stayed true forever → soft lock (reported as Charmander learning Ember). Fix: set _pending="done" + _pendingResult before say() so pump() can complete the sequence on the next update tick once the dialog drains, matching how the 4-move full path already uses _pending="delete". The say() callback is still wired so contexts whose pushMsg does honour it (party_menu TM flow) finish inline as before. --- src/core/game3/battle/learn_move.lua | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/core/game3/battle/learn_move.lua b/src/core/game3/battle/learn_move.lua index 06d63f72..654a0c66 100644 --- a/src/core/game3/battle/learn_move.lua +++ b/src/core/game3/battle/learn_move.lua @@ -32,6 +32,7 @@ function LearnMove.reset() LearnMove._onDone = nil LearnMove._waitingChoice = false LearnMove._pending = nil + LearnMove._pendingResult = false LearnMove._forgetSlots = nil LearnMove._queue = nil LearnMove._queueIdx = 0 @@ -181,7 +182,10 @@ function LearnMove.pump() return false -- still active, waiting for finish from choice path or free teach end LearnMove._pending = nil - if pending == "delete" then + if pending == "done" then + local r = LearnMove._pendingResult + finish(r) + elseif pending == "delete" then open_delete_prompt() elseif pending == "stop" then open_stop_prompt() @@ -225,8 +229,19 @@ function LearnMove.begin(opts) say(LearnMove._name .. " learned\n" .. LearnMove._moveName .. "!") finish(ok) else + -- pushMsg in the battle context (Ui.push) does not honour the callback, + -- so we cannot rely on say(..., cb) to call finish(). Instead we queue + -- the message then set _pending="done" so pump() finishes us once the + -- battle dialog drains. If pushMsg does honour the callback the say() + -- call fires it immediately and we finish inline; _pending is cleared + -- by finish() via reset() so the pump path is a safe no-op. + LearnMove._pendingResult = ok + LearnMove._pending = "done" say(LearnMove._name .. " learned\n" .. LearnMove._moveName .. "!", function() - finish(ok) + if LearnMove._active and LearnMove._pending == "done" then + LearnMove._pending = nil + finish(ok) + end end) end else