2015-04-06 01:18:46 -07:00
|
|
|
local Battle = {}
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
local Textbox = require "action.textbox"
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
local Combat = require "ai.combat"
|
|
|
|
local Control = require "ai.control"
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
local Memory = require "util.memory"
|
|
|
|
local Menu = require "util.menu"
|
|
|
|
local Input = require "util.input"
|
|
|
|
local Utils = require "util.utils"
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
local Inventory = require "storage.inventory"
|
|
|
|
local Pokemon = require "storage.pokemon"
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-09 02:19:46 -07:00
|
|
|
-- HELPERS
|
|
|
|
|
2015-04-04 18:37:48 -07:00
|
|
|
local function potionsForHit(potion, curr_hp, max_hp)
|
2015-03-30 15:29:00 -07:00
|
|
|
if not potion then
|
2014-07-12 18:47:39 -07:00
|
|
|
return
|
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
local ours, killAmount = Combat.inKillRange()
|
2015-03-30 15:29:00 -07:00
|
|
|
if ours then
|
2015-04-19 11:54:14 -07:00
|
|
|
if Control.yolo and killAmount > 6 and killAmount == curr_hp then
|
2015-04-18 21:08:29 -07:00
|
|
|
return false
|
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
return Utils.canPotionWith(potion, killAmount, curr_hp, max_hp)
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function recover()
|
2015-04-06 01:18:46 -07:00
|
|
|
if Control.canRecover() then
|
2015-04-26 16:31:07 -07:00
|
|
|
local curr_hp = Combat.hp()
|
|
|
|
if curr_hp > 0 then
|
|
|
|
local max_hp = Combat.maxHP()
|
|
|
|
if curr_hp < max_hp then
|
2014-07-12 18:47:39 -07:00
|
|
|
local first, second
|
2015-04-15 01:38:51 -07:00
|
|
|
if Control.preferredPotion == "full" then
|
2014-07-12 18:47:39 -07:00
|
|
|
first, second = "full_restore", "super_potion"
|
2015-04-26 16:31:07 -07:00
|
|
|
if max_hp - curr_hp > 54 then
|
2014-07-12 18:47:39 -07:00
|
|
|
first = "full_restore"
|
|
|
|
second = "super_potion"
|
|
|
|
else
|
|
|
|
first = "super_potion"
|
|
|
|
second = "full_restore"
|
|
|
|
end
|
|
|
|
else
|
2015-04-26 16:31:07 -07:00
|
|
|
if Control.preferredPotion == "super" and max_hp - curr_hp > 22 then
|
2014-07-12 18:47:39 -07:00
|
|
|
first = "super_potion"
|
|
|
|
second = "potion"
|
|
|
|
else
|
|
|
|
first = "potion"
|
|
|
|
second = "super_potion"
|
|
|
|
end
|
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
local potion = Inventory.contains(first, second)
|
2015-04-26 16:31:07 -07:00
|
|
|
if potionsForHit(potion, curr_hp, max_hp) then
|
2015-04-06 01:18:46 -07:00
|
|
|
Inventory.use(potion, nil, true)
|
2014-07-12 18:47:39 -07:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
2015-04-17 17:30:00 -07:00
|
|
|
if Combat.isParalyzed() then
|
2015-04-06 01:18:46 -07:00
|
|
|
local heals = Inventory.contains("paralyze_heal", "full_restore")
|
2015-03-30 15:29:00 -07:00
|
|
|
if heals then
|
2015-04-06 01:18:46 -07:00
|
|
|
Inventory.use(heals, nil, true)
|
2014-07-12 18:47:39 -07:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function openBattleMenu()
|
2015-04-06 01:18:46 -07:00
|
|
|
if Memory.value("battle", "text") == 1 then
|
|
|
|
Input.cancel()
|
2014-07-12 18:47:39 -07:00
|
|
|
return false
|
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
local battleMenu = Memory.value("battle", "menu")
|
|
|
|
local col = Menu.getCol()
|
2015-03-30 15:29:00 -07:00
|
|
|
if battleMenu == 106 or (battleMenu == 94 and col == 5) then
|
2014-07-12 18:47:39 -07:00
|
|
|
return true
|
2015-04-24 21:03:06 -07:00
|
|
|
elseif Menu.onBattleSelect(battleMenu) then
|
2015-04-06 01:18:46 -07:00
|
|
|
local rowSelected = Memory.value("menu", "row")
|
2015-03-30 15:29:00 -07:00
|
|
|
if col == 9 then
|
|
|
|
if rowSelected == 1 then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("Up")
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("A")
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("Left")
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("B")
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
local function attack(attackIndex)
|
2015-04-15 11:16:02 -07:00
|
|
|
if not Battle.opponentAlive() then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2015-03-30 15:29:00 -07:00
|
|
|
elseif openBattleMenu() then
|
2015-04-06 01:18:46 -07:00
|
|
|
Menu.select(attackIndex, true, false, false, false, 3)
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-09 02:19:46 -07:00
|
|
|
function movePP(name)
|
|
|
|
local midx = Pokemon.battleMove(name)
|
|
|
|
if not midx then
|
|
|
|
return 0
|
|
|
|
end
|
|
|
|
return Memory.raw(0x102C + midx)
|
|
|
|
end
|
|
|
|
Battle.pp = movePP
|
|
|
|
|
|
|
|
-- UTILS
|
2014-07-12 18:47:39 -07:00
|
|
|
|
2015-04-16 12:15:50 -07:00
|
|
|
function Battle.swapMove(move, toIndex)
|
|
|
|
toIndex = toIndex + 1
|
2015-03-30 15:29:00 -07:00
|
|
|
if openBattleMenu() then
|
2015-04-16 12:15:50 -07:00
|
|
|
local moveIndex = Pokemon.battleMove(move)
|
|
|
|
if not moveIndex or moveIndex == toIndex then
|
|
|
|
return true
|
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
local selection = Memory.value("menu", "selection_mode")
|
2014-07-12 18:47:39 -07:00
|
|
|
local swapSelect
|
2015-04-16 12:15:50 -07:00
|
|
|
if selection == toIndex then
|
|
|
|
swapSelect = moveIndex
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-16 12:15:50 -07:00
|
|
|
swapSelect = toIndex
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
2015-04-16 12:15:50 -07:00
|
|
|
local menuSize = Memory.raw(0x101F) == 0 and 3 or 4
|
|
|
|
if Menu.select(swapSelect, true, false, nil, true, menuSize) then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("Select")
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.isActive()
|
|
|
|
return Memory.value("game", "battle") > 0
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.isTrainer()
|
|
|
|
local battleType = Memory.value("game", "battle")
|
2015-03-30 15:29:00 -07:00
|
|
|
if battleType == 2 then
|
2014-07-12 18:47:39 -07:00
|
|
|
return true
|
|
|
|
end
|
2015-03-30 15:29:00 -07:00
|
|
|
if battleType == 1 then
|
2015-04-06 17:29:05 -07:00
|
|
|
Battle.handle()
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Textbox.handle()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.opponent()
|
|
|
|
return Pokemon.getName(Memory.value("battle", "opponent_id"))
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
|
2015-04-21 22:37:00 -07:00
|
|
|
function Battle.deployed()
|
|
|
|
return Pokemon.getName(Memory.value("battle", "our_id"))
|
|
|
|
end
|
|
|
|
|
2015-04-15 11:16:02 -07:00
|
|
|
function Battle.opponentAlive()
|
|
|
|
return Memory.double("battle", "opponent_hp") > 0
|
|
|
|
end
|
|
|
|
|
2015-05-04 19:08:08 -07:00
|
|
|
function Battle.opponentDamaged(factor)
|
|
|
|
if not factor then
|
|
|
|
factor = 1
|
|
|
|
end
|
|
|
|
return Memory.double("battle", "opponent_hp") * factor < Memory.double("battle", "opponent_max_hp")
|
|
|
|
end
|
|
|
|
|
2015-04-09 02:19:46 -07:00
|
|
|
-- HANDLE
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.run()
|
2015-04-15 11:16:02 -07:00
|
|
|
if not Battle.opponentAlive() then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2015-04-24 21:03:06 -07:00
|
|
|
elseif not Menu.onBattleSelect() then
|
2015-04-06 01:18:46 -07:00
|
|
|
if Memory.value("menu", "text_length") == 127 then
|
|
|
|
Input.press("B")
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
elseif Textbox.handle() then
|
|
|
|
local selected = Memory.value("menu", "selection")
|
2015-03-30 15:29:00 -07:00
|
|
|
if selected == 239 then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("A", 2)
|
2015-04-15 11:16:02 -07:00
|
|
|
elseif selected == 233 then
|
|
|
|
Input.press("Right")
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.escape()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-06 17:29:05 -07:00
|
|
|
function Battle.handle()
|
|
|
|
if not Control.shouldCatch() then
|
|
|
|
if Control.shouldFight() then
|
|
|
|
Battle.fight()
|
|
|
|
else
|
|
|
|
Battle.run()
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-23 10:25:20 -07:00
|
|
|
function Battle.handleWild(battleStatus)
|
|
|
|
if not battleStatus then
|
|
|
|
battleStatus = Memory.value("game", "battle")
|
|
|
|
end
|
|
|
|
if battleStatus ~= 1 then
|
2014-07-12 18:47:39 -07:00
|
|
|
return true
|
|
|
|
end
|
2015-04-06 17:29:05 -07:00
|
|
|
Battle.handle()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
|
2015-04-09 16:53:56 -07:00
|
|
|
function Battle.fight(move, skipBuffs)
|
2015-03-30 15:29:00 -07:00
|
|
|
if move then
|
2015-04-09 16:53:56 -07:00
|
|
|
if type(move) ~= "number" then
|
2015-04-06 01:18:46 -07:00
|
|
|
move = Pokemon.battleMove(move)
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
attack(move)
|
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
move = Combat.bestMove()
|
2015-03-30 15:29:00 -07:00
|
|
|
if move then
|
2015-04-09 16:53:56 -07:00
|
|
|
Battle.accurateAttack = move.accuracy == 100
|
2014-07-12 18:47:39 -07:00
|
|
|
attack(move.midx)
|
2015-04-06 01:18:46 -07:00
|
|
|
elseif Memory.value("menu", "text_length") == 127 then
|
|
|
|
Input.press("B")
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.swap(target)
|
2015-04-24 21:03:06 -07:00
|
|
|
if Menu.onPokemonSelect() then
|
2015-04-06 01:18:46 -07:00
|
|
|
if Menu.getCol() == 0 then
|
2015-04-14 14:36:22 -07:00
|
|
|
Pokemon.select(target)
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("A")
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
2015-04-24 21:03:06 -07:00
|
|
|
elseif Menu.onBattleSelect() then
|
2015-04-06 01:18:46 -07:00
|
|
|
local selected = Memory.value("menu", "selection")
|
2015-03-30 15:29:00 -07:00
|
|
|
if selected == 199 then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("A", 2)
|
|
|
|
elseif Menu.getCol() == 9 then
|
|
|
|
Input.press("Right", 0)
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("Up", 0)
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.automate(moveName, skipBuffs)
|
2015-03-30 15:29:00 -07:00
|
|
|
if not recover() then
|
2015-04-06 01:18:46 -07:00
|
|
|
local state = Memory.value("game", "battle")
|
2015-03-30 15:29:00 -07:00
|
|
|
if state == 0 then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.cancel()
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-03-30 15:29:00 -07:00
|
|
|
if moveName and movePP(moveName) == 0 then
|
2014-07-12 18:47:39 -07:00
|
|
|
moveName = nil
|
|
|
|
end
|
2015-03-30 15:29:00 -07:00
|
|
|
if state == 1 then
|
2015-04-06 01:18:46 -07:00
|
|
|
if Control.shouldFight() then
|
2015-04-09 16:53:56 -07:00
|
|
|
Battle.fight(moveName, skipBuffs)
|
2014-07-12 18:47:39 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
Battle.run()
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
2015-03-30 15:29:00 -07:00
|
|
|
elseif state == 2 then
|
2015-04-09 16:53:56 -07:00
|
|
|
Battle.fight(moveName, skipBuffs)
|
2014-07-12 18:47:39 -07:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2015-04-09 02:19:46 -07:00
|
|
|
-- SACRIFICE
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.sacrifice(...)
|
|
|
|
local sacrifice = Pokemon.getSacrifice(...)
|
2015-03-30 15:29:00 -07:00
|
|
|
if sacrifice then
|
2015-04-06 01:18:46 -07:00
|
|
|
Battle.swap(sacrifice)
|
2015-03-30 14:46:37 -07:00
|
|
|
return true
|
|
|
|
end
|
|
|
|
return false
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
function Battle.redeployNidoking()
|
|
|
|
if Pokemon.isDeployed("nidoking") then
|
2015-04-24 21:28:36 -07:00
|
|
|
Control.ignoreMiss = false
|
2015-03-30 14:46:37 -07:00
|
|
|
return false
|
|
|
|
end
|
2015-04-24 21:28:36 -07:00
|
|
|
Control.ignoreMiss = true
|
2015-04-13 00:43:20 -07:00
|
|
|
if Menu.onPokemonSelect() then
|
2015-04-14 14:36:22 -07:00
|
|
|
Pokemon.select("nidoking")
|
2015-04-13 00:43:20 -07:00
|
|
|
elseif Menu.hasTextbox() and Menu.getCol() == 1 then
|
2015-04-06 01:18:46 -07:00
|
|
|
Input.press("A")
|
2015-03-30 14:46:37 -07:00
|
|
|
else
|
2015-04-06 01:18:46 -07:00
|
|
|
local __, turns = Combat.bestMove()
|
2015-03-30 15:29:00 -07:00
|
|
|
if turns == 1 then
|
2015-04-09 16:53:56 -07:00
|
|
|
if Pokemon.isDeployed("spearow") then
|
|
|
|
forced = "growl"
|
2015-04-11 10:30:38 -07:00
|
|
|
elseif Pokemon.isDeployed("squirtle") then
|
|
|
|
forced = "tail_whip"
|
2015-04-09 16:53:56 -07:00
|
|
|
else
|
|
|
|
forced = "sand_attack"
|
|
|
|
end
|
2015-03-30 14:46:37 -07:00
|
|
|
end
|
2015-04-06 01:18:46 -07:00
|
|
|
Battle.automate(forced)
|
2015-03-30 14:46:37 -07:00
|
|
|
end
|
|
|
|
return true
|
|
|
|
end
|
|
|
|
|
2015-04-06 01:18:46 -07:00
|
|
|
return Battle
|