mirror of
https://github.com/bryanthaboi/gen1recomp.git
synced 2026-08-20 04:31:09 +02:00
CLOSES #998, CLOSES #1472, CLOSES #1526, CLOSES #1529, CLOSES #1530, CLOSES #1532, CLOSES #1534, CLOSES #1547, CLOSES #1549, CLOSES #1550, CLOSES #1551
This commit is contained in:
@@ -0,0 +1,122 @@
|
||||
-- SwitchPlayerMon (engine/battle/core.asm:2419-2423) prints RetreatMon and
|
||||
-- holds 50 frames BEFORE the outgoing pic is recalled, and only then does
|
||||
-- SendOutMon shout "Go! X!" (#1534). The port queued the send-out line
|
||||
-- alone, so the withdraw box never existed. PlayerMon2Text's adjective
|
||||
-- (engine/battle/common_text.asm:167-243) reads the ENEMY HP lost since
|
||||
-- this mon switched in, from wLastSwitchInEnemyMonHP.
|
||||
package.path = "./?.lua;./?/init.lua;" .. package.path
|
||||
|
||||
local T = require("tests.modkit")
|
||||
local Data = T.fixtures.fresh()
|
||||
require("src.render.Font").load(Data)
|
||||
local BattleState = require("src.battle.BattleState")
|
||||
local Pokemon = require("src.pokemon.Pokemon")
|
||||
local SaveData = require("src.core.SaveData")
|
||||
local Timing = require("src.core.Timing")
|
||||
local TypeChart = require("src.battle.TypeChart")
|
||||
TypeChart.load(Data)
|
||||
|
||||
local function newBattle()
|
||||
local save = SaveData.newGame()
|
||||
save.party = { Pokemon.new(Data, "FIXMON_A", 30), Pokemon.new(Data, "FIXMON_B", 30) }
|
||||
local game = { data = Data, save = save,
|
||||
stack = { top = function() return nil end, push = function() end } }
|
||||
local battle = BattleState.newWild(game, "FIXMON_C", 30)
|
||||
battle.rng = function() return 0 end
|
||||
battle.enemyAction = function() return { id = "FIX_SCRATCH", pp = 35 } end
|
||||
return battle
|
||||
end
|
||||
|
||||
-- drain the queue the way updateQueue does, recording rows in order plus
|
||||
-- who was in the player slot when each row was emitted
|
||||
local function drain(battle)
|
||||
local rows = {}
|
||||
for _ = 1, 400 do
|
||||
local item = table.remove(battle.queue, 1)
|
||||
if not item then return rows end
|
||||
rows[#rows + 1] = { text = item.text, anim = item.anim,
|
||||
auto = item.auto, autoDelay = item.autoDelay,
|
||||
playerSpecies = battle.player.mon.species }
|
||||
if item.fn then
|
||||
battle.nextInsert = 0
|
||||
item.fn()
|
||||
end
|
||||
end
|
||||
error("the queue never drained")
|
||||
end
|
||||
|
||||
local function indexOf(rows, pred)
|
||||
for i, row in ipairs(rows) do
|
||||
if pred(row) then return i end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- the voluntary party-menu switch: withdraw line, then the send-out
|
||||
-- ---------------------------------------------------------------------
|
||||
do
|
||||
local battle = newBattle()
|
||||
drain(battle) -- the intro stamps lastSwitchInEnemyHP through sendOutText
|
||||
local outgoing = battle.player.mon.species
|
||||
local oldNick = battle.player.name
|
||||
battle.queue, battle.nextInsert = {}, 0
|
||||
battle:resolveSwitch(battle.game.save.party[2])
|
||||
local rows = drain(battle)
|
||||
|
||||
local wIdx = indexOf(rows, function(r)
|
||||
return r.text and r.text:find("Come back!", 1, true) ~= nil
|
||||
end)
|
||||
T.check(wIdx ~= nil, "the withdraw line is queued")
|
||||
T.eq(rows[wIdx].text, oldNick .. " enough!\nCome back!",
|
||||
"an untouched foe gives the `enough!` variant")
|
||||
T.eq(rows[wIdx].auto, true, "the page ends `done`, so it never waits on A")
|
||||
T.eq(rows[wIdx].autoDelay, Timing.SWITCH_PLAYER_MON,
|
||||
"it holds the 50 frames DelayFrames pays (core.asm:2421-2422)")
|
||||
T.eq(rows[wIdx].playerSpecies, outgoing,
|
||||
"the outgoing mon is still in the slot while the line prints")
|
||||
|
||||
local sIdx = indexOf(rows, function(r)
|
||||
return r.text and r.text:find("! ", 1, true) and r.text:find("Come back!", 1, true) == nil
|
||||
end)
|
||||
T.check(sIdx ~= nil and sIdx > wIdx, "the send-out shout follows the withdraw line")
|
||||
T.eq(rows[sIdx].auto, true, "the send-out page ends `done` too (#1472)")
|
||||
T.neq(rows[sIdx].playerSpecies, outgoing, "the swap happened between the two")
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- the adjective branches on enemy HP lost since the switch-in
|
||||
-- ---------------------------------------------------------------------
|
||||
do
|
||||
local battle = newBattle()
|
||||
drain(battle)
|
||||
local nick = battle.player.name
|
||||
local max = battle.enemy.mon.stats.hp
|
||||
local quarter = math.floor(max / 4)
|
||||
local function withdrawAt(dropPercent)
|
||||
battle.lastSwitchInEnemyHP = max
|
||||
battle.enemy.mon.hp = max - math.floor(dropPercent * quarter / 25)
|
||||
return battle:withdrawText(nick)
|
||||
end
|
||||
T.eq(withdrawAt(0), nick .. " enough!\nCome back!", "no damage -> `enough!`")
|
||||
T.eq(withdrawAt(50), nick .. " OK!\nCome back!", "30-69 -> `OK!`")
|
||||
T.eq(withdrawAt(80), nick .. " good!\nCome back!", "70+ -> `good!`")
|
||||
T.eq(withdrawAt(10), nick .. " \nCome back!", "1-29 -> no adjective at all")
|
||||
end
|
||||
|
||||
-- ---------------------------------------------------------------------
|
||||
-- ChooseNextMon (core.asm:1086-1128) calls SendOutMon with NO RetreatMon
|
||||
-- ---------------------------------------------------------------------
|
||||
do
|
||||
local battle = newBattle()
|
||||
drain(battle)
|
||||
battle.queue, battle.nextInsert = {}, 0
|
||||
battle.player.mon.hp = 0
|
||||
battle:openReplacementMenu()
|
||||
local rows = drain(battle)
|
||||
T.check(indexOf(rows, function(r)
|
||||
return r.text and r.text:find("Come back!", 1, true) ~= nil
|
||||
end) == nil, "the post-faint replacement prints no withdraw line")
|
||||
end
|
||||
|
||||
T.finish("switch withdraw text (#1534)")
|
||||
Reference in New Issue
Block a user