mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-16 16:21:30 +02:00
269 lines
8.7 KiB
Lua
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")
|