Files
gen1recomp/tests/engine/gen2_pay_day_bug1212.lua
T

269 lines
8.7 KiB
Lua

-- engine/battle/move_effects/pay_day.asm:13, engine/battle/core.asm:8014-8042
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 BattleState = require("src.ui.gen2.BattleState")
local Effects = require("src.battle.gen2.Effects")
local Mon = require("src.battle.gen2.Mon")
local Prize = require("src.battle.gen2.Prize")
local LEVEL = 15
local TYPES = {
NORMAL = { id = "NORMAL", index = 0, category = "physical" },
}
local MOVES = {
TACKLE = { id = "TACKLE", name = "TACKLE", power = 35, type = "NORMAL",
accuracy = 100, pp = 35, effect = "EFFECT_NORMAL_HIT" },
PAY_DAY = { id = "PAY_DAY", name = "PAY DAY", power = 40, type = "NORMAL",
accuracy = 100, pp = 20, effect = "EFFECT_PAY_DAY" },
}
local POKEMON = {
growthRates = {
GROWTH_MEDIUM_FAST = { numerator = 1, denominator = 1, squared = 0,
linear = 0, constant = 0 },
},
MEOWTH = {
id = "MEOWTH", index = 52, name = "MEOWTH",
baseStats = { hp = 40, attack = 45, defense = 35, speed = 90,
specialAttack = 40, specialDefense = 40 },
types = { "NORMAL", "NORMAL" }, catchRate = 255, baseExp = 69,
growthRate = "GROWTH_MEDIUM_FAST", genderRatio = 127,
levelMoves = { { level = 1, move = "PAY_DAY" } }, evolutions = {},
},
RATTATA = {
id = "RATTATA", index = 19, name = "RATTATA",
baseStats = { hp = 30, attack = 56, defense = 35, speed = 72,
specialAttack = 25, specialDefense = 35 },
types = { "NORMAL", "NORMAL" }, catchRate = 255, baseExp = 51,
growthRate = "GROWTH_MEDIUM_FAST", genderRatio = 127,
levelMoves = { { level = 1, move = "TACKLE" } }, evolutions = {},
},
}
local DATA = {
pokemon = POKEMON,
moves = MOVES,
type_chart = { types = TYPES, matchups = {} },
items = {},
}
local perfect = { attack = 15, defense = 15, speed = 15, special = 15 }
perfect.hp = Mon.hpDV(perfect)
local function highRoll(n) return 99 % math.max(1, n or 1) end
local function newSave()
return { player = { name = "GOLD", money = 1000, id = 4242 },
mom = { savedMoney = 500 }, party = {} }
end
local function newBattle(save)
local player = Mon.new(DATA, "MEOWTH", LEVEL, { dvs = perfect })
player.moves = {
{ id = "PAY_DAY", pp = 20, maxPp = 20 },
{ id = "TACKLE", pp = 35, maxPp = 35 },
}
local wild = Mon.new(DATA, "RATTATA", LEVEL, { dvs = perfect })
wild.moves = { { id = "TACKLE", pp = 35, maxPp = 35 } }
wild.maxHp = 999
wild.hp = 999
local battle = Battle.new({ data = DATA, party = { player }, wild = wild,
random = highRoll, save = save })
return battle, player, wild
end
local function eventWithText(events, text)
for _, event in ipairs(events or {}) do
if event.text == text then return event end
end
return nil
end
local function findText(events, text)
return eventWithText(events, text) ~= nil
end
do
local battle, player, wild = newBattle(newSave())
battle:useMove(player, wild, "PAY_DAY")
T.eq(battle.payDay, 2 * LEVEL, "one connected hit is 2 x the user's level")
T.check(findText(battle:takeEvents(), "Coins scattered\neverywhere!"),
"CoinsScatteredText rides the hit")
battle:useMove(player, wild, "PAY_DAY")
T.eq(battle.payDay, 4 * LEVEL, "a second hit adds the same again")
battle:useMove(player, wild, "TACKLE")
T.eq(battle.payDay, 4 * LEVEL, "another move adds nothing")
end
do
local battle, player, wild = newBattle(newSave())
battle.stages.enemy.evasion = Effects.MAX_STAGE
battle:useMove(player, wild, "PAY_DAY")
T.eq(battle.payDay, nil, "a miss accumulates nothing")
end
do
local battle, player, wild = newBattle(newSave())
battle.amuletCoin = true
battle:useMove(player, wild, "PAY_DAY")
battle:useMove(player, wild, "PAY_DAY")
T.eq(battle.payDay, 4 * LEVEL,
"the Amulet Coin does not double the running counter")
end
do
local battle, player, wild = newBattle(newSave())
local enemy = battle.enemy
enemy.level = 40
battle:useMove(enemy, player, "PAY_DAY")
T.eq(battle.payDay, 80, "an enemy's PAY DAY pays the player, at ITS level")
T.check(wild == battle.enemy, "the enemy is the wild mon")
end
do
local save = newSave()
T.eq(Prize.payDay(save, 30, false), 30, "the payout returns what it paid")
T.eq(save.player.money, 1030, "and writes the wallet directly")
T.eq(save.mom.savedMoney, 500, "with no Mom split")
end
do
local save = newSave()
T.eq(Prize.payDay(save, 30, true), 60, "the Amulet Coin doubles the total")
T.eq(save.player.money, 1060, "once, at payout")
end
do
local save = newSave()
T.eq(Prize.payDay(save, 0, true), nil, "an empty counter pays nothing")
T.eq(Prize.payDay(save, nil, false), nil, "and neither does an unset one")
T.eq(save.player.money, 1000, "the wallet is untouched")
T.eq(Prize.payDay(nil, 30, false), nil, "a save-less battle pays nothing")
end
do
local save = newSave()
save.player.money = Prize.MAX_MONEY - 10
Prize.payDay(save, 500, true)
T.eq(save.player.money, Prize.MAX_MONEY, "AddBattleMoneyToAccount clamps")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
wild.hp = 0
T.check(battle:resolveFaints(), "the enemy faint ends the battle")
T.eq(battle.outcome, "win", "on the win arm")
T.eq(save.player.money, 1000 + 2 * LEVEL, "which is where CheckPayDay runs")
T.eq(battle.payDay, nil, "and the counter is cleared")
local paid = eventWithText(battle:takeEvents(), "GOLD picked up ¥30!")
T.check(paid, "BattleText_PlayerPickedUpPayDayMoney")
T.eq(paid and paid.kind, "money", "on the same event kind the prize uses")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle.amuletCoin = true
battle:useMove(player, wild, "PAY_DAY")
wild.hp = 0
battle:resolveFaints()
T.eq(save.player.money, 1000 + 4 * LEVEL,
"the Amulet Coin doubles once on the way out")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
player.hp = 0
T.check(battle:resolveFaints(), "a whiteout ends the battle")
T.eq(battle.outcome, "lose", "on the lose arm")
T.eq(save.player.money, 1000, "which pays nothing")
T.eq(battle.payDay, 2 * LEVEL, "the counter is dropped, not banked")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
battle:endBattle("run")
T.eq(save.player.money, 1000, "running away pays nothing")
end
local function newScreen(save, battle, opts)
opts = opts or {}
local pushed = {}
local screen = setmetatable({
save = save, battle = battle, picHidden = {},
contest = opts.contest, tutorial = opts.tutorial,
contestCaught = false,
push = function(self, event) pushed[#pushed + 1] = event end,
name = function(_, mon) return mon.species end,
hasPokedex = function() return false end,
currentBox = function() return 1 end,
contestCatch = function(self) self.contestCaught = true end,
}, { __index = BattleState })
return screen, pushed
end
local function caughtEnemy(battle)
local enemy = battle.enemy
enemy.hp = 1
return enemy
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
local screen, pushed = newScreen(save, battle)
screen:pushCaught(caughtEnemy(battle), "POKE_BALL")
T.eq(save.player.money, 1000 + 2 * LEVEL, "a capture pays out")
T.eq(battle.payDay, nil, "and clears the counter")
T.check(findText(pushed, "GOLD picked up ¥30!"), "with the payout line")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
local screen = newScreen(save, battle, { contest = true })
screen:pushCaught(caughtEnemy(battle), "PARK_BALL")
T.check(screen.contestCaught, "the contest arm still holds the mon")
T.eq(save.player.money, 1000 + 2 * LEVEL, "and a contest catch pays too")
T.eq(battle.payDay, nil, "clearing the counter with it")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
local screen = newScreen(save, battle, { tutorial = true })
screen:pushCaught(caughtEnemy(battle), "POKE_BALL")
T.eq(save.player.money, 1000, "the catching tutorial pays nothing")
T.eq(battle.payDay, 2 * LEVEL, "and leaves the counter alone")
end
do
local save = newSave()
local battle, player, wild = newBattle(save)
battle:useMove(player, wild, "PAY_DAY")
wild.hp = 0
battle:resolveFaints()
local screen = newScreen(save, battle, { contest = true })
screen:pushPayDay()
T.eq(save.player.money, 1000 + 2 * LEVEL,
"a contest KO that already paid does not pay a second time")
end
T.finish("gen2 pay day bug 1212")