mirror of
https://github.com/bryanthaboi/gen1recomp
synced 2026-09-26 13:33:27 -04:00
123feef3a1
CLOSES #2425, CLOSES #2428, CLOSES #2431, CLOSES #2432, CLOSES #2433, CLOSES #2435, CLOSES #2436, CLOSES #2437, CLOSES #2440
278 lines
10 KiB
Lua
278 lines
10 KiB
Lua
-- engine/items/item_effects.asm:2752, :2801, :2836
|
|
|
|
package.path = "./?.lua;./?/init.lua;" .. package.path
|
|
|
|
local S = require("tests.harness").suite("gen2 max pp")
|
|
local check, eq = S.check, S.eq
|
|
|
|
love = require("tests.love_stub")
|
|
|
|
local Boxes = require("src.core.gen2.Boxes")
|
|
local Breeding = require("src.core.gen2.Breeding")
|
|
local ItemEffects = require("src.core.gen2.ItemEffects")
|
|
local Mon = require("src.battle.gen2.Mon")
|
|
local World = require("src.world.gen2.World")
|
|
|
|
local MOVES = {
|
|
WATER_GUN = { id = "WATER_GUN", name = "WATER GUN", pp = 25 },
|
|
RAGE = { id = "RAGE", name = "RAGE", pp = 20 },
|
|
LEER = { id = "LEER", name = "LEER", pp = 30 },
|
|
SCRATCH = { id = "SCRATCH", name = "SCRATCH", pp = 35 },
|
|
MEAN_LOOK = { id = "MEAN_LOOK", name = "MEAN LOOK", pp = 5 },
|
|
GROWL = { id = "GROWL", name = "GROWL", pp = 40 },
|
|
SKETCH = { id = "SKETCH", name = "SKETCH", pp = 1 },
|
|
}
|
|
|
|
local POKEMON = {
|
|
growthRates = {
|
|
GROWTH_MEDIUM_FAST = { numerator = 1, denominator = 1, squared = 0,
|
|
linear = 0, constant = 0 },
|
|
},
|
|
TOTODILE = {
|
|
id = "TOTODILE", index = 158, dex = 158, name = "TOTODILE",
|
|
baseStats = { hp = 50, attack = 65, defense = 64, speed = 43,
|
|
specialAttack = 44, specialDefense = 48 },
|
|
types = { "WATER", "WATER" }, growthRate = "GROWTH_MEDIUM_FAST",
|
|
genderRatio = 31, eggGroups = { "EGG_MONSTER", "EGG_WATER_1" },
|
|
evolutions = {}, levelMoves = { { level = 1, move = "SCRATCH" } },
|
|
tmhm = {},
|
|
},
|
|
}
|
|
|
|
local DATA = { pokemon = POKEMON, moves = MOVES, items = {} }
|
|
|
|
local function broken()
|
|
return {
|
|
{ id = "LEER", pp = 30, maxPp = 30 },
|
|
{ id = "SCRATCH", pp = 35, maxPp = 35 },
|
|
{ id = "RAGE", pp = 9 },
|
|
{ id = "WATER_GUN", pp = 1 },
|
|
}
|
|
end
|
|
|
|
local function toto(moves)
|
|
local mon = Mon.new(DATA, "TOTODILE", 16, {
|
|
dvs = { attack = 10, defense = 10, speed = 10, special = 10 },
|
|
moves = moves or broken(),
|
|
})
|
|
mon.hp = 1
|
|
return mon
|
|
end
|
|
|
|
do
|
|
eq(Mon.maxPpOf({ id = "WATER_GUN", pp = 1 }, DATA), 25,
|
|
"a record with no maxPp reads the move's base PP")
|
|
eq(Mon.maxPpOf({ id = "WATER_GUN", pp = 1, maxPp = 1 }, DATA), 25,
|
|
"a stored max below base cannot lower it")
|
|
eq(Mon.maxPpOf({ id = "WATER_GUN", pp = 3, maxPp = 30 }, DATA), 30,
|
|
"a stored max one PP Up above base keeps that PP Up")
|
|
eq(Mon.maxPpOf({ id = "WATER_GUN", pp = 3, maxPp = 31 }, DATA), 25,
|
|
"a stored max ComputeMaxPP cannot produce infers no PP Up")
|
|
eq(Mon.maxPpOf({ id = "GROWL", pp = 0, ppUps = 3 }, DATA), 61,
|
|
"three PP Ups on a 40 PP move cap at 61")
|
|
eq(Mon.maxPpOf({ id = "GROWL", pp = 0, ppUps = 9 }, DATA), 61,
|
|
"the PP Up count is two bits")
|
|
eq(Mon.maxPpOf({ id = "MEAN_LOOK", pp = 4, maxPp = 4 }, DATA), 5,
|
|
"MEAN LOOK 4/4 reads 5")
|
|
eq(Mon.maxPpOf({ id = "SKETCH", pp = 1, ppUps = 3 }, DATA), 1,
|
|
"a 1 PP move gains nothing per PP Up")
|
|
eq(Mon.ppUpsOf({ id = "WATER_GUN", maxPp = 40 }, DATA), 3,
|
|
"ppUpsOf infers three from a stored 40 on a 25 PP move")
|
|
end
|
|
|
|
do
|
|
local mon = toto()
|
|
local save = { party = { mon } }
|
|
World.healParty({ game = { save = save, data = DATA } })
|
|
eq(mon.moves[3].pp, 20, "HealParty refills RAGE to 20, not 9")
|
|
eq(mon.moves[4].pp, 25, "HealParty refills WATER GUN to 25, not 1")
|
|
eq(mon.moves[4].maxPp, 25, "and writes the derived max back")
|
|
eq(mon.hp, mon.maxHp, "HP is still refilled")
|
|
end
|
|
|
|
do
|
|
local keep = toto()
|
|
keep.hp = keep.maxHp
|
|
local mon = toto()
|
|
local save = { party = { keep, mon }, boxes = {}, boxNames = {},
|
|
currentBox = 1 }
|
|
local ok = Boxes.deposit(save, 2, 1, DATA)
|
|
check(ok, "the deposit went through")
|
|
eq(mon.moves[3].pp, 20, "RestorePPOfDepositedPokemon refills RAGE to 20")
|
|
eq(mon.moves[4].pp, 25, "and WATER GUN to 25")
|
|
|
|
local caught = toto()
|
|
Boxes.enterBox(caught, DATA)
|
|
eq(caught.moves[4].pp, 25, "enterBox with data refills from the move table")
|
|
end
|
|
|
|
do
|
|
local mon = toto()
|
|
mon.moves[4].pp = 0
|
|
local res = ItemEffects.usePpItem("ETHER", mon, 4, DATA)
|
|
check(res.used, "an ETHER on a spent maxPp-less move is not refused")
|
|
eq(mon.moves[4].pp, 10, "and adds 10")
|
|
res = ItemEffects.usePpItem("MAX_ETHER", mon, 4, DATA)
|
|
check(res.used, "MAX ETHER still has room")
|
|
eq(mon.moves[4].pp, 25, "and fills to 25")
|
|
|
|
local full = toto()
|
|
full.moves[3].pp, full.moves[4].pp = 20, 25
|
|
res = ItemEffects.usePpItem("MAX_ELIXER", full, nil, DATA)
|
|
eq(res.used, false, "MAX ELIXER on a full moveset is refused")
|
|
end
|
|
|
|
do
|
|
local mon = toto({ { id = "WATER_GUN", pp = 30, maxPp = 30 } })
|
|
local res = ItemEffects.usePpItem("PP_UP", mon, 1, DATA)
|
|
check(res.used, "PP UP on a move with one inferred PP Up works")
|
|
eq(mon.moves[1].ppUps, 2, "and counts from the inferred one")
|
|
eq(mon.moves[1].maxPp, 35, "to 35")
|
|
local maxed = toto({ { id = "WATER_GUN", pp = 40, maxPp = 40 } })
|
|
res = ItemEffects.usePpItem("PP_UP", maxed, 1, DATA)
|
|
eq(res.used, false, "a stored 40 on a 25 PP move is already maxed")
|
|
end
|
|
|
|
do
|
|
local save = { party = {}, player = { name = "KRIS", id = 1, money = 3000 },
|
|
pokedex = { seen = {}, caught = {} }, events = {} }
|
|
local dc = Breeding.dayCare(save)
|
|
dc.man.mon = toto()
|
|
local ok, back = Breeding.withdraw(DATA, save, "man")
|
|
check(ok, "the Day-Care withdrawal went through")
|
|
eq(back.moves[4].pp, 25, "HealPartyMon refills WATER GUN to 25, not nil")
|
|
eq(back.moves[3].pp, 20, "and RAGE to 20")
|
|
end
|
|
|
|
do
|
|
local party = toto()
|
|
local boxed = toto()
|
|
local daycare = toto()
|
|
local legacy = toto({ { id = "WATER_GUN" }, { id = "RAGE", pp = 50 } })
|
|
local upped = toto({ { id = "WATER_GUN", pp = 12, maxPp = 35 } })
|
|
local save = { party = { party, legacy, upped }, boxes = { { boxed } },
|
|
dayCare = { man = { mon = daycare }, lady = {} } }
|
|
Mon.syncSaveIdentity(save, DATA)
|
|
eq(party.moves[4].maxPp, 25, "the party's WATER GUN gets its max back")
|
|
eq(party.moves[4].pp, 1, "and keeps the PP it had left")
|
|
eq(party.moves[3].maxPp, 20, "RAGE gets 20")
|
|
eq(boxed.moves[4].maxPp, 25, "boxed mons are repaired too")
|
|
eq(daycare.moves[4].maxPp, 25, "and the Day-Care's")
|
|
eq(legacy.moves[1].pp, 25, "a record with no PP at all reads full")
|
|
eq(legacy.moves[2].pp, 20, "and PP past max is clamped")
|
|
eq(upped.moves[1].maxPp, 35, "a real PP Up max survives the repair")
|
|
eq(upped.moves[1].pp, 12, "with its current PP")
|
|
end
|
|
|
|
do
|
|
local BoxMenu = require("src.ui.gen2.BoxMenu")
|
|
local BugContest = require("src.core.gen2.BugContest")
|
|
local game = { data = DATA, input = { wasPressed = function() return false end,
|
|
isDown = function() return false end } }
|
|
|
|
local keep = toto()
|
|
keep.hp = keep.maxHp
|
|
local mon = toto()
|
|
local save = { party = { keep, mon }, boxes = {}, boxNames = {},
|
|
currentBox = 1 }
|
|
game.save = save
|
|
local menu = BoxMenu.new(game, { save = save, mode = "deposit",
|
|
onClose = function() end })
|
|
menu.index = 2
|
|
menu:doDeposit()
|
|
eq(Boxes.box(save, 1)[1], mon, "the PC DEPOSIT went through")
|
|
eq(mon.moves[4].pp, 25, "PC DEPOSIT refills WATER GUN to 25")
|
|
eq(mon.moves[3].pp, 20, "and RAGE to 20")
|
|
|
|
keep = toto()
|
|
keep.hp = keep.maxHp
|
|
mon = toto()
|
|
save = { party = { keep, mon }, boxes = {}, boxNames = {}, currentBox = 1 }
|
|
game.save = save
|
|
menu = BoxMenu.new(game, { save = save, mode = "move",
|
|
onClose = function() end })
|
|
menu.moveFrom = { box = 0, slot = 2 }
|
|
menu.boxIndex, menu.index = 1, 1
|
|
menu:insertMon()
|
|
eq(Boxes.box(save, 1)[1], mon, "MOVE party -> box went through")
|
|
eq(mon.moves[4].pp, 25, "MOVE into a box refills WATER GUN to 25")
|
|
|
|
save = { party = { toto(), toto(), toto(), toto(), toto(), toto() },
|
|
boxes = {}, boxNames = {}, currentBox = 2, playerName = "KRIS" }
|
|
BugContest.start(save)
|
|
local caught = toto()
|
|
BugContest.switchCaught(save, caught)
|
|
local result = BugContest.collectCaughtMon(save, 6, nil, DATA)
|
|
eq(result, BugContest.BOXED_MON, "a full party boxes the contest catch")
|
|
eq(caught.moves[4].pp, 25, "the boxed contest catch has WATER GUN at 25")
|
|
eq(caught.moves[3].pp, 20, "and RAGE at 20")
|
|
end
|
|
|
|
-- engine/items/item_effects.asm:2381
|
|
do
|
|
local Battle = require("src.battle.gen2.Battle")
|
|
local TDATA = {
|
|
moves = {
|
|
TRANSFORM = { id = "TRANSFORM", name = "TRANSFORM", pp = 10 },
|
|
TACKLE = { id = "TACKLE", name = "TACKLE", pp = 35 },
|
|
ROCK_THROW = { id = "ROCK_THROW", name = "ROCK THROW", pp = 15 },
|
|
},
|
|
pokemon = {
|
|
DITTO = { id = "DITTO", name = "DITTO", types = { "NORMAL", "NORMAL" } },
|
|
GEODUDE = { id = "GEODUDE", name = "GEODUDE", types = { "ROCK", "GROUND" } },
|
|
},
|
|
items = {},
|
|
}
|
|
local function transformed(transformPp)
|
|
local ditto = { species = "DITTO", hp = 30, maxHp = 30, stats = {},
|
|
moves = { { id = "TRANSFORM", pp = transformPp or 10, maxPp = 10 } } }
|
|
local geodude = { species = "GEODUDE", hp = 30, maxHp = 30, stats = {},
|
|
moves = { { id = "TACKLE", pp = 35, maxPp = 35 },
|
|
{ id = "ROCK_THROW", pp = 15, maxPp = 15 } } }
|
|
local b = setmetatable({ data = TDATA, events = {} }, Battle)
|
|
b.player, b.enemy = ditto, geodude
|
|
Battle.MOVE_EFFECTS.EFFECT_TRANSFORM(b, ditto, geodude)
|
|
return ditto
|
|
end
|
|
|
|
local d = transformed()
|
|
d.moves[1].pp = 0
|
|
local r = ItemEffects.usePpItem("ETHER", d, 1, TDATA)
|
|
eq(r.used, false, "ETHER on a transformed mon with a full TRANSFORM is refused")
|
|
eq(d.moves[1].pp, 0, "ETHER leaves the spent TACKLE copy alone")
|
|
eq(d.moves[1].maxPp, 5, "the TACKLE copy keeps its 5 max")
|
|
|
|
d = transformed()
|
|
r = ItemEffects.usePpItem("MAX_ETHER", d, 1, TDATA)
|
|
eq(r.used, false, "MAX ETHER is refused while TRANSFORM is full")
|
|
eq(d.moves[1].pp, 5, "the full TACKLE copy stays 5/5")
|
|
|
|
d = transformed()
|
|
d.moves[2].pp = 0
|
|
r = ItemEffects.usePpItem("ELIXER", d, nil, TDATA)
|
|
eq(r.used, false, "ELIXER is refused while the party moves are full")
|
|
eq(d.moves[1].pp, 5, "ELIXER leaves TACKLE's copy at 5")
|
|
eq(d.moves[2].pp, 0, "ELIXER leaves ROCK THROW's copy at 0")
|
|
|
|
d = transformed(2)
|
|
r = ItemEffects.usePpItem("ETHER", d, 1, TDATA)
|
|
eq(r.used, true, "ETHER lands on the party TRANSFORM")
|
|
eq(d.volatile.preTransform.moves[1].pp, 10, "TRANSFORM refilled to 10")
|
|
eq(d.moves[1].pp, 5, "the TACKLE copy is untouched")
|
|
eq(Mon.partyMoves(d)[1].id, "TRANSFORM", "party move list is Ditto's own")
|
|
end
|
|
|
|
do
|
|
local move = { id = "RAGE", pp = 20, maxPp = 32 }
|
|
Mon.repairMoves({ moves = { move } }, DATA)
|
|
eq(move.ppUps, 3, "repairMoves stamps inferred PP Ups")
|
|
eq(move.maxPp, 32, "and keeps the 32 max")
|
|
local plain = { id = "RAGE", pp = 20, maxPp = 20 }
|
|
Mon.repairMoves({ moves = { plain } }, DATA)
|
|
eq(plain.ppUps, nil, "no PP Ups leaves ppUps unset")
|
|
local growl = { id = "GROWL", pp = 1, maxPp = 54 }
|
|
eq(Mon.ppUpsOf(growl, DATA), 2, "GROWL 54 max infers 2 ups at 7 per up")
|
|
end
|
|
|
|
S.finish()
|