CLOSES #1396, CLOSES #1398, CLOSES #1400, CLOSES #1401, CLOSES #1406, CLOSES #1407, CLOSES #1411, CLOSES #1413, CLOSES #1415, CLOSES #1416, CLOSES #1417, CLOSES #1419, CLOSES #1421, CLOSES #1422, CLOSES #1423, CLOSES #1424, CLOSES #1425, CLOSES #1427, CLOSES #1428, CLOSES #1429, CLOSES #1431, CLOSES #1432, CLOSES #1433, CLOSES #1435, CLOSES #1437, CLOSES #1440, CLOSES #1441, CLOSES #1442, CLOSES #1443, CLOSES #1444, CLOSES #1447, CLOSES #1449, CLOSES #1456, CLOSES #1461, CLOSES #1464, CLOSES #1465, CLOSES #1466, CLOSES #1468, CLOSES #1469, CLOSES #1470

This commit is contained in:
bryanthaboi
2026-08-17 10:27:14 -04:00
parent 45519ad550
commit 8c9af95598
11 changed files with 186 additions and 10 deletions
@@ -46,4 +46,30 @@ do
T.eq(tradedWithId.otId, 777, "a recorded foreign OT id is never overwritten")
end
-- #1461: saves that passed through 0.1.82-0.1.9x already have the player's
-- own id written onto traded mons, so stamping correctly from now on does
-- not help them. The repair runs on every load, not behind a format gate.
do
local SaveData = require("src.core.SaveData")
local save = newSave()
local poisoned = { traded = true, otId = 12345 }
local foreign = { traded = true, otId = 777 }
local caught = { otId = 12345 }
save.party = { poisoned, foreign, caught }
save.boxes = { { { traded = true, otId = 12345 } } }
T.eq(SaveData.repairTradedOtIds(save), 2, "both poisoned mons are repaired")
T.eq(poisoned.otId, nil, "a traded mon carrying the player id is cleared")
T.eq(save.boxes[1][1].otId, nil, "boxed mons are repaired too")
T.eq(foreign.otId, 777, "a real foreign OT id is left alone")
T.eq(caught.otId, 12345, "a caught mon keeps the player id")
T.eq(caught.traded, nil, "and is never marked traded")
T.eq(SaveData.repairTradedOtIds(save), 0, "the repair is idempotent")
-- and after the repair the stamp loop must not re-adopt it
BattleState.stampOT(save, poisoned)
T.eq(poisoned.otId, nil, "the stamp loop does not undo the repair")
end
T.finish("exp traded ot survives reload bug 1265")
@@ -0,0 +1,62 @@
-- engine/battle/effect_commands.asm:5788, :3671, :3646, :4019
package.path = "./?.lua;./?/init.lua;" .. package.path
love = require("tests.love_stub")
local T = require("tests.harness")
local Battle = require("src.battle.gen2.Battle")
local MATCHUPS = {
{ attacker = "ELECTRIC", defender = "GROUND", multiplier = 0 },
{ attacker = "POISON", defender = "STEEL", multiplier = 0 },
{ attacker = "POISON", defender = "POISON", multiplier = 5 },
{ attacker = "NORMAL", defender = "GHOST", multiplier = 0 },
{ attacker = "PSYCHIC_TYPE", defender = "GROUND", multiplier = 10 },
}
local POKEMON = {
GEODUDE = { types = { "ROCK", "GROUND" } },
MAGNEMITE = { types = { "STEEL", "ELECTRIC" } },
ZUBAT = { types = { "POISON", "FLYING" } },
GASTLY = { types = { "GHOST", "POISON" } },
PIDGEY = { types = { "NORMAL", "FLYING" } },
}
local battle = setmetatable({
data = { type_chart = { matchups = MATCHUPS }, pokemon = POKEMON },
}, { __index = Battle })
local function mon(species) return { species = species, hp = 20 } end
local function refused(species, moveType, status)
return battle:statusRefusedByType(mon(species), moveType, status)
end
-- The two repros the reporter filed, neither of which the #1318 fix touched.
T.eq(refused("GEODUDE", "ELECTRIC", "paralyze"), true,
"Thunder Wave does not affect a GROUND type")
T.eq(refused("MAGNEMITE", "POISON", "poison"), true,
"Poison Gas does not affect a STEEL type")
-- Poison vs POISON is 0.5x, not an immunity, so only CheckIfTargetIsPoisonType
-- refuses it: this is the Poison Sting on Zubat case.
T.eq(refused("ZUBAT", "POISON", "poison"), true,
"a POISON type cannot be poisoned even on a resisted, landed hit")
T.eq(refused("GASTLY", "POISON", "toxic"), true,
"Toxic is refused by the same check")
T.eq(refused("GASTLY", "NORMAL", "paralyze"), true,
"Glare does not affect a GHOST type")
-- Everything the cart deliberately leaves ungated stays ungated.
T.eq(refused("GEODUDE", "PSYCHIC_TYPE", "sleep"), false,
"Hypnosis still lands on a GROUND type")
T.eq(refused("GEODUDE", "PSYCHIC_TYPE", "confuse"), false,
"confusion is never type-gated")
T.eq(refused("PIDGEY", "ELECTRIC", "paralyze"), false,
"Thunder Wave still paralyses a non-immune target")
T.eq(refused("PIDGEY", "POISON", "poison"), false,
"a non-POISON target is still poisonable")
T.eq(refused("GEODUDE", nil, "paralyze"), false,
"a status with no move type behind it is not refused")
T.finish("gen2 status type immunity bug 1444")