From 2da2168dacca8f6ecc037d86fe0951bb1929f0c8 Mon Sep 17 00:00:00 2001 From: sanjinpepic Date: Sun, 16 Aug 2026 20:13:14 +0200 Subject: [PATCH] Refuse a TM/HM on a species with no tmhm list instead of crashing ItemEffects.use walked speciesDef.tmhm with a bare ipairs() to check whether the species could learn the machine's move. A record with no tmhm field at all -- a mod species that never set one, or any record missing it for whatever reason -- hit ipairs(nil) and took the whole game down on the first TM/HM use, rather than reaching the ordinary "can't learn that move" refusal a species whose list simply omits the move already gets. An absent list now reads the same as an empty one: nothing to learn, same refusal, same sound, same text. --- src/inventory/ItemEffects.lua | 5 ++++- tests/engine/item_tmhm_nil_test.lua | 31 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 tests/engine/item_tmhm_nil_test.lua diff --git a/src/inventory/ItemEffects.lua b/src/inventory/ItemEffects.lua index a900fec9..691b859d 100644 --- a/src/inventory/ItemEffects.lua +++ b/src/inventory/ItemEffects.lua @@ -515,7 +515,10 @@ function ItemEffects.use(data, save, itemId, target, battle, moveIndex, ow) if not target then return "failed", { noEffect(data) } end local speciesDef = data.pokemon[target.species] local ok = false - for _, m in ipairs(speciesDef.tmhm) do + -- a species record with no tmhm list at all is "teaches nothing", the + -- same as one whose list just does not name this move -- not a reason + -- to crash instead of refusing normally + for _, m in ipairs(speciesDef.tmhm or {}) do if m == itemDef.machine.move then ok = true break end end if not ok then diff --git a/tests/engine/item_tmhm_nil_test.lua b/tests/engine/item_tmhm_nil_test.lua new file mode 100644 index 00000000..217db2ee --- /dev/null +++ b/tests/engine/item_tmhm_nil_test.lua @@ -0,0 +1,31 @@ +-- ItemEffects.use crashed instead of refusing when a species record carried +-- no tmhm list at all (ipairs(nil)), which is a different situation from a +-- species whose list simply does not name the move being taught -- that +-- case already refuses cleanly with MonCannotLearnMachineMoveText. A mod +-- species missing the field entirely took the whole game down on the very +-- first TM/HM use rather than reaching that refusal. + +package.path = "./?.lua;./?/init.lua;" .. package.path +if not _G.love then _G.love = require("tests.love_stub") end + +local T = require("tests.harness").suite("item effects tmhm nil") +local Fixtures = require("tests.modkit.fixtures") +local ItemEffects = require("src.inventory.ItemEffects") +local Pokemon = require("src.pokemon.Pokemon") + +local Data = Fixtures.fresh() +Data.pokemon.FIXMON_A.tmhm = nil + +local mon = Pokemon.new(Data, "FIXMON_A", 10) +local save = { player = { name = "RED" } } + +local ok, result, payload = pcall(ItemEffects.use, Data, save, "FIX_TM", mon) +T.check(ok, "using a TM on a species with no tmhm list does not crash: " + .. tostring(result)) +if ok then + T.eq(result, "failed", "the species refuses the move instead of crashing into it") + T.check(type(payload) == "table" and payload[1] ~= nil, + "a refusal message is still returned") +end + +T.finish()