mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-12 16:31:05 +02:00
97 lines
4.1 KiB
Lua
97 lines
4.1 KiB
Lua
-- Gen 1 fixed-damage moves and Super Fang ignore the type chart (#616).
|
|
-- SPECIAL_DAMAGE_EFFECT and SUPER_FANG_EFFECT are the SetDamageEffects
|
|
-- table (data/battle/set_damage_effects.asm); engine/battle/core.asm:3139
|
|
-- jumps straight to MoveHitTest for them, so CalculateDamage and
|
|
-- AdjustDamageForMoveType never run and ApplyAttackToEnemyPokemon
|
|
-- (core.asm:4612) stores wDamage unscaled. Night Shade therefore hits
|
|
-- Normal-types and Super Fang hits Ghosts. OHKO is the exception: it
|
|
-- returns through AdjustDamageForMoveType (core.asm:4329, 4467) and a 0x
|
|
-- matchup still zeroes its 65535 and sets wMoveMissed.
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local T = require("tests.modkit")
|
|
local Data = T.fixtures.fresh()
|
|
local Font = require("src.render.Font")
|
|
Font.load(Data)
|
|
local BattleState = require("src.battle.BattleState")
|
|
local Pokemon = require("src.pokemon.Pokemon")
|
|
local SaveData = require("src.core.SaveData")
|
|
-- the shared fixture type chart is just the GRASS/FIRE/WATER triangle
|
|
-- (tests/fixture_data/type_chart.lua) with no 0x row, so this suite adds
|
|
-- its own immune matchups: one for the SetDamageEffects moves under test
|
|
-- and a separate one for OHKO, kept apart so neither probe leaks into
|
|
-- the other's assertion
|
|
table.insert(Data.type_chart.matchups,
|
|
{ attacker = "FIX_ATK_A", defender = "FIX_DEF_A", multiplier = 0 })
|
|
table.insert(Data.type_chart.matchups,
|
|
{ attacker = "FIX_ATK_B", defender = "FIX_DEF_B", multiplier = 0 })
|
|
local TypeChart = require("src.battle.TypeChart")
|
|
TypeChart.load(Data)
|
|
|
|
-- Night Shade's shape: 0 BP, fixed damage equal to the user's level,
|
|
-- attacking type that the fixture chart marks as 0x against the target
|
|
Data.moves.FIX_NIGHT_SHADE = {
|
|
id = "FIX_NIGHT_SHADE", index = 98, name = "FIX NSHADE",
|
|
type = "FIX_ATK_A", power = 0, accuracy = 100, pp = 15,
|
|
effect = "SPECIAL_DAMAGE_EFFECT", fixedDamage = "level",
|
|
}
|
|
Data.moves.FIX_SUPER_FANG = {
|
|
id = "FIX_SUPER_FANG", index = 97, name = "FIX SFANG",
|
|
type = "FIX_ATK_A", power = 1, accuracy = 90, pp = 10,
|
|
effect = "SUPER_FANG_EFFECT",
|
|
}
|
|
Data.moves.FIX_FISSURE = {
|
|
id = "FIX_FISSURE", index = 96, name = "FIX FISSURE",
|
|
type = "FIX_ATK_B", power = 1, accuracy = 30, pp = 5,
|
|
effect = "OHKO_EFFECT",
|
|
}
|
|
|
|
local function mkseq(vals) -- scripted rng: pops vals, then max rolls
|
|
local i = 0
|
|
return function(_, hi)
|
|
i = i + 1
|
|
return vals[i] ~= nil and vals[i] or hi
|
|
end
|
|
end
|
|
|
|
-- a battle whose target's live types are forced to `types` (curTypes is
|
|
-- what TypeChart reads, BattleState.lua:443)
|
|
local function mkbattle(level, types)
|
|
local save = SaveData.newGame()
|
|
save.party = { Pokemon.new(Data, "FIXMON_A", level) }
|
|
local game = { data = Data, save = save,
|
|
stack = { top = function() return nil end, push = function() end } }
|
|
local b = BattleState.newWild(game, "FIXMON_C", 5)
|
|
b.enemy.curTypes = types
|
|
b.rng = mkseq({ 0 }) -- accuracy hits; nothing else rolls
|
|
return b
|
|
end
|
|
|
|
-- FIX_ATK_A is 0x against FIX_DEF_A, and Night Shade lands anyway
|
|
T.eq(TypeChart.effectiveness("FIX_ATK_A", { "FIX_DEF_A" }), 0,
|
|
"FIX_ATK_A does nothing to FIX_DEF_A")
|
|
local ns = mkbattle(12, { "FIX_DEF_A" })
|
|
local before = ns.enemy.mon.hp
|
|
ns:performMove(ns.player, ns.enemy, { id = "FIX_NIGHT_SHADE", pp = 15 })
|
|
T.eq(before - ns.enemy.mon.hp, 12, "Night Shade takes level damage off an immune type")
|
|
|
|
-- same 0x matchup, and Super Fang still halves
|
|
local sf = mkbattle(12, { "FIX_DEF_A" })
|
|
local hp = sf.enemy.mon.hp
|
|
sf:performMove(sf.player, sf.enemy, { id = "FIX_SUPER_FANG", pp = 10 })
|
|
T.eq(hp - sf.enemy.mon.hp, math.max(1, math.floor(hp / 2)),
|
|
"Super Fang halves an immune type's HP")
|
|
|
|
-- OHKO keeps its immunity gate: it does return through AdjustDamageForMoveType
|
|
T.eq(TypeChart.effectiveness("FIX_ATK_B", { "FIX_DEF_B" }), 0,
|
|
"FIX_ATK_B does nothing to FIX_DEF_B")
|
|
local ko = mkbattle(50, { "FIX_DEF_B" })
|
|
local full = ko.enemy.mon.hp
|
|
ko:performMove(ko.player, ko.enemy, { id = "FIX_FISSURE", pp = 5 })
|
|
T.eq(ko.enemy.mon.hp, full, "OHKO still cannot touch an immune type")
|
|
|
|
Data.moves.FIX_NIGHT_SHADE = nil
|
|
Data.moves.FIX_SUPER_FANG = nil
|
|
Data.moves.FIX_FISSURE = nil
|
|
T.finish("fixed damage ignores type immunity")
|