mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Fixed Rollout being affected by Parental Bond, fixed multi-turn moves being stopped by Torment, fixed BGM not stopping when returning to the title screen, removed AI references
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
# AI skill levels:
|
||||
# 0: Wild Pokémon
|
||||
# 1-31: Basic trainer (young/inexperienced)
|
||||
# 32-47: Some skill
|
||||
# 48-99: High skill
|
||||
# 100+: Best trainers (Gym Leaders, Elite Four, Champion)
|
||||
# NOTE: A trainer's skill value can range from 0-255, but by default only four
|
||||
# distinct skill levels exist. The skill value is typically the same as
|
||||
# the trainer's base money value.
|
||||
module PBTrainerAI
|
||||
# Minimum skill level to be in each AI category.
|
||||
def self.minimumSkill; return 1; end
|
||||
def self.mediumSkill; return 32; end
|
||||
def self.highSkill; return 48; end
|
||||
def self.bestSkill; return 100; end
|
||||
end
|
||||
|
||||
|
||||
|
||||
class PokeBattle_AI
|
||||
def initialize(battle)
|
||||
@battle = battle
|
||||
end
|
||||
|
||||
def pbAIRandom(x); return rand(x); end
|
||||
|
||||
def pbStdDev(choices)
|
||||
sum = 0
|
||||
n = 0
|
||||
choices.each do |c|
|
||||
sum += c[1]
|
||||
n += 1
|
||||
end
|
||||
return 0 if n<2
|
||||
mean = sum.to_f/n.to_f
|
||||
varianceTimesN = 0
|
||||
choices.each do |c|
|
||||
next if c[1]<=0
|
||||
deviation = c[1].to_f-mean
|
||||
varianceTimesN += deviation*deviation
|
||||
end
|
||||
# Using population standard deviation
|
||||
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
|
||||
return Math.sqrt(varianceTimesN/n)
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should Mega Evolve their Pokémon
|
||||
#=============================================================================
|
||||
def pbEnemyShouldMegaEvolve?(idxBattler)
|
||||
battler = @battle.battlers[idxBattler]
|
||||
if @battle.pbCanMegaEvolve?(idxBattler) # Simple "always should if possible"
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Mega Evolve")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Choose an action
|
||||
#=============================================================================
|
||||
def pbDefaultChooseEnemyCommand(idxBattler)
|
||||
return if pbEnemyShouldUseItem?(idxBattler)
|
||||
return if pbEnemyShouldWithdraw?(idxBattler)
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
|
||||
pbChooseMoves(idxBattler)
|
||||
end
|
||||
end
|
||||
@@ -1,182 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should use an item on the Pokémon
|
||||
#=============================================================================
|
||||
def pbEnemyShouldUseItem?(idxBattler)
|
||||
user = @battle.battlers[idxBattler]
|
||||
item, idxTarget = pbEnemyItemToUse(idxBattler)
|
||||
return false if item==0
|
||||
# Determine target of item (always the Pokémon choosing the action)
|
||||
useType = pbGetItemData(item,ITEM_BATTLE_USE)
|
||||
if useType && (useType==1 || useType==6) # Use on Pokémon
|
||||
idxTarget = @battle.battlers[idxTarget].pokemonIndex # Party Pokémon
|
||||
end
|
||||
# Register use of item
|
||||
@battle.pbRegisterItem(idxBattler,item,idxTarget)
|
||||
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use item #{PBItems.getName(item)}")
|
||||
return true
|
||||
end
|
||||
|
||||
# NOTE: The AI will only consider using an item on the Pokémon it's currently
|
||||
# choosing an action for.
|
||||
def pbEnemyItemToUse(idxBattler)
|
||||
return 0 if !@internalBattle
|
||||
items = @battle.pbGetOwnerItems(idxBattler)
|
||||
return 0 if !items || items.length==0
|
||||
# Determine target of item (always the Pokémon choosing the action)
|
||||
idxTarget = idxBattler # Battler using the item
|
||||
battler = @battle.battlers[idxTarget]
|
||||
pkmn = battler.pokemon
|
||||
# Item categories
|
||||
hpItems = {
|
||||
:POTION => 20,
|
||||
:SUPERPOTION => 50,
|
||||
:HYPERPOTION => 200,
|
||||
:MAXPOTION => 999,
|
||||
:BERRYJUICE => 20,
|
||||
:SWEETHEART => 20,
|
||||
:FRESHWATER => 50,
|
||||
:SODAPOP => 60,
|
||||
:LEMONADE => 80,
|
||||
:MOOMOOMILK => 100,
|
||||
:ORANBERRY => 10,
|
||||
:SITRUSBERRY => battler.totalhp/4,
|
||||
:ENERGYPOWDER => 50,
|
||||
:ENERGYROOT => 200
|
||||
}
|
||||
hpItems[:RAGECANDYBAR] = 20 if !NEWEST_BATTLE_MECHANICS
|
||||
fullRestoreItems = [
|
||||
:FULLRESTORE
|
||||
]
|
||||
oneStatusItems = [ # Preferred over items that heal all status problems
|
||||
:AWAKENING,:CHESTOBERRY,:BLUEFLUTE,
|
||||
:ANTIDOTE,:PECHABERRY,
|
||||
:BURNHEAL,:RAWSTBERRY,
|
||||
:PARALYZEHEAL,:PARLYZHEAL,:CHERIBERRY,
|
||||
:ICEHEAL,:ASPEARBERRY
|
||||
]
|
||||
allStatusItems = [
|
||||
:FULLHEAL,:LAVACOOKIE,:OLDGATEAU,:CASTELIACONE,:LUMIOSEGALETTE,
|
||||
:SHALOURSABLE,:BIGMALASADA,:LUMBERRY,:HEALPOWDER
|
||||
]
|
||||
allStatusItems.push(:RAGECANDYBAR) if NEWEST_BATTLE_MECHANICS
|
||||
xItems = {
|
||||
:XATTACK => [PBStats::ATTACK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XATTACK2 => [PBStats::ATTACK,2],
|
||||
:XATTACK3 => [PBStats::ATTACK,3],
|
||||
:XATTACK6 => [PBStats::ATTACK,6],
|
||||
:XDEFENSE => [PBStats::DEFENSE,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XDEFENSE2 => [PBStats::DEFENSE,2],
|
||||
:XDEFENSE3 => [PBStats::DEFENSE,3],
|
||||
:XDEFENSE6 => [PBStats::DEFENSE,6],
|
||||
:XDEFEND => [PBStats::DEFENSE,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XDEFEND2 => [PBStats::DEFENSE,2],
|
||||
:XDEFEND3 => [PBStats::DEFENSE,3],
|
||||
:XDEFEND6 => [PBStats::DEFENSE,6],
|
||||
:XSPATK => [PBStats::SPATK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPATK2 => [PBStats::SPATK,2],
|
||||
:XSPATK3 => [PBStats::SPATK,3],
|
||||
:XSPATK6 => [PBStats::SPATK,6],
|
||||
:XSPECIAL => [PBStats::SPATK,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPECIAL2 => [PBStats::SPATK,2],
|
||||
:XSPECIAL3 => [PBStats::SPATK,3],
|
||||
:XSPECIAL6 => [PBStats::SPATK,6],
|
||||
:XSPDEF => [PBStats::SPDEF,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPDEF2 => [PBStats::SPDEF,2],
|
||||
:XSPDEF3 => [PBStats::SPDEF,3],
|
||||
:XSPDEF6 => [PBStats::SPDEF,6],
|
||||
:XSPEED => [PBStats::SPEED,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPEED2 => [PBStats::SPEED,2],
|
||||
:XSPEED3 => [PBStats::SPEED,3],
|
||||
:XSPEED6 => [PBStats::SPEED,6],
|
||||
:XACCURACY => [PBStats::ACCURACY,(NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XACCURACY2 => [PBStats::ACCURACY,2],
|
||||
:XACCURACY3 => [PBStats::ACCURACY,3],
|
||||
:XACCURACY6 => [PBStats::ACCURACY,6]
|
||||
}
|
||||
losthp = battler.totalhp-battler.hp
|
||||
preferFullRestore = (battler.hp<=battler.totalhp*2/3 &&
|
||||
(battler.status!=PBStatuses::NONE || battler.effects[PBEffects::Confusion]>0))
|
||||
# Find all usable items
|
||||
usableHPItems = []
|
||||
usableStatusItems = []
|
||||
usableXItems = []
|
||||
items.each do |i|
|
||||
next if !i || i==0
|
||||
next if !@battle.pbCanUseItemOnPokemon?(i,pkmn,battler,@battle.scene,false)
|
||||
next if !ItemHandlers.triggerCanUseInBattle(i,pkmn,battler,nil,
|
||||
false,self,@battle.scene,false)
|
||||
checkedItem = false
|
||||
# Log HP healing items
|
||||
if losthp>0
|
||||
hpItems.each do |item, power|
|
||||
next if !isConst?(i,PBItems,item)
|
||||
checkedItem = true
|
||||
usableHPItems.push([i,5,power])
|
||||
end
|
||||
next if checkedItem
|
||||
end
|
||||
# Log Full Restores (HP healer and status curer)
|
||||
if losthp>0 || battler.status!=PBStatuses::NONE
|
||||
fullRestoreItems.each do |item|
|
||||
next if !isConst?(i,PBItems,item)
|
||||
checkedItem = true
|
||||
usableHPItems.push([i,(preferFullRestore) ? 3 : 7,999])
|
||||
usableStatusItems.push([i,(preferFullRestore) ? 3 : 9])
|
||||
end
|
||||
next if checkedItem
|
||||
end
|
||||
# Log single status-curing items
|
||||
if battler.status!=PBStatuses::NONE
|
||||
oneStatusItems.each do |item|
|
||||
next if !isConst?(i,PBItems,item)
|
||||
checkedItem = true
|
||||
usableStatusItems.push([i,5])
|
||||
end
|
||||
next if checkedItem
|
||||
# Log Full Heal-type items
|
||||
allStatusItems.each do |item|
|
||||
next if !isConst?(i,PBItems,item)
|
||||
checkedItem = true
|
||||
usableStatusItems.push([i,7])
|
||||
end
|
||||
next if checkedItem
|
||||
end
|
||||
# Log stat-raising items
|
||||
xItems.each do |item, data|
|
||||
next if !isConst?(i,PBItems,item)
|
||||
checkedItem = true
|
||||
usableXItems.push([i,battler.stages[data[0]],data[1]])
|
||||
end
|
||||
next if checkedItem
|
||||
end
|
||||
# Prioritise using a HP restoration item
|
||||
if usableHPItems.length>0 && (battler.hp<=battler.totalhp/4 ||
|
||||
(battler.hp<=battler.totalhp/2 && pbAIRandom(100)<30))
|
||||
usableHPItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
|
||||
prevItem = nil
|
||||
usableHPItems.each do |i|
|
||||
return i[0],idxTarget if i[2]>=losthp
|
||||
prevItem = i
|
||||
end
|
||||
return prevItem[0],idxTarget
|
||||
end
|
||||
# Next prioritise using a status-curing item
|
||||
if usableStatusItems.length>0 && pbAIRandom(100)<40
|
||||
usableStatusItems.sort! { |a,b| a[1]<=>b[1] }
|
||||
return usableStatusItems[0][0],idxTarget
|
||||
end
|
||||
# Next try using an X item
|
||||
if usableXItems.length>0 && pbAIRandom(100)<30
|
||||
usableXItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
|
||||
prevItem = nil
|
||||
usableXItems.each do |i|
|
||||
break if prevItem && i[1]>prevItem[1]
|
||||
return i[0],idxTarget if i[1]+i[2]>=6
|
||||
prevItem = i
|
||||
end
|
||||
return prevItem[0],idxTarget
|
||||
end
|
||||
return 0
|
||||
end
|
||||
end
|
||||
@@ -1,182 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should switch Pokémon
|
||||
#=============================================================================
|
||||
def pbEnemyShouldWithdraw?(idxBattler)
|
||||
return pbEnemyShouldWithdrawEx?(idxBattler,false)
|
||||
end
|
||||
|
||||
def pbEnemyShouldWithdrawEx?(idxBattler,forceSwitch)
|
||||
return false if @battle.wildBattle?
|
||||
shouldSwitch = forceSwitch
|
||||
batonPass = -1
|
||||
moveType = -1
|
||||
skill = @battle.pbGetOwnerFromBattlerIndex(idxBattler).skill || 0
|
||||
battler = @battle.battlers[idxBattler]
|
||||
# If Pokémon is within 6 levels of the foe, and foe's last move was
|
||||
# super-effective and powerful
|
||||
if !shouldSwitch && battler.turnCount>0 && skill>=PBTrainerAI.highSkill
|
||||
target = battler.pbDirectOpposing(true)
|
||||
if !target.fainted? && target.lastMoveUsed>0 &&
|
||||
(target.level-battler.level).abs<=6
|
||||
moveData = pbGetMoveData(target.lastMoveUsed)
|
||||
moveType = moveData[MOVE_TYPE]
|
||||
typeMod = pbCalcTypeMod(moveType,target,battler)
|
||||
if PBTypes.superEffective?(typeMod) && moveData[MOVE_BASE_DAMAGE]>50
|
||||
switchChance = (moveData[MOVE_BASE_DAMAGE]>70) ? 30 : 20
|
||||
shouldSwitch = (pbAIRandom(100)<switchChance)
|
||||
end
|
||||
end
|
||||
end
|
||||
# Pokémon can't do anything (must have been in battle for at least 5 rounds)
|
||||
if !@battle.pbCanChooseAnyMove?(idxBattler) &&
|
||||
battler.turnCount && battler.turnCount>=5
|
||||
shouldSwitch = true
|
||||
end
|
||||
# Pokémon is Perish Songed and has Baton Pass
|
||||
if skill>=PBTrainerAI.highSkill && battler.effects[PBEffects::PerishSong]==1
|
||||
battler.eachMoveWithIndex do |m,i|
|
||||
next if m.function!="0ED" # Baton Pass
|
||||
next if !@battle.pbCanChooseMove?(idxBattler,i,false)
|
||||
batonPass = i
|
||||
break
|
||||
end
|
||||
end
|
||||
# Pokémon will faint because of bad poisoning at the end of this round, but
|
||||
# would survive at least one more round if it were regular poisoning instead
|
||||
if battler.status==PBStatuses::POISON && battler.statusCount>0 &&
|
||||
skill>=PBTrainerAI.highSkill
|
||||
toxicHP = battler.totalhp/16
|
||||
nextToxicHP = toxicHP*(battler.effects[PBEffects::Toxic]+1)
|
||||
if battler.hp<=nextToxicHP && battler.hp>toxicHP*2
|
||||
shouldSwitch = true if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
# Pokémon is Encored into an unfavourable move
|
||||
if battler.effects[PBEffects::Encore]>0 && skill>=PBTrainerAI.mediumSkill
|
||||
idxEncoredMove = battler.pbEncoredMoveIndex
|
||||
if idxEncoredMove>=0
|
||||
scoreSum = 0
|
||||
scoreCount = 0
|
||||
battler.eachOpposing do |b|
|
||||
scoreSum += pbGetMoveScore(battler.moves[idxEncoredMove],battler,b,skill)
|
||||
scoreCount += 1
|
||||
end
|
||||
if scoreCount>0 && scoreSum/scoreCount<=20
|
||||
shouldSwitch = true if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
end
|
||||
# If there is a single foe and it is resting after Hyper Beam or is
|
||||
# Truanting (i.e. free turn)
|
||||
if @battle.pbSideSize(battler.index+1)==1 &&
|
||||
!battler.pbDirectOpposing.fainted? && skill>=PBTrainerAI.highSkill
|
||||
opp = battler.pbDirectOpposing
|
||||
if opp.effects[PBEffects::HyperBeam]>0 ||
|
||||
(opp.hasActiveAbility?(:TRUANT) && opp.effects[PBEffects::Truant])
|
||||
shouldSwitch = false if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
# Sudden Death rule - I'm not sure what this means
|
||||
if @battle.rules["suddendeath"] && battler.turnCount>0
|
||||
if battler.hp<=battler.totalhp/4 && pbAIRandom(100)<30
|
||||
shouldSwitch = true
|
||||
elsif battler.hp<=battler.totalhp/2 && pbAIRandom(100)<80
|
||||
shouldSwitch = true
|
||||
end
|
||||
end
|
||||
# Pokémon is about to faint because of Perish Song
|
||||
if battler.effects[PBEffects::PerishSong]==1
|
||||
shouldSwitch = true
|
||||
end
|
||||
if shouldSwitch
|
||||
list = []
|
||||
@battle.pbParty(idxBattler).each_with_index do |pkmn,i|
|
||||
next if !@battle.pbCanSwitch?(idxBattler,i)
|
||||
# If perish count is 1, it may be worth it to switch
|
||||
# even with Spikes, since Perish Song's effect will end
|
||||
if battler.effects[PBEffects::PerishSong]!=1
|
||||
# Will contain effects that recommend against switching
|
||||
spikes = battler.pbOwnSide.effects[PBEffects::Spikes]
|
||||
# Don't switch to this if too little HP
|
||||
if spikes>0
|
||||
spikesDmg = [8,6,4][spikes-1]
|
||||
if pkmn.hp<=pkmn.totalhp/spikesDmg
|
||||
next if !pkmn.hasType?(:FLYING) && !pkmn.hasActiveAbility?(:LEVITATE)
|
||||
end
|
||||
end
|
||||
end
|
||||
# moveType is the type of the target's last used move
|
||||
if moveType>=0 && PBTypes.ineffective?(pbCalcTypeMod(moveType,battler,battler))
|
||||
weight = 65
|
||||
typeMod = pbCalcTypeModPokemon(pkmn,battler.pbDirectOpposing(true))
|
||||
if PBTypes.superEffective?(typeMod.to_f/PBTypeEffectivenesss::NORMAL_EFFECTIVE)
|
||||
# Greater weight if new Pokemon's type is effective against target
|
||||
weight = 85
|
||||
end
|
||||
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
|
||||
elsif moveType>=0 && PBTypes.resistant?(pbCalcTypeMod(moveType,battler,battler))
|
||||
weight = 40
|
||||
typeMod = pbCalcTypeModPokemon(pkmn,battler.pbDirectOpposing(true))
|
||||
if PBTypes.superEffective?(typeMod.to_f/PBTypeEffectivenesss::NORMAL_EFFECTIVE)
|
||||
# Greater weight if new Pokemon's type is effective against target
|
||||
weight = 60
|
||||
end
|
||||
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
|
||||
else
|
||||
list.push(i) # put this Pokemon last
|
||||
end
|
||||
end
|
||||
if list.length>0
|
||||
if batonPass>=0 && @battle.pbRegisterMove(idxBattler,batonPass,false)
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will use Baton Pass to avoid Perish Song")
|
||||
return true
|
||||
end
|
||||
if @battle.pbRegisterSwitch(idxBattler,list[0])
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will switch with " +
|
||||
"#{@battle.pbParty(idxBattler)[list[0]].name}")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Choose a replacement Pokémon
|
||||
#=============================================================================
|
||||
def pbDefaultChooseNewEnemy(idxBattler,party)
|
||||
enemies = []
|
||||
party.each_with_index do |_p,i|
|
||||
enemies.push(i) if @battle.pbCanSwitchLax?(idxBattler,i)
|
||||
end
|
||||
return -1 if enemies.length==0
|
||||
return pbChooseBestNewEnemy(idxBattler,party,enemies)
|
||||
end
|
||||
|
||||
def pbChooseBestNewEnemy(idxBattler,party,enemies)
|
||||
return -1 if !enemies || enemies.length==0
|
||||
best = -1
|
||||
bestSum = 0
|
||||
movesData = pbLoadMovesData
|
||||
enemies.each do |i|
|
||||
pkmn = party[i]
|
||||
sum = 0
|
||||
pkmn.moves.each do |m|
|
||||
next if m.id==0
|
||||
moveData = movesData[m.id]
|
||||
next if moveData[MOVE_BASE_DAMAGE]==0
|
||||
@battle.battlers[idxBattler].eachOpposing do |b|
|
||||
bTypes = b.pbTypes(true)
|
||||
sum += PBTypes.getCombinedEffectiveness(moveData[MOVE_TYPE],
|
||||
bTypes[0],bTypes[1],bTypes[2])
|
||||
end
|
||||
end
|
||||
if best==-1 || sum>bestSum
|
||||
best = i
|
||||
bestSum = sum
|
||||
end
|
||||
end
|
||||
return best
|
||||
end
|
||||
end
|
||||
@@ -1,286 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Main move-choosing method (moves with higher scores are more likely to be
|
||||
# chosen)
|
||||
#=============================================================================
|
||||
def pbChooseMoves(idxBattler)
|
||||
user = @battle.battlers[idxBattler]
|
||||
wildBattler = (@battle.wildBattle? && @battle.opposes?(idxBattler))
|
||||
skill = 0
|
||||
if !wildBattler
|
||||
skill = @battle.pbGetOwnerFromBattlerIndex(user.index).skill || 0
|
||||
end
|
||||
# Get scores and targets for each move
|
||||
# NOTE: A move is only added to the choices array if it has a non-zero
|
||||
# score.
|
||||
choices = []
|
||||
user.eachMoveWithIndex do |_m,i|
|
||||
next if !@battle.pbCanChooseMove?(idxBattler,i,false)
|
||||
if wildBattler
|
||||
pbRegisterMoveWild(user,i,choices)
|
||||
else
|
||||
pbRegisterMoveTrainer(user,i,choices,skill)
|
||||
end
|
||||
end
|
||||
# Figure out useful information about the choices
|
||||
totalScore = 0
|
||||
maxScore = 0
|
||||
choices.each do |c|
|
||||
totalScore += c[1]
|
||||
maxScore = c[1] if maxScore<c[1]
|
||||
end
|
||||
# Log the available choices
|
||||
if $INTERNAL
|
||||
logMsg = "[AI] Move choices for #{user.pbThis(true)} (#{user.index}): "
|
||||
choices.each_with_index do |c,i|
|
||||
logMsg += "#{user.moves[c[0]].name}=#{c[1]}"
|
||||
logMsg += " (target #{c[2]})" if c[2]>=0
|
||||
logMsg += ", " if i<choices.length-1
|
||||
end
|
||||
PBDebug.log(logMsg)
|
||||
end
|
||||
# Find any preferred moves and just choose from them
|
||||
if !wildBattler && skill>=PBTrainerAI.highSkill && maxScore>100
|
||||
stDev = pbStdDev(choices)
|
||||
if stDev>=40 && pbAIRandom(100)<90
|
||||
preferredMoves = []
|
||||
choices.each do |c|
|
||||
next if c[1]<200 && c[1]<maxScore*0.8
|
||||
preferredMoves.push(c)
|
||||
preferredMoves.push(c) if c[1]==maxScore # Doubly prefer the best move
|
||||
end
|
||||
if preferredMoves.length>0
|
||||
m = preferredMoves[pbAIRandom(preferredMoves.length)]
|
||||
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) prefers #{user.moves[m[0]].name}")
|
||||
@battle.pbRegisterMove(idxBattler,m[0],false)
|
||||
@battle.pbRegisterTarget(idxBattler,m[2]) if m[2]>=0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
# Decide whether all choices are bad, and if so, try switching instead
|
||||
if !wildBattler && skill>=PBTrainerAI.highSkill
|
||||
badMoves = false
|
||||
if (maxScore<=20 && user.turnCount>2) ||
|
||||
(maxScore<=40 && user.turnCount>5)
|
||||
badMoves = true if pbAIRandom(100)<80
|
||||
end
|
||||
if !badMoves && totalScore<100 && user.turnCount>1
|
||||
badMoves = true
|
||||
choices.each do |c|
|
||||
next if !user.moves[c[0]].damagingMove?
|
||||
badMoves = false
|
||||
break
|
||||
end
|
||||
badMoves = false if badMoves && pbAIRandom(100)<10
|
||||
end
|
||||
if badMoves && pbEnemyShouldWithdrawEx?(idxBattler,true)
|
||||
if $INTERNAL
|
||||
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will switch due to terrible moves")
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
# Randomly choose a move to use
|
||||
if choices.length==0
|
||||
# If there are no calculated choices, use Struggle (or an Encored move)
|
||||
@battle.pbAutoChooseMove(idxBattler)
|
||||
else
|
||||
# Randomly choose a move from the choices and register it
|
||||
randNum = pbAIRandom(totalScore)
|
||||
choices.each do |c|
|
||||
randNum -= c[1]
|
||||
next if randNum>=0
|
||||
@battle.pbRegisterMove(idxBattler,c[0],false)
|
||||
@battle.pbRegisterTarget(idxBattler,c[2]) if c[2]>=0
|
||||
break
|
||||
end
|
||||
end
|
||||
# Log the result
|
||||
if @battle.choices[idxBattler][2]
|
||||
PBDebug.log("[AI] #{user.pbThis} (#{user.index}) will use #{@battle.choices[user.index][2].name}")
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get scores for the given move against each possible target
|
||||
#=============================================================================
|
||||
# Wild Pokémon choose their moves randomly.
|
||||
def pbRegisterMoveWild(_user,idxMove,choices)
|
||||
choices.push([idxMove,100,-1]) # Move index, score, target
|
||||
end
|
||||
|
||||
# Trainer Pokémon calculate how much they want to use each of their moves.
|
||||
def pbRegisterMoveTrainer(user,idxMove,choices,skill)
|
||||
move = user.moves[idxMove]
|
||||
targetType = move.pbTarget(user)
|
||||
if PBTargets.multipleTargets?(targetType)
|
||||
# If move affects multiple battlers and you don't choose a particular one
|
||||
totalScore = 0
|
||||
@battle.eachBattler do |b|
|
||||
next if !@battle.pbMoveCanTarget?(user.index,b.index,targetType)
|
||||
score = pbGetMoveScore(move,user,b,skill)
|
||||
totalScore += ((user.opposes?(b)) ? score : -score)
|
||||
end
|
||||
choices.push([idxMove,totalScore,-1]) if totalScore>0
|
||||
elsif PBTargets.noTargets?(targetType)
|
||||
# If move has no targets, affects the user, a side or the whole field
|
||||
score = pbGetMoveScore(move,user,user,skill)
|
||||
choices.push([idxMove,score,-1]) if score>0
|
||||
else
|
||||
# If move affects one battler and you have to choose which one
|
||||
scoresAndTargets = []
|
||||
@battle.eachBattler do |b|
|
||||
next if !@battle.pbMoveCanTarget?(user.index,b.index,targetType)
|
||||
next if PBTargets.canChooseFoeTarget?(targetType) && !user.opposes?(b)
|
||||
score = pbGetMoveScore(move,user,b,skill)
|
||||
scoresAndTargets.push([score,b.index]) if score>0
|
||||
end
|
||||
if scoresAndTargets.length>0
|
||||
# Get the one best target for the move
|
||||
scoresAndTargets.sort! { |a,b| b[0]<=>a[0] }
|
||||
choices.push([idxMove,scoresAndTargets[0][0],scoresAndTargets[0][1]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move being used against the given target
|
||||
#=============================================================================
|
||||
def pbGetMoveScore(move,user,target,skill=100)
|
||||
skill = PBTrainerAI.minimumSkill if skill<PBTrainerAI.minimumSkill
|
||||
score = 100
|
||||
score = pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
# A score of 0 here means it absolutely should not be used
|
||||
return 0 if score<=0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
# Prefer damaging moves if AI has no more Pokémon or AI is less clever
|
||||
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
|
||||
if !(skill>=PBTrainerAI.highSkill && @battle.pbAbleNonActiveCount(target.idxOwnSide)>0)
|
||||
if move.statusMove?
|
||||
score /= 1.5
|
||||
elsif target.hp<=target.totalhp/2
|
||||
score *= 1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
# Don't prefer attacking the target if they'd be semi-invulnerable
|
||||
if skill>=PBTrainerAI.highSkill && move.accuracy>0 &&
|
||||
(target.semiInvulnerable? || target.effects[PBEffects::SkyDrop]>=0)
|
||||
miss = true
|
||||
miss = false if user.hasActiveAbility?(:NOGUARD) || target.hasActiveAbility?(:NOGUARD)
|
||||
if miss && pbRoughStat(user,PBStats::SPEED,skill)>pbRoughStat(target,PBStats::SPEED,skill)
|
||||
# Knows what can get past semi-invulnerability
|
||||
if target.effects[PBEffects::SkyDrop]>=0
|
||||
miss = false if move.hitsFlyingTargets?
|
||||
else
|
||||
if target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
|
||||
miss = false if move.hitsFlyingTargets?
|
||||
elsif target.inTwoTurnAttack?("0CA") # Dig
|
||||
miss = false if move.hitsDiggingTargets?
|
||||
elsif target.inTwoTurnAttack?("0CB") # Dive
|
||||
miss = false if move.hitsDivingTargets?
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 80 if miss
|
||||
end
|
||||
# Pick a good move for the Choice items
|
||||
if user.hasActiveItem?([:CHOICEBAND,:CHOICESPECS,:CHOICESCARF])
|
||||
if move.baseDamage>=60; score += 60
|
||||
elsif move.damagingMove?; score += 30
|
||||
elsif move.function=="0F2"; score += 70 # Trick
|
||||
else; score -= 60
|
||||
end
|
||||
end
|
||||
# If user is asleep, prefer moves that are usable while asleep
|
||||
if user.status==PBStatuses::SLEEP && !move.usableWhenAsleep?
|
||||
user.eachMove do |m|
|
||||
next unless m.usableWhenAsleep?
|
||||
score -= 60
|
||||
break
|
||||
end
|
||||
end
|
||||
# If user is frozen, prefer a move that can thaw the user
|
||||
if user.status==PBStatuses::FROZEN
|
||||
if move.thawsUser?
|
||||
score += 40
|
||||
else
|
||||
user.eachMove do |m|
|
||||
next unless m.thawsUser?
|
||||
score -= 60
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
# If target is frozen, don't prefer moves that could thaw them
|
||||
if target.status==PBStatuses::FROZEN
|
||||
user.eachMove do |m|
|
||||
next if m.thawsUser?
|
||||
score -= 60
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
# Adjust score based on how much damage it can deal
|
||||
if move.damagingMove?
|
||||
score = pbGetMoveScoreDamage(score,move,user,target,skill)
|
||||
else # Status moves
|
||||
# Don't prefer attacks which don't deal damage
|
||||
score -= 10
|
||||
# Account for accuracy of move
|
||||
accuracy = pbRoughAccuracy(move,user,target,skill)
|
||||
score *= accuracy/100.0
|
||||
score = 0 if score<=10 && skill>=PBTrainerAI.highSkill
|
||||
end
|
||||
score = score.to_i
|
||||
score = 0 if score<0
|
||||
return score
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Add to a move's score based on how much damage it will deal (as a percentage
|
||||
# of the target's current HP)
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreDamage(score,move,user,target,skill)
|
||||
# Don't prefer moves that are ineffective because of abilities or effects
|
||||
return 0 if score<=0 || pbCheckMoveImmunity(score,move,user,target,skill)
|
||||
# Calculate how much damage the move will do (roughly)
|
||||
baseDmg = pbMoveBaseDamage(move,user,target,skill)
|
||||
realDamage = pbRoughDamage(move,user,target,skill,baseDmg)
|
||||
# Account for accuracy of move
|
||||
accuracy = pbRoughAccuracy(move,user,target,skill)
|
||||
realDamage *= accuracy/100.0
|
||||
# Two-turn attacks waste 2 turns to deal one lot of damage
|
||||
if move.chargingTurnMove? || move.function=="0C2" # Hyper Beam
|
||||
realDamage *= 2/3 # Not halved because semi-invulnerable during use or hits first turn
|
||||
end
|
||||
# Prefer flinching external effects (note that move effects which cause
|
||||
# flinching are dealt with in the function code part of score calculation)
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
!target.hasActiveAbility?(:SHIELDDUST) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
canFlinch = false
|
||||
if move.canKingsRock? && user.hasActiveItem?([:KINGSROCK,:RAZORFANG])
|
||||
canFlinch = true
|
||||
end
|
||||
if user.hasActiveAbility?(:STENCH) && !move.flinchingMove?
|
||||
canFlinch = true
|
||||
end
|
||||
realDamage *= 1.3 if canFlinch
|
||||
end
|
||||
end
|
||||
# Convert damage to percentage of target's remaining HP
|
||||
damagePercentage = realDamage*100.0/target.hp
|
||||
# Don't prefer weak attacks
|
||||
# damagePercentage /= 2 if damagePercentage<20
|
||||
# Prefer damaging attack if level difference is significantly high
|
||||
damagePercentage *= 1.2 if user.level-10>target.level
|
||||
# Adjust score
|
||||
damagePercentage = 120 if damagePercentage>120 # Treat all lethal moves the same
|
||||
damagePercentage += 40 if damagePercentage>100 # Prefer moves likely to be lethal
|
||||
score += damagePercentage.to_i
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,838 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "000" # No extra effect
|
||||
#---------------------------------------------------------------------------
|
||||
when "001"
|
||||
score -= 95
|
||||
score = 0 if skill>=PBTrainerAI.highSkill
|
||||
#---------------------------------------------------------------------------
|
||||
when "002" # Struggle
|
||||
#---------------------------------------------------------------------------
|
||||
when "003"
|
||||
if target.pbCanSleep?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 30 if target.effects[PBEffects::Yawn]>0
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 30 if target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if target.pbHasMoveFunction?("011","0B4") # Snore, Sleep Talk
|
||||
score -= 50
|
||||
end
|
||||
end
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "004"
|
||||
if target.effects[PBEffects::Yawn]>0 || !target.pbCanSleep?(user,false)
|
||||
score -= 90 if skill>=PBTrainerAI.mediumSkill
|
||||
else
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 30 if target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if target.pbHasMoveFunction?("011","0B4") # Snore, Sleep Talk
|
||||
score -= 50
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "005", "006", "0BE"
|
||||
if target.pbCanPoison?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score += 30 if target.hp<=target.totalhp/4
|
||||
score += 50 if target.hp<=target.totalhp/8
|
||||
score -= 40 if target.effects[PBEffects::Yawn]>0
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 10 if pbRoughStat(target,PBStats::DEFENSE,skill)>100
|
||||
score += 10 if pbRoughStat(target,PBStats::SPDEF,skill)>100
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
|
||||
end
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "007", "008", "009", "0C5"
|
||||
if target.pbCanParalyze?(user,false) &&
|
||||
!(skill>=PBTrainerAI.mediumSkill &&
|
||||
isConst?(move.id,PBMoves,:THUNDERWAVE) &&
|
||||
PBTypes.ineffective?(pbCalcTypeMod(move.type,user,target)))
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if aspeed<ospeed
|
||||
score += 30
|
||||
elsif aspeed>ospeed
|
||||
score -= 40
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
|
||||
end
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "00A", "00B", "0C6"
|
||||
if target.pbCanBurn?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
|
||||
end
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "00C", "00D", "00E"
|
||||
if target.pbCanFreeze?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "00F"
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "010"
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
score += 30 if target.effects[PBEffects::Minimize]
|
||||
#---------------------------------------------------------------------------
|
||||
when "011"
|
||||
if user.asleep?
|
||||
score += 100 # Because it can only be used while asleep
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
else
|
||||
score -= 90 # Because it will fail here
|
||||
score = 0 if skill>=PBTrainerAI.bestSkill
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "012"
|
||||
if user.turnCount==0
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
else
|
||||
score -= 90 # Because it will fail here
|
||||
score = 0 if skill>=PBTrainerAI.bestSkill
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "013", "014", "015"
|
||||
if target.pbCanConfuse?(user,false)
|
||||
score += 30
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if move.statusMove?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "016"
|
||||
canattract = true
|
||||
agender = user.gender
|
||||
ogender = target.gender
|
||||
if agender==2 || ogender==2 || agender==ogender
|
||||
score -= 90; canattract = false
|
||||
elsif target.effects[PBEffects::Attract]>=0
|
||||
score -= 80; canattract = false
|
||||
elsif skill>=PBTrainerAI.bestSkill && target.hasActiveAbility?(:OBLIVIOUS)
|
||||
score -= 80; canattract = false
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if canattract && target.hasActiveItem?(:DESTINYKNOT) &&
|
||||
user.pbCanAttract?(target,false)
|
||||
score -= 30
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "017"
|
||||
score += 30 if target.status==PBStatuses::NONE
|
||||
#---------------------------------------------------------------------------
|
||||
when "018"
|
||||
case user.status
|
||||
when PBStatuses::POISON
|
||||
score += 40
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if user.hp<user.totalhp/8
|
||||
score += 60
|
||||
elsif skill>=PBTrainerAI.highSkill &&
|
||||
user.hp<(user.effects[PBEffects::Toxic]+1)*user.totalhp/16
|
||||
score += 60
|
||||
end
|
||||
end
|
||||
when PBStatuses::BURN, PBStatuses::PARALYSIS
|
||||
score += 40
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "019"
|
||||
statuses = 0
|
||||
@battle.pbParty(user.index).each do |pkmn|
|
||||
statuses += 1 if pkmn && pkmn.status!=PBStatuses::NONE
|
||||
end
|
||||
if statuses==0
|
||||
score -= 80
|
||||
else
|
||||
score += 20*statuses
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "01A"
|
||||
if user.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
score -= 80
|
||||
elsif user.status!=0
|
||||
score -= 40
|
||||
else
|
||||
score += 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "01B"
|
||||
if user.status==PBStatuses::NONE
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "01C"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::ATTACK)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::ATTACK]<0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "01D", "01E", "0C8"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::DEFENSE)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::DEFENSE]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "01F"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::SPEED]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "020"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPATK)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::SPATK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::SPATK]<0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "021"
|
||||
foundMove = false
|
||||
user.eachMove do |m|
|
||||
next if !isConst?(m.type,PBTypes,:ELECTRIC) || !m.damagingMove?
|
||||
foundMove = true
|
||||
break
|
||||
end
|
||||
score += 20 if foundMove
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::SPDEF]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "022"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::EVASION)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::EVASION]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "023"
|
||||
if move.statusMove?
|
||||
if user.effects[PBEffects::FocusEnergy]>=2
|
||||
score -= 80
|
||||
else
|
||||
score += 30
|
||||
end
|
||||
else
|
||||
score += 30 if user.effects[PBEffects::FocusEnergy]<2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "024"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::DEFENSE)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::DEFENSE]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "025"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::DEFENSE) &&
|
||||
user.statStageAtMax?(PBStats::ACCURACY)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::DEFENSE]*10
|
||||
score -= user.stages[PBStats::ACCURACY]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "026"
|
||||
score += 40 if user.turnCount==0 # Dragon Dance tends to be popular
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 20 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "027", "028"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::SPATK)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::SPATK]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasDamagingAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingAttack = true
|
||||
break
|
||||
end
|
||||
if hasDamagingAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if move.function=="028" # Growth
|
||||
score += 20 if @battle.pbWeather==PBWeather::Sun ||
|
||||
@battle.pbWeather==PBWeather::HarshSun
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "029"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::ACCURACY)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::ACCURACY]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02A"
|
||||
if user.statStageAtMax?(PBStats::DEFENSE) &&
|
||||
user.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::DEFENSE]*10
|
||||
score -= user.stages[PBStats::SPDEF]*10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02B"
|
||||
if user.statStageAtMax?(PBStats::SPEED) &&
|
||||
user.statStageAtMax?(PBStats::SPATK) &&
|
||||
user.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::SPATK]*10
|
||||
score -= user.stages[PBStats::SPDEF]*10
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if aspeed<ospeed && aspeed*2>ospeed
|
||||
score += 20
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02C"
|
||||
if user.statStageAtMax?(PBStats::SPATK) &&
|
||||
user.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0 # Calm Mind tends to be popular
|
||||
score -= user.stages[PBStats::SPATK]*10
|
||||
score -= user.stages[PBStats::SPDEF]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02D"
|
||||
PBStats.eachMainBattleStat { |s| score += 10 if user.stages[s]<0 }
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasDamagingAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasDamagingAttack
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02E"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::ATTACK)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::ATTACK]<0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "02F"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::DEFENSE)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::DEFENSE]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "030", "031"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score += 20 if user.turnCount==0
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::SPEED]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "032"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPATK)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::SPATK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::SPATK]<0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "033"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::SPDEF]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "034"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::EVASION)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if user.stages[PBStats::EVASION]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "035"
|
||||
score -= user.stages[PBStats::ATTACK]*20
|
||||
score -= user.stages[PBStats::SPEED]*20
|
||||
score -= user.stages[PBStats::SPATK]*20
|
||||
score += user.stages[PBStats::DEFENSE]*10
|
||||
score += user.stages[PBStats::SPDEF]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasDamagingAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasDamagingAttack
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "036"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "037"
|
||||
avgStat = 0; canChangeStat = false
|
||||
PBStats.eachBattleStat do |s|
|
||||
next if target.statStageAtMax?(s)
|
||||
avgStat -= target.stages[s]
|
||||
canChangeStat = true
|
||||
end
|
||||
if canChangeStat
|
||||
avgStat = avgStat/2 if avgStat<0 # More chance of getting even better
|
||||
score += avgStat*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "038"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::DEFENSE)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::DEFENSE]*30
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 30 if user.stages[PBStats::DEFENSE]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "039"
|
||||
if move.statusMove?
|
||||
if user.statStageAtMax?(PBStats::SPATK)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score -= user.stages[PBStats::SPATK]*30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 30 if user.stages[PBStats::SPATK]<0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 30 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "03A"
|
||||
if user.statStageAtMax?(PBStats::ATTACK) ||
|
||||
user.hp<=user.totalhp/2
|
||||
score -= 100
|
||||
else
|
||||
score += (6-user.stages[PBStats::ATTACK])*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 40
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "03B"
|
||||
avg = user.stages[PBStats::ATTACK]*10
|
||||
avg += user.stages[PBStats::DEFENSE]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "03C"
|
||||
avg = user.stages[PBStats::DEFENSE]*10
|
||||
avg += user.stages[PBStats::SPDEF]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "03D"
|
||||
avg = user.stages[PBStats::DEFENSE]*10
|
||||
avg += user.stages[PBStats::SPEED]*10
|
||||
avg += user.stages[PBStats::SPDEF]*10
|
||||
score += (avg/3).floor
|
||||
#---------------------------------------------------------------------------
|
||||
when "03E"
|
||||
score += user.stages[PBStats::SPEED]*10
|
||||
#---------------------------------------------------------------------------
|
||||
when "03F"
|
||||
score += user.stages[PBStats::SPATK]*10
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,797 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __b__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
score = __b__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "040"
|
||||
if !target.pbCanConfuse?(user,false)
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if target.stages[PBStats::SPATK]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "041"
|
||||
if !target.pbCanConfuse?(user,false)
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if target.stages[PBStats::ATTACK]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "042"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::ATTACK]>0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "043"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "044"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPEED,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::SPEED]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "045"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += user.stages[PBStats::SPATK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if user.stages[PBStats::SPATK]>0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "046"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPDEF,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::SPDEF]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "047"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::ACCURACY,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::ACCURACY]*10
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::ACCURACY]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "048"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::EVASION]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "049"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 20 if target.stages[PBStats::EVASION]>0
|
||||
end
|
||||
score += 30 if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::Mist]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
score -= 30 if target.pbOwnSide.effects[PBEffects::Spikes]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
#---------------------------------------------------------------------------
|
||||
when "04A"
|
||||
avg = target.stages[PBStats::ATTACK]*10
|
||||
avg += target.stages[PBStats::DEFENSE]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "04B"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if target.stages[PBStats::ATTACK]>0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04C"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04D"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPEED,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 20 if user.turnCount==0
|
||||
score += target.stages[PBStats::SPEED]*20
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 30 if target.stages[PBStats::SPEED]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04E"
|
||||
if user.gender==2 || target.gender==2 || user.gender==target.gender ||
|
||||
target.hasActiveAbility?(:OBLIVIOUS)
|
||||
score -= 90
|
||||
elsif move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::SPATK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if target.stages[PBStats::SPATK]>0
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 30 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04F"
|
||||
if move.statusMove?
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPDEF,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 10 if user.turnCount==0
|
||||
score += 20 if target.stages[PBStats::SPDEF]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "050"
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
else
|
||||
avg = 0; anyChange = false
|
||||
PBStats.eachBattleStat do |s|
|
||||
next if target.stages[s]==0
|
||||
avg += target.stages[s]
|
||||
anyChange = true
|
||||
end
|
||||
if anyChange
|
||||
score += avg*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "051"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
stages = 0
|
||||
@battle.eachBattler do |b|
|
||||
totalStages = 0
|
||||
PBStats.eachBattleStat { |s| totalStages += b.stages[s] }
|
||||
if b.opposes?(user)
|
||||
stages += totalStages
|
||||
else
|
||||
stages -= totalStages
|
||||
end
|
||||
end
|
||||
score += stages*10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "052"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aatk = user.stages[PBStats::ATTACK]
|
||||
aspa = user.stages[PBStats::SPATK]
|
||||
oatk = target.stages[PBStats::ATTACK]
|
||||
ospa = target.stages[PBStats::SPATK]
|
||||
if aatk>=oatk && aspa>=ospa
|
||||
score -= 80
|
||||
else
|
||||
score += (oatk-aatk)*10
|
||||
score += (ospa-aspa)*10
|
||||
end
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "053"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
adef = user.stages[PBStats::DEFENSE]
|
||||
aspd = user.stages[PBStats::SPDEF]
|
||||
odef = target.stages[PBStats::DEFENSE]
|
||||
ospd = target.stages[PBStats::SPDEF]
|
||||
if adef>=odef && aspd>=ospd
|
||||
score -= 80
|
||||
else
|
||||
score += (odef-adef)*10
|
||||
score += (ospd-aspd)*10
|
||||
end
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "054"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
userStages = 0; targetStages = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
userStages += user.stages[s]
|
||||
targetStages += target.stages[s]
|
||||
end
|
||||
score += (targetStages-userStages)*10
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "055"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
equal = true
|
||||
PBStats.eachBattleStat do |s|
|
||||
stagediff = target.stages[s]-user.stages[s]
|
||||
score += stagediff*10
|
||||
equal = false if stagediff!=0
|
||||
end
|
||||
score -= 80 if equal
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "056"
|
||||
score -= 80 if user.pbOwnSide.effects[PBEffects::Mist]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "057"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aatk = pbRoughStat(user,PBStats::ATTACK,skill)
|
||||
adef = pbRoughStat(user,PBStats::DEFENSE,skill)
|
||||
if aatk==adef ||
|
||||
user.effects[PBEffects::PowerTrick] # No flip-flopping
|
||||
score -= 90
|
||||
elsif adef>aatk # Prefer a higher Attack
|
||||
score += 30
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "058"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aatk = pbRoughStat(user,PBStats::ATTACK,skill)
|
||||
aspatk = pbRoughStat(user,PBStats::SPATK,skill)
|
||||
oatk = pbRoughStat(target,PBStats::ATTACK,skill)
|
||||
ospatk = pbRoughStat(target,PBStats::SPATK,skill)
|
||||
if aatk<oatk && aspatk<ospatk
|
||||
score += 50
|
||||
elsif aatk+aspatk<oatk+ospatk
|
||||
score += 30
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "059"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
adef = pbRoughStat(user,PBStats::DEFENSE,skill)
|
||||
aspdef = pbRoughStat(user,PBStats::SPDEF,skill)
|
||||
odef = pbRoughStat(target,PBStats::DEFENSE,skill)
|
||||
ospdef = pbRoughStat(target,PBStats::SPDEF,skill)
|
||||
if adef<odef && aspdef<ospdef
|
||||
score += 50
|
||||
elsif adef+aspdef<odef+ospdef
|
||||
score += 30
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05A"
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif user.hp>=(user.hp+target.hp)/2
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05B"
|
||||
score -= 90 if user.pbOwnSide.effects[PBEffects::Tailwind]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "05C"
|
||||
moveBlacklist = [
|
||||
"002", # Struggle
|
||||
"014", # Chatter
|
||||
"05C", # Mimic
|
||||
"05D", # Sketch
|
||||
"0B6" # Metronome
|
||||
]
|
||||
lastMoveData = pbGetMoveData(target.lastRegularMoveUsed)
|
||||
if user.effects[PBEffects::Transform] ||
|
||||
target.lastRegularMoveUsed<=0 ||
|
||||
moveBlacklist.include?(lastMoveData[MOVE_FUNCTION_CODE]) ||
|
||||
isConst?(lastMoveData[MOVE_TYPE],PBTypes,:SHADOW)
|
||||
score -= 90
|
||||
end
|
||||
user.eachMove do |m|
|
||||
next if m.id!=target.lastRegularMoveUsed
|
||||
score -= 90
|
||||
break
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05D"
|
||||
moveBlacklist = [
|
||||
"002", # Struggle
|
||||
"014", # Chatter
|
||||
"05D" # Sketch
|
||||
]
|
||||
lastMoveData = pbGetMoveData(target.lastRegularMoveUsed)
|
||||
if user.effects[PBEffects::Transform] ||
|
||||
target.lastRegularMoveUsed<=0 ||
|
||||
moveBlacklist.include?(lastMoveData[MOVE_FUNCTION_CODE]) ||
|
||||
isConst?(lastMoveData[MOVE_TYPE],PBTypes,:SHADOW)
|
||||
score -= 90
|
||||
end
|
||||
user.eachMove do |m|
|
||||
next if m.id!=target.lastRegularMoveUsed
|
||||
score -= 90 # User already knows the move that will be Sketched
|
||||
break
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05E"
|
||||
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90
|
||||
else
|
||||
types = []
|
||||
user.eachMove do |m|
|
||||
next if m.id==@id
|
||||
next if PBTypes.isPseudoType?(m.type)
|
||||
next if user.pbHasType?(m.type)
|
||||
types.push(m.type) if !types.include?(m.type)
|
||||
end
|
||||
score -= 90 if types.length==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05F"
|
||||
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90
|
||||
elsif target.lastMoveUsed<=0 ||
|
||||
PBTypes.isPseudoType?(pbGetMoveData(target.lastMoveUsed,MOVE_TYPE))
|
||||
score -= 90
|
||||
else
|
||||
aType = -1
|
||||
target.eachMove do |m|
|
||||
next if m.id!=target.lastMoveUsed
|
||||
aType = m.pbCalcType(user)
|
||||
break
|
||||
end
|
||||
if aType<0
|
||||
score -= 90
|
||||
else
|
||||
types = []
|
||||
for i in 0..PBTypes.maxValue
|
||||
next if user.pbHasType?(i)
|
||||
types.push(i) if PBTypes.resistant?(aType,i)
|
||||
end
|
||||
score -= 90 if types.length==0
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "060"
|
||||
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
envtypes = [
|
||||
:NORMAL, # None
|
||||
:GRASS, # Grass
|
||||
:GRASS, # Tall grass
|
||||
:WATER, # Moving water
|
||||
:WATER, # Still water
|
||||
:WATER, # Underwater
|
||||
:ROCK, # Rock
|
||||
:ROCK, # Cave
|
||||
:GROUND # Sand
|
||||
]
|
||||
type = envtypes[@environment]
|
||||
score -= 90 if user.pbHasType?(type)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "061"
|
||||
if target.effects[PBEffects::Substitute]>0 ||
|
||||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90
|
||||
elsif target.pbHasType?(:WATER)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "062"
|
||||
if isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90
|
||||
elsif user.pbHasType?(target.type1) &&
|
||||
user.pbHasType?(target.type2) &&
|
||||
target.pbHasType?(user.type1) &&
|
||||
target.pbHasType?(user.type2)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "063"
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
if isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:SIMPLE) ||
|
||||
isConst?(target.ability,PBAbilities,:TRUANT)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "064"
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
if isConst?(target.ability,PBAbilities,:INSOMNIA) ||
|
||||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:TRUANT)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "065"
|
||||
score -= 40 # don't prefer this move
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if target.ability==0 || user.ability==target.ability ||
|
||||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:FLOWERGIFT) ||
|
||||
isConst?(target.ability,PBAbilities,:FORECAST) ||
|
||||
isConst?(target.ability,PBAbilities,:ILLUSION) ||
|
||||
isConst?(target.ability,PBAbilities,:IMPOSTER) ||
|
||||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:TRACE) ||
|
||||
isConst?(target.ability,PBAbilities,:WONDERGUARD) ||
|
||||
isConst?(target.ability,PBAbilities,:ZENMODE)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if isConst?(target.ability,PBAbilities,:TRUANT) &&
|
||||
user.opposes?(target)
|
||||
score -= 90
|
||||
elsif isConst?(target.ability,PBAbilities,:SLOWSTART) &&
|
||||
user.opposes?(target)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "066"
|
||||
score -= 40 # don't prefer this move
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
if user.ability==0 || user.ability==target.ability ||
|
||||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:TRUANT) ||
|
||||
isConst?(user.ability,PBAbilities,:FLOWERGIFT) ||
|
||||
isConst?(user.ability,PBAbilities,:FORECAST) ||
|
||||
isConst?(user.ability,PBAbilities,:ILLUSION) ||
|
||||
isConst?(user.ability,PBAbilities,:IMPOSTER) ||
|
||||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(user.ability,PBAbilities,:TRACE) ||
|
||||
isConst?(user.ability,PBAbilities,:ZENMODE)
|
||||
score -= 90
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if isConst?(user.ability,PBAbilities,:TRUANT) &&
|
||||
user.opposes?(target)
|
||||
score += 90
|
||||
elsif isConst?(user.ability,PBAbilities,:SLOWSTART) &&
|
||||
user.opposes?(target)
|
||||
score += 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "067"
|
||||
score -= 40 # don't prefer this move
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if (user.ability==0 && target.ability==0) ||
|
||||
user.ability==target.ability ||
|
||||
isConst?(user.ability,PBAbilities,:ILLUSION) ||
|
||||
isConst?(user.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(user.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(user.ability,PBAbilities,:WONDERGUARD) ||
|
||||
isConst?(target.ability,PBAbilities,:ILLUSION) ||
|
||||
isConst?(target.ability,PBAbilities,:MULTITYPE) ||
|
||||
isConst?(target.ability,PBAbilities,:RKSSYSTEM) ||
|
||||
isConst?(target.ability,PBAbilities,:WONDERGUARD)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if isConst?(target.ability,PBAbilities,:TRUANT) &&
|
||||
user.opposes?(target)
|
||||
score -= 90
|
||||
elsif isConst?(target.ability,PBAbilities,:SLOWSTART) &&
|
||||
user.opposes?(target)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "068"
|
||||
if target.effects[PBEffects::Substitute]>0 ||
|
||||
target.effects[PBEffects::GastroAcid]
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90 if isConst?(target.ability,PBAbilities,:MULTITYPE)
|
||||
score -= 90 if isConst?(target.ability,PBAbilities,:RKSSYSTEM)
|
||||
score -= 90 if isConst?(target.ability,PBAbilities,:SLOWSTART)
|
||||
score -= 90 if isConst?(target.ability,PBAbilities,:TRUANT)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "069"
|
||||
score -= 70
|
||||
#---------------------------------------------------------------------------
|
||||
when "06A"
|
||||
if target.hp<=20
|
||||
score += 80
|
||||
elsif target.level>=25
|
||||
score -= 60 # Not useful against high-level Pokemon
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "06B"
|
||||
score += 80 if target.hp<=40
|
||||
#---------------------------------------------------------------------------
|
||||
when "06C"
|
||||
score -= 50
|
||||
score += target.hp*100/target.totalhp
|
||||
#---------------------------------------------------------------------------
|
||||
when "06D"
|
||||
score += 80 if target.hp<=user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "06E"
|
||||
if user.hp>=target.hp
|
||||
score -= 90
|
||||
elsif user.hp<target.hp/2
|
||||
score += 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "06F"
|
||||
score += 30 if target.hp<=user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "070"
|
||||
score -= 90 if target.hasActiveAbility?(:STURDY)
|
||||
score -= 90 if target.level>user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "071"
|
||||
if target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
attack = pbRoughStat(user,PBStats::ATTACK,skill)
|
||||
spatk = pbRoughStat(user,PBStats::SPATK,skill)
|
||||
if attack*1.5<spatk
|
||||
score -= 60
|
||||
elsif skill>=PBTrainerAI.mediumSkill && target.lastMoveUsed>0
|
||||
moveData = pbGetMoveData(target.lastMoveUsed)
|
||||
if moveData[MOVE_BASE_DAMAGE]>0 &&
|
||||
(MOVE_CATEGORY_PER_MOVE && moveData[MOVE_CATEGORY]==0) ||
|
||||
(!MOVE_CATEGORY_PER_MOVE && PBTypes.isPhysicalType?(moveData[MOVE_TYPE]))
|
||||
score -= 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "072"
|
||||
if target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
attack = pbRoughStat(user,PBStats::ATTACK,skill)
|
||||
spatk = pbRoughStat(user,PBStats::SPATK,skill)
|
||||
if attack>spatk*1.5
|
||||
score -= 60
|
||||
elsif skill>=PBTrainerAI.mediumSkill && target.lastMoveUsed>0
|
||||
moveData = pbGetMoveData(target.lastMoveUsed)
|
||||
if moveData[MOVE_BASE_DAMAGE]>0 &&
|
||||
(MOVE_CATEGORY_PER_MOVE && moveData[MOVE_CATEGORY]==1) ||
|
||||
(!MOVE_CATEGORY_PER_MOVE && !PBTypes.isSpecialType?(moveData[MOVE_TYPE]))
|
||||
score -= 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "073"
|
||||
score -= 90 if target.effects[PBEffects::HyperBeam]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "074"
|
||||
target.eachAlly do |b|
|
||||
next if !b.near?(target)
|
||||
score += 10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "075"
|
||||
#---------------------------------------------------------------------------
|
||||
when "076"
|
||||
#---------------------------------------------------------------------------
|
||||
when "077"
|
||||
#---------------------------------------------------------------------------
|
||||
when "078"
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 30 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "079"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07C"
|
||||
score -= 20 if target.status==PBStatuses::PARALYSIS # Will cure status
|
||||
#---------------------------------------------------------------------------
|
||||
when "07D"
|
||||
score -= 20 if target.status==PBStatuses::SLEEP && # Will cure status
|
||||
target.statusCount>1
|
||||
#---------------------------------------------------------------------------
|
||||
when "07E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07F"
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,228 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __c__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
score = __c__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "080"
|
||||
#---------------------------------------------------------------------------
|
||||
when "081"
|
||||
attspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
oppspeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if oppspeed>attspeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "082"
|
||||
score += 20 if @battle.pbOpposingBattlerCount(user)>1
|
||||
#---------------------------------------------------------------------------
|
||||
when "083"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
user.eachAlly do |b|
|
||||
next if !b.pbHasMove?(move.id)
|
||||
score += 20
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "084"
|
||||
attspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
oppspeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if oppspeed>attspeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "085"
|
||||
#---------------------------------------------------------------------------
|
||||
when "086"
|
||||
#---------------------------------------------------------------------------
|
||||
when "087"
|
||||
#---------------------------------------------------------------------------
|
||||
when "088"
|
||||
#---------------------------------------------------------------------------
|
||||
when "089"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08C"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "090"
|
||||
#---------------------------------------------------------------------------
|
||||
when "091"
|
||||
#---------------------------------------------------------------------------
|
||||
when "092"
|
||||
#---------------------------------------------------------------------------
|
||||
when "093"
|
||||
score += 25 if user.effects[PBEffects::Rage]
|
||||
#---------------------------------------------------------------------------
|
||||
when "094"
|
||||
#---------------------------------------------------------------------------
|
||||
when "095"
|
||||
#---------------------------------------------------------------------------
|
||||
when "096"
|
||||
score -= 90 if !pbIsBerry?(user.item) || !user.itemActive?
|
||||
#---------------------------------------------------------------------------
|
||||
when "097"
|
||||
#---------------------------------------------------------------------------
|
||||
when "098"
|
||||
#---------------------------------------------------------------------------
|
||||
when "099"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09C"
|
||||
hasAlly = false
|
||||
user.eachAlly do |b|
|
||||
hasAlly = true
|
||||
score += 30
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "09D"
|
||||
score -= 90 if user.effects[PBEffects::MudSport]
|
||||
#---------------------------------------------------------------------------
|
||||
when "09E"
|
||||
score -= 90 if user.effects[PBEffects::WaterSport]
|
||||
#---------------------------------------------------------------------------
|
||||
when "09F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A1"
|
||||
score -= 90 if user.pbOwnSide.effects[PBEffects::LuckyChant]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A2"
|
||||
score -= 90 if user.pbOwnSide.effects[PBEffects::Reflect]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A3"
|
||||
score -= 90 if user.pbOwnSide.effects[PBEffects::LightScreen]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A4"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A5"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A6"
|
||||
score -= 90 if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90 if user.effects[PBEffects::LockOn]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A7"
|
||||
if target.effects[PBEffects::Foresight]
|
||||
score -= 90
|
||||
elsif target.pbHasType?(:GHOST)
|
||||
score += 70
|
||||
elsif target.stages[PBStats::EVASION]<=0
|
||||
score -= 60
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A8"
|
||||
if target.effects[PBEffects::MiracleEye]
|
||||
score -= 90
|
||||
elsif target.pbHasType?(:DARK)
|
||||
score += 70
|
||||
elsif target.stages[PBStats::EVASION]<=0
|
||||
score -= 60
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A9"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AA"
|
||||
if user.effects[PBEffects::ProtectRate]>1 ||
|
||||
target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if user.turnCount==0
|
||||
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AB"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AC"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AE"
|
||||
score -= 40
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 100 if target.lastRegularMoveUsed<=0 ||
|
||||
!pbGetMoveData(target.lastRegularMoveUsed,MOVE_FLAGS)[/e/] # Not copyable by Mirror Move
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AF"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B4"
|
||||
if user.asleep?
|
||||
score += 100 # Because it can only be used while asleep
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B5"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B6"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B7"
|
||||
score -= 90 if target.effects[PBEffects::Torment]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B8"
|
||||
score -= 90 if user.effects[PBEffects::Imprison]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B9"
|
||||
score -= 90 if target.effects[PBEffects::Disable]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BA"
|
||||
score -= 90 if target.effects[PBEffects::Taunt]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BB"
|
||||
score -= 90 if target.effects[PBEffects::HealBlock]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BC"
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if target.effects[PBEffects::Encore]>0
|
||||
score -= 90
|
||||
elsif aspeed>ospeed
|
||||
if target.lastMoveUsed<=0
|
||||
score -= 90
|
||||
else
|
||||
moveData = pbGetMoveData(target.lastRegularMoveUsed)
|
||||
if moveData[MOVE_CATEGORY]==2 && # Status move
|
||||
(moveData[MOVE_TARGET]==PBTargets::User ||
|
||||
moveData[MOVE_TARGET]==PBTargets::BothSides)
|
||||
score += 60
|
||||
elsif moveData[MOVE_CATEGORY]!=2 && # Damaging move
|
||||
moveData[MOVE_TARGET]==PBTargets::NearOther &&
|
||||
PBTypes.ineffective?(pbCalcTypeMod(moveData[MOVE_TYPE],target,user))
|
||||
score += 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BF"
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,375 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __d__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
score = __d__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C4"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C7"
|
||||
score += 20 if user.effects[PBEffects::FocusEnergy]>0
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 20 if !target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C9"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CA"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CB"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CC"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CE"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CF"
|
||||
score += 40 if target.effects[PBEffects::Trapping]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D0"
|
||||
score += 40 if target.effects[PBEffects::Trapping]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D4"
|
||||
if user.hp<=user.totalhp/4
|
||||
score -= 90
|
||||
elsif user.hp<=user.totalhp/2
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D5", "0D6"
|
||||
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D7"
|
||||
score -= 90 if @battle.positions[user.index].effects[PBEffects::Wish]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D8"
|
||||
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
case @battle.pbWeather
|
||||
when PBWeather::Sun, PBWeather::HarshSun
|
||||
score += 30
|
||||
when PBWeather::None
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D9"
|
||||
if user.hp==user.totalhp || !user.pbCanSleep?(user,false,nil,true)
|
||||
score -= 90
|
||||
else
|
||||
score += 70
|
||||
score -= user.hp*140/user.totalhp
|
||||
score += 30 if user.status!=0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DA"
|
||||
score -= 90 if user.effects[PBEffects::AquaRing]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DB"
|
||||
score -= 90 if user.effects[PBEffects::Ingrain]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DC"
|
||||
if target.effects[PBEffects::LeechSeed]>=0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill && target.pbHasType?(:GRASS)
|
||||
score -= 90
|
||||
else
|
||||
score += 60 if user.turnCount==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DD"
|
||||
if skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 70
|
||||
else
|
||||
score += 20 if user.hp<=user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DE"
|
||||
if !target.asleep?
|
||||
score -= 100
|
||||
elsif skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 70
|
||||
else
|
||||
score += 20 if user.hp<=user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DF"
|
||||
if user.opposes?(target)
|
||||
score -= 100
|
||||
else
|
||||
score += 20 if target.hp<target.totalhp/2 &&
|
||||
target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E0"
|
||||
reserves = @battle.pbAbleNonActiveCount(user.idxOwnSide)
|
||||
foes = @battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||
if @battle.pbCheckGlobalAbility(:DAMP)
|
||||
score -= 100
|
||||
elsif skill>=PBTrainerAI.mediumSkill && reserves==0 && foes>0
|
||||
score -= 100 # don't want to lose
|
||||
elsif skill>=PBTrainerAI.highSkill && reserves==0 && foes==0
|
||||
score += 80 # want to draw
|
||||
else
|
||||
score -= user.hp*100/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E2"
|
||||
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user) &&
|
||||
!target.pbCanLowerStatStage?(PBStats::SPATK,user)
|
||||
score -= 100
|
||||
elsif @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
|
||||
score -= 100
|
||||
else
|
||||
score += target.stages[PBStats::ATTACK]*10
|
||||
score += target.stages[PBStats::SPATK]*10
|
||||
score -= user.hp*100/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E3", "0E4"
|
||||
score -= 70
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E5"
|
||||
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
|
||||
score -= 90
|
||||
else
|
||||
score -= 90 if target.effects[PBEffects::PerishSong]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E6"
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
score += 30 if user.hp<=user.totalhp/10
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E7"
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
score += 30 if user.hp<=user.totalhp/10
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E8"
|
||||
score -= 25 if user.hp>user.totalhp/2
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90 if user.effects[PBEffects::ProtectRate]>1
|
||||
score -= 90 if target.effects[PBEffects::HyperBeam]>0
|
||||
else
|
||||
score -= user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E9"
|
||||
if target.hp==1
|
||||
score -= 90
|
||||
elsif target.hp<=target.totalhp/8
|
||||
score -= 60
|
||||
elsif target.hp<=target.totalhp/4
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EA"
|
||||
score -= 100 if @battle.trainerBattle?
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EB"
|
||||
if target.effects[PBEffects::Ingrain] ||
|
||||
(skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:SUCTIONCUPS))
|
||||
score -= 90
|
||||
else
|
||||
ch = 0
|
||||
@battle.pbParty(target.index).each_with_index do |pkmn,i|
|
||||
ch += 1 if @battle.pbCanSwitchLax?(target.index,i)
|
||||
end
|
||||
score -= 90 if ch==0
|
||||
end
|
||||
if score>20
|
||||
score += 50 if target.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 50 if target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 50 if target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EC"
|
||||
if !target.effects[PBEffects::Ingrain] &&
|
||||
!(skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:SUCTIONCUPS))
|
||||
score += 40 if target.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 40 if target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 40 if target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0ED"
|
||||
if !@battle.pbCanChooseNonActive?(user.index)
|
||||
score -= 80
|
||||
else
|
||||
score -= 40 if user.effects[PBEffects::Confusion]>0
|
||||
total = 0
|
||||
PBStats.eachBattleStat { |s| total += user.stages[s] }
|
||||
if total<=0 || user.turnCount==0
|
||||
score -= 60
|
||||
else
|
||||
score += total*10
|
||||
# special case: user has no damaging moves
|
||||
hasDamagingMove = false
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingMove = true
|
||||
break
|
||||
end
|
||||
score += 75 if !hasDamagingMove
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EE"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EF"
|
||||
score -= 90 if target.effects[PBEffects::MeanLook]>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F0"
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 20 if target.item!=0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F1"
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if user.item==0 && target.item!=0
|
||||
score += 40
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
else
|
||||
score -= 80
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F2"
|
||||
if user.item==0 && target.item==0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:STICKYHOLD)
|
||||
score -= 90
|
||||
elsif user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
|
||||
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
|
||||
score += 50
|
||||
elsif user.item==0 && target.item!=0
|
||||
score -= 30 if pbGetMoveData(user.lastMoveUsed,MOVE_FUNCTION_CODE)=="0F2" # Trick/Switcheroo
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F3"
|
||||
if user.item==0 || target.item!=0
|
||||
score -= 90
|
||||
else
|
||||
if user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
|
||||
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
|
||||
score += 50
|
||||
else
|
||||
score -= 80
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F4", "0F5"
|
||||
if target.effects[PBEffects::Substitute]==0
|
||||
if skill>=PBTrainerAI.highSkill && pbIsBerry?(target.item)
|
||||
score += 30
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F6"
|
||||
if user.recycleItem==0 || user.item!=0
|
||||
score -= 80
|
||||
elsif user.recycleItem!=0
|
||||
score += 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F7"
|
||||
if user.item==0 || !user.itemActive? ||
|
||||
user.unlosableItem?(user.item) || pbIsPokeBall?(user.item)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F8"
|
||||
score -= 90 if target.effects[PBEffects::Embargo]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F9"
|
||||
if @battle.field.effects[PBEffects::MagicRoom]>0
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if user.item==0 && target.item!=0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FA"
|
||||
score -= 25
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FB"
|
||||
score -= 30
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FC"
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FD"
|
||||
score -= 30
|
||||
if target.pbCanParalyze?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if aspeed<ospeed
|
||||
score += 30
|
||||
elsif aspeed>ospeed
|
||||
score -= 40
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FE"
|
||||
score -= 30
|
||||
if target.pbCanBurn?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FF"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Sun
|
||||
score -= 90
|
||||
else
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove? || !isConst?(m.type,PBTypes,:FIRE)
|
||||
score += 20
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,498 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __e__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
score = __e__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "100"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Rain
|
||||
score -= 90
|
||||
else
|
||||
user.eachMove do |m|
|
||||
next if !m.damagingMove? || !isConst?(m.type,PBTypes,:WATER)
|
||||
score += 20
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "101"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Sandstorm
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "102"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Hail
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "103"
|
||||
if user.pbOpposingSide.effects[PBEffects::Spikes]>=3
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 10*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||
score += [40,26,13][user.pbOpposingSide.effects[PBEffects::Spikes]]
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "104"
|
||||
if user.pbOpposingSide.effects[PBEffects::ToxicSpikes]>=2
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 8*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||
score += [26,13][user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "105"
|
||||
if user.pbOpposingSide.effects[PBEffects::StealthRock]
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 10*@battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "106"
|
||||
#---------------------------------------------------------------------------
|
||||
when "107"
|
||||
#---------------------------------------------------------------------------
|
||||
when "108"
|
||||
#---------------------------------------------------------------------------
|
||||
when "109"
|
||||
#---------------------------------------------------------------------------
|
||||
when "10A"
|
||||
score += 20 if user.pbOpposingSide.effects[PBEffects::AuroraVeil]>0
|
||||
score += 20 if user.pbOpposingSide.effects[PBEffects::Reflect]>0
|
||||
score += 20 if user.pbOpposingSide.effects[PBEffects::LightScreen]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "10B"
|
||||
score += 10*(user.stages[PBStats::ACCURACY]-target.stages[PBStats::EVASION])
|
||||
#---------------------------------------------------------------------------
|
||||
when "10C"
|
||||
if user.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif user.hp<=user.totalhp/4
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "10D"
|
||||
if user.pbHasType?(:GHOST)
|
||||
if target.effects[PBEffects::Curse]
|
||||
score -= 90
|
||||
elsif user.hp<=user.totalhp/2
|
||||
if @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
|
||||
score -= 90
|
||||
else
|
||||
score -= 50
|
||||
score -= 30 if @battle.switchStyle
|
||||
end
|
||||
end
|
||||
else
|
||||
avg = user.stages[PBStats::SPEED]*10
|
||||
avg -= user.stages[PBStats::ATTACK]*10
|
||||
avg -= user.stages[PBStats::DEFENSE]*10
|
||||
score += avg/3
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "10E"
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "10F"
|
||||
if target.effects[PBEffects::Nightmare] ||
|
||||
target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif !target.asleep?
|
||||
score -= 90
|
||||
else
|
||||
score -= 90 if target.statusCount<=1
|
||||
score += 50 if target.statusCount>3
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "110"
|
||||
score += 30 if user.effects[PBEffects::Trapping]>0
|
||||
score += 30 if user.effects[PBEffects::LeechSeed]>=0
|
||||
if @battle.pbAbleNonActiveCount(user.idxOwnSide)>0
|
||||
score += 80 if user.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 80 if user.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 80 if user.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "111"
|
||||
if @battle.positions[target.index].effects[PBEffects::FutureSightCounter]>0
|
||||
score -= 100
|
||||
elsif @battle.pbAbleNonActiveCount(user.idxOwnSide)==0
|
||||
# Future Sight tends to be wasteful if down to last Pokemon
|
||||
score -= 70
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "112"
|
||||
avg = 0
|
||||
avg -= user.stages[PBStats::DEFENSE]*10
|
||||
avg -= user.stages[PBStats::SPDEF]*10
|
||||
score += avg/2
|
||||
if user.effects[PBEffects::Stockpile]>=3
|
||||
score -= 80
|
||||
else
|
||||
# More preferable if user also has Spit Up/Swallow
|
||||
score += 20 if user.pbHasMoveFunction?("113","114") # Spit Up, Swallow
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "113"
|
||||
score -= 100 if user.effects[PBEffects::Stockpile]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "114"
|
||||
if user.effects[PBEffects::Stockpile]==0
|
||||
score -= 90
|
||||
elsif user.hp==user.totalhp
|
||||
score -= 90
|
||||
else
|
||||
mult = [0,25,50,100][user.effects[PBEffects::Stockpile]]
|
||||
score += mult
|
||||
score -= user.hp*mult*2/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "115"
|
||||
score += 50 if target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 35 if target.hp<=target.totalhp/2 # If target is weak, no
|
||||
score -= 70 if target.hp<=target.totalhp/4 # need to risk this move
|
||||
#---------------------------------------------------------------------------
|
||||
when "116"
|
||||
#---------------------------------------------------------------------------
|
||||
when "117"
|
||||
hasAlly = false
|
||||
user.eachAlly do |b|
|
||||
hasAlly = true
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "118"
|
||||
if @battle.field.effects[PBEffects::Gravity]>0
|
||||
score -= 90
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
score -= 30
|
||||
score -= 20 if user.effects[PBEffects::SkyDrop]>=0
|
||||
score -= 20 if user.effects[PBEffects::MagnetRise]>0
|
||||
score -= 20 if user.effects[PBEffects::Telekinesis]>0
|
||||
score -= 20 if user.pbHasType?(:FLYING)
|
||||
score -= 20 if user.hasActiveAbility?(:LEVITATE)
|
||||
score -= 20 if user.hasActiveItem?(:AIRBALLOON)
|
||||
score += 20 if target.effects[PBEffects::SkyDrop]>=0
|
||||
score += 20 if target.effects[PBEffects::MagnetRise]>0
|
||||
score += 20 if target.effects[PBEffects::Telekinesis]>0
|
||||
score += 20 if target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
|
||||
score += 20 if target.pbHasType?(:FLYING)
|
||||
score += 20 if target.hasActiveAbility?(:LEVITATE)
|
||||
score += 20 if target.hasActiveItem?(:AIRBALLOON)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "119"
|
||||
if user.effects[PBEffects::MagnetRise]>0 ||
|
||||
user.effects[PBEffects::Ingrain] ||
|
||||
user.effects[PBEffects::SmackDown]
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11A"
|
||||
if target.effects[PBEffects::Telekinesis]>0 ||
|
||||
target.effects[PBEffects::Ingrain] ||
|
||||
target.effects[PBEffects::SmackDown]
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11C"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score += 20 if target.effects[PBEffects::MagnetRise]>0
|
||||
score += 20 if target.effects[PBEffects::Telekinesis]>0
|
||||
score += 20 if target.inTwoTurnAttack?("0C9","0CC") # Fly, Bounce
|
||||
score += 20 if target.pbHasType?(:FLYING)
|
||||
score += 20 if target.hasActiveAbility?(:LEVITATE)
|
||||
score += 20 if target.hasActiveItem?(:AIRBALLOON)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "120"
|
||||
#---------------------------------------------------------------------------
|
||||
when "121"
|
||||
#---------------------------------------------------------------------------
|
||||
when "122"
|
||||
#---------------------------------------------------------------------------
|
||||
when "123"
|
||||
if !target.pbHasType?(user.type1) &&
|
||||
!target.pbHasType?(user.type2)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "124"
|
||||
#---------------------------------------------------------------------------
|
||||
when "125"
|
||||
#---------------------------------------------------------------------------
|
||||
when "126"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
#---------------------------------------------------------------------------
|
||||
when "127"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if target.pbCanParalyze?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if aspeed<ospeed
|
||||
score += 30
|
||||
elsif aspeed>ospeed
|
||||
score -= 40
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "128"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if target.pbCanBurn?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "129"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if target.pbCanFreeze?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12A"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if target.pbCanConfuse?(user,false)
|
||||
score += 30
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12B"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if !target.pbCanLowerStatStage?(PBStats::DEFENSE,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12C"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if !target.pbCanLowerStatStage?(PBStats::EVASION,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::EVASION]*15
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12D"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
#---------------------------------------------------------------------------
|
||||
when "12E"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score += 20 if target.hp>=target.totalhp/2
|
||||
score -= 20 if user.hp<user.hp/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "12F"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score -= 110 if target.effects[PBEffects::MeanLook]>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "130"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "131"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::ShadowSky
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "132"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
target.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
score += 30
|
||||
score -= 90 if user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
user.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
user.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
user.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
else
|
||||
score -= 110
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "133", "134"
|
||||
score -= 95
|
||||
score = 0 if skill>=PBTrainerAI.highSkill
|
||||
#---------------------------------------------------------------------------
|
||||
when "135"
|
||||
if target.pbCanFreeze?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score -= 20 if target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "136"
|
||||
score += 20 if user.stages[PBStats::DEFENSE]<0
|
||||
#---------------------------------------------------------------------------
|
||||
when "137"
|
||||
hasEffect = user.statStageAtMax?(PBStats::DEFENSE) &&
|
||||
user.statStageAtMax?(PBStats::SPDEF)
|
||||
user.eachAlly do |b|
|
||||
next if b.statStageAtMax?(PBStats::DEFENSE) && b.statStageAtMax?(PBStats::SPDEF)
|
||||
hasEffect = true
|
||||
score -= b.stages[PBStats::DEFENSE]*10
|
||||
score -= b.stages[PBStats::SPDEF]*10
|
||||
end
|
||||
if hasEffect
|
||||
score -= user.stages[PBStats::DEFENSE]*10
|
||||
score -= user.stages[PBStats::SPDEF]*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "138"
|
||||
if target.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score -= target.stages[PBStats::SPDEF]*10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "139"
|
||||
if !target.pbCanLowerStatStage?(PBStats::ATTACK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += target.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13A"
|
||||
avg = target.stages[PBStats::ATTACK]*10
|
||||
avg += target.stages[PBStats::SPATK]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "13B"
|
||||
if !user.isSpecies?(:HOOPA) || user.form!=1
|
||||
score -= 100
|
||||
else
|
||||
score += 20 if target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13C"
|
||||
score += 20 if target.stages[PBStats::SPATK]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "13D"
|
||||
if !target.pbCanLowerStatStage?(PBStats::SPATK,user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if user.turnCount==0
|
||||
score += target.stages[PBStats::SPATK]*20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13E"
|
||||
count = 0
|
||||
@battle.eachBattler do |b|
|
||||
if b.pbHasType?(:GRASS) && !b.airborne? &&
|
||||
(!b.statStageAtMax?(PBStats::ATTACK) || !b.statStageAtMax?(PBStats::SPATK))
|
||||
count += 1
|
||||
if user.opposes?(b)
|
||||
score -= 20
|
||||
else
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::SPATK]*10
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "13F"
|
||||
count = 0
|
||||
@battle.eachBattler do |b|
|
||||
if b.pbHasType?(:GRASS) && !b.statStageAtMax?(PBStats::DEFENSE)
|
||||
count += 1
|
||||
if user.opposes?(b)
|
||||
score -= 20
|
||||
else
|
||||
score -= user.stages[PBStats::DEFENSE]*10
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,409 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __f__pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill=100)
|
||||
score = __f__pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "140"
|
||||
count=0
|
||||
@battle.eachBattler do |b|
|
||||
if b.poisoned? &&
|
||||
(!b.statStageAtMin?(PBStats::ATTACK) ||
|
||||
!b.statStageAtMin?(PBStats::SPATK) ||
|
||||
!b.statStageAtMin?(PBStats::SPEED))
|
||||
count += 1
|
||||
if user.opposes?(b)
|
||||
score += user.stages[PBStats::ATTACK]*10
|
||||
score += user.stages[PBStats::SPATK]*10
|
||||
score += user.stages[PBStats::SPEED]*10
|
||||
else
|
||||
score -= 20
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "141"
|
||||
if target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
else
|
||||
numpos = 0; numneg = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
numpos += target.stages[s] if target.stages[s]>0
|
||||
numneg += target.stages[s] if target.stages[s]<0
|
||||
end
|
||||
if numpos!=0 || numneg!=0
|
||||
score += (numpos-numneg)*10
|
||||
else
|
||||
score -= 95
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "142"
|
||||
score -= 90 if target.pbHasType?(:GHOST)
|
||||
#---------------------------------------------------------------------------
|
||||
when "143"
|
||||
score -= 90 if target.pbHasType?(:GRASS)
|
||||
#---------------------------------------------------------------------------
|
||||
when "144"
|
||||
#---------------------------------------------------------------------------
|
||||
when "145"
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score -= 90 if aspeed>ospeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "146"
|
||||
#---------------------------------------------------------------------------
|
||||
when "147"
|
||||
#---------------------------------------------------------------------------
|
||||
when "148"
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if aspeed>ospeed
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if target.pbHasMoveType?(:FIRE)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "149"
|
||||
if user.turnCount==0
|
||||
score += 30
|
||||
else
|
||||
score -= 90 # Because it will fail here
|
||||
score = 0 if skill>=PBTrainerAI.bestSkill
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "14B", "14C"
|
||||
if user.effects[PBEffects::ProtectRate]>1 ||
|
||||
target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if user.turnCount==0
|
||||
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "14E"
|
||||
if user.statStageAtMax?(PBStats::SPATK) &&
|
||||
user.statStageAtMax?(PBStats::SPDEF) &&
|
||||
user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score -= user.stages[PBStats::SPATK]*10 # Only *10 isntead of *20
|
||||
score -= user.stages[PBStats::SPDEF]*10 # because two-turn attack
|
||||
score -= user.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasSpecialAttack = false
|
||||
user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecialAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecialAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14F"
|
||||
if skill>=PBTrainerAI.highSkill && target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 80
|
||||
else
|
||||
score += 40 if user.hp<=user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "150"
|
||||
score += 20 if !user.statStageAtMax?(PBStats::ATTACK) && target.hp<=target.totalhp/4
|
||||
#---------------------------------------------------------------------------
|
||||
when "151"
|
||||
avg = target.stages[PBStats::ATTACK]*10
|
||||
avg += target.stages[PBStats::SPATK]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "152"
|
||||
#---------------------------------------------------------------------------
|
||||
when "153"
|
||||
score -= 95 if target.pbOwnSide.effects[PBEffects::StickyWeb]
|
||||
#---------------------------------------------------------------------------
|
||||
when "154"
|
||||
#---------------------------------------------------------------------------
|
||||
when "155"
|
||||
#---------------------------------------------------------------------------
|
||||
when "156"
|
||||
#---------------------------------------------------------------------------
|
||||
when "157"
|
||||
score -= 90
|
||||
#---------------------------------------------------------------------------
|
||||
when "158"
|
||||
score -= 90 if !user.belched?
|
||||
#---------------------------------------------------------------------------
|
||||
when "159"
|
||||
if !target.pbCanPoison?(user,false) && !target.pbCanLowerStatStage?(PBStats::SPEED,user)
|
||||
score -= 90
|
||||
else
|
||||
if target.pbCanPoison?(user,false)
|
||||
score += 30
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score += 30 if target.hp<=target.totalhp/4
|
||||
score += 50 if target.hp<=target.totalhp/8
|
||||
score -= 40 if target.effects[PBEffects::Yawn]>0
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
score += 10 if pbRoughStat(target,PBStats::DEFENSE,skill)>100
|
||||
score += 10 if pbRoughStat(target,PBStats::SPDEF,skill)>100
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
|
||||
end
|
||||
end
|
||||
if target.pbCanLowerStatStage?(PBStats::SPEED,user)
|
||||
score += target.stages[PBStats::SPEED]*10
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
ospeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15A"
|
||||
if target.opposes?(user)
|
||||
score -= 40 if target.status==PBStatuses::BURN
|
||||
else
|
||||
score += 40 if target.status==PBStatuses::BURN
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15B"
|
||||
if target.status==PBStatuses::NONE
|
||||
score -= 90
|
||||
elsif user.hp==user.totalhp && target.opposes?(user)
|
||||
score -= 90
|
||||
else
|
||||
score += (user.totalhp-user.hp)*50/user.totalhp
|
||||
score -= 30 if target.opposes?(user)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15C"
|
||||
hasEffect = user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
user.statStageAtMax?(PBStats::SPATK)
|
||||
user.eachAlly do |b|
|
||||
next if b.statStageAtMax?(PBStats::ATTACK) && b.statStageAtMax?(PBStats::SPATK)
|
||||
hasEffect = true
|
||||
score -= b.stages[PBStats::ATTACK]*10
|
||||
score -= b.stages[PBStats::SPATK]*10
|
||||
end
|
||||
if hasEffect
|
||||
score -= user.stages[PBStats::ATTACK]*10
|
||||
score -= user.stages[PBStats::SPATK]*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15D"
|
||||
numStages = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
next if target.stages[s]<=0
|
||||
numStages += target.stages[s]
|
||||
end
|
||||
score += numStages*20
|
||||
#---------------------------------------------------------------------------
|
||||
when "15E"
|
||||
if user.effects[PBEffects::LaserFocus]>0
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15F"
|
||||
score += user.stages[PBStats::DEFENSE]*10
|
||||
#---------------------------------------------------------------------------
|
||||
when "160"
|
||||
if target.statStageAtMin?(PBStats::ATTACK)
|
||||
score -= 90
|
||||
else
|
||||
if target.pbCanLowerStatStage?(PBStats::ATTACK,user)
|
||||
score += target.stages[PBStats::ATTACK]*20
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
score += (user.totalhp-user.hp)*50/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "161"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if user.speed>target.speed
|
||||
score += 50
|
||||
else
|
||||
score -= 70
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "162"
|
||||
score -= 90 if !user.pbHasType?(:FIRE)
|
||||
#---------------------------------------------------------------------------
|
||||
when "163"
|
||||
#---------------------------------------------------------------------------
|
||||
when "164"
|
||||
#---------------------------------------------------------------------------
|
||||
when "165"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
userSpeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
targetSpeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
if userSpeed<targetSpeed
|
||||
score += 30
|
||||
end
|
||||
else
|
||||
score += 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "166"
|
||||
#---------------------------------------------------------------------------
|
||||
when "167"
|
||||
if user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 || @battle.pbWeather!=PBWeather::Hail
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "168"
|
||||
if user.effects[PBEffects::ProtectRate]>1 ||
|
||||
target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score -= user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if user.turnCount==0
|
||||
score += 30 if target.effects[PBEffects::TwoTurnAttack]>0
|
||||
score += 20 # Because of possible poisoning
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "169"
|
||||
#---------------------------------------------------------------------------
|
||||
when "16A"
|
||||
hasAlly = false
|
||||
target.eachAlly do |b|
|
||||
hasAlly = true
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "16B"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if target.lastRegularMoveUsed<0 ||
|
||||
!target.pbHasMove?(target.lastRegularMoveUsed) ||
|
||||
target.usingMultiTurnAttack?
|
||||
score -= 90
|
||||
else
|
||||
# Without lots of code here to determine good/bad moves and relative
|
||||
# speeds, using this move is likely to just be a waste of a turn
|
||||
score -= 50
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16C"
|
||||
if target.effects[PBEffects::ThroatChop]==0 && skill>=PBTrainerAI.highSkill
|
||||
hasSoundMove = false
|
||||
user.eachMove do |m|
|
||||
next if !m.soundMove?
|
||||
hasSoundMove = true
|
||||
break
|
||||
end
|
||||
score += 40 if hasSoundMove
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16D"
|
||||
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
score += 30 if @battle.pbWeather==PBWeather::Sandstorm
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16E"
|
||||
if user.hp==user.totalhp || (skill>=PBTrainerAI.mediumSkill && !user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= user.hp*100/user.totalhp
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
score += 30 if @battle.field.terrain==PBBattleTerrains::Grassy
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16F"
|
||||
if !target.opposes?(user)
|
||||
if target.hp==target.totalhp || (skill>=PBTrainerAI.mediumSkill && !target.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= target.hp*100/target.totalhp
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "170"
|
||||
reserves = @battle.pbAbleNonActiveCount(user.idxOwnSide)
|
||||
foes = @battle.pbAbleNonActiveCount(user.idxOpposingSide)
|
||||
if @battle.pbCheckGlobalAbility(:DAMP)
|
||||
score -= 100
|
||||
elsif skill>=PBTrainerAI.mediumSkill && reserves==0 && foes>0
|
||||
score -= 100 # don't want to lose
|
||||
elsif skill>=PBTrainerAI.highSkill && reserves==0 && foes==0
|
||||
score += 80 # want to draw
|
||||
else
|
||||
score -= (user.total.hp-user.hp)*75/user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "171"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
hasPhysicalAttack = false
|
||||
target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score -= 80 if !hasPhysicalAttack
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "172"
|
||||
score += 20 # Because of possible burning
|
||||
#---------------------------------------------------------------------------
|
||||
when "173"
|
||||
#---------------------------------------------------------------------------
|
||||
when "174"
|
||||
score -= 90 if user.turnCount>0 || user.lastRoundMoved>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "175"
|
||||
score += 30 if target.effects[PBEffects::Minimize]
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,661 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
def pbTargetsMultiple?(move,user)
|
||||
numTargets = 0
|
||||
case move.pbTarget(user)
|
||||
when PBTargets::AllNearFoes
|
||||
@battle.eachOtherSideBattler(user) { |b| numTargets += 1 if b.near?(user) }
|
||||
return numTargets>1
|
||||
when PBTargets::AllNearOthers
|
||||
@battle.eachBattler { |b| numTargets += 1 if b.near?(user) }
|
||||
return numTargets>1
|
||||
when PBTargets::UserAndAllies
|
||||
@battle.eachSameSideBattler(user) { |_b| numTargets += 1 }
|
||||
return numTargets>1
|
||||
when PBTargets::AllFoes
|
||||
@battle.eachOtherSideBattler(user) { |_b| numTargets += 1 }
|
||||
return numTargets>1
|
||||
when PBTargets::AllBattlers
|
||||
@battle.eachBattler { |_b| numTargets += 1 }
|
||||
return numTargets>1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Move's type effectiveness
|
||||
#=============================================================================
|
||||
def pbCalcTypeModSingle(moveType,defType,user,target)
|
||||
ret = PBTypes.getEffectiveness(moveType,defType)
|
||||
# Ring Target
|
||||
if target.hasActiveItem?(:RINGTARGET)
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Foresight
|
||||
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :GHOST &&
|
||||
PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Miracle Eye
|
||||
if target.effects[PBEffects::MiracleEye]
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :DARK &&
|
||||
PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Delta Stream's weather
|
||||
if @battle.pbWeather==PBWeather::StrongWinds
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING &&
|
||||
PBTypes.superEffective?(moveType,defType)
|
||||
end
|
||||
# Grounded Flying-type Pokémon become susceptible to Ground moves
|
||||
if !target.airborne?
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING && moveType == :GROUND
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def pbCalcTypeMod(moveType,user,target)
|
||||
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType<0
|
||||
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType == :GROUND &&
|
||||
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
|
||||
# Determine types
|
||||
tTypes = target.pbTypes(true)
|
||||
# Get effectivenesses
|
||||
typeMods = [PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
|
||||
tTypes.each_with_index do |type,i|
|
||||
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
|
||||
end
|
||||
# Multiply all effectivenesses together
|
||||
ret = 1
|
||||
typeMods.each { |m| ret *= m }
|
||||
return ret
|
||||
end
|
||||
|
||||
# For switching. Determines the effectiveness of a potential switch-in against
|
||||
# an opposing battler.
|
||||
def pbCalcTypeModPokemon(battlerThis,_battlerOther)
|
||||
mod1 = PBTypes.getCombinedEffectiveness(battlerThis.type1,target.type1,target.type2)
|
||||
mod2 = PBTypeEffectiveness::NORMAL_EFFECTIVE
|
||||
if battlerThis.type1!=battlerThis.type2
|
||||
mod2 = PBTypes.getCombinedEffectiveness(battlerThis.type2,target.type1,target.type2)
|
||||
end
|
||||
return mod1*mod2 # Normal effectiveness is 64 here
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Immunity to a move because of the target's ability, item or other effects
|
||||
#=============================================================================
|
||||
def pbCheckMoveImmunity(score,move,user,target,skill)
|
||||
type = pbRoughType(move,user,skill)
|
||||
typeMod = pbCalcTypeMod(type,user,target)
|
||||
# Type effectiveness
|
||||
return true if PBTypeEffectiveness.ineffective?(typeMod) || score<=0
|
||||
# Immunity due to ability/item/other effects
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
case move.type
|
||||
when :GROUND
|
||||
return true if target.airborne? && !move.hitsFlyingTargets?
|
||||
when :FIRE
|
||||
return true if target.hasActiveAbility?(:FLASHFIRE)
|
||||
when :WATER
|
||||
return true if target.hasActiveAbility?([:DRYSKIN,:STORMDRAIN,:WATERABSORB])
|
||||
when :GRASS
|
||||
return true if target.hasActiveAbility?(:SAPSIPPER)
|
||||
when :ELECTRIC
|
||||
return true if target.hasActiveAbility?([:LIGHTNINGROD,:MOTORDRIVE,:VOLTABSORB])
|
||||
end
|
||||
return true if PBTypeEffectiveness.notVeryEffective?(typeMod) &&
|
||||
target.hasActiveAbility?(:WONDERGUARD)
|
||||
return true if move.damagingMove? && user.index!=target.index && !target.opposes?(user) &&
|
||||
target.hasActiveAbility?(:TELEPATHY)
|
||||
return true if move.canMagicCoat? && target.hasActiveAbility?(:MAGICBOUNCE) &&
|
||||
target.opposes?(user)
|
||||
return true if move.soundMove? && target.hasActiveAbility?(:SOUNDPROOF)
|
||||
return true if move.bombMove? && target.hasActiveAbility?(:BULLETPROOF)
|
||||
if move.powderMove?
|
||||
return true if target.pbHasType?(:GRASS)
|
||||
return true if target.hasActiveAbility?(:OVERCOAT)
|
||||
return true if target.hasActiveItem?(:SAFETYGOGGLES)
|
||||
end
|
||||
return true if target.effects[PBEffects::Substitute]>0 && move.statusMove? &&
|
||||
!move.ignoresSubstitute?(user) && user.index!=target.index
|
||||
return true if NEWEST_BATTLE_MECHANICS && user.hasActiveAbility?(:PRANKSTER) &&
|
||||
target.pbHasType?(:DARK) && target.opposes?(user)
|
||||
return true if move.priority>0 && @battle.field.terrain==PBBattleTerrains::Psychic &&
|
||||
target.affectedByTerrain? && target.opposes?(user)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get approximate properties for a battler
|
||||
#=============================================================================
|
||||
def pbRoughType(move,user,skill)
|
||||
ret = move.type
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
ret = move.pbCalcType(user)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def pbRoughStat(battler,stat,skill)
|
||||
return battler.pbSpeed if skill>=PBTrainerAI.highSkill && stat==PBStats::SPEED
|
||||
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
|
||||
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
|
||||
stage = battler.stages[stat]+6
|
||||
value = 0
|
||||
case stat
|
||||
when PBStats::ATTACK then value = battler.attack
|
||||
when PBStats::DEFENSE then value = battler.defense
|
||||
when PBStats::SPATK then value = battler.spatk
|
||||
when PBStats::SPDEF then value = battler.spdef
|
||||
when PBStats::SPEED then value = battler.speed
|
||||
end
|
||||
return (value.to_f*stageMul[stage]/stageDiv[stage]).floor
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get a better move's base damage value
|
||||
#=============================================================================
|
||||
def pbMoveBaseDamage(move,user,target,skill)
|
||||
baseDmg = move.baseDamage
|
||||
baseDmg = 60 if baseDmg==1
|
||||
return baseDmg if skill<PBTrainerAI.mediumSkill
|
||||
# Covers all function codes which have their own def pbBaseDamage
|
||||
case move.function
|
||||
when "010" # Stomp
|
||||
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
|
||||
# Sonic Boom, Dragon Rage, Super Fang, Night Shade, Endeavor
|
||||
when "06A", "06B", "06C", "06D", "06E"
|
||||
baseDmg = move.pbFixedDamage(user,target)
|
||||
when "06F" # Psywave
|
||||
baseDmg = user.level
|
||||
when "070" # OHKO
|
||||
baseDmg = 200
|
||||
when "071", "072", "073" # Counter, Mirror Coat, Metal Burst
|
||||
baseDmg = 60
|
||||
when "075", "076", "0D0", "12D" # Surf, Earthquake, Whirlpool, Shadow Storm
|
||||
baseDmg = move.pbModifyDamage(baseDmg,user,target)
|
||||
# Gust, Twister, Venoshock, Smelling Salts, Wake-Up Slap, Facade, Hex, Brine,
|
||||
# Retaliate, Weather Ball, Return, Frustration, Eruption, Crush Grip,
|
||||
# Stored Power, Punishment, Hidden Power, Fury Cutter, Echoed Voice,
|
||||
# Trump Card, Flail, Electro Ball, Low Kick, Fling, Spit Up
|
||||
when "077", "078", "07B", "07C", "07D", "07E", "07F", "080", "085", "087",
|
||||
"089", "08A", "08B", "08C", "08E", "08F", "090", "091", "092", "097",
|
||||
"098", "099", "09A", "0F7", "113"
|
||||
baseDmg = move.pbBaseDamage(baseDmg,user,target)
|
||||
when "086" # Acrobatics
|
||||
baseDmg *= 2 if !user.item || user.hasActiveItem?(:FLYINGGEM)
|
||||
when "08D" # Gyro Ball
|
||||
targetSpeed = pbRoughStat(target,PBStats::SPEED,skill)
|
||||
userSpeed = pbRoughStat(user,PBStats::SPEED,skill)
|
||||
baseDmg = [[(25*targetSpeed/userSpeed).floor,150].min,1].max
|
||||
when "094" # Present
|
||||
baseDmg = 50
|
||||
when "095" # Magnitude
|
||||
baseDmg = 71
|
||||
baseDmg *= 2 if target.inTwoTurnAttack?("0CA") # Dig
|
||||
when "096" # Natural Gift
|
||||
baseDmg = move.pbNaturalGiftBaseDamage(user.item_id)
|
||||
when "09B" # Heavy Slam
|
||||
baseDmg = move.pbBaseDamage(baseDmg,user,target)
|
||||
baseDmg *= 2 if NEWEST_BATTLE_MECHANICS && skill>=PBTrainerAI.mediumSkill &&
|
||||
target.effects[PBEffects::Minimize]
|
||||
when "0A0", "0BD", "0BE" # Frost Breath, Double Kick, Twineedle
|
||||
baseDmg *= 2
|
||||
when "0BF" # Triple Kick
|
||||
baseDmg *= 6 # Hits do x1, x2, x3 baseDmg in turn, for x6 in total
|
||||
when "0C0" # Fury Attack
|
||||
if user.hasActiveAbility?(:SKILLLINK)
|
||||
baseDmg *= 5
|
||||
else
|
||||
baseDmg = (baseDmg*19/6).floor # Average damage dealt
|
||||
end
|
||||
when "0C1" # Beat Up
|
||||
mult = 0
|
||||
@battle.eachInTeamFromBattlerIndex(user.index) do |pkmn,_i|
|
||||
mult += 1 if pkmn && pkmn.able? && pkmn.status==PBStatuses::NONE
|
||||
end
|
||||
baseDmg *= mult
|
||||
when "0C4" # Solar Beam
|
||||
baseDmg = move.pbBaseDamageMultiplier(baseDmg,user,target)
|
||||
when "0D3" # Rollout
|
||||
baseDmg *= 2 if user.effects[PBEffects::DefenseCurl]
|
||||
when "0D4" # Bide
|
||||
baseDmg = 40
|
||||
when "0E1" # Final Gambit
|
||||
baseDmg = user.hp
|
||||
when "144" # Flying Press
|
||||
if GameData::Type.exists?(:FLYING)
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
targetTypes = target.pbTypes(true)
|
||||
mult = PBTypes.getCombinedEffectiveness(:FLYING,
|
||||
targetTypes[0],targetTypes[1],targetTypes[2])
|
||||
baseDmg = (baseDmg.to_f*mult/PBTypeEffectiveness::NORMAL_EFFECTIVE).round
|
||||
else
|
||||
mult = PBTypes.getCombinedEffectiveness(:FLYING,
|
||||
target.type1,target.type2,target.effects[PBEffects::Type3])
|
||||
baseDmg = (baseDmg.to_f*mult/PBTypeEffectiveness::NORMAL_EFFECTIVE).round
|
||||
end
|
||||
end
|
||||
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
|
||||
when "166" # Stomping Tantrum
|
||||
baseDmg *= 2 if user.lastRoundMoveFailed
|
||||
when "175" # Double Iron Bash
|
||||
baseDmg *= 2
|
||||
baseDmg *= 2 if skill>=PBTrainerAI.mediumSkill && target.effects[PBEffects::Minimize]
|
||||
end
|
||||
return baseDmg
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Damage calculation
|
||||
#=============================================================================
|
||||
def pbRoughDamage(move,user,target,skill,baseDmg)
|
||||
# Fixed damage moves
|
||||
return baseDmg if move.is_a?(PokeBattle_FixedDamageMove)
|
||||
# Get the move's type
|
||||
type = pbRoughType(move,user,skill)
|
||||
##### Calculate user's attack stat #####
|
||||
atk = pbRoughStat(user,PBStats::ATTACK,skill)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,PBStats::ATTACK,skill)
|
||||
elsif move.specialMove?(type)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,PBStats::SPATK,skill)
|
||||
else
|
||||
atk = pbRoughStat(user,PBStats::SPATK,skill)
|
||||
end
|
||||
end
|
||||
##### Calculate target's defense stat #####
|
||||
defense = pbRoughStat(target,PBStats::DEFENSE,skill)
|
||||
if move.specialMove?(type) && move.function!="122" # Psyshock
|
||||
defense = pbRoughStat(target,PBStats::SPDEF,skill)
|
||||
end
|
||||
##### Calculate all multiplier effects #####
|
||||
multipliers = [1.0, 1.0, 1.0, 1.0]
|
||||
# Ability effects that alter damage
|
||||
moldBreaker = false
|
||||
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
|
||||
moldBreaker = true
|
||||
end
|
||||
if skill>=PBTrainerAI.mediumSkill && user.abilityActive?
|
||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||
# round.
|
||||
abilityBlacklist = [:ANALYTIC,:SNIPER,:TINTEDLENS,:AERILATE,:PIXILATE,:REFRIGERATE]
|
||||
canCheck = true
|
||||
abilityBlacklist.each do |m|
|
||||
next if move.id != m
|
||||
canCheck = false
|
||||
break
|
||||
end
|
||||
if canCheck
|
||||
BattleHandlers.triggerDamageCalcUserAbility(user.ability,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.mediumSkill && !moldBreaker
|
||||
user.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerDamageCalcUserAllyAbility(b.ability,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill && !moldBreaker && target.abilityActive?
|
||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||
# round.
|
||||
abilityBlacklist = [:FILTER,:SOLIDROCK]
|
||||
canCheck = true
|
||||
abilityBlacklist.each do |m|
|
||||
next if move.id != m
|
||||
canCheck = false
|
||||
break
|
||||
end
|
||||
if canCheck
|
||||
BattleHandlers.triggerDamageCalcTargetAbility(target.ability,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill && !moldBreaker
|
||||
target.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerDamageCalcTargetAllyAbility(b.ability,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
# Item effects that alter damage
|
||||
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
|
||||
# round.
|
||||
if skill>=PBTrainerAI.mediumSkill && user.itemActive?
|
||||
# NOTE: These items aren't suitable for checking at the start of the
|
||||
# round.
|
||||
itemBlacklist = [:EXPERTBELT,:LIFEORB]
|
||||
if !itemBlacklist.include?(user.item_id)
|
||||
BattleHandlers.triggerDamageCalcUserItem(user.item,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill && target.itemActive?
|
||||
# NOTE: Type-weakening berries aren't suitable for checking at the start
|
||||
# of the round.
|
||||
if !target.item.is_berry?
|
||||
BattleHandlers.triggerDamageCalcTargetItem(target.item,
|
||||
user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
# Global abilities
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
|
||||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
|
||||
if @battle.pbCheckGlobalAbility(:AURABREAK)
|
||||
multipliers[BASE_DMG_MULT] *= 2/3
|
||||
else
|
||||
multipliers[BASE_DMG_MULT] *= 4/3
|
||||
end
|
||||
end
|
||||
end
|
||||
# Parental Bond
|
||||
if skill>=PBTrainerAI.mediumSkill && user.hasActiveAbility?(:PARENTALBOND)
|
||||
multipliers[BASE_DMG_MULT] *= 1.25
|
||||
end
|
||||
# Me First
|
||||
# TODO
|
||||
# Helping Hand - n/a
|
||||
# Charge
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
|
||||
multipliers[BASE_DMG_MULT] *= 2
|
||||
end
|
||||
end
|
||||
# Mud Sport and Water Sport
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if type == :ELECTRIC
|
||||
@battle.eachBattler do |b|
|
||||
next if !b.effects[PBEffects::MudSport]
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
break
|
||||
end
|
||||
if @battle.field.effects[PBEffects::MudSportField]>0
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
end
|
||||
end
|
||||
if type == :FIRE
|
||||
@battle.eachBattler do |b|
|
||||
next if !b.effects[PBEffects::WaterSport]
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
break
|
||||
end
|
||||
if @battle.field.effects[PBEffects::WaterSportField]>0
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
end
|
||||
end
|
||||
end
|
||||
# Terrain moves
|
||||
if user.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
|
||||
case @battle.field.terrain
|
||||
when PBBattleTerrains::Electric
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
|
||||
when PBBattleTerrains::Grassy
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
|
||||
when PBBattleTerrains::Psychic
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
|
||||
end
|
||||
end
|
||||
if target.affectedByTerrain? && skill>=PBTrainerAI.mediumSkill
|
||||
if @battle.field.terrain==PBBattleTerrains::Misty && type == :DRAGON
|
||||
multipliers[BASE_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
# Badge multipliers
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if @battle.internalBattle
|
||||
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
|
||||
# won't control the player's Pokémon.
|
||||
if target.pbOwnedByPlayer?
|
||||
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
|
||||
multipliers[DEF_MULT] *= 1.1
|
||||
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
|
||||
multipliers[DEF_MULT] *= 1.1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Multi-targeting attacks
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if pbTargetsMultiple?(move,user)
|
||||
multipliers[FINAL_DMG_MULT] *= 0.75
|
||||
end
|
||||
end
|
||||
# Weather
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
case @battle.pbWeather
|
||||
when PBWeather::Sun, PBWeather::HarshSun
|
||||
if type == :FIRE
|
||||
multipliers[FINAL_DMG_MULT] *= 1.5
|
||||
elsif type == :WATER
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
when PBWeather::Rain, PBWeather::HeavyRain
|
||||
if type == :FIRE
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
elsif type == :WATER
|
||||
multipliers[FINAL_DMG_MULT] *= 1.5
|
||||
end
|
||||
when PBWeather::Sandstorm
|
||||
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
|
||||
multipliers[DEF_MULT] *= 1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
# Critical hits - n/a
|
||||
# Random variance - n/a
|
||||
# STAB
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if type && user.pbHasType?(type)
|
||||
if user.hasActiveAbility?(:ADAPTABILITY)
|
||||
multipliers[FINAL_DMG_MULT] *= 2
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] *= 1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
# Type effectiveness
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
typemod = pbCalcTypeMod(type,user,target)
|
||||
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
|
||||
end
|
||||
# Burn
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if user.status==PBStatuses::BURN && move.physicalMove?(type) &&
|
||||
!user.hasActiveAbility?(:GUTS) &&
|
||||
!(NEWEST_BATTLE_MECHANICS && move.function=="07E") # Facade
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
# Aurora Veil, Reflect, Light Screen
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if !move.ignoresReflect? && !user.hasActiveAbility?(:INFILTRATOR)
|
||||
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2/3.0
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2/3.0
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2/3.0
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Minimize
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(2)
|
||||
multipliers[FINAL_DMG_MULT] *= 2
|
||||
end
|
||||
end
|
||||
# Move-specific base damage modifiers
|
||||
# TODO
|
||||
# Move-specific final damage modifiers
|
||||
# TODO
|
||||
##### Main damage calculation #####
|
||||
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
|
||||
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
|
||||
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
|
||||
damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
|
||||
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
|
||||
# "AI-specific calculations below"
|
||||
# Increased critical hit rates
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
c = 0
|
||||
# Ability effects that alter critical hit rate
|
||||
if c>=0 && user.abilityActive?
|
||||
c = BattleHandlers.triggerCriticalCalcUserAbility(user.ability,user,target,c)
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if c>=0 && !moldBreaker && target.abilityActive?
|
||||
c = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability,user,target,c)
|
||||
end
|
||||
end
|
||||
# Item effects that alter critical hit rate
|
||||
if c>=0 && user.itemActive?
|
||||
c = BattleHandlers.triggerCriticalCalcUserItem(user.item,user,target,c)
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if c>=0 && target.itemActive?
|
||||
c = BattleHandlers.triggerCriticalCalcTargetItem(target.item,user,target,c)
|
||||
end
|
||||
end
|
||||
# Other efffects
|
||||
c = -1 if target.pbOwnSide.effects[PBEffects::LuckyChant]>0
|
||||
if c>=0
|
||||
c += 1 if move.highCriticalRate?
|
||||
c += user.effects[PBEffects::FocusEnergy]
|
||||
c += 1 if user.inHyperMode? && move.type == :SHADOW
|
||||
end
|
||||
if c>=0
|
||||
c = 4 if c>4
|
||||
damage += damage*0.1*c
|
||||
end
|
||||
end
|
||||
return damage.floor
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Accuracy calculation
|
||||
#=============================================================================
|
||||
def pbRoughAccuracy(move,user,target,skill)
|
||||
# "Always hit" effects and "always hit" accuracy
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
return 125 if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(1)
|
||||
return 125 if target.effects[PBEffects::Telekinesis]>0
|
||||
end
|
||||
baseAcc = move.accuracy
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
baseAcc = move.pbBaseAccuracy(user,target)
|
||||
end
|
||||
return 125 if baseAcc==0 && skill>=PBTrainerAI.mediumSkill
|
||||
# Get the move's type
|
||||
type = pbRoughType(move,user,skill)
|
||||
# Calculate all modifier effects
|
||||
modifiers = []
|
||||
modifiers[BASE_ACC] = baseAcc
|
||||
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
|
||||
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
|
||||
modifiers[ACC_MULT] = 1.0
|
||||
modifiers[EVA_MULT] = 1.0
|
||||
pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
|
||||
# Check if move can't miss
|
||||
return 125 if modifiers[BASE_ACC]==0
|
||||
# Calculation
|
||||
accStage = [[modifiers[ACC_STAGE],-6].max,6].min + 6
|
||||
evaStage = [[modifiers[EVA_STAGE],-6].max,6].min + 6
|
||||
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
|
||||
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
|
||||
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
|
||||
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
|
||||
accuracy = (accuracy * modifiers[ACC_MULT]).round
|
||||
evasion = (evasion * modifiers[EVA_MULT]).round
|
||||
evasion = 1 if evasion<1
|
||||
return modifiers[BASE_ACC] * accuracy / evasion
|
||||
end
|
||||
|
||||
def pbCalcAccuracyModifiers(user,target,modifiers,move,type,skill)
|
||||
moldBreaker = false
|
||||
if skill>=PBTrainerAI.highSkill && target.hasMoldBreaker?
|
||||
moldBreaker = true
|
||||
end
|
||||
# Ability effects that alter accuracy calculation
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if user.abilityActive?
|
||||
BattleHandlers.triggerAccuracyCalcUserAbility(user.ability,
|
||||
modifiers,user,target,move,type)
|
||||
end
|
||||
user.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerAccuracyCalcUserAllyAbility(b.ability,
|
||||
modifiers,user,target,move,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if target.abilityActive? && !moldBreaker
|
||||
BattleHandlers.triggerAccuracyCalcTargetAbility(target.ability,
|
||||
modifiers,user,target,move,type)
|
||||
end
|
||||
end
|
||||
# Item effects that alter accuracy calculation
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if user.itemActive?
|
||||
BattleHandlers.triggerAccuracyCalcUserItem(user.item,
|
||||
modifiers,user,target,move,type)
|
||||
end
|
||||
end
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
if target.itemActive?
|
||||
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
|
||||
modifiers,user,target,move,type)
|
||||
end
|
||||
end
|
||||
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if @battle.field.effects[PBEffects::Gravity]>0
|
||||
modifiers[ACC_MULT] *= 5/3.0
|
||||
end
|
||||
if user.effects[PBEffects::MicleBerry]
|
||||
modifiers[ACC_MULT] *= 1.2
|
||||
end
|
||||
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
|
||||
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE]>0
|
||||
end
|
||||
# "AI-specific calculations below"
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
modifiers[EVA_STAGE] = 0 if move.function=="0A9" # Chip Away
|
||||
modifiers[BASE_ACC] = 0 if ["0A5","139","13A","13B","13C", # "Always hit"
|
||||
"147"].include?(move.function)
|
||||
modifiers[BASE_ACC] = 0 if user.effects[PBEffects::LockOn]>0 &&
|
||||
user.effects[PBEffects::LockOnPos]==target.index
|
||||
end
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if move.function=="006" # Toxic
|
||||
modifiers[BASE_ACC] = 0 if NEWEST_BATTLE_MECHANICS && move.statusMove? &&
|
||||
user.pbHasType?(:POISON)
|
||||
end
|
||||
if move.function=="070" # OHKO moves
|
||||
modifiers[BASE_ACC] = move.accuracy+user.level-target.level
|
||||
modifiers[ACC_MULT] = 0 if target.level>user.level
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
modifiers[ACC_MULT] = 0 if target.hasActiveAbility?(:STURDY)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,108 +0,0 @@
|
||||
class PBStuff
|
||||
#Standardized lists of moves with similar purposes/characteristics
|
||||
#(mostly just "stuff that gets called together")
|
||||
UNFREEZEMOVE = [PBMoves::FLAMEWHEEL,PBMoves::SACREDFIRE,PBMoves::FLAREBLITZ,
|
||||
PBMoves::FUSIONFLARE,PBMoves::SCALD,PBMoves::STEAMERUPTION,PBMoves::BURNUP]
|
||||
SWITCHOUTMOVE = [PBMoves::ROAR,PBMoves::WHIRLWIND,PBMoves::CIRCLETHROW,
|
||||
PBMoves::DRAGONTAIL,PBMoves::YAWN,PBMoves::PERISHSONG]
|
||||
SETUPMOVE = [PBMoves::SWORDSDANCE,PBMoves::DRAGONDANCE,PBMoves::CALMMIND,
|
||||
PBMoves::WORKUP,PBMoves::NASTYPLOT,PBMoves::TAILGLOW,PBMoves::BELLYDRUM,
|
||||
PBMoves::BULKUP,PBMoves::COIL,PBMoves::CURSE,PBMoves::GROWTH,
|
||||
PBMoves::HONECLAWS,PBMoves::QUIVERDANCE,PBMoves::SHELLSMASH]
|
||||
PROTECTMOVE = [PBMoves::PROTECT,PBMoves::DETECT,PBMoves::KINGSSHIELD,
|
||||
PBMoves::SPIKYSHIELD,PBMoves::BANEFULBUNKER]
|
||||
PROTECTIGNORINGMOVE = [PBMoves::FEINT,PBMoves::HYPERSPACEHOLE,
|
||||
PBMoves::HYPERSPACEFURY,PBMoves::SHADOWFORCE,PBMoves::PHANTOMFORCE]
|
||||
SCREENBREAKERMOVE = [PBMoves::DEFOG,PBMoves::BRICKBREAK,PBMoves::PSYCHICFANGS]
|
||||
CONTRARYBAITMOVE = [PBMoves::SUPERPOWER,PBMoves::OVERHEAT,PBMoves::DRACOMETEOR,
|
||||
PBMoves::LEAFSTORM,PBMoves::FLEURCANNON,PBMoves::PSYCHOBOOST]
|
||||
TWOTURNAIRMOVE = [PBMoves::BOUNCE,PBMoves::FLY,PBMoves::SKYDROP]
|
||||
PIVOTMOVE = [PBMoves::UTURN,PBMoves::VOLTSWITCH,PBMoves::PARTINGSHOT]
|
||||
DANCEMOVE = [PBMoves::QUIVERDANCE,PBMoves::DRAGONDANCE,PBMoves::FIERYDANCE,
|
||||
PBMoves::FEATHERDANCE,PBMoves::PETALDANCE,PBMoves::SWORDSDANCE,
|
||||
PBMoves::TEETERDANCE,PBMoves::LUNARDANCE,PBMoves::REVELATIONDANCE]
|
||||
BULLETMOVE = [PBMoves::ACIDSPRAY,PBMoves::AURASPHERE,PBMoves::BARRAGE,
|
||||
PBMoves::BULLETSEED,PBMoves::EGGBOMB,PBMoves::ELECTROBALL,PBMoves::ENERGYBALL,
|
||||
PBMoves::FOCUSBLAST,PBMoves::GYROBALL,PBMoves::ICEBALL,PBMoves::MAGNETBOMB,
|
||||
PBMoves::MISTBALL,PBMoves::MUDBOMB,PBMoves::OCTAZOOKA,PBMoves::ROCKWRECKER,
|
||||
PBMoves::SEARINGSHOT,PBMoves::SEEDBOMB,PBMoves::SHADOWBALL,PBMoves::SLUDGEBOMB,
|
||||
PBMoves::WEATHERBALL,PBMoves::ZAPCANNON,PBMoves::BEAKBLAST]
|
||||
|
||||
BURNMOVE = [PBMoves::WILLOWISP,PBMoves::SACREDFIRE,PBMoves::INFERNO]
|
||||
PARAMOVE = [PBMoves::THUNDERWAVE,PBMoves::STUNSPORE,PBMoves::GLARE,
|
||||
PBMoves::NUZZLE,PBMoves::ZAPCANNON]
|
||||
SLEEPMOVE = [PBMoves::SPORE,PBMoves::SLEEPPOWDER,PBMoves::HYPNOSIS,PBMoves::DARKVOID,
|
||||
PBMoves::GRASSWHISTLE,PBMoves::LOVELYKISS,PBMoves::SING]
|
||||
POISONMOVE = [PBMoves::TOXIC,PBMoves::POISONPOWDER,PBMoves::POISONGAS,PBMoves::TOXICTHREAD]
|
||||
CONFUMOVE = [PBMoves::CONFUSERAY,PBMoves::SUPERSONIC,PBMoves::FLATTER,PBMoves::SWAGGER,
|
||||
PBMoves::SWEETKISS,PBMoves::TEETERDANCE,PBMoves::CHATTER,PBMoves::DYNAMICPUNCH]
|
||||
|
||||
HEALFUNCTIONS = [0xD5,0xD6,0xD7,0xD8,0xD9,0xDD,0xDE,0xDF,0xE3,0xE4,0x114,0x139,0x158,0x162,0x169,0x16C,0x172]
|
||||
|
||||
#massive arrays of stuff that no one wants to see
|
||||
NATURALGIFTDAMAGE={
|
||||
100 => [:WATMELBERRY,:DURINBERRY,:BELUEBERRY,:LIECHIBERRY,:GANLONBERRY,:SALACBERRY,
|
||||
:PETAYABERRY,:APICOTBERRY,:LANSATBERRY,:STARFBERRY,:ENIGMABERRY,:MICLEBERRY,
|
||||
:CUSTAPBERRY,:JABOCABERRY,:ROWAPBERRY],
|
||||
90 => [:BLUKBERRY,:NANABBERRY,:WEPEARBERRY,:PINAPBERRY,:POMEGBERRY,:KELPSYBERRY,
|
||||
:QUALOTBERRY,:HONDEWBERRY,:GREPABERRY,:TAMATOBERRY,:CORNNBERRY,:MAGOSTBERRY,
|
||||
:RABUTABERRY,:NOMELBERRY,:SPELONBERRY,:PAMTREBERRY],
|
||||
80 => [:CHERIBERRY,:CHESTOBERRY,:PECHABERRY,:RAWSTBERRY,:ASPEARBERRY,:LEPPABERRY,
|
||||
:ORANBERRY,:PERSIMBERRY,:LUMBERRY,:SITRUSBERRY,:FIGYBERRY,:WIKIBERRY,
|
||||
:MAGOBERRY,:AGUAVBERRY,:IAPAPABERRY,:RAZZBERRY,:OCCABERRY,:PASSHOBERRY,
|
||||
:WACANBERRY,:RINDOBERRY,:YACHEBERRY,:CHOPLEBERRY,:KEBIABERRY,:SHUCABERRY,
|
||||
:COBABERRY,:PAYAPABERRY,:TANGABERRY,:CHARTIBERRY,:KASIBBERRY,:HABANBERRY,
|
||||
:COLBURBERRY,:BABIRIBERRY,:CHILANBERRY]}
|
||||
FLINGDAMAGE={
|
||||
300 => [:MEMEONADE],
|
||||
130 => [:IRONBALL],
|
||||
100 => [:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HARDSTONE,:HELIXFOSSIL,
|
||||
:OLDAMBER,:PLUMEFOSSIL,:RAREBONE,:ROOTFOSSIL,:SKULLFOSSIL],
|
||||
90 => [:DEEPSEATOOTH,:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
|
||||
:GRIPCLAW,:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
|
||||
:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,:THICKCLUB,:TOXICPLATE,
|
||||
:ZAPPLATE],
|
||||
80 => [:DAWNSTONE,:DUSKSTONE,:ELECTIRIZER,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
|
||||
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SHINYSTONE,:STICKYBARB,:ASSAULTVEST],
|
||||
70 => [:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:DRAGONFANG,:POISONBARB,:POWERANKLET,
|
||||
:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,:POWERWEIGHT,:SHOCKDRIVE],
|
||||
60 => [:ADAMANTORB,:DAMPROCK,:HEATROCK,:LUSTROUSORB,:MACHOBRACE,:ROCKYHELMET,
|
||||
:STICK,:AMPLIFIELDROCK,:ADRENALINEORB],
|
||||
50 => [:DUBIOUSDISC,:SHARPBEAK],
|
||||
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH,:PROTECTIVEPADS],
|
||||
30 => [:ABILITYURGE,:ABSORBBULB,:AMULETCOIN,:ANTIDOTE,:AWAKENING,:BALMMUSHROOM,
|
||||
:BERRYJUICE,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:BINDINGBAND,:BLACKBELT,
|
||||
:BLACKFLUTE,:BLACKGLASSES,:BLACKSLUDGE,:BLUEFLUTE,:BLUESHARD,:BURNHEAL,
|
||||
:CALCIUM,:CARBOS,:CASTELIACONE,:CELLBATTERY,:CHARCOAL,:CLEANSETAG,
|
||||
:COMETSHARD,:DAMPMULCH,:DEEPSEASCALE,:DIREHIT,:DIREHIT2,:DIREHIT3,
|
||||
:DRAGONSCALE,:EJECTBUTTON,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ESCAPEROPE,
|
||||
:ETHER,:EVERSTONE,:EXPSHARE,:FIRESTONE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,
|
||||
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:GOOEYMULCH,:GREENSHARD,:GROWTHMULCH,
|
||||
:GUARDSPEC,:HEALPOWDER,:HEARTSCALE,:HONEY,:HPUP,:HYPERPOTION,:ICEHEAL,
|
||||
:IRON,:ITEMDROP,:ITEMURGE,:KINGSROCK,:LAVACOOKIE,:LEAFSTONE,:LEMONADE,
|
||||
:LIFEORB,:LIGHTBALL,:LIGHTCLAY,:LUCKYEGG,:MAGNET,:MAXELIXIR,:MAXETHER,
|
||||
:MAXPOTION,:MAXREPEL,:MAXREVIVE,:METALCOAT,:METRONOME,:MIRACLESEED,
|
||||
:MOOMOOMILK,:MOONSTONE,:MYSTICWATER,:NEVERMELTICE,:NUGGET,:OLDGATEAU,
|
||||
:PARLYZHEAL,:PEARL,:PEARLSTRING,:POKEDOLL,:POKETOY,:POTION,:PPMAX,:PPUP,
|
||||
:PRISMSCALE,:PROTEIN,:RAGECANDYBAR,:RARECANDY,:RAZORFANG,:REDFLUTE,
|
||||
:REDSHARD,:RELICBAND,:RELICCOPPER,:RELICCROWN,:RELICGOLD,:RELICSILVER,
|
||||
:RELICSTATUE,:RELICVASE,:REPEL,:RESETURGE,:REVIVALHERB,:REVIVE,:SACREDASH,
|
||||
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SODAPOP,:SOULDEW,
|
||||
:SPELLTAG,:STABLEMULCH,:STARDUST,:STARPIECE,:SUNSTONE,:SUPERPOTION,
|
||||
:SUPERREPEL,:SWEETHEART,:THUNDERSTONE,:TINYMUSHROOM,:TOXICORB,
|
||||
:TWISTEDSPOON,:UPGRADE,:WATERSTONE,:WHITEFLUTE,:XACCURACY,:XACCURACY2,
|
||||
:XACCURACY3,:XACCURACY6,:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,:XDEFEND,
|
||||
:XDEFEND2,:XDEFEND3,:XDEFEND6,:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,:XSPECIAL,
|
||||
:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
|
||||
:YELLOWFLUTE,:YELLOWSHARD,:ZINC,:BIGMALASADA,:ICESTONE],
|
||||
20 => [:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
|
||||
:RESISTWING,:SWIFTWING],
|
||||
10 => [:AIRBALLOON,:BIGROOT,:BLUESCARF,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
|
||||
:CHOICESPECS,:DESTINYKNOT,:EXPERTBELT,:FOCUSBAND,:FOCUSSASH,:FULLINCENSE,
|
||||
:GREENSCARF,:LAGGINGTAIL,:LAXINCENSE,:LEFTOVERS,:LUCKINCENSE,:MENTALHERB,
|
||||
:METALPOWDER,:MUSCLEBAND,:ODDINCENSE,:PINKSCARF,:POWERHERB,:PUREINCENSE,
|
||||
:QUICKPOWDER,:REAPERCLOTH,:REDCARD,:REDSCARF,:RINGTARGET,:ROCKINCENSE,
|
||||
:ROSEINCENSE,:SEAINCENSE,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
|
||||
:SOFTSAND,:SOOTHEBELL,:WAVEINCENSE,:WHITEHERB,:WIDELENS,:WISEGLASSES,
|
||||
:YELLOWSCARF,:ZOOMLENS,:BLUEMIC,:VANILLAIC,:STRAWBIC,:CHOCOLATEIC]}
|
||||
end
|
||||
@@ -1,154 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
# Legacy method that should stop being used.
|
||||
def pbGetOwner(battlerIndex)
|
||||
if opposes?(battlerIndex)
|
||||
if @opponent.is_a?(Array)
|
||||
return (battlerIndex==1) ? @opponent[0] : @opponent[1]
|
||||
else
|
||||
return @opponent
|
||||
end
|
||||
else
|
||||
if @player.is_a?(Array)
|
||||
return (battlerIndex==0) ? @player[0] : @player[1]
|
||||
else
|
||||
return @player
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Reborn method (the difference is that each element in "choices" is an array
|
||||
# in Essentials but just a number in Reborn)
|
||||
def pbStdDev(choices)
|
||||
sum = 0
|
||||
n = 0
|
||||
choices.each do |c|
|
||||
sum += c
|
||||
n += 1
|
||||
end
|
||||
return 0 if n<2
|
||||
mean = sum.to_f/n.to_f
|
||||
varianceTimesN = 0
|
||||
for i in 0...choices.length
|
||||
next if choices[i]<=0
|
||||
deviation = choices[i].to_f-mean
|
||||
varianceTimesN += deviation*deviation
|
||||
end
|
||||
# Using population standard deviation
|
||||
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
|
||||
return Math.sqrt(varianceTimesN/n)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Choose an action.
|
||||
##############################################################################
|
||||
def pbDefaultChooseEnemyCommand(idxBattler)
|
||||
if !@battle.pbCanShowFightMenu?(idxBattler)
|
||||
return if pbEnemyShouldUseItem?(idxBattler)
|
||||
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
|
||||
return if pbShouldSwitch?(idxBattler)
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbAutoChooseMove(idxBattler)
|
||||
return
|
||||
end
|
||||
pbBuildMoveScores(idxBattler) # Grab the array of scores/targets before doing anything else
|
||||
return if pbShouldSwitch?(idxBattler)
|
||||
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
|
||||
return if pbEnemyShouldUseItem?(idxBattler)
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbRegisterUltraBurst(idxBattler) if pbEnemyShouldUltraBurst?(idxBattler)
|
||||
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
|
||||
if pbEnemyShouldZMove?(idxBattler)
|
||||
return pbChooseEnemyZMove(idxBattler)
|
||||
end
|
||||
pbChooseMoves(idxBattler)
|
||||
end
|
||||
|
||||
def pbChooseEnemyZMove(index) #Put specific cases for trainers using status Z-Moves
|
||||
chosenmove=false
|
||||
chosenindex=-1
|
||||
attacker = @battlers[index]
|
||||
opponent=attacker.pbOppositeOpposing
|
||||
otheropp=opponent.pbPartner
|
||||
skill=pbGetOwner(attacker.index).skill || 0
|
||||
for i in 0..3
|
||||
move=@battlers[index].moves[i]
|
||||
if @battlers[index].pbCompatibleZMoveFromMove?(move)
|
||||
if move.id == (PBMoves::CONVERSION) || move.id == (PBMoves::SPLASH)
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,i,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
return
|
||||
end
|
||||
if !chosenmove
|
||||
chosenindex = i
|
||||
chosenmove=move
|
||||
else
|
||||
if move.basedamage>chosenmove.basedamage
|
||||
chosenindex=i
|
||||
chosenmove=move
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#oppeff1 = chosenmove.pbTypeModifier(chosenmove.type,attacker,opponent)
|
||||
oppeff1 = pbTypeModNoMessages(chosenmove.type,attacker,opponent,chosenmove,skill)
|
||||
#oppeff2 = chosenmove.pbTypeModifier(chosenmove.type,attacker,otheropp)
|
||||
oppeff2 = pbTypeModNoMessages(chosenmove.type,attacker,otheropp,chosenmove,skill)
|
||||
oppeff1 = 0 if opponent.hp<(opponent.totalhp/2.0).round
|
||||
oppeff1 = 0 if (opponent.effects[PBEffects::Substitute]>0 || opponent.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
|
||||
oppeff2 = 0 if otheropp.hp<(otheropp.totalhp/2.0).round
|
||||
oppeff2 = 0 if (otheropp.effects[PBEffects::Substitute]>0 || otheropp.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
|
||||
oppmult=0
|
||||
for i in 1..7 #iterates through all the stats
|
||||
oppmult+=opponent.stages[i] if opponent.stages[i]>0
|
||||
end
|
||||
othermult=0
|
||||
for i in 1..7
|
||||
othermult+=otheropp.stages[i] if otheropp.stages[i]>0
|
||||
end
|
||||
if (oppeff1<4) && ((oppeff2<4) || otheropp.hp==0)
|
||||
pbChooseMoves(index)
|
||||
elsif oppeff1>oppeff2
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
elsif oppeff1<oppeff2
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
elsif oppeff1==oppeff2
|
||||
if oppmult > othermult
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
elsif oppmult < othermult
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
else
|
||||
if otheropp.hp > opponent.hp
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
else
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should Ultra Burst their Pokémon.
|
||||
#=============================================================================
|
||||
def pbEnemyShouldUltraBurst?(idxBattler)
|
||||
battler = @battlers[idxBattler]
|
||||
if pbCanUltraBurst?(idxBattler) # Simple "always should if possible"
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Ultra Burst")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -1,495 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
################################################################################
|
||||
# Decide whether the opponent should use an item on the Pokémon.
|
||||
################################################################################
|
||||
def pbEnemyShouldUseItem?(index)
|
||||
item=pbEnemyItemToUse(index)
|
||||
if item>0 && @battlers[index].effects[PBEffects::Embargo]==0
|
||||
pbRegisterItem(index,item,nil)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def pbEnemyItemAlreadyUsed?(index,item,items)
|
||||
if @choices[1][0]==3 && @choices[1][1]==item
|
||||
qty=0
|
||||
for i in items
|
||||
qty+=1 if i==item
|
||||
end
|
||||
return true if qty<=1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def pbEnemyItemToUse(index)
|
||||
return 0 if !@opponent
|
||||
return 0 if !@internalbattle
|
||||
items=pbGetOwnerItems(index)
|
||||
return 0 if !items
|
||||
skill=pbGetOwner(index).skill || 0
|
||||
battler=@battlers[index]
|
||||
party = pbParty(index)
|
||||
opponent1 = battler.pbOppositeOpposing
|
||||
opponent2 = opponent1.pbPartner
|
||||
currentroles = pbGetMonRole(battler,opponent1,skill)
|
||||
return 0 if battler.isFainted?
|
||||
highscore = 0
|
||||
movecount = -1
|
||||
maxplaypri = -1
|
||||
partynumber = 0
|
||||
aimem = getAIMemory(skill,opponent1.pokemonIndex)
|
||||
for i in party
|
||||
next if i.nil?
|
||||
next if i.hp == 0
|
||||
partynumber+=1
|
||||
end
|
||||
itemnumber = 0
|
||||
for i in items
|
||||
next if pbEnemyItemAlreadyUsed?(index,i,items)
|
||||
itemnumber+=1
|
||||
end
|
||||
#highest score
|
||||
for i in battler.moves
|
||||
scorearray = 0
|
||||
scorearray = @scores[i] if @scores[i]
|
||||
if scorearray>100 && i.priority>maxplaypri
|
||||
maxplaypri = i.priority
|
||||
end
|
||||
end
|
||||
highscore = @scores.max
|
||||
highdamage = -1
|
||||
maxopppri = -1
|
||||
pridam = -1
|
||||
bestid = -1
|
||||
#expected damage
|
||||
#if battler.pbSpeed<pbRoughStat(opponent1,PBStats::SPEED,skill)
|
||||
if aimem.length > 0
|
||||
for i in aimem
|
||||
tempdam = pbRoughDamage(i,opponent1,battler,skill,i.basedamage)
|
||||
if tempdam>highdamage
|
||||
highdamage = tempdam
|
||||
bestid = i.id
|
||||
end
|
||||
if i.priority > maxopppri
|
||||
maxopppri = i.priority
|
||||
pridam = tempdam
|
||||
end
|
||||
end
|
||||
end
|
||||
highratio = -1
|
||||
#expected damage percentage
|
||||
if battler.hp!=0
|
||||
highratio = highdamage*(1.0/battler.hp)
|
||||
end
|
||||
scorearray = []
|
||||
arraycount = -1
|
||||
PBDebug.log(sprintf("Beginning AI Item use check.")) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
for i in items
|
||||
arraycount+=1
|
||||
scorearray.push(0)
|
||||
itemscore=100
|
||||
ishpitem = false
|
||||
isstatusitem = false
|
||||
next if pbEnemyItemAlreadyUsed?(index,i,items)
|
||||
if (i== PBItems::POTION) ||
|
||||
(i== PBItems::ULTRAPOTION) ||
|
||||
(i== PBItems::SUPERPOTION) ||
|
||||
(i== PBItems::HYPERPOTION) ||
|
||||
(i== PBItems::MAXPOTION) ||
|
||||
(i== PBItems::FULLRESTORE) ||
|
||||
(i== PBItems::FRESHWATER) ||
|
||||
(i== PBItems::SODAPOP) ||
|
||||
(i== PBItems::LEMONADE) ||
|
||||
(i== PBItems::MOOMOOMILK) ||
|
||||
(i== PBItems::MEMEONADE) ||
|
||||
(i== PBItems::STRAWBIC) ||
|
||||
(i== PBItems::CHOCOLATEIC) ||
|
||||
(i== PBItems::BLUEMIC)
|
||||
ishpitem=true
|
||||
end
|
||||
if (i== PBItems::FULLRESTORE) ||
|
||||
(i== PBItems::FULLHEAL) ||
|
||||
(i== PBItems::RAGECANDYBAR) ||
|
||||
(i== PBItems::LAVACOOKIE) ||
|
||||
(i== PBItems::OLDGATEAU) ||
|
||||
(i== PBItems::CASTELIACONE) ||
|
||||
(i== PBItems::LUMIOSEGALETTE) ||
|
||||
(i== PBItems::BIGMALASADA)
|
||||
isstatusitem=true
|
||||
end
|
||||
if ishpitem
|
||||
PBDebug.log(sprintf("This is a HP-healing item.")) if $INTERNAL
|
||||
restoreamount=0
|
||||
if (i== PBItems::POTION)
|
||||
restoreamount=20
|
||||
elsif (i== PBItems::ULTRAPOTION)
|
||||
restoreamount=200
|
||||
elsif (i== PBItems::SUPERPOTION)
|
||||
restoreamount=60
|
||||
elsif (i== PBItems::HYPERPOTION)
|
||||
restoreamount=120
|
||||
elsif (i== PBItems::MAXPOTION) || (i== PBItems::FULLRESTORE)
|
||||
restoreamount=battler.totalhp
|
||||
elsif (i== PBItems::FRESHWATER)
|
||||
restoreamount=30
|
||||
elsif (i== PBItems::SODAPOP)
|
||||
restoreamount=50
|
||||
elsif (i== PBItems::LEMONADE)
|
||||
restoreamount=70
|
||||
elsif (i== PBItems::MOOMOOMILK)
|
||||
restoreamount=110
|
||||
elsif (i== PBItems::MEMEONADE)
|
||||
restoreamount=103
|
||||
elsif (i== PBItems::STRAWBIC)
|
||||
restoreamount=90
|
||||
elsif (i== PBItems::CHOCOLATEIC)
|
||||
restoreamount=70
|
||||
elsif (i== PBItems::BLUEMIC)
|
||||
restoreamount=200
|
||||
end
|
||||
resratio=restoreamount*(1.0/battler.totalhp)
|
||||
itemscore*= (2 - (2*(battler.hp*(1.0/battler.totalhp))))
|
||||
if highdamage>=battler.hp
|
||||
if highdamage > [battler.hp+restoreamount,battler.totalhp].min
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.2
|
||||
end
|
||||
healmove = false
|
||||
for j in battler.moves
|
||||
if j.isHealingMove?
|
||||
healmove=true
|
||||
end
|
||||
end
|
||||
if healmove
|
||||
if battler.pbSpeed < opponent1.pbSpeed
|
||||
if highdamage>=battler.hp
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.6
|
||||
if resratio<0.55
|
||||
itemscore*=0.2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
itemscore*=0.4
|
||||
end
|
||||
if highdamage > restoreamount
|
||||
itemscore*=0
|
||||
else
|
||||
if restoreamount-highdamage < 15
|
||||
itemscore*=0.5
|
||||
end
|
||||
end
|
||||
if battler.pbSpeed > opponent1.pbSpeed
|
||||
itemscore*=0.8
|
||||
if highscore >=110
|
||||
if maxopppri > maxplaypri
|
||||
itemscore*=1.3
|
||||
if pridam>battler.hp
|
||||
if pridam>(battler.hp/2.0)
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=2
|
||||
end
|
||||
end
|
||||
elsif !(!opponent1.abilitynulled && opponent1.ability == PBAbilities::STURDY)
|
||||
itemscore*=0
|
||||
end
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SWEEPER)
|
||||
itemscore*=1.1
|
||||
end
|
||||
else
|
||||
if highdamage*2 > [battler.hp+restoreamount,battler.totalhp].min
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.5
|
||||
if highscore >=110
|
||||
itemscore*=1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.hp == battler.totalhp
|
||||
itemscore*=0
|
||||
elsif battler.hp >= (battler.totalhp*0.8)
|
||||
itemscore*=0.2
|
||||
elsif battler.hp >= (battler.totalhp*0.6)
|
||||
itemscore*=0.3
|
||||
elsif battler.hp >= (battler.totalhp*0.5)
|
||||
itemscore*=0.5
|
||||
end
|
||||
minipot = (partynumber-1)
|
||||
minimini = -1
|
||||
for j in items
|
||||
next if pbEnemyItemAlreadyUsed?(index,j,items)
|
||||
next if !((j== PBItems::POTION) || (j== PBItems::ULTRAPOTION) ||
|
||||
(j== PBItems::SUPERPOTION) || (j== PBItems::HYPERPOTION) ||
|
||||
(j== PBItems::MAXPOTION) || (j== PBItems::FULLRESTORE) ||
|
||||
(j== PBItems::FRESHWATER) || (j== PBItems::SODAPOP) ||
|
||||
(j== PBItems::LEMONADE) || (j== PBItems::MOOMOOMILK) ||
|
||||
(j== PBItems::MEMEONADE) || (j== PBItems::STRAWBIC) ||
|
||||
(j== PBItems::CHOCOLATEIC) || (j== PBItems::BLUEMIC))
|
||||
minimini+=1
|
||||
end
|
||||
if minipot>minimini
|
||||
itemscore*=(0.9**(minipot-minimini))
|
||||
minipot=minimini
|
||||
elsif minimini>minipot
|
||||
itemscore*=(1.1**(minimini-minipot))
|
||||
minimini=minipot
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::LEAD) || currentroles.include?(PBMonRoles::SCREENER)
|
||||
itemscore*=0.6
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::TANK)
|
||||
itemscore*=1.1
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SECOND)
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.hasWorkingItem(:LEFTOVERS) || (battler.hasWorkingItem(:BLACKSLUDGE) && battler.pbHasType?(:POISON))
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.status!=0 && !(i== PBItems::FULLRESTORE)
|
||||
itemscore*=0.7
|
||||
if battler.effects[PBEffects::Toxic]>0 && partynumber>1
|
||||
itemscore*=0.2
|
||||
end
|
||||
end
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)>4
|
||||
itemscore*=0.7
|
||||
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
|
||||
itemscore*=1.1
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
|
||||
itemscore*=1.2
|
||||
end
|
||||
end
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type2,battler.type1,battler.type2)>4
|
||||
itemscore*=0.6
|
||||
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
|
||||
itemscore*=1.1
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
|
||||
itemscore*=1.2
|
||||
end
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::REGENERATOR) && partynumber>1
|
||||
itemscore*=0.7
|
||||
end
|
||||
end
|
||||
if isstatusitem
|
||||
PBDebug.log(sprintf("This is a status-curing item.")) if $INTERNAL
|
||||
if !(i== PBItems::FULLRESTORE)
|
||||
if battler.status==0
|
||||
itemscore*=0
|
||||
else
|
||||
if highdamage>battler.hp
|
||||
if (bestid==106 && battler.status==PBStatuses::SLEEP) || (bestid==298 && battler.status==PBStatuses::PARALYSIS) || bestid==179
|
||||
if highdamage*0.5>battler.hp
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.4
|
||||
end
|
||||
else
|
||||
itemscore*=0
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::SLEEP
|
||||
if battler.pbHasMove?((PBMoves::SLEEPTALK)) ||
|
||||
battler.pbHasMove?((PBMoves::SNORE)) ||
|
||||
battler.pbHasMove?((PBMoves::REST)) ||
|
||||
(!battler.abilitynulled && battler.ability == PBAbilities::COMATOSE)
|
||||
itemscore*=0.6
|
||||
end
|
||||
if checkAImoves([PBMoves::DREAMEATER,PBMoves::NIGHTMARE],aimem) || (!opponent1.abilitynulled && opponent1.ability == PBAbilities::BADDREAMS)
|
||||
itemscore*=1.3
|
||||
end
|
||||
if highdamage*(1.0/battler.hp)>0.2
|
||||
itemscore*=1.3
|
||||
else
|
||||
itemscore*=0.7
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::PARALYSIS
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::QUICKFEET) || (!battler.abilitynulled && battler.ability == PBAbilities::GUTS)
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.pbSpeed>opponent1.pbSpeed && (battler.pbSpeed*0.5)<opponent1.pbSpeed
|
||||
itemscore*=1.3
|
||||
end
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.status==PBStatuses::BURN
|
||||
itemscore*=1.1
|
||||
if battler.attack>battler.spatk
|
||||
itemscore*=1.2
|
||||
else
|
||||
itemscore*=0.8
|
||||
end
|
||||
if !battler.abilitynulled
|
||||
itemscore*=0.6 if battler.ability == PBAbilities::GUTS
|
||||
itemscore*=0.7 if battler.ability == PBAbilities::MAGICGUARD
|
||||
itemscore*=0.8 if battler.ability == PBAbilities::FLAREBOOST
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::POISON
|
||||
itemscore*=1.1
|
||||
if !battler.abilitynulled
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::GUTS
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::MAGICGUARD
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::TOXICBOOST
|
||||
itemscore*=0.4 if battler.ability == PBAbilities::POISONHEAL
|
||||
end
|
||||
if battler.effects[PBEffects::Toxic]>0
|
||||
itemscore*=1.1
|
||||
if battler.effects[PBEffects::Toxic]>3
|
||||
itemscore*=1.3
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::FROZEN
|
||||
itemscore*=1.3
|
||||
thawmove=false
|
||||
for j in battler.moves
|
||||
if j.canThawUser?
|
||||
thawmove=true
|
||||
end
|
||||
end
|
||||
if thawmove
|
||||
itemscore*=0.5
|
||||
end
|
||||
if highdamage*(1.0/battler.hp)>0.15
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.9
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.pbHasMove?((PBMoves::REFRESH)) ||
|
||||
battler.pbHasMove?((PBMoves::REST)) ||
|
||||
battler.pbHasMove?((PBMoves::PURIFY))
|
||||
itemscore*=0.5
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::NATURALCURE) && partynumber>1
|
||||
itemscore*=0.2
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::SHEDSKIN)
|
||||
itemscore*=0.3
|
||||
end
|
||||
end
|
||||
if partynumber==1 || currentroles.include?(PBMonRoles::ACE)
|
||||
itemscore*=1.2
|
||||
else
|
||||
itemscore*=0.8
|
||||
if battler.itemUsed2
|
||||
itemscore*=0.6
|
||||
end
|
||||
end
|
||||
if battler.effects[PBEffects::Confusion]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.effects[PBEffects::Attract]>=0
|
||||
itemscore*=0.6
|
||||
end
|
||||
if battler.effects[PBEffects::Substitute]>0
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.effects[PBEffects::LeechSeed]>=0
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.effects[PBEffects::Curse]
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.effects[PBEffects::PerishSong]>0
|
||||
itemscore*=0.2
|
||||
end
|
||||
minipot=0
|
||||
for s in [PBStats::ATTACK,PBStats::DEFENSE,PBStats::SPEED,
|
||||
PBStats::SPATK,PBStats::SPDEF,PBStats::ACCURACY,PBStats::EVASION]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::PHYSICALWALL) || currentroles.include?(PBMonRoles::SPECIALWALL)
|
||||
for s in [PBStats::DEFENSE,PBStats::SPDEF]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SWEEPER)
|
||||
for s in [PBStats::SPEED]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
if battler.attack>battler.spatk
|
||||
for s in [PBStats::ATTACK]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
else
|
||||
for s in [PBStats::SPATK]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
end
|
||||
end
|
||||
minipot*=5
|
||||
minipot+=100
|
||||
minipot*=0.01
|
||||
itemscore*=minipot
|
||||
if opponent1.effects[PBEffects::TwoTurnAttack]>0 || opponent1.effects[PBEffects::HyperBeam]>0
|
||||
itemscore*=1.2
|
||||
end
|
||||
if highscore>70
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.9
|
||||
end
|
||||
fielddisrupt = getFieldDisruptScore(battler,opponent1,skill)
|
||||
if fielddisrupt <= 0
|
||||
fielddisrupt=0.6
|
||||
end
|
||||
itemscore*= (1.0/fielddisrupt)
|
||||
if @trickroom > 0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::Tailwind]>0
|
||||
itemscore*=0.6
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::Reflect]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::LightScreen]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::AuroraVeil]>0
|
||||
itemscore*=0.8
|
||||
end
|
||||
if @doublebattle
|
||||
itemscore*=0.8
|
||||
end
|
||||
itemscore-=100
|
||||
PBDebug.log(sprintf("Score for %s: %d",PBItems.getName(i),itemscore)) if $INTERNAL
|
||||
scorearray[arraycount] = itemscore
|
||||
end
|
||||
bestitem=-1
|
||||
bestscore=-10000
|
||||
counter=-1
|
||||
for k in scorearray
|
||||
counter+=1
|
||||
if k>bestscore
|
||||
bestscore = k
|
||||
bestitem = items[counter]
|
||||
end
|
||||
end
|
||||
PBDebug.log(sprintf("Highest item score: %d",bestscore)) if $INTERNAL
|
||||
PBDebug.log(sprintf("Highest move score: %d",highscore)) if $INTERNAL
|
||||
if highscore<bestscore
|
||||
PBDebug.log(sprintf("Using %s",PBItems.getName(bestitem))) if $INTERNAL
|
||||
return bestitem
|
||||
else
|
||||
PBDebug.log(sprintf("Not using an item.")) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,832 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
attr_accessor :scores
|
||||
attr_accessor :targets
|
||||
attr_accessor :myChoices
|
||||
|
||||
################################################################################
|
||||
# Choose a move to use.
|
||||
# Called before any decisions are made.
|
||||
################################################################################
|
||||
def pbBuildMoveScores(index) #Generates an array of movescores for decisions
|
||||
# Ally targetting stuff marked with ###
|
||||
attacker=@battlers[index]
|
||||
@scores=[0,0,0,0]
|
||||
@targets=nil
|
||||
@myChoices=[]
|
||||
totalscore=0
|
||||
target=-1
|
||||
skill=0
|
||||
wildbattle=!@opponent && pbIsOpposing?(index)
|
||||
if wildbattle # If wild battle
|
||||
preference = attacker.personalID % 16
|
||||
preference = preference % 4
|
||||
for i in 0...4
|
||||
if pbCanChooseMove?(index,i,false)
|
||||
@scores[i]=100
|
||||
if preference == i # for personality
|
||||
@scores[i]+=100
|
||||
end
|
||||
@myChoices.push(i)
|
||||
end
|
||||
end
|
||||
else
|
||||
skill=pbGetOwner(attacker.index).skill || 0
|
||||
opponent=attacker.pbOppositeOpposing
|
||||
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
|
||||
if fastermon && opponent
|
||||
PBDebug.log(sprintf("AI Pokemon #{attacker.name} is faster than #{opponent.name}.")) if $INTERNAL
|
||||
elsif opponent
|
||||
PBDebug.log(sprintf("Player Pokemon #{opponent.name} is faster than #{attacker.name}.")) if $INTERNAL
|
||||
end
|
||||
#if @doublebattle && !opponent.isFainted? && !opponent.pbPartner.isFainted?
|
||||
if @doublebattle && ((!opponent.isFainted? && !opponent.pbPartner.isFainted?) || !attacker.pbPartner.isFainted?)
|
||||
# Choose a target and move. Also care about partner.
|
||||
otheropp=opponent.pbPartner
|
||||
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
|
||||
if fastermon && otheropp
|
||||
PBDebug.log(sprintf("AI Pokemon #{attacker.name} is faster than #{otheropp.name}.")) if $INTERNAL
|
||||
elsif otheropp
|
||||
PBDebug.log(sprintf("Player Pokemon #{otheropp.name} is faster than #{attacker.name}.")) if $INTERNAL
|
||||
end
|
||||
notopp=attacker.pbPartner ###
|
||||
scoresAndTargets=[]
|
||||
@targets=[-1,-1,-1,-1]
|
||||
maxscore1=0
|
||||
maxscore2=0
|
||||
totalscore1=0
|
||||
totalscore2=0
|
||||
baseDamageArray=[]
|
||||
baseDamageArray2=[]
|
||||
baseDamageArray3=[] ###
|
||||
for j in 0...4
|
||||
next if attacker.moves[j].id < 1
|
||||
# check attacker.moves[j].basedamage and if this is 0 instead check the status method
|
||||
dmgValue = pbRoughDamage(attacker.moves[j],attacker,opponent,skill,attacker.moves[j].basedamage)
|
||||
if attacker.moves[j].basedamage!=0
|
||||
if opponent.hp==0
|
||||
dmgPercent = 0
|
||||
else
|
||||
dmgPercent = (dmgValue*100)/(opponent.hp)
|
||||
dmgPercent = 110 if dmgPercent > 110
|
||||
end
|
||||
else
|
||||
dmgPercent = pbStatusDamage(attacker.moves[j])
|
||||
end
|
||||
baseDamageArray.push(dmgPercent)
|
||||
#Second opponent
|
||||
dmgValue2 = pbRoughDamage(attacker.moves[j],attacker,otheropp,skill,attacker.moves[j].basedamage)
|
||||
if attacker.moves[j].basedamage!=0
|
||||
if otheropp.hp==0
|
||||
dmgPercent2=0
|
||||
else
|
||||
dmgPercent2 = (dmgValue2*100)/(otheropp.hp)
|
||||
dmgPercent2 = 110 if dmgPercent2 > 110
|
||||
end
|
||||
else
|
||||
dmgPercent2 = pbStatusDamage(attacker.moves[j])
|
||||
end
|
||||
baseDamageArray2.push(dmgPercent2)
|
||||
#Partner ###
|
||||
dmgValue3 = pbRoughDamage(attacker.moves[j],attacker,notopp,skill,attacker.moves[j].basedamage)
|
||||
if attacker.moves[j].basedamage!=0
|
||||
if notopp.hp==0
|
||||
dmgPercent3=0
|
||||
else
|
||||
dmgPercent3 = (dmgValue3*100)/(notopp.hp)
|
||||
dmgPercent3 = 110 if dmgPercent3 > 110
|
||||
end
|
||||
else
|
||||
dmgPercent3 = pbStatusDamage(attacker.moves[j])
|
||||
end
|
||||
baseDamageArray3.push(dmgPercent3)
|
||||
end
|
||||
for i in 0...4
|
||||
if pbCanChooseMove?(index,i,false)
|
||||
score1=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill,baseDamageArray[i],baseDamageArray,i)
|
||||
score2=pbGetMoveScore(attacker.moves[i],attacker,otheropp,skill,baseDamageArray2[i],baseDamageArray2,i)
|
||||
totalscore = score1+score2
|
||||
if (attacker.moves[i].target&0x08)!=0 # Targets all users
|
||||
score1=totalscore # Consider both scores as it will hit BOTH targets
|
||||
score2=totalscore
|
||||
if attacker.pbPartner.isFainted? || (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::TELEPATHY) # No partner
|
||||
score1*=1.66
|
||||
score2*=1.66
|
||||
else
|
||||
# If this move can also target the partner, get the partner's
|
||||
# score too
|
||||
v=pbRoughDamage(attacker.moves[i],attacker,attacker.pbPartner,skill,attacker.moves[i].basedamage)
|
||||
p=(v*100)/(attacker.pbPartner.hp)
|
||||
s=pbGetMoveScore(attacker.moves[i],attacker,attacker.pbPartner,skill,p)
|
||||
s=110 if s>110
|
||||
if !attacker.pbPartner.abilitynulled &&
|
||||
(attacker.moves[i].type == PBTypes::FIRE && attacker.pbPartner.ability == PBAbilities::FLASHFIRE) ||
|
||||
(attacker.moves[i].type == PBTypes::WATER && [PBAbilities::WATERABSORB, PBAbilities::STORMDRAIN, PBAbilities::DRYSKIN].include?(attacker.pbPartner.ability)) ||
|
||||
(attacker.moves[i].type == PBTypes::GRASS && attacker.pbPartner.ability == PBAbilities::SAPSIPPER) ||
|
||||
(attacker.moves[i].type == PBTypes::ELECTRIC && [PBAbilities::VOLTABSORB, PBAbilities::LIGHTNINGROD, PBAbilities::MOTORDRIVE].include?(attacker.pbPartner.ability))
|
||||
score1*=2.00
|
||||
score2*=2.00
|
||||
else
|
||||
if (attacker.pbPartner.hp.to_f)/attacker.pbPartner.totalhp>0.10 || ((attacker.pbPartner.pbSpeed<attacker.pbSpeed) ^ (@trickroom!=0))
|
||||
s = 100-s
|
||||
s=0 if s<0
|
||||
s/=100.0
|
||||
s * 0.5 # multiplier to control how much to arbitrarily care about hitting partner; lower cares more
|
||||
if (attacker.pbPartner.pbSpeed<attacker.pbSpeed) ^ (@trickroom!=0)
|
||||
s * 0.5 # care more if we're faster and would knock it out before it attacks
|
||||
end
|
||||
score1*=s
|
||||
score2*=s
|
||||
end
|
||||
end
|
||||
end
|
||||
score1=score1.to_i
|
||||
score2=score2.to_i
|
||||
PBDebug.log(sprintf("%s: Final Score after Multi-Target Adjustment: %d",PBMoves.getName(attacker.moves[i].id),score1))
|
||||
PBDebug.log(sprintf(""))
|
||||
end
|
||||
if attacker.moves[i].target==PBTargets::AllOpposing # Consider both scores as it will hit BOTH targets
|
||||
totalscore = score1+score2
|
||||
score1=totalscore
|
||||
score2=totalscore
|
||||
PBDebug.log(sprintf("%s: Final Score after Multi-Target Adjustment: %d",PBMoves.getName(attacker.moves[i].id),score1))
|
||||
PBDebug.log(sprintf(""))
|
||||
end
|
||||
@myChoices.push(i)
|
||||
scoresAndTargets.push([i*2,i,score1,opponent.index])
|
||||
scoresAndTargets.push([i*2+1,i,score2,otheropp.index])
|
||||
else
|
||||
scoresAndTargets.push([i*2,i,-1,opponent.index])
|
||||
scoresAndTargets.push([i*2+1,i,-1,otheropp.index])
|
||||
end
|
||||
end
|
||||
for i in 0...4 ### This whole bit
|
||||
if pbCanChooseMove?(index,i,false)
|
||||
movecode = attacker.moves[i].function
|
||||
if movecode == 0xDF || movecode == 0x63 || movecode == 0x67 || #Heal Pulse, Simple Beam, Skill Swap,
|
||||
movecode == 0xA0 || movecode == 0xC1 || movecode == 0x142 || #Frost Breath, Beat Up, Topsy-Turvy,
|
||||
movecode == 0x162 || movecode == 0x164 || movecode == 0x167 || #Floral Healing, Instruct, Pollen Puff,
|
||||
movecode == 0x169 || movecode == 0x170 || movecode == 0x55 || #Purify, Spotlight, Psych Up,
|
||||
movecode == 0x40 || movecode == 0x41 || movecode == 0x66 #Swagger, Flatter, Entrainment
|
||||
partnerscore=pbGetMoveScore(attacker.moves[i],attacker,notopp,skill,baseDamageArray3[i],baseDamageArray3,i)
|
||||
PBDebug.log(sprintf("%s: Score for using on partner: %d",PBMoves.getName(attacker.moves[i].id),partnerscore))
|
||||
PBDebug.log(sprintf(""))
|
||||
scoresAndTargets.push([i*10,i,partnerscore,notopp.index])
|
||||
end
|
||||
end
|
||||
end
|
||||
scoresAndTargets.sort!{|a,b|
|
||||
if a[2]==b[2] # if scores are equal
|
||||
a[0]<=>b[0] # sort by index (for stable comparison)
|
||||
else
|
||||
b[2]<=>a[2]
|
||||
end
|
||||
}
|
||||
for i in 0...scoresAndTargets.length
|
||||
idx=scoresAndTargets[i][1]
|
||||
thisScore=scoresAndTargets[i][2]
|
||||
if thisScore>0 || thisScore==-1
|
||||
if scores[idx]==0 || ((scores[idx]==thisScore && pbAIRandom(10)<5) ||
|
||||
(scores[idx] < thisScore))
|
||||
# (scores[idx]!=thisScore && pbAIRandom(10)<3))
|
||||
@scores[idx]=thisScore
|
||||
@targets[idx]=scoresAndTargets[i][3]
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
# Choose a move. There is only 1 opposing Pokémon.
|
||||
if @doublebattle && opponent.isFainted?
|
||||
opponent=opponent.pbPartner
|
||||
end
|
||||
baseDamageArray=[]
|
||||
baseDamageArrayAdj=[]
|
||||
for j in 0...4
|
||||
next if attacker.moves[j].id < 1
|
||||
# check attacker.moves[j].basedamage and if this is 0 instead check the status method
|
||||
dmgValue = pbRoughDamage(attacker.moves[j],attacker,opponent,skill,attacker.moves[j].basedamage)
|
||||
if attacker.moves[j].basedamage!=0
|
||||
dmgPercent = (dmgValue*100)/(opponent.hp)
|
||||
dmgPercent = 110 if dmgPercent > 110
|
||||
if attacker.moves[j].function == 0x115 || attacker.moves[j].function == 0xC3 ||
|
||||
attacker.moves[j].function == 0xC4 || attacker.moves[j].function == 0xC5 ||
|
||||
attacker.moves[j].function == 0xC6 || attacker.moves[j].function == 0xC7 ||
|
||||
attacker.moves[j].function == 0xC8
|
||||
dmgPercentAdj = (dmgPercent * 0.5)
|
||||
else
|
||||
dmgPercentAdj = dmgPercent
|
||||
end
|
||||
else
|
||||
dmgPercent = pbStatusDamage(attacker.moves[j])
|
||||
dmgPercentAdj = dmgPercent
|
||||
end
|
||||
baseDamageArray.push(dmgPercent)
|
||||
baseDamageArrayAdj.push(dmgPercentAdj)
|
||||
end
|
||||
for i in 0...4
|
||||
if pbCanChooseMove?(index,i,false)
|
||||
@scores[i]=pbGetMoveScore(attacker.moves[i],attacker,opponent,skill,baseDamageArray[i],baseDamageArrayAdj,i)
|
||||
@myChoices.push(i)
|
||||
else
|
||||
@scores[i] = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# Primary method for deciding which move to use.
|
||||
################################################################################
|
||||
def pbChooseMoves(index)
|
||||
maxscore=0
|
||||
totalscore=0
|
||||
attacker=@battlers[index]
|
||||
skill=pbGetOwner(attacker.index).skill rescue 0
|
||||
wildbattle=!@opponent && pbIsOpposing?(index)
|
||||
for i in 0...4
|
||||
#next if scores[i] == -1
|
||||
@scores[i]=0 if @scores[i]<0
|
||||
maxscore=@scores[i] if @scores[i]>maxscore
|
||||
totalscore+=@scores[i]
|
||||
end
|
||||
# Minmax choices depending on AI
|
||||
if !wildbattle && skill>=PBTrainerAI.mediumSkill
|
||||
threshold=(skill>=PBTrainerAI.bestSkill) ? 1.5 : (skill>=PBTrainerAI.highSkill) ? 2 : 3
|
||||
newscore=(skill>=PBTrainerAI.bestSkill) ? 5 : (skill>=PBTrainerAI.highSkill) ? 10 : 15
|
||||
for i in 0...@scores.length
|
||||
if @scores[i]>newscore && @scores[i]*threshold<maxscore
|
||||
totalscore-=(@scores[i]-newscore)
|
||||
@scores[i]=newscore
|
||||
end
|
||||
end
|
||||
end
|
||||
if $INTERNAL
|
||||
x="[#{attacker.pbThis}: "
|
||||
j=0
|
||||
for i in 0...4
|
||||
if attacker.moves[i].id!=0
|
||||
x+=", " if j>0
|
||||
x+=PBMoves.getName(attacker.moves[i].id)+"="+@scores[i].to_s
|
||||
j+=1
|
||||
end
|
||||
end
|
||||
x+="]"
|
||||
PBDebug.log(x)
|
||||
end
|
||||
if !wildbattle #&& maxscore>100
|
||||
stdev=pbStdDev(@scores)
|
||||
preferredMoves=[]
|
||||
for i in 0...4
|
||||
if attacker.moves[i].id!=0 && (@scores[i] >= (maxscore*0.95)) && pbCanChooseMove?(index,i,false)
|
||||
preferredMoves.push(i)
|
||||
preferredMoves.push(i) if @scores[i]==maxscore # Doubly prefer the best move
|
||||
end
|
||||
end
|
||||
if preferredMoves.length>0
|
||||
i=preferredMoves[pbAIRandom(preferredMoves.length)]
|
||||
PBDebug.log("[Prefer "+PBMoves.getName(attacker.moves[i].id)+"]") if $INTERNAL
|
||||
pbRegisterMove(index,i,false)
|
||||
target=@targets[i] if @targets
|
||||
if @doublebattle && target && target>=0
|
||||
pbRegisterTarget(index,target)
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
PBDebug.log("If this battle is not wild, something has gone wrong in scoring moves (no preference chosen).") if $INTERNAL
|
||||
if !wildbattle && attacker.turncount
|
||||
badmoves=false
|
||||
if ((maxscore<=20 && attacker.turncount>2) ||
|
||||
(maxscore<=30 && attacker.turncount>5)) && pbAIRandom(10)<8
|
||||
badmoves=true
|
||||
end
|
||||
if totalscore<100 && attacker.turncount>1
|
||||
badmoves=true
|
||||
movecount=0
|
||||
for i in 0...4
|
||||
if attacker.moves[i].id!=0
|
||||
if @scores[i]>0 && attacker.moves[i].basedamage>0
|
||||
badmoves=false
|
||||
end
|
||||
movecount+=1
|
||||
end
|
||||
end
|
||||
badmoves=badmoves && pbAIRandom(10)!=0
|
||||
end
|
||||
end
|
||||
if maxscore<=0
|
||||
# If all scores are 0 or less, choose a move at random
|
||||
if @myChoices.length>0
|
||||
pbRegisterMove(index,@myChoices[pbAIRandom(@myChoices.length)],false)
|
||||
else
|
||||
pbAutoChooseMove(index)
|
||||
end
|
||||
else
|
||||
randnum=pbAIRandom(totalscore)
|
||||
cumtotal=0
|
||||
for i in 0...4
|
||||
if @scores[i]>0
|
||||
cumtotal+=@scores[i]
|
||||
if randnum<cumtotal
|
||||
pbRegisterMove(index,i,false)
|
||||
target=@targets[i] if @targets
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if @doublebattle && target && target>=0
|
||||
pbRegisterTarget(index,target)
|
||||
end
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Get a score for each move being considered (trainer-owned Pokémon only).
|
||||
# Moves with higher scores are more likely to be chosen.
|
||||
##############################################################################
|
||||
def pbGetMoveScore(move,attacker,opponent,skill=100,roughdamage=10,initialscores=[],scoreindex=-1)
|
||||
if roughdamage<1
|
||||
roughdamage=1
|
||||
end
|
||||
PBDebug.log(sprintf("%s: initial score: %d",PBMoves.getName(move.id),roughdamage)) if $INTERNAL
|
||||
skill=PBTrainerAI.minimumSkill if skill<PBTrainerAI.minimumSkill
|
||||
#score=(pbRoughDamage(move,attacker,opponent,skill,move.basedamage)*100/opponent.hp) #roughdamage
|
||||
score=roughdamage
|
||||
#Temporarly mega-ing pokemon if it can #perry
|
||||
if pbCanMegaEvolve?(attacker.index)
|
||||
attacker.pokemon.makeMega
|
||||
attacker.pbUpdate(true)
|
||||
attacker.form=attacker.startform
|
||||
megaEvolved=true
|
||||
end
|
||||
#Little bit of prep before getting into the case statement
|
||||
oppitemworks = opponent.itemWorks?
|
||||
attitemworks = attacker.itemWorks?
|
||||
aimem = getAIMemory(skill,opponent.pokemonIndex)
|
||||
bettertype = move.pbType(move.type,attacker,opponent)
|
||||
opponent=attacker.pbOppositeOpposing if !opponent
|
||||
opponent=opponent.pbPartner if opponent && opponent.isFainted?
|
||||
roles = pbGetMonRole(attacker,opponent,skill)
|
||||
if move.priority>0 || (move.basedamage==0 && !attacker.abilitynulled && attacker.ability == PBAbilities::PRANKSTER)
|
||||
if move.basedamage>0
|
||||
PBDebug.log(sprintf("Priority Check Begin")) if $INTERNAL
|
||||
fastermon = (attacker.pbSpeed>pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
|
||||
if fastermon
|
||||
PBDebug.log(sprintf("AI Pokemon is faster.")) if $INTERNAL
|
||||
else
|
||||
PBDebug.log(sprintf("Player Pokemon is faster.")) if $INTERNAL
|
||||
end
|
||||
if score>100
|
||||
if @doublebattle
|
||||
score*=1.3
|
||||
else
|
||||
if fastermon
|
||||
score*=1.3
|
||||
else
|
||||
score*=2
|
||||
end
|
||||
end
|
||||
else
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::STANCECHANGE)
|
||||
if !fastermon
|
||||
score*=0.7
|
||||
end
|
||||
end
|
||||
end
|
||||
movedamage = -1
|
||||
opppri = false
|
||||
pridam = -1
|
||||
if (attacker.pbSpeed<pbRoughStat(opponent,PBStats::SPEED,skill)) ^ (@trickroom!=0)
|
||||
if aimem.length > 0
|
||||
for i in aimem
|
||||
tempdam = pbRoughDamage(i,opponent,attacker,skill,i.basedamage)
|
||||
if i.priority>0
|
||||
opppri=true
|
||||
if tempdam>pridam
|
||||
pridam = tempdam
|
||||
end
|
||||
end
|
||||
if tempdam>movedamage
|
||||
movedamage = tempdam
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
PBDebug.log(sprintf("Expected damage taken: %d",movedamage)) if $INTERNAL
|
||||
if !fastermon
|
||||
if movedamage>attacker.hp
|
||||
if @doublebattle
|
||||
score+=75
|
||||
else
|
||||
score+=150
|
||||
end
|
||||
end
|
||||
end
|
||||
if opppri
|
||||
score*=1.1
|
||||
if pridam>attacker.hp
|
||||
if fastermon
|
||||
score*=3
|
||||
else
|
||||
score*=0.5
|
||||
end
|
||||
end
|
||||
end
|
||||
if !fastermon && opponent.effects[PBEffects::TwoTurnAttack]>0
|
||||
score*=0
|
||||
end
|
||||
if $fefieldeffect==37
|
||||
score*=0
|
||||
end
|
||||
if !opponent.abilitynulled && (opponent.ability == PBAbilities::DAZZLING || opponent.ability == PBAbilities::QUEENLYMAJESTY)
|
||||
score*=0
|
||||
end
|
||||
end
|
||||
score*=0.2 if checkAImoves([PBMoves::QUICKGUARD],aimem)
|
||||
PBDebug.log(sprintf("Priority Check End")) if $INTERNAL
|
||||
elsif move.priority<0
|
||||
if fastermon
|
||||
score*=0.9
|
||||
if move.basedamage>0
|
||||
if opponent.effects[PBEffects::TwoTurnAttack]>0
|
||||
score*=2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##### Alter score depending on the move's function code ########################
|
||||
score = pbGetMoveScoreFunctions(move,attacker,opponent,skill,roughdamage,initialscores,scoreindex,
|
||||
score, oppitemworks, attitemworks, aimem, bettertype, roles, tempdam)
|
||||
###### END FUNCTION CODES
|
||||
|
||||
if (!opponent.abilitynulled && opponent.ability == PBAbilities::DANCER)
|
||||
if (PBStuff::DANCEMOVE).include?(move.id)
|
||||
score*=0.5
|
||||
score*=0.1 if $fefieldeffect==6
|
||||
end
|
||||
end
|
||||
ioncheck = false
|
||||
destinycheck = false
|
||||
widecheck = false
|
||||
powdercheck = false
|
||||
shieldcheck = false
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
for j in aimem
|
||||
ioncheck = true if j.id==(PBMoves::IONDELUGE)
|
||||
destinycheck = true if j.id==(PBMoves::DESTINYBOND)
|
||||
widecheck = true if j.id==(PBMoves::WIDEGUARD)
|
||||
powdercheck = true if j.id==(PBMoves::POWDER)
|
||||
shieldcheck = true if j.id==(PBMoves::SPIKYSHIELD) ||
|
||||
j.id==(PBMoves::KINGSSHIELD) || j.id==(PBMoves::BANEFULBUNKER)
|
||||
end
|
||||
if @doublebattle && @aiMoveMemory[2][opponent.pbPartner.pokemonIndex].length>0
|
||||
for j in @aiMoveMemory[2][opponent.pbPartner.pokemonIndex]
|
||||
widecheck = true if j.id==(PBMoves::WIDEGUARD)
|
||||
powdercheck = true if j.id==(PBMoves::POWDER)
|
||||
end
|
||||
end
|
||||
end
|
||||
if ioncheck == true
|
||||
if move.type == 0
|
||||
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD) ||
|
||||
(!opponent.abilitynulled && opponent.ability == PBAbilities::LIGHTNINGROD) ||
|
||||
(!opponent.abilitynulled && opponent.ability == PBAbilities::VOLTABSORB) ||
|
||||
(!opponent.abilitynulled && opponent.ability == PBAbilities::MOTORDRIVE)
|
||||
score *= 0.3
|
||||
end
|
||||
end
|
||||
end
|
||||
if (move.target==PBTargets::SingleNonUser || move.target==PBTargets::RandomOpposing ||
|
||||
move.target==PBTargets::AllOpposing || move.target==PBTargets::SingleOpposing ||
|
||||
move.target==PBTargets::OppositeOpposing)
|
||||
if move.type==13 || (ioncheck == true && move.type == 0)
|
||||
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD)
|
||||
score*=0
|
||||
elsif (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::LIGHTNINGROD)
|
||||
score*=0.3
|
||||
end
|
||||
elsif move.type==11
|
||||
if (!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::LIGHTNINGROD)
|
||||
score*=0
|
||||
elsif (!attacker.pbPartner.abilitynulled && attacker.pbPartner.ability == PBAbilities::LIGHTNINGROD)
|
||||
score*=0.3
|
||||
end
|
||||
end
|
||||
end
|
||||
if move.isSoundBased?
|
||||
if ((!opponent.abilitynulled && opponent.ability == PBAbilities::SOUNDPROOF) && !opponent.moldbroken) || attacker.effects[PBEffects::ThroatChop]!=0
|
||||
score*=0
|
||||
else
|
||||
score *= 0.6 if checkAImoves([PBMoves::THROATCHOP],aimem)
|
||||
end
|
||||
end
|
||||
if move.flags&0x80!=0 # Boosted crit moves
|
||||
if !((!opponent.abilitynulled && opponent.ability == PBAbilities::SHELLARMOR) ||
|
||||
(!opponent.abilitynulled && opponent.ability == PBAbilities::BATTLEARMOR) ||
|
||||
attacker.effects[PBEffects::LaserFocus]>0)
|
||||
boostercount = 0
|
||||
if move.pbIsPhysical?(move.type)
|
||||
boostercount += opponent.stages[PBStats::DEFENSE] if opponent.stages[PBStats::DEFENSE]>0
|
||||
boostercount -= attacker.stages[PBStats::ATTACK] if attacker.stages[PBStats::ATTACK]<0
|
||||
elsif move.pbIsSpecial?(move.type)
|
||||
boostercount += opponent.stages[PBStats::SPDEF] if opponent.stages[PBStats::SPDEF]>0
|
||||
boostercount -= attacker.stages[PBStats::SPATK] if attacker.stages[PBStats::SPATK]<0
|
||||
end
|
||||
score*=(1.05**boostercount)
|
||||
end
|
||||
end
|
||||
if move.basedamage>0
|
||||
if skill>=PBTrainerAI.highSkill
|
||||
if opponent.effects[PBEffects::DestinyBond]
|
||||
score*=0.2
|
||||
else
|
||||
if ((opponent.pbSpeed>attacker.pbSpeed) ^ (@trickroom!=0)) && destinycheck
|
||||
score*=0.7
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if widecheck && ((move.target == PBTargets::AllOpposing) || (move.target == PBTargets::AllNonUsers))
|
||||
score*=0.2
|
||||
end
|
||||
if powdercheck && move.type==10
|
||||
score*=0.2
|
||||
end
|
||||
if move.isContactMove? && !(attacker.item == PBItems::PROTECTIVEPADS) && !(!attacker.abilitynulled && attacker.ability == PBAbilities::LONGREACH)
|
||||
if (oppitemworks && opponent.item == PBItems::ROCKYHELMET) || shieldcheck
|
||||
score*=0.85
|
||||
end
|
||||
if !opponent.abilitynulled
|
||||
if opponent.ability == PBAbilities::ROUGHSKIN || opponent.ability == PBAbilities::IRONBARBS
|
||||
score*=0.85
|
||||
elsif opponent.ability == PBAbilities::EFFECTSPORE
|
||||
score*=0.75
|
||||
elsif opponent.ability == PBAbilities::FLAMEBODY && attacker.pbCanBurn?(false)
|
||||
score*=0.75
|
||||
elsif opponent.ability == PBAbilities::STATIC && attacker.pbCanParalyze?(false)
|
||||
score*=0.75
|
||||
elsif opponent.ability == PBAbilities::POISONPOINT && attacker.pbCanPoison?(false)
|
||||
score*=0.75
|
||||
elsif opponent.ability == PBAbilities::CUTECHARM && attacker.effects[PBEffects::Attract]<0
|
||||
if initialscores.length>0
|
||||
if initialscores[scoreindex] < 102
|
||||
score*=0.8
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::GOOEY || opponent.ability == PBAbilities::TANGLINGHAIR
|
||||
if attacker.pbCanReduceStatStage?(PBStats::SPEED)
|
||||
score*=0.9
|
||||
if ((pbRoughStat(opponent,PBStats::SPEED,skill)<attacker.pbSpeed) ^ (@trickroom!=0))
|
||||
score*=0.8
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::MUMMY
|
||||
if !attacker.abilitynulled && !attacker.unstoppableAbility? &&
|
||||
attacker.ability != opponent.ability && attacker.ability != PBAbilities::SHIELDDUST
|
||||
mummyscore = getAbilityDisruptScore(move,opponent,attacker,skill)
|
||||
if mummyscore < 2
|
||||
mummyscore = 2 - mummyscore
|
||||
else
|
||||
mummyscore = 0
|
||||
end
|
||||
score*=mummyscore
|
||||
end
|
||||
end
|
||||
end
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::POISONTOUCH) && opponent.pbCanPoison?(false)
|
||||
score*=1.1
|
||||
end
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::PICKPOCKET) && opponent.item!=0 && !pbIsUnlosableItem(opponent,opponent.item)
|
||||
score*=1.1
|
||||
end
|
||||
if opponent.effects[PBEffects::KingsShield]== true ||
|
||||
opponent.effects[PBEffects::BanefulBunker]== true ||
|
||||
opponent.effects[PBEffects::SpikyShield]== true
|
||||
score *=0.1
|
||||
end
|
||||
end
|
||||
if move.basedamage>0 && (opponent.effects[PBEffects::SpikyShield] ||
|
||||
opponent.effects[PBEffects::BanefulBunker] || opponent.effects[PBEffects::KingsShield])
|
||||
score*=0.1
|
||||
end
|
||||
if move.basedamage==0
|
||||
if hasgreatmoves(initialscores,scoreindex,skill)
|
||||
maxdam=checkAIdamage(aimem,attacker,opponent,skill)
|
||||
if maxdam>0 && maxdam<(attacker.hp*0.3)
|
||||
score*=0.6
|
||||
else
|
||||
score*=0.2 ### highly controversial, revert to 0.1 if shit sucks
|
||||
end
|
||||
end
|
||||
end
|
||||
ispowder = (move.id==214 || move.id==218 || move.id==220 || move.id==445 || move.id==600 || move.id==18 || move.id==219)
|
||||
if ispowder && (opponent.type==(PBTypes::GRASS) ||
|
||||
(!opponent.abilitynulled && opponent.ability == PBAbilities::OVERCOAT) ||
|
||||
(oppitemworks && opponent.item == PBItems::SAFETYGOGGLES))
|
||||
score*=0
|
||||
end
|
||||
# A score of 0 here means it should absolutely not be used
|
||||
if score<=0
|
||||
PBDebug.log(sprintf("%s: final score: 0",PBMoves.getName(move.id))) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
attacker.pbUpdate(true) if defined?(megaEvolved) && megaEvolved==true #perry
|
||||
return score
|
||||
end
|
||||
##### Other score modifications ################################################
|
||||
# Prefer damaging moves if AI has no more Pokémon
|
||||
if attacker.pbNonActivePokemonCount==0
|
||||
if skill>=PBTrainerAI.mediumSkill &&
|
||||
!(skill>=PBTrainerAI.highSkill && opponent.pbNonActivePokemonCount>0)
|
||||
if move.basedamage==0
|
||||
PBDebug.log("[Not preferring status move]") if $INTERNAL
|
||||
score*=0.9
|
||||
elsif opponent.hp<=opponent.totalhp/2.0
|
||||
PBDebug.log("[Preferring damaging move]") if $INTERNAL
|
||||
score*=1.1
|
||||
end
|
||||
end
|
||||
end
|
||||
# Don't prefer attacking the opponent if they'd be semi-invulnerable
|
||||
if opponent.effects[PBEffects::TwoTurnAttack]>0 &&
|
||||
skill>=PBTrainerAI.highSkill
|
||||
invulmove=$pkmn_move[opponent.effects[PBEffects::TwoTurnAttack]][0] #the function code of the current move
|
||||
if move.accuracy>0 && # Checks accuracy, i.e. targets opponent
|
||||
([0xC9,0xCA,0xCB,0xCC,0xCD,0xCE].include?(invulmove) ||
|
||||
opponent.effects[PBEffects::SkyDrop]) &&
|
||||
((attacker.pbSpeed>opponent.pbSpeed) ^ (@trickroom!=0))
|
||||
if skill>=PBTrainerAI.bestSkill # Can get past semi-invulnerability
|
||||
miss=false
|
||||
case invulmove
|
||||
when 0xC9, 0xCC # Fly, Bounce
|
||||
miss=true unless move.function==0x08 || # Thunder
|
||||
move.function==0x15 || # Hurricane
|
||||
move.function==0x77 || # Gust
|
||||
move.function==0x78 || # Twister
|
||||
move.function==0x11B || # Sky Uppercut
|
||||
move.function==0x11C || # Smack Down
|
||||
(move.id == PBMoves::WHIRLWIND)
|
||||
when 0xCA # Dig
|
||||
miss=true unless move.function==0x76 || # Earthquake
|
||||
move.function==0x95 # Magnitude
|
||||
when 0xCB # Dive
|
||||
miss=true unless move.function==0x75 || # Surf
|
||||
move.function==0xD0 || # Whirlpool
|
||||
move.function==0x12D # Shadow Storm
|
||||
when 0xCD # Shadow Force
|
||||
miss=true
|
||||
when 0xCE # Sky Drop
|
||||
miss=true unless move.function==0x08 || # Thunder
|
||||
move.function==0x15 || # Hurricane
|
||||
move.function==0x77 || # Gust
|
||||
move.function==0x78 || # Twister
|
||||
move.function==0x11B || # Sky Uppercut
|
||||
move.function==0x11C # Smack Down
|
||||
end
|
||||
if opponent.effects[PBEffects::SkyDrop]
|
||||
miss=true unless move.function==0x08 || # Thunder
|
||||
move.function==0x15 || # Hurricane
|
||||
move.function==0x77 || # Gust
|
||||
move.function==0x78 || # Twister
|
||||
move.function==0x11B || # Sky Uppercut
|
||||
move.function==0x11C # Smack Down
|
||||
end
|
||||
score*=0 if miss
|
||||
else
|
||||
score*=0
|
||||
end
|
||||
end
|
||||
end
|
||||
# Pick a good move for the Choice items
|
||||
if attitemworks && (attacker.item == PBItems::CHOICEBAND ||
|
||||
attacker.item == PBItems::CHOICESPECS || attacker.item == PBItems::CHOICESCARF)
|
||||
if move.basedamage==0 && move.function!=0xF2 # Trick
|
||||
score*=0.1
|
||||
end
|
||||
if ((move.type == PBTypes::NORMAL) && $fefieldeffect!=29) ||
|
||||
(move.type == PBTypes::GHOST) || (move.type == PBTypes::FIGHTING) ||
|
||||
(move.type == PBTypes::DRAGON) || (move.type == PBTypes::PSYCHIC) ||
|
||||
(move.type == PBTypes::GROUND) || (move.type == PBTypes::ELECTRIC) ||
|
||||
(move.type == PBTypes::POISON)
|
||||
score*=0.95
|
||||
end
|
||||
if (move.type == PBTypes::FIRE) || (move.type == PBTypes::WATER) ||
|
||||
(move.type == PBTypes::GRASS) || (move.type == PBTypes::ELECTRIC)
|
||||
score*=0.95
|
||||
end
|
||||
if move.accuracy > 0
|
||||
miniacc = (move.accuracy/100.0)
|
||||
score *= miniacc
|
||||
end
|
||||
if move.pp < 6
|
||||
score *= 0.9
|
||||
end
|
||||
end
|
||||
#If user is frozen, prefer a move that can thaw the user
|
||||
if attacker.status==PBStatuses::FROZEN
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if move.canThawUser?
|
||||
score+=30
|
||||
else
|
||||
hasFreezeMove=false
|
||||
for m in attacker.moves
|
||||
if m.canThawUser?
|
||||
hasFreezeMove=true; break
|
||||
end
|
||||
end
|
||||
score*=0 if hasFreezeMove
|
||||
end
|
||||
end
|
||||
end
|
||||
# If target is frozen, don't prefer moves that could thaw them
|
||||
if opponent.status==PBStatuses::FROZEN
|
||||
if (move.type == PBTypes::FIRE)
|
||||
score *= 0.1
|
||||
end
|
||||
end
|
||||
# Adjust score based on how much damage it can deal
|
||||
if move.basedamage>0
|
||||
typemod=pbTypeModNoMessages(bettertype,attacker,opponent,move,skill)
|
||||
if typemod==0 || score<=0
|
||||
score=0
|
||||
elsif skill>=PBTrainerAI.mediumSkill && !(!attacker.abilitynulled &&
|
||||
(attacker.ability == PBAbilities::MOLDBREAKER ||
|
||||
attacker.ability == PBAbilities::TURBOBLAZE ||
|
||||
attacker.ability == PBAbilities::TERAVOLT))
|
||||
if !opponent.abilitynulled
|
||||
if (typemod<=4 && opponent.ability == PBAbilities::WONDERGUARD) ||
|
||||
(move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)) ||
|
||||
(move.type == PBTypes::FIRE && opponent.ability == PBAbilities::FLASHFIRE) ||
|
||||
(move.type == PBTypes::WATER && (opponent.ability == PBAbilities::WATERABSORB || opponent.ability == PBAbilities::STORMDRAIN || opponent.ability == PBAbilities::DRYSKIN)) ||
|
||||
(move.type == PBTypes::GRASS && opponent.ability == PBAbilities::SAPSIPPER) ||
|
||||
(move.type == PBTypes::ELECTRIC)&& (opponent.ability == PBAbilities::VOLTABSORB || opponent.ability == PBAbilities::LIGHTNINGROD || opponent.ability == PBAbilities::MOTORDRIVE)
|
||||
score=0
|
||||
end
|
||||
end
|
||||
else
|
||||
if move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)
|
||||
score=0
|
||||
end
|
||||
end
|
||||
if score != 0
|
||||
# Calculate how much damage the move will do (roughly)
|
||||
realBaseDamage=move.basedamage
|
||||
realBaseDamage=60 if move.basedamage==1
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
realBaseDamage=pbBetterBaseDamage(move,attacker,opponent,skill,realBaseDamage)
|
||||
end
|
||||
end
|
||||
else # non-damaging moves
|
||||
if !opponent.abilitynulled
|
||||
if (move.type == PBTypes::GROUND && (opponent.ability == PBAbilities::LEVITATE || (oppitemworks && opponent.item == PBItems::AIRBALLOON) || opponent.effects[PBEffects::MagnetRise]>0)) ||
|
||||
(move.type == PBTypes::FIRE && opponent.ability == PBAbilities::FLASHFIRE) ||
|
||||
(move.type == PBTypes::WATER && (opponent.ability == PBAbilities::WATERABSORB || opponent.ability == PBAbilities::STORMDRAIN || opponent.ability == PBAbilities::DRYSKIN)) ||
|
||||
(move.type == PBTypes::GRASS && opponent.ability == PBAbilities::SAPSIPPER) ||
|
||||
(move.type == PBTypes::ELECTRIC)&& (opponent.ability == PBAbilities::VOLTABSORB || opponent.ability == PBAbilities::LIGHTNINGROD || opponent.ability == PBAbilities::MOTORDRIVE)
|
||||
score=0
|
||||
end
|
||||
end
|
||||
end
|
||||
accuracy=pbRoughAccuracy(move,attacker,opponent,skill)
|
||||
score*=accuracy/100.0
|
||||
#score=0 if score<=10 && skill>=PBTrainerAI.highSkill
|
||||
if (move.basedamage==0 && !(move.id == PBMoves::NATUREPOWER)) &&
|
||||
(move.target==PBTargets::SingleNonUser || move.target==PBTargets::RandomOpposing ||
|
||||
move.target==PBTargets::AllOpposing || move.target==PBTargets::OpposingSide ||
|
||||
move.target==PBTargets::SingleOpposing || move.target==PBTargets::OppositeOpposing) &&
|
||||
((!opponent.abilitynulled && opponent.ability == PBAbilities::MAGICBOUNCE) ||
|
||||
(!opponent.pbPartner.abilitynulled && opponent.pbPartner.ability == PBAbilities::MAGICBOUNCE))
|
||||
score=0
|
||||
end
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::PRANKSTER)
|
||||
if opponent.pbHasType?(:DARK)
|
||||
if move.basedamage==0 && move.priority>-1
|
||||
score=0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
# Avoid shiny wild pokemon if you're an AI partner
|
||||
if pbIsWild?
|
||||
if attacker.index == 2
|
||||
if opponent.pokemon.isShiny?
|
||||
score *= 0.15
|
||||
end
|
||||
end
|
||||
end
|
||||
score=score.to_i
|
||||
score=0 if score<0
|
||||
PBDebug.log(sprintf("%s: final score: %d",PBMoves.getName(move.id),score)) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
attacker.pbUpdate(true) if defined?(megaEvolved) && megaEvolved==true #perry
|
||||
return score
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Decide whether the opponent should use a Z-Move.
|
||||
##############################################################################
|
||||
def pbEnemyShouldZMove?(index)
|
||||
return pbCanZMove?(index) #Conditions based on effectiveness and type handled later
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
attr_accessor :aiMoveMemory
|
||||
|
||||
alias __ai__initialize initialize
|
||||
def initialize(battle)
|
||||
__ai__initialize(battle)
|
||||
@aiMoveMemory = [[],
|
||||
[],
|
||||
[[], [], [], [], [], [], [], [], [], [], [], []] # One array for each party index
|
||||
]
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# AI Memory utility functions
|
||||
################################################################################
|
||||
def getAIMemory(skill,index=0)
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
return @aiMoveMemory[2][index]
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
return @aiMoveMemory[1]
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
return @aiMoveMemory[0]
|
||||
else
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
||||
def checkAImoves(moveID,memory)
|
||||
#basic "does the other mon have x"
|
||||
return false if memory.length == 0
|
||||
for i in moveID
|
||||
for j in memory
|
||||
j = pbChangeMove(j,nil)#doesn't matter that i'm passing nil, won't get used
|
||||
return true if i == j.id #i should already be an ID here
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIhealing(memory)
|
||||
#less basic "can the other mon heal"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
return true if j.isHealingMove?
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIpriority(memory)
|
||||
#"does the other mon have priority"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
return true if j.priority>0
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIaccuracy(memory)
|
||||
#"does the other mon have moves that don't miss"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
j = pbChangeMove(j,nil)
|
||||
return true if j.accuracy==0
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIdamage(memory,attacker,opponent,skill)
|
||||
#returns how much damage the AI expects to take
|
||||
return -1 if memory.length == 0
|
||||
maxdam=0
|
||||
for j in memory
|
||||
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
|
||||
maxdam=tempdam if tempdam>maxdam
|
||||
end
|
||||
return maxdam
|
||||
end
|
||||
|
||||
def checkAIbest(memory,modifier,type=[],usepower=true,attacker=nil,opponent=nil,skill=nil)
|
||||
return false if memory.length == 0
|
||||
#had to split this because switching ai uses power
|
||||
bestmove = 0
|
||||
if usepower
|
||||
biggestpower = 0
|
||||
for j in memory
|
||||
if j.basedamage>biggestpower
|
||||
biggestpower=j.basedamage
|
||||
bestmove=j
|
||||
end
|
||||
end
|
||||
else #maxdam
|
||||
maxdam=0
|
||||
for j in memory
|
||||
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
|
||||
if tempdam>maxdam
|
||||
maxdam=tempdam
|
||||
bestmove=j
|
||||
end
|
||||
end
|
||||
end
|
||||
return false if bestmove==0
|
||||
#i don't want to make multiple functions for rare cases
|
||||
#we're doing it in one and you're gonna like it
|
||||
case modifier
|
||||
when 1 #type mod. checks types from a list.
|
||||
return true if type.include?(bestmove.type)
|
||||
when 2 #physical mod.
|
||||
return true if bestmove.pbIsPhysical?(bestmove.type)
|
||||
when 3 #special mod.
|
||||
return true if bestmove.pbIsSpecial?(bestmove.type)
|
||||
when 4 #contact mod.
|
||||
return true if bestmove.isContactMove?
|
||||
when 5 #sound mod.
|
||||
return true if bestmove.isSoundBased?
|
||||
when 6 #why.
|
||||
return true if (PBStuff::BULLETMOVE).include?(bestmove.id)
|
||||
end
|
||||
return false #you're still here? it's over! go home.
|
||||
end
|
||||
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,308 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
def pbGetMonRole(mon,opponent,skill,position=0,party=nil)
|
||||
#PBDebug.log(sprintf("Beginning role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
monRoles=[]
|
||||
monability = mon.ability.to_i
|
||||
curemove=false
|
||||
healingmove=false
|
||||
wishmove=false
|
||||
phasemove=false
|
||||
priorityko=false
|
||||
pivotmove=false
|
||||
spinmove=false
|
||||
batonmove=false
|
||||
tauntmove=false
|
||||
restmove=false
|
||||
weathermove=false
|
||||
fieldmove=false
|
||||
if mon.class == PokeBattle_Battler
|
||||
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
|
||||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
|
||||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
|
||||
monRoles.push(PBMonRoles::SWEEPER)
|
||||
end
|
||||
for i in mon.moves
|
||||
next if i.nil?
|
||||
next if i.id == 0
|
||||
if i.priority>0
|
||||
dam=pbRoughDamage(i,mon,opponent,skill,i.basedamage)
|
||||
if opponent.hp>0
|
||||
percentage=(dam*100.0)/opponent.hp
|
||||
priorityko=true if percentage>100
|
||||
end
|
||||
end
|
||||
if i.isHealingMove?
|
||||
healingmove=true
|
||||
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
|
||||
curemove=true
|
||||
elsif (i.id == (PBMoves::WISH))
|
||||
wishmove=true
|
||||
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
|
||||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
|
||||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
|
||||
phasemove=true
|
||||
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
|
||||
pivotmove=true
|
||||
elsif (i.id == (PBMoves::RAPIDSPIN))
|
||||
spinmove=true
|
||||
elsif (i.id == (PBMoves::BATONPASS))
|
||||
batonmove=true
|
||||
elsif (i.id == (PBMoves::TAUNT))
|
||||
tauntmove=true
|
||||
elsif (i.id == (PBMoves::REST))
|
||||
restmove=true
|
||||
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
|
||||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
|
||||
weathermove=true
|
||||
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
|
||||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
|
||||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
|
||||
i.id == (PBMoves::TOPSYTURVY))
|
||||
fieldmove=true
|
||||
end
|
||||
end
|
||||
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
|
||||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
|
||||
mon.nature==PBNatures::LAX))
|
||||
monRoles.push(PBMonRoles::PHYSICALWALL)
|
||||
end
|
||||
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
|
||||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
|
||||
mon.nature==PBNatures::CAREFUL))
|
||||
monRoles.push(PBMonRoles::SPECIALWALL)
|
||||
end
|
||||
if mon.pokemonIndex==0
|
||||
monRoles.push(PBMonRoles::LEAD)
|
||||
end
|
||||
if curemove || (wishmove && mon.ev[0]>251)
|
||||
monRoles.push(PBMonRoles::CLERIC)
|
||||
end
|
||||
if phasemove == true
|
||||
monRoles.push(PBMonRoles::PHAZER)
|
||||
end
|
||||
if mon.item==(PBItems::LIGHTCLAY)
|
||||
monRoles.push(PBMonRoles::SCREENER)
|
||||
end
|
||||
if priorityko || (mon.speed>opponent.speed)
|
||||
monRoles.push(PBMonRoles::REVENGEKILLER)
|
||||
end
|
||||
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
|
||||
monRoles.push(PBMonRoles::PIVOT)
|
||||
end
|
||||
if spinmove
|
||||
monRoles.push(PBMonRoles::SPINNER)
|
||||
end
|
||||
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
|
||||
monRoles.push(PBMonRoles::TANK)
|
||||
end
|
||||
if batonmove
|
||||
monRoles.push(PBMonRoles::BATONPASSER)
|
||||
end
|
||||
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS)
|
||||
monRoles.push(PBMonRoles::STALLBREAKER)
|
||||
end
|
||||
if restmove || (monability == PBAbilities::COMATOSE) ||
|
||||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
|
||||
(monability == PBAbilities::GUTS) ||
|
||||
(monability == PBAbilities::QUICKFEET)||
|
||||
(monability == PBAbilities::FLAREBOOST) ||
|
||||
(monability == PBAbilities::TOXICBOOST) ||
|
||||
(monability == PBAbilities::NATURALCURE) ||
|
||||
(monability == PBAbilities::MAGICGUARD) ||
|
||||
(monability == PBAbilities::MAGICBOUNCE) ||
|
||||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
|
||||
monRoles.push(PBMonRoles::STATUSABSORBER)
|
||||
end
|
||||
if (monability == PBAbilities::SHADOWTAG) ||
|
||||
(monability == PBAbilities::ARENATRAP) ||
|
||||
(monability == PBAbilities::MAGNETPULL)
|
||||
monRoles.push(PBMonRoles::TRAPPER)
|
||||
end
|
||||
if weathermove || (monability == PBAbilities::DROUGHT) ||
|
||||
(monability == PBAbilities::SANDSTREAM) ||
|
||||
(monability == PBAbilities::DRIZZLE) ||
|
||||
(monability == PBAbilities::SNOWWARNING) ||
|
||||
(monability == PBAbilities::PRIMORDIALSEA) ||
|
||||
(monability == PBAbilities::DESOLATELAND) ||
|
||||
(monability == PBAbilities::DELTASTREAM)
|
||||
monRoles.push(PBMonRoles::WEATHERSETTER)
|
||||
end
|
||||
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
|
||||
(monability == PBAbilities::ELECTRICSURGE) ||
|
||||
(monability == PBAbilities::MISTYSURGE) ||
|
||||
(monability == PBAbilities::PSYCHICSURGE) ||
|
||||
mon.item==(PBItems::AMPLIFIELDROCK)
|
||||
monRoles.push(PBMonRoles::FIELDSETTER)
|
||||
end
|
||||
#if $game_switches[525] && mon.pokemonIndex==(pbParty(mon.index).length-1)
|
||||
if mon.pokemonIndex==(pbParty(mon.index).length-1)
|
||||
monRoles.push(PBMonRoles::ACE)
|
||||
end
|
||||
secondhighest=true
|
||||
if pbParty(mon.index).length>2
|
||||
for i in 0..(pbParty(mon.index).length-2)
|
||||
next if pbParty(mon.index)[i].nil?
|
||||
if mon.level<pbParty(mon.index)[i].level
|
||||
secondhighest=false
|
||||
end
|
||||
end
|
||||
end
|
||||
#if $game_switches[525]&& secondhighest
|
||||
if secondhighest
|
||||
monRoles.push(PBMonRoles::SECOND)
|
||||
end
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
elsif mon.class == PokeBattle_Pokemon
|
||||
movelist = []
|
||||
for i in mon.moves
|
||||
next if i.nil?
|
||||
next if i.id == 0
|
||||
movedummy = PokeBattle_Move.pbFromPBMove(self,i,mon)
|
||||
movelist.push(movedummy)
|
||||
end
|
||||
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
|
||||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
|
||||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
|
||||
monRoles.push(PBMonRoles::SWEEPER)
|
||||
end
|
||||
for i in movelist
|
||||
next if i.nil?
|
||||
if i.isHealingMove?
|
||||
healingmove=true
|
||||
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
|
||||
curemove=true
|
||||
elsif (i.id == (PBMoves::WISH))
|
||||
wishmove=true
|
||||
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
|
||||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
|
||||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
|
||||
phasemove=true
|
||||
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
|
||||
pivotmove=true
|
||||
elsif (i.id == (PBMoves::RAPIDSPIN))
|
||||
spinmove=true
|
||||
elsif (i.id == (PBMoves::BATONPASS))
|
||||
batonmove=true
|
||||
elsif(i.id == (PBMoves::TAUNT))
|
||||
tauntmove=true
|
||||
elsif (i.id == (PBMoves::REST))
|
||||
restmove=true
|
||||
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
|
||||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
|
||||
weathermove=true
|
||||
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
|
||||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
|
||||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
|
||||
i.id == (PBMoves::TOPSYTURVY))
|
||||
fieldmove=true
|
||||
end
|
||||
end
|
||||
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
|
||||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
|
||||
mon.nature==PBNatures::LAX))
|
||||
monRoles.push(PBMonRoles::PHYSICALWALL)
|
||||
end
|
||||
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
|
||||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
|
||||
mon.nature==PBNatures::CAREFUL))
|
||||
monRoles.push(PBMonRoles::SPECIALWALL)
|
||||
end
|
||||
if position==0
|
||||
monRoles.push(PBMonRoles::LEAD)
|
||||
end
|
||||
if (phasemove)
|
||||
monRoles.push(PBMonRoles::PHAZER)
|
||||
end
|
||||
if mon.item==(PBItems::LIGHTCLAY)
|
||||
monRoles.push(PBMonRoles::SCREENER)
|
||||
end
|
||||
# pbRoughDamage does not take Pokemon objects, this will cause issues
|
||||
priorityko=false
|
||||
for i in movelist
|
||||
next if i.priority<1
|
||||
next if i.basedamage<10
|
||||
priorityko=true
|
||||
end
|
||||
if priorityko || (mon.speed>opponent.speed)
|
||||
monRoles.push(PBMonRoles::REVENGEKILLER)
|
||||
end
|
||||
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
|
||||
monRoles.push(PBMonRoles::PIVOT)
|
||||
end
|
||||
if spinmove
|
||||
monRoles.push(PBMonRoles::SPINNER)
|
||||
end
|
||||
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
|
||||
monRoles.push(PBMonRoles::TANK)
|
||||
end
|
||||
if batonmove
|
||||
monRoles.push(PBMonRoles::BATONPASSER)
|
||||
end
|
||||
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS)
|
||||
monRoles.push(PBMonRoles::STALLBREAKER)
|
||||
end
|
||||
if restmove || (monability == PBAbilities::COMATOSE) ||
|
||||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
|
||||
(monability == PBAbilities::GUTS) ||
|
||||
(monability == PBAbilities::QUICKFEET) ||
|
||||
(monability == PBAbilities::FLAREBOOST) ||
|
||||
(monability == PBAbilities::TOXICBOOST) ||
|
||||
(monability == PBAbilities::NATURALCURE) ||
|
||||
(monability == PBAbilities::MAGICGUARD) ||
|
||||
(monability == PBAbilities::MAGICBOUNCE) ||
|
||||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
|
||||
monRoles.push(PBMonRoles::STATUSABSORBER)
|
||||
end
|
||||
if (monability == PBAbilities::SHADOWTAG) ||
|
||||
(monability == PBAbilities::ARENATRAP) ||
|
||||
(monability == PBAbilities::MAGNETPULL)
|
||||
monRoles.push(PBMonRoles::TRAPPER)
|
||||
end
|
||||
if weathermove || (monability == PBAbilities::DROUGHT) ||
|
||||
(monability == PBAbilities::SANDSTREAM) ||
|
||||
(monability == PBAbilities::DRIZZLE) ||
|
||||
(monability == PBAbilities::SNOWWARNING) ||
|
||||
(monability == PBAbilities::PRIMORDIALSEA) ||
|
||||
(monability == PBAbilities::DESOLATELAND) ||
|
||||
(monability == PBAbilities::DELTASTREAM)
|
||||
monRoles.push(PBMonRoles::WEATHERSETTER)
|
||||
end
|
||||
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
|
||||
(monability == PBAbilities::ELECTRICSURGE) ||
|
||||
(monability == PBAbilities::MISTYSURGE) ||
|
||||
(monability == PBAbilities::PSYCHICSURGE) ||
|
||||
mon.item==(PBItems::AMPLIFIELDROCK)
|
||||
monRoles.push(PBMonRoles::FIELDSETTER)
|
||||
end
|
||||
if position==(party.length-1)
|
||||
#if $game_switches[525] && position==(party.length-1)
|
||||
monRoles.push(PBMonRoles::ACE)
|
||||
end
|
||||
secondhighest=true
|
||||
if party.length>2
|
||||
for i in 0..(party.length-2)
|
||||
next if party[i].nil?
|
||||
if mon.level<party[i].level
|
||||
secondhighest=false
|
||||
end
|
||||
end
|
||||
end
|
||||
#if $game_switches[525]&& secondhighest
|
||||
if secondhighest
|
||||
monRoles.push(PBMonRoles::SECOND)
|
||||
end
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
end
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,209 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
attr_reader :battleAI
|
||||
|
||||
alias mkai_initialize initialize
|
||||
def initialize(*args)
|
||||
mkai_initialize(*args)
|
||||
@battleAI = MKAI.new(self, self.wildBattle?)
|
||||
@battleAI.sides[0].set_party(@party1)
|
||||
@battleAI.sides[0].set_trainers(@player)
|
||||
@battleAI.sides[1].set_party(@party2)
|
||||
@battleAI.sides[1].set_trainers(@opponent)
|
||||
end
|
||||
|
||||
def pbRecallAndReplace(idxBattler, idxParty, batonPass = false)
|
||||
if !@battlers[idxBattler].fainted?
|
||||
@scene.pbRecall(idxBattler)
|
||||
@battleAI.sides[idxBattler % 2].recall(idxBattler)
|
||||
end
|
||||
@battlers[idxBattler].pbAbilitiesOnSwitchOut # Inc. primordial weather check
|
||||
@scene.pbShowPartyLineup(idxBattler & 1) if pbSideSize(idxBattler) == 1
|
||||
pbMessagesOnReplace(idxBattler, idxParty)
|
||||
pbReplace(idxBattler, idxParty, batonPass)
|
||||
end
|
||||
|
||||
# Bug fix (used b instead of battler)
|
||||
def pbMessageOnRecall(battler)
|
||||
if battler.pbOwnedByPlayer?
|
||||
if battler.hp<=battler.totalhp/4
|
||||
pbDisplayBrief(_INTL("Good job, {1}! Come back!",battler.name))
|
||||
elsif battler.hp<=battler.totalhp/2
|
||||
pbDisplayBrief(_INTL("OK, {1}! Come back!",battler.name))
|
||||
elsif battler.turnCount>=5
|
||||
pbDisplayBrief(_INTL("{1}, that’s enough! Come back!",battler.name))
|
||||
elsif battler.turnCount>=2
|
||||
pbDisplayBrief(_INTL("{1}, come back!",battler.name))
|
||||
else
|
||||
pbDisplayBrief(_INTL("{1}, switch out! Come back!",battler.name))
|
||||
end
|
||||
else
|
||||
owner = pbGetOwnerName(battler.index)
|
||||
pbDisplayBrief(_INTL("{1} withdrew {2}!",owner,battler.name))
|
||||
end
|
||||
end
|
||||
|
||||
alias mkai_pbEndOfRoundPhase pbEndOfRoundPhase
|
||||
def pbEndOfRoundPhase
|
||||
mkai_pbEndOfRoundPhase
|
||||
@battleAI.end_of_round
|
||||
end
|
||||
|
||||
alias mkai_pbShowAbilitySplash pbShowAbilitySplash
|
||||
def pbShowAbilitySplash(battler, delay = false, logTrigger = true)
|
||||
mkai_pbShowAbilitySplash(battler, delay, logTrigger)
|
||||
@battleAI.reveal_ability(battler)
|
||||
end
|
||||
end
|
||||
|
||||
class PokeBattle_Move
|
||||
attr_reader :statUp
|
||||
attr_reader :statDown
|
||||
|
||||
alias mkai_pbReduceDamage pbReduceDamage
|
||||
def pbReduceDamage(user, target)
|
||||
mkai_pbReduceDamage(user, target)
|
||||
@battle.battleAI.register_damage(self, user, target, target.damageState.hpLost)
|
||||
end
|
||||
|
||||
def pbCouldBeCritical?(user, target)
|
||||
return false if target.pbOwnSide.effects[PBEffects::LuckyChant] > 0
|
||||
# Set up the critical hit ratios
|
||||
ratios = (NEWEST_BATTLE_MECHANICS) ? [24,8,2,1] : [16,8,4,3,2]
|
||||
c = 0
|
||||
# Ability effects that alter critical hit rate
|
||||
if c >= 0 && user.abilityActive?
|
||||
c = BattleHandlers.triggerCriticalCalcUserAbility(user.ability, user, target, c)
|
||||
end
|
||||
if c >= 0 && target.abilityActive? && !@battle.moldBreaker
|
||||
c = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability, user, target, c)
|
||||
end
|
||||
# Item effects that alter critical hit rate
|
||||
if c >= 0 && user.itemActive?
|
||||
c = BattleHandlers.triggerCriticalCalcUserItem(user.item, user, target, c)
|
||||
end
|
||||
if c >= 0 && target.itemActive?
|
||||
c = BattleHandlers.triggerCriticalCalcTargetItem(target.item, user, target, c)
|
||||
end
|
||||
return false if c < 0
|
||||
# Move-specific "always/never a critical hit" effects
|
||||
return false if pbCritialOverride(user,target) == -1
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
class MKAI
|
||||
def pbAIRandom(x)
|
||||
return rand(x)
|
||||
end
|
||||
|
||||
def pbDefaultChooseEnemyCommand(idxBattler)
|
||||
sideIndex = idxBattler % 2
|
||||
index = MKAI.battler_to_proj_index(idxBattler)
|
||||
side = @sides[sideIndex]
|
||||
projection = side.battlers[index]
|
||||
# Choose move
|
||||
data = projection.choose_move
|
||||
if data.nil?
|
||||
# Struggle
|
||||
@battle.pbAutoChooseMove(idxBattler)
|
||||
elsif data[0] == :ITEM
|
||||
# [:ITEM, item_id, target&]
|
||||
item = data[1]
|
||||
# Determine target of item (always the Pokémon choosing the action)
|
||||
useType = pbGetItemData(item, ITEM_BATTLE_USE)
|
||||
if data[2]
|
||||
target_index = data[2]
|
||||
else
|
||||
target_index = idxBattler
|
||||
if useType && (useType == 1 || useType == 6) # Use on Pokémon
|
||||
target_index = @battle.battlers[target_index].pokemonIndex # Party Pokémon
|
||||
end
|
||||
end
|
||||
# Register our item
|
||||
@battle.pbRegisterItem(idxBattler, item, target_index)
|
||||
elsif data[0] == :SWITCH
|
||||
# [:SWITCH, pokemon_index]
|
||||
@battle.pbRegisterSwitch(idxBattler, data[1])
|
||||
else
|
||||
# [move_index, move_target]
|
||||
move_index, move_target = data
|
||||
# Mega evolve if we determine that we should
|
||||
@battle.pbRegisterMegaEvolution(idxBattler) if projection.should_mega_evolve?(idxBattler)
|
||||
# Register our move
|
||||
@battle.pbRegisterMove(idxBattler, move_index, false)
|
||||
# Register the move's target
|
||||
@battle.pbRegisterTarget(idxBattler, move_target)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#=============================================================================
|
||||
# Choose a replacement Pokémon
|
||||
#=============================================================================
|
||||
def pbDefaultChooseNewEnemy(idxBattler, party)
|
||||
proj = self.battler_to_projection(@battle.battlers[idxBattler])
|
||||
scores = proj.get_optimal_switch_choice
|
||||
scores.each do |_, _, proj|
|
||||
pkmn = proj.pokemon
|
||||
index = @battle.pbParty(idxBattler).index(pkmn)
|
||||
if @battle.pbCanSwitchLax?(idxBattler, index)
|
||||
return index
|
||||
end
|
||||
end
|
||||
return -1
|
||||
end
|
||||
end
|
||||
|
||||
class PokeBattle_Battler
|
||||
alias mkai_pbInitialize pbInitialize
|
||||
def pbInitialize(pkmn, idxParty, batonPass = false)
|
||||
mkai_pbInitialize(pkmn, idxParty, batonPass)
|
||||
ai = @battle.battleAI
|
||||
sideIndex = @index % 2
|
||||
ai.sides[sideIndex].send_out(@index, self)
|
||||
end
|
||||
|
||||
alias mkai_pbFaint pbFaint
|
||||
def pbFaint(*args)
|
||||
mkai_pbFaint(*args)
|
||||
@battle.battleAI.faint_battler(self)
|
||||
end
|
||||
end
|
||||
|
||||
class PokeBattle_PoisonMove
|
||||
attr_reader :toxic
|
||||
end
|
||||
|
||||
class Array
|
||||
def sum
|
||||
n = 0
|
||||
self.each { |e| n += e }
|
||||
n
|
||||
end
|
||||
end
|
||||
|
||||
# Overwrite Frisk to show the enemy held item
|
||||
BattleHandlers::AbilityOnSwitchIn.add(:FRISK,
|
||||
proc { |ability,battler,battle|
|
||||
foes = []
|
||||
battle.eachOtherSideBattler(battler.index) do |b|
|
||||
foes.push(b) if b.item > 0
|
||||
end
|
||||
if foes.length > 0
|
||||
battle.pbShowAbilitySplash(battler)
|
||||
if NEWEST_BATTLE_MECHANICS
|
||||
foes.each do |b|
|
||||
battle.pbDisplay(_INTL("{1} frisked {2} and found its {3}!",
|
||||
battler.pbThis, b.pbThis(true), PBItems.getName(b.item)))
|
||||
battle.battleAI.reveal_item(b)
|
||||
end
|
||||
else
|
||||
foe = foes[battle.pbRandom(foes.length)]
|
||||
battle.pbDisplay(_INTL("{1} frisked the foe and found one {2}!",
|
||||
battler.pbThis, PBItems.getName(foe.item)))
|
||||
battle.battleAI.reveal_item(foe)
|
||||
end
|
||||
battle.pbHideAbilitySplash(battler)
|
||||
end
|
||||
}
|
||||
)
|
||||
@@ -1,133 +0,0 @@
|
||||
class MKAI
|
||||
attr_reader :battle
|
||||
attr_reader :sides
|
||||
|
||||
def initialize(battle, wild_battle)
|
||||
@battle = battle
|
||||
@sides = [Side.new(self, 0), Side.new(self, 1, wild_battle)]
|
||||
MKAI.log("AI initialized")
|
||||
end
|
||||
|
||||
def self.battler_to_proj_index(battlerIndex)
|
||||
if battlerIndex % 2 == 0 # Player side: 0, 2, 4 -> 0, 1, 2
|
||||
return battlerIndex / 2
|
||||
else # Opponent side: 1, 3, 5 -> 0, 1, 2
|
||||
return (battlerIndex - 1) / 2
|
||||
end
|
||||
end
|
||||
|
||||
def self.weighted_rand(weights)
|
||||
num = rand(weights.sum)
|
||||
for i in 0...weights.size
|
||||
if num < weights[i]
|
||||
return i
|
||||
else
|
||||
num -= weights[i]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def self.get_weights(factor, weights)
|
||||
avg = weights.sum / weights.size.to_f
|
||||
newweights = weights.map do |e|
|
||||
diff = e - avg
|
||||
next [0, ((e - diff * factor) * 100).round].max
|
||||
end
|
||||
return newweights
|
||||
end
|
||||
|
||||
def self.weighted_factored_rand(factor, weights)
|
||||
avg = weights.sum / weights.size.to_f
|
||||
newweights = weights.map do |e|
|
||||
diff = e - avg
|
||||
next [0, ((e - diff * factor) * 100).round].max
|
||||
end
|
||||
return weighted_rand(newweights)
|
||||
end
|
||||
|
||||
def self.log(msg)
|
||||
echoln msg
|
||||
end
|
||||
|
||||
def battler_to_projection(battler)
|
||||
@sides.each do |side|
|
||||
side.battlers.each do |projection|
|
||||
if projection && projection.pokemon == battler.pokemon
|
||||
return projection
|
||||
end
|
||||
end
|
||||
side.party.each do |projection|
|
||||
if projection && projection.pokemon == battler.pokemon
|
||||
return projection
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def pokemon_to_projection(pokemon)
|
||||
@sides.each do |side|
|
||||
side.battlers.each do |projection|
|
||||
if projection && projection.pokemon == pokemon
|
||||
return projection
|
||||
end
|
||||
end
|
||||
side.party.each do |projection|
|
||||
if projection && projection.pokemon == pokemon
|
||||
return projection
|
||||
end
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def register_damage(move, user, target, damage)
|
||||
user = battler_to_projection(user)
|
||||
target = battler_to_projection(target)
|
||||
user.register_damage_dealt(move, target, damage)
|
||||
target.register_damage_taken(move, user, damage)
|
||||
end
|
||||
|
||||
def faint_battler(battler)
|
||||
# Remove the battler from the AI's list of the active battlers
|
||||
@sides.each do |side|
|
||||
side.battlers.each_with_index do |proj, index|
|
||||
if proj && proj.battler == battler
|
||||
# Decouple the projection from the battler
|
||||
side.recall(battler.index)
|
||||
side.battlers[index] = nil
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def end_of_round
|
||||
@sides.each { |side| side.end_of_round }
|
||||
end
|
||||
|
||||
def reveal_ability(battler)
|
||||
@sides.each do |side|
|
||||
side.battlers.each do |proj|
|
||||
if proj && proj.battler == battler && !proj.revealed_ability
|
||||
proj.revealed_ability = true
|
||||
MKAI.log("#{proj.pokemon.name}'s ability was revealed.")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def reveal_item(battler)
|
||||
@sides.each do |side|
|
||||
side.battlers.each do |proj|
|
||||
if proj.battler == battler && !proj.revealed_item
|
||||
proj.revealed_item = true
|
||||
MKAI.log("#{proj.pokemon.name}'s item was revealed.")
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,68 +0,0 @@
|
||||
class MKAI
|
||||
class Side
|
||||
attr_reader :ai
|
||||
attr_reader :index
|
||||
attr_reader :battlers
|
||||
attr_reader :party
|
||||
attr_reader :trainers
|
||||
attr_reader :flags
|
||||
|
||||
def initialize(ai, index, wild_pokemon = false)
|
||||
@ai = ai
|
||||
@index = index
|
||||
@battle = @ai.battle
|
||||
@wild_pokemon = wild_pokemon
|
||||
@battlers = []
|
||||
@party = []
|
||||
@flags = {}
|
||||
end
|
||||
|
||||
def effects
|
||||
return @battle.sides[@index].effects
|
||||
end
|
||||
|
||||
def set_party(party)
|
||||
@party = party.map { |pokemon| BattlerProjection.new(self, pokemon, @wild_pokemon) }
|
||||
end
|
||||
|
||||
def set_trainers(trainers)
|
||||
@trainers = trainers
|
||||
end
|
||||
|
||||
def opposing_side
|
||||
return @ai.sides[1 - @index]
|
||||
end
|
||||
|
||||
def recall(battlerIndex)
|
||||
index = MKAI.battler_to_proj_index(battlerIndex)
|
||||
proj = @battlers[index]
|
||||
if proj.nil?
|
||||
raise "Battler to be recalled was not found in the active battlers list."
|
||||
end
|
||||
if !proj.active?
|
||||
raise "Battler to be recalled was not active."
|
||||
end
|
||||
@battlers[index] = nil
|
||||
proj.battler = nil
|
||||
end
|
||||
|
||||
def send_out(battlerIndex, battler)
|
||||
proj = @party.find { |proj| proj && proj.pokemon == battler.pokemon }
|
||||
if proj.nil?
|
||||
raise "Battler to be sent-out was not found in the party list."
|
||||
end
|
||||
if proj.active?
|
||||
raise "Battler to be sent-out was already sent out before."
|
||||
end
|
||||
index = MKAI.battler_to_proj_index(battlerIndex)
|
||||
@battlers[index] = proj
|
||||
proj.ai_index = index
|
||||
proj.battler = battler
|
||||
end
|
||||
|
||||
def end_of_round
|
||||
@battlers.each { |proj| proj.end_of_round if proj }
|
||||
@flags = {}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,92 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
# AI skill levels:
|
||||
# 0: Wild Pokémon
|
||||
# 1-31: Basic trainer (young/inexperienced)
|
||||
# 32-47: Some skill
|
||||
# 48-99: High skill
|
||||
# 100+: Best trainers (Gym Leaders, Elite Four, Champion)
|
||||
# NOTE: A trainer's skill value can range from 0-255, but by default only four
|
||||
# distinct skill levels exist. The skill value is typically the same as
|
||||
# the trainer's base money value.
|
||||
module AILevel
|
||||
# Minimum skill level to be in each AI skill bracket.
|
||||
def self.minimum; return 1; end
|
||||
def self.medium; return 32; end
|
||||
def self.high; return 48; end
|
||||
def self.best; return 100; end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
def initialize(battle)
|
||||
@battle = battle
|
||||
@skill = 0
|
||||
@user = nil
|
||||
@wildBattler = @battle.wildBattle? # Whether AI is choosing for a wild Pokémon
|
||||
@roles = [Array.new(@battle.pbParty(0).length) { |i| determine_roles(0, i) },
|
||||
Array.new(@battle.pbParty(1).length) { |i| determine_roles(1, i) }]
|
||||
end
|
||||
|
||||
def pbAIRandom(x); return rand(x); end
|
||||
|
||||
def pbStdDev(choices)
|
||||
sum = 0
|
||||
n = 0
|
||||
choices.each do |c|
|
||||
sum += c[1]
|
||||
n += 1
|
||||
end
|
||||
return 0 if n<2
|
||||
mean = sum.to_f/n.to_f
|
||||
varianceTimesN = 0
|
||||
choices.each do |c|
|
||||
next if c[1]<=0
|
||||
deviation = c[1].to_f-mean
|
||||
varianceTimesN += deviation*deviation
|
||||
end
|
||||
# Using population standard deviation
|
||||
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
|
||||
return Math.sqrt(varianceTimesN/n)
|
||||
end
|
||||
|
||||
# Decide whether the opponent should Mega Evolve their Pokémon
|
||||
def pbEnemyShouldMegaEvolve?
|
||||
if @battle.pbCanMegaEvolve?(@user.index) # Simple "always should if possible"
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will Mega Evolve")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Choose an action
|
||||
def pbDefaultChooseEnemyCommand(idxBattler)
|
||||
set_up(idxBattler)
|
||||
choices = pbGetMoveScores
|
||||
return if pbEnemyShouldUseItem?
|
||||
return if pbEnemyShouldWithdraw?
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?
|
||||
pbChooseMove(choices)
|
||||
end
|
||||
|
||||
# Set some class variables for the Pokémon whose action is being chosen
|
||||
def set_up(idxBattler)
|
||||
# TODO: Where relevant, pretend the user is Mega Evolved if it isn't but can
|
||||
# be.
|
||||
@user = @battle.battlers[idxBattler]
|
||||
@wildBattler = (@battle.wildBattle? && @user.opposes?)
|
||||
@skill = 0
|
||||
if !@wildBattler
|
||||
@skill = @battle.pbGetOwnerFromBattlerIndex(@user.index).skill || 0
|
||||
@skill = AILevel.minimum if @skill < AILevel.minimum
|
||||
end
|
||||
end
|
||||
|
||||
def skill_check(threshold)
|
||||
return @skill >= threshold
|
||||
end
|
||||
end
|
||||
@@ -1,170 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should use an item on the Pokémon
|
||||
#=============================================================================
|
||||
def pbEnemyShouldUseItem?
|
||||
item, idxTarget = pbEnemyItemToUse
|
||||
return false if !item
|
||||
# Determine target of item (always the Pokémon choosing the action)
|
||||
useType = GameData::Item.get(item).battle_use
|
||||
if useType==1 || useType==6 # Use on Pokémon
|
||||
idxTarget = @battle.battlers[idxTarget].pokemonIndex # Party Pokémon
|
||||
end
|
||||
# Register use of item
|
||||
@battle.pbRegisterItem(@user.index,item,idxTarget)
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use item #{GameData::Item.get(item).name}")
|
||||
return true
|
||||
end
|
||||
|
||||
# NOTE: The AI will only consider using an item on the Pokémon it's currently
|
||||
# choosing an action for.
|
||||
def pbEnemyItemToUse
|
||||
return nil if !@battle.internalBattle
|
||||
items = @battle.pbGetOwnerItems(@user.index)
|
||||
return nil if !items || items.length==0
|
||||
# Determine target of item (always the Pokémon choosing the action)
|
||||
idxTarget = @user.index # Battler using the item
|
||||
battler = @battle.battlers[idxTarget]
|
||||
pkmn = battler.pokemon
|
||||
# Item categories
|
||||
hpItems = {
|
||||
:POTION => 20,
|
||||
:SUPERPOTION => 50,
|
||||
:HYPERPOTION => 200,
|
||||
:MAXPOTION => 999,
|
||||
:BERRYJUICE => 20,
|
||||
:SWEETHEART => 20,
|
||||
:FRESHWATER => 50,
|
||||
:SODAPOP => 60,
|
||||
:LEMONADE => 80,
|
||||
:MOOMOOMILK => 100,
|
||||
:ORANBERRY => 10,
|
||||
:SITRUSBERRY => battler.totalhp/4,
|
||||
:ENERGYPOWDER => 50,
|
||||
:ENERGYROOT => 200
|
||||
}
|
||||
hpItems[:RAGECANDYBAR] = 20 if !NEWEST_BATTLE_MECHANICS
|
||||
fullRestoreItems = [
|
||||
:FULLRESTORE
|
||||
]
|
||||
oneStatusItems = [ # Preferred over items that heal all status problems
|
||||
:AWAKENING, :CHESTOBERRY, :BLUEFLUTE,
|
||||
:ANTIDOTE, :PECHABERRY,
|
||||
:BURNHEAL, :RAWSTBERRY,
|
||||
:PARALYZEHEAL, :PARLYZHEAL, :CHERIBERRY,
|
||||
:ICEHEAL, :ASPEARBERRY
|
||||
]
|
||||
allStatusItems = [
|
||||
:FULLHEAL, :LAVACOOKIE, :OLDGATEAU, :CASTELIACONE, :LUMIOSEGALETTE,
|
||||
:SHALOURSABLE, :BIGMALASADA, :LUMBERRY, :HEALPOWDER
|
||||
]
|
||||
allStatusItems.push(:RAGECANDYBAR) if NEWEST_BATTLE_MECHANICS
|
||||
xItems = {
|
||||
:XATTACK => [PBStats::ATTACK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XATTACK2 => [PBStats::ATTACK, 2],
|
||||
:XATTACK3 => [PBStats::ATTACK, 3],
|
||||
:XATTACK6 => [PBStats::ATTACK, 6],
|
||||
:XDEFENSE => [PBStats::DEFENSE, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XDEFENSE2 => [PBStats::DEFENSE, 2],
|
||||
:XDEFENSE3 => [PBStats::DEFENSE, 3],
|
||||
:XDEFENSE6 => [PBStats::DEFENSE, 6],
|
||||
:XDEFEND => [PBStats::DEFENSE, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XDEFEND2 => [PBStats::DEFENSE, 2],
|
||||
:XDEFEND3 => [PBStats::DEFENSE, 3],
|
||||
:XDEFEND6 => [PBStats::DEFENSE, 6],
|
||||
:XSPATK => [PBStats::SPATK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPATK2 => [PBStats::SPATK, 2],
|
||||
:XSPATK3 => [PBStats::SPATK, 3],
|
||||
:XSPATK6 => [PBStats::SPATK, 6],
|
||||
:XSPECIAL => [PBStats::SPATK, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPECIAL2 => [PBStats::SPATK, 2],
|
||||
:XSPECIAL3 => [PBStats::SPATK, 3],
|
||||
:XSPECIAL6 => [PBStats::SPATK, 6],
|
||||
:XSPDEF => [PBStats::SPDEF, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPDEF2 => [PBStats::SPDEF, 2],
|
||||
:XSPDEF3 => [PBStats::SPDEF, 3],
|
||||
:XSPDEF6 => [PBStats::SPDEF, 6],
|
||||
:XSPEED => [PBStats::SPEED, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XSPEED2 => [PBStats::SPEED, 2],
|
||||
:XSPEED3 => [PBStats::SPEED, 3],
|
||||
:XSPEED6 => [PBStats::SPEED, 6],
|
||||
:XACCURACY => [PBStats::ACCURACY, (NEWEST_BATTLE_MECHANICS) ? 2 : 1],
|
||||
:XACCURACY2 => [PBStats::ACCURACY, 2],
|
||||
:XACCURACY3 => [PBStats::ACCURACY, 3],
|
||||
:XACCURACY6 => [PBStats::ACCURACY, 6]
|
||||
}
|
||||
losthp = battler.totalhp - battler.hp
|
||||
preferFullRestore = (battler.hp <= battler.totalhp * 2 / 3 &&
|
||||
(battler.status != PBStatuses::NONE || battler.effects[PBEffects::Confusion] > 0))
|
||||
# Find all usable items
|
||||
usableHPItems = []
|
||||
usableStatusItems = []
|
||||
usableXItems = []
|
||||
items.each do |i|
|
||||
next if !i
|
||||
next if !@battle.pbCanUseItemOnPokemon?(i,pkmn,battler,@battle.scene,false)
|
||||
next if !ItemHandlers.triggerCanUseInBattle(i,pkmn,battler,nil,
|
||||
false,self,@battle.scene,false)
|
||||
# Log HP healing items
|
||||
if losthp > 0
|
||||
power = hpItems[i]
|
||||
if power
|
||||
usableHPItems.push([i, 5, power])
|
||||
next
|
||||
end
|
||||
end
|
||||
# Log Full Restores (HP healer and status curer)
|
||||
if losthp > 0 || battler.status != PBStatuses::NONE
|
||||
if fullRestoreItems.include?(i)
|
||||
usableHPItems.push([i, (preferFullRestore) ? 3 : 7, 999])
|
||||
usableStatusItems.push([i, (preferFullRestore) ? 3 : 9])
|
||||
next
|
||||
end
|
||||
end
|
||||
# Log single status-curing items
|
||||
if oneStatusItems.include?(i)
|
||||
usableStatusItems.push([i, 5])
|
||||
next
|
||||
end
|
||||
# Log Full Heal-type items
|
||||
if allStatusItems.include?(i)
|
||||
usableStatusItems.push([i, 7])
|
||||
next
|
||||
end
|
||||
# Log stat-raising items
|
||||
if xItems[i]
|
||||
data = xItems[i]
|
||||
usableXItems.push([i, battler.stages[data[0]], data[1]])
|
||||
next
|
||||
end
|
||||
end
|
||||
# Prioritise using a HP restoration item
|
||||
if usableHPItems.length>0 && (battler.hp<=battler.totalhp/4 ||
|
||||
(battler.hp<=battler.totalhp/2 && pbAIRandom(100)<30))
|
||||
usableHPItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
|
||||
prevItem = nil
|
||||
usableHPItems.each do |i|
|
||||
return i[0], idxTarget if i[2]>=losthp
|
||||
prevItem = i
|
||||
end
|
||||
return prevItem[0], idxTarget
|
||||
end
|
||||
# Next prioritise using a status-curing item
|
||||
if usableStatusItems.length>0 && pbAIRandom(100)<40
|
||||
usableStatusItems.sort! { |a,b| a[1]<=>b[1] }
|
||||
return usableStatusItems[0][0], idxTarget
|
||||
end
|
||||
# Next try using an X item
|
||||
if usableXItems.length>0 && pbAIRandom(100)<30
|
||||
usableXItems.sort! { |a,b| (a[1]==b[1]) ? a[2]<=>b[2] : a[1]<=>b[1] }
|
||||
prevItem = nil
|
||||
usableXItems.each do |i|
|
||||
break if prevItem && i[1]>prevItem[1]
|
||||
return i[0], idxTarget if i[1]+i[2]>=6
|
||||
prevItem = i
|
||||
end
|
||||
return prevItem[0], idxTarget
|
||||
end
|
||||
return nil
|
||||
end
|
||||
end
|
||||
@@ -1,178 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should switch Pokémon
|
||||
#=============================================================================
|
||||
def pbEnemyShouldWithdraw?
|
||||
return pbEnemyShouldWithdrawEx?(false)
|
||||
end
|
||||
|
||||
def pbEnemyShouldWithdrawEx?(forceSwitch)
|
||||
return false if @wildBattler
|
||||
shouldSwitch = forceSwitch
|
||||
batonPass = -1
|
||||
moveType = nil
|
||||
# If Pokémon is within 6 levels of the foe, and foe's last move was
|
||||
# super-effective and powerful
|
||||
if !shouldSwitch && @user.turnCount > 0 && skill_check(AILevel.high)
|
||||
target = @user.pbDirectOpposing(true)
|
||||
if !target.fainted? && target.lastMoveUsed &&
|
||||
(target.level - @user.level).abs <= 6
|
||||
moveData = GameData::Move.get(target.lastMoveUsed)
|
||||
moveType = moveData.type
|
||||
typeMod = pbCalcTypeMod(moveType, target, @user)
|
||||
if PBTypeEffectiveness.superEffective?(typeMod) && moveData.base_damage > 50
|
||||
switchChance = (moveData.base_damage > 70) ? 30 : 20
|
||||
shouldSwitch = (pbAIRandom(100) < switchChance)
|
||||
end
|
||||
end
|
||||
end
|
||||
# Pokémon can't do anything (must have been in battle for at least 5 rounds)
|
||||
if !@battle.pbCanChooseAnyMove?(@user.index) &&
|
||||
@user.turnCount && @user.turnCount>=5
|
||||
shouldSwitch = true
|
||||
end
|
||||
# Pokémon is Perish Songed and has Baton Pass
|
||||
if skill_check(AILevel.high) && @user.effects[PBEffects::PerishSong]==1
|
||||
@user.eachMoveWithIndex do |m,i|
|
||||
next if m.function!="0ED" # Baton Pass
|
||||
next if !@battle.pbCanChooseMove?(@user.index,i,false)
|
||||
batonPass = i
|
||||
break
|
||||
end
|
||||
end
|
||||
# Pokémon will faint because of bad poisoning at the end of this round, but
|
||||
# would survive at least one more round if it were regular poisoning instead
|
||||
if @user.status==PBStatuses::POISON && @user.statusCount>0 &&
|
||||
skill_check(AILevel.high)
|
||||
toxicHP = @user.totalhp/16
|
||||
nextToxicHP = toxicHP*(@user.effects[PBEffects::Toxic]+1)
|
||||
if @user.hp<=nextToxicHP && @user.hp>toxicHP*2
|
||||
shouldSwitch = true if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
# Pokémon is Encored into an unfavourable move
|
||||
if @user.effects[PBEffects::Encore]>0 && skill_check(AILevel.medium)
|
||||
idxEncoredMove = @user.pbEncoredMoveIndex
|
||||
if idxEncoredMove>=0
|
||||
scoreSum = 0
|
||||
scoreCount = 0
|
||||
@user.eachOpposing do |b|
|
||||
scoreSum += pbGetMoveScore(@user.moves[idxEncoredMove],b)
|
||||
scoreCount += 1
|
||||
end
|
||||
if scoreCount>0 && scoreSum/scoreCount<=20
|
||||
shouldSwitch = true if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
end
|
||||
# If there is a single foe and it is resting after Hyper Beam or is
|
||||
# Truanting (i.e. free turn)
|
||||
if @battle.pbSideSize(@user.index+1)==1 &&
|
||||
!@user.pbDirectOpposing.fainted? && skill_check(AILevel.high)
|
||||
opp = @user.pbDirectOpposing
|
||||
if opp.effects[PBEffects::HyperBeam]>0 ||
|
||||
(opp.hasActiveAbility?(:TRUANT) && opp.effects[PBEffects::Truant])
|
||||
shouldSwitch = false if pbAIRandom(100)<80
|
||||
end
|
||||
end
|
||||
# Sudden Death rule - I'm not sure what this means
|
||||
if @battle.rules["suddendeath"] && @user.turnCount>0
|
||||
if @user.hp<=@user.totalhp/4 && pbAIRandom(100)<30
|
||||
shouldSwitch = true
|
||||
elsif @user.hp<=@user.totalhp/2 && pbAIRandom(100)<80
|
||||
shouldSwitch = true
|
||||
end
|
||||
end
|
||||
# Pokémon is about to faint because of Perish Song
|
||||
if @user.effects[PBEffects::PerishSong]==1
|
||||
shouldSwitch = true
|
||||
end
|
||||
if shouldSwitch
|
||||
list = []
|
||||
@battle.pbParty(@user.index).each_with_index do |pkmn,i|
|
||||
next if !@battle.pbCanSwitch?(@user.index,i)
|
||||
# If perish count is 1, it may be worth it to switch
|
||||
# even with Spikes, since Perish Song's effect will end
|
||||
if @user.effects[PBEffects::PerishSong]!=1
|
||||
# Will contain effects that recommend against switching
|
||||
spikes = @user.pbOwnSide.effects[PBEffects::Spikes]
|
||||
# Don't switch to this if too little HP
|
||||
if spikes>0
|
||||
spikesDmg = [8,6,4][spikes-1]
|
||||
if pkmn.hp<=pkmn.totalhp/spikesDmg
|
||||
next if !pkmn.hasType?(:FLYING) && !pkmn.hasActiveAbility?(:LEVITATE)
|
||||
end
|
||||
end
|
||||
end
|
||||
# moveType is the type of the target's last used move
|
||||
if moveType && PBTypeEffectiveness.ineffective?(pbCalcTypeMod(moveType,@user,@user))
|
||||
weight = 65
|
||||
typeMod = pbCalcTypeModPokemon(pkmn,@user.pbDirectOpposing(true))
|
||||
if PBTypeEffectiveness.superEffective?(typeMod)
|
||||
# Greater weight if new Pokemon's type is effective against target
|
||||
weight = 85
|
||||
end
|
||||
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
|
||||
elsif moveType && PBTypeEffectiveness.resistant?(pbCalcTypeMod(moveType,@user,@user))
|
||||
weight = 40
|
||||
typeMod = pbCalcTypeModPokemon(pkmn,@user.pbDirectOpposing(true))
|
||||
if PBTypeEffectiveness.superEffective?(typeMod)
|
||||
# Greater weight if new Pokemon's type is effective against target
|
||||
weight = 60
|
||||
end
|
||||
list.unshift(i) if pbAIRandom(100)<weight # Put this Pokemon first
|
||||
else
|
||||
list.push(i) # put this Pokemon last
|
||||
end
|
||||
end
|
||||
if list.length>0
|
||||
if batonPass>=0 && @battle.pbRegisterMove(@user.index,batonPass,false)
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use Baton Pass to avoid Perish Song")
|
||||
return true
|
||||
end
|
||||
if @battle.pbRegisterSwitch(@user.index,list[0])
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will switch with " +
|
||||
"#{@battle.pbParty(@user.index)[list[0]].name}")
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Choose a replacement Pokémon (called directly from @battle, not part of
|
||||
# action choosing)
|
||||
#=============================================================================
|
||||
def pbDefaultChooseNewEnemy(idxBattler,party)
|
||||
set_up(idxBattler)
|
||||
enemies = []
|
||||
party.each_with_index do |_p,i|
|
||||
enemies.push(i) if @battle.pbCanSwitchLax?(idxBattler,i)
|
||||
end
|
||||
return -1 if enemies.length==0
|
||||
return pbChooseBestNewEnemy(idxBattler,party,enemies)
|
||||
end
|
||||
|
||||
def pbChooseBestNewEnemy(idxBattler,party,enemies)
|
||||
return -1 if !enemies || enemies.length==0
|
||||
best = -1
|
||||
bestSum = 0
|
||||
enemies.each do |i|
|
||||
pkmn = party[i]
|
||||
sum = 0
|
||||
pkmn.moves.each do |m|
|
||||
next if m.base_damage == 0
|
||||
@battle.battlers[idxBattler].eachOpposing do |b|
|
||||
bTypes = b.pbTypes(true)
|
||||
sum += PBTypes.getCombinedEffectiveness(m.type, bTypes[0], bTypes[1], bTypes[2])
|
||||
end
|
||||
end
|
||||
if best==-1 || sum>bestSum
|
||||
best = i
|
||||
bestSum = sum
|
||||
end
|
||||
end
|
||||
return best
|
||||
end
|
||||
end
|
||||
@@ -1,497 +0,0 @@
|
||||
<<<class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Main move-choosing method (moves with higher scores are more likely to be
|
||||
# chosen)
|
||||
#=============================================================================
|
||||
def pbChooseMove(choices)
|
||||
# Figure out useful information about the choices
|
||||
totalScore = 0
|
||||
maxScore = 0
|
||||
choices.each do |c|
|
||||
totalScore += c[1]
|
||||
maxScore = c[1] if maxScore < c[1]
|
||||
end
|
||||
|
||||
# Find any preferred moves and just choose from them
|
||||
if skill_check(AILevel.high) && maxScore > 100
|
||||
stDev = pbStdDev(choices)
|
||||
if stDev >= 40 && pbAIRandom(100) < 90
|
||||
preferredMoves = []
|
||||
choices.each do |c|
|
||||
next if c[1] < 200 && c[1] < maxScore * 0.8
|
||||
preferredMoves.push(c)
|
||||
preferredMoves.push(c) if c[1] == maxScore # Doubly prefer the best move
|
||||
end
|
||||
if preferredMoves.length > 0
|
||||
m = preferredMoves[pbAIRandom(preferredMoves.length)]
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) prefers #{@user.moves[m[0]].name}")
|
||||
@battle.pbRegisterMove(@user.index, m[0], false)
|
||||
@battle.pbRegisterTarget(@user.index, m[2]) if m[2] >= 0
|
||||
return
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Decide whether all choices are bad, and if so, try switching instead
|
||||
if !@wildBattler && skill_check(AILevel.high)
|
||||
badMoves = false
|
||||
if (maxScore <= 20 && @user.turnCount > 2) ||
|
||||
(maxScore <= 40 && @user.turnCount > 5)
|
||||
badMoves = true if pbAIRandom(100) < 80
|
||||
end
|
||||
if !badMoves && totalScore < 100 && @user.turnCount > 1
|
||||
badMoves = true
|
||||
choices.each do |c|
|
||||
next if !@user.moves[c[0]].damagingMove?
|
||||
badMoves = false
|
||||
break
|
||||
end
|
||||
badMoves = false if badMoves && pbAIRandom(100) < 10
|
||||
end
|
||||
if badMoves && pbEnemyShouldWithdrawEx?(true)
|
||||
if $INTERNAL
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will switch due to terrible moves")
|
||||
end
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# If there are no calculated choices, pick one at random
|
||||
if choices.length == 0
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) doesn't want to use any moves; picking one at random")
|
||||
@user.eachMoveWithIndex do |_m, i|
|
||||
next if !@battle.pbCanChooseMove?(@user.index, i, false)
|
||||
choices.push([i, 100, -1]) # Move index, score, target
|
||||
end
|
||||
if choices.length == 0 # No moves are physically possible to use; use Struggle
|
||||
@battle.pbAutoChooseMove(@user.index)
|
||||
end
|
||||
end
|
||||
|
||||
# Randomly choose a move from the choices and register it
|
||||
randNum = pbAIRandom(totalScore)
|
||||
choices.each do |c|
|
||||
randNum -= c[1]
|
||||
next if randNum >= 0
|
||||
@battle.pbRegisterMove(@user.index, c[0], false)
|
||||
@battle.pbRegisterTarget(@user.index, c[2]) if c[2] >= 0
|
||||
break
|
||||
end
|
||||
|
||||
# Log the result
|
||||
if @battle.choices[@user.index][2]
|
||||
PBDebug.log("[AI] #{@user.pbThis} (#{@user.index}) will use #{@battle.choices[@user.index][2].name}")
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get scores for the user's moves (done before any action is assessed)
|
||||
# NOTE: A move is only added to the choices array if it has a non-zero score.
|
||||
#=============================================================================
|
||||
def pbGetMoveScores
|
||||
# Get scores and targets for each move
|
||||
choices = []
|
||||
# TODO: Split this into two, the first part being the calculation of all
|
||||
# predicted damages and the second part being the score calculations
|
||||
# (which are based on the predicted damages). Note that this requires
|
||||
# saving each of the scoresAndTargets entries in here rather than in
|
||||
# def pbRegisterMoveTrainer, and only at the very end are they
|
||||
# whittled down to one per move which are chosen from. Multi-target
|
||||
# moves could be fiddly since damages should be calculated for each
|
||||
# target but they're all related.
|
||||
@user.eachMoveWithIndex do |_m, i|
|
||||
next if !@battle.pbCanChooseMove?(@user.index, i, false)
|
||||
if @wildBattler
|
||||
pbRegisterMoveWild(i, choices)
|
||||
else
|
||||
pbRegisterMoveTrainer(i, choices)
|
||||
end
|
||||
end
|
||||
# Log the available choices
|
||||
if $INTERNAL
|
||||
logMsg = "[AI] Move choices for #{@user.pbThis(true)} (#{@user.index}): "
|
||||
choices.each_with_index do |c, i|
|
||||
logMsg += "#{@user.moves[c[0]].name}=#{c[1]}"
|
||||
logMsg += " (target #{c[2]})" if c[2] >= 0
|
||||
logMsg += ", " if i < choices.length-1
|
||||
end
|
||||
PBDebug.log(logMsg)
|
||||
end
|
||||
return choices
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get scores for the given move against each possible target
|
||||
#=============================================================================
|
||||
# Wild Pokémon choose their moves randomly.
|
||||
def pbRegisterMoveWild(idxMove, choices)
|
||||
score = 100
|
||||
# Doubly prefer one of the user's moves (the choice is random but consistent
|
||||
# and does not correlate to any other property of the user)
|
||||
score *= 2 if @user.pokemon.personalID % @user.moves.length == idxMove
|
||||
choices.push([idxMove, score, -1]) # Move index, score, target
|
||||
end
|
||||
|
||||
# Trainer Pokémon calculate how much they want to use each of their moves.
|
||||
def pbRegisterMoveTrainer(idxMove, choices)
|
||||
move = @user.moves[idxMove]
|
||||
targetType = move.pbTarget(@user)
|
||||
# TODO: Alter targetType if user has Protean and move is Curse.
|
||||
if PBTargets.multipleTargets?(targetType)
|
||||
# Move affects multiple battlers and you don't choose a particular one
|
||||
totalScore = 0
|
||||
@battle.eachBattler do |b|
|
||||
next if !@battle.pbMoveCanTarget?(@user.index, b.index, targetType)
|
||||
score = pbGetMoveScore(move, b)
|
||||
totalScore += ((@user.opposes?(b)) ? score : -score)
|
||||
end
|
||||
choices.push([idxMove, totalScore, -1]) if totalScore > 0
|
||||
elsif PBTargets.noTargets?(targetType)
|
||||
# Move has no targets, affects the user, a side or the whole field
|
||||
score = pbGetMoveScore(move)
|
||||
choices.push([idxMove, score, -1]) if score > 0
|
||||
else
|
||||
# Move affects one battler and you have to choose which one
|
||||
scoresAndTargets = []
|
||||
@battle.eachBattler do |b|
|
||||
next if !@battle.pbMoveCanTarget?(@user.index, b.index, targetType)
|
||||
next if PBTargets.canChooseFoeTarget?(targetType) && !@user.opposes?(b)
|
||||
score = pbGetMoveScore(move, b)
|
||||
scoresAndTargets.push([score, b.index]) if score > 0
|
||||
end
|
||||
if scoresAndTargets.length > 0
|
||||
# Get the one best target for the move
|
||||
scoresAndTargets.sort! { |a, b| b[0] <=> a[0] }
|
||||
choices.push([idxMove, scoresAndTargets[0][0], scoresAndTargets[0][1]])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Set some class variables for the move being assessed
|
||||
#=============================================================================
|
||||
def set_up_move_check(move, target)
|
||||
@move = move
|
||||
@target = target
|
||||
# TODO: Calculate pbRoughType once here.
|
||||
# Determine whether user or target is faster, and store that result so it
|
||||
# doesn't need recalculating
|
||||
if @target
|
||||
user_speed = pbRoughStat(@user, PBStats::SPEED)
|
||||
target_speed = pbRoughStat(@target, PBStats::SPEED)
|
||||
@user_faster = (user_speed > target_speed) ^ (@battle.field.effects[PBEffects::TrickRoom] > 0)
|
||||
else
|
||||
@user_faster = false # Won't be used if there is no target
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move being used against the given target
|
||||
#=============================================================================
|
||||
def pbGetMoveScore(move, target = nil)
|
||||
set_up_move_check(move, target)
|
||||
|
||||
# Get the base score for the move
|
||||
if @move.damagingMove?
|
||||
# Is also the predicted damage amount as a percentage of target's current HP
|
||||
score = pbGetDamagingMoveBaseScore
|
||||
else # Status moves
|
||||
# Depends on the move's effect
|
||||
score = pbGetStatusMoveBaseScore
|
||||
end
|
||||
# Modify the score according to the move's effect
|
||||
score = pbGetMoveScoreFunctions(score)
|
||||
|
||||
# A score of 0 here means it absolutely should not be used
|
||||
return 0 if score <= 0
|
||||
|
||||
# TODO: High priority checks:
|
||||
# => Prefer move if it will KO the target (moreso if user is slower than target)
|
||||
# => Don't prefer damaging move if it won't KO, user has Stance Change and
|
||||
# is in shield form, and user is slower than the target
|
||||
# => Check memory for past damage dealt by a target's non-high priority move,
|
||||
# and prefer move if user is slower than the target and another hit from
|
||||
# the same amount will KO the user
|
||||
# => Check memory for past damage dealt by a target's priority move, and don't
|
||||
# prefer the move if user is slower than the target and can't move faster
|
||||
# than it because of priority
|
||||
# => Discard move if user is slower than the target and target is semi-
|
||||
# invulnerable (and move won't hit it)
|
||||
# => Check memory for whether target has previously used Quick Guard, and
|
||||
# don't prefer move if so
|
||||
|
||||
# TODO: Low priority checks:
|
||||
# => Don't prefer move if user is faster than the target
|
||||
# => Prefer move if user is faster than the target and target is semi-
|
||||
# invulnerable
|
||||
|
||||
# Don't prefer a dancing move if the target has the Dancer ability
|
||||
# TODO: Check all battlers, not just the target.
|
||||
if skill_check(AILevel.high) && @move.danceMove? && @target.hasActiveAbility?(:DANCER)
|
||||
score /= 2
|
||||
end
|
||||
|
||||
# TODO: Check memory for whether target has previously used Ion Deluge, and
|
||||
# don't prefer move if it's Normal-type and target is immune because
|
||||
# of its ability (Lightning Rod, etc.).
|
||||
|
||||
# TODO: Discard move if it can be redirected by a non-target's ability
|
||||
# (Lightning Rod/Storm Drain). Include checking for a previous use of
|
||||
# Ion Deluge and this move being Normal-type.
|
||||
# => If non-target is a user's ally, don't prefer move (rather than discarding
|
||||
# it)
|
||||
|
||||
# TODO: Discard move if it's sound-based and user has been Throat Chopped.
|
||||
# Don't prefer move if user hasn't been Throat Chopped but target has
|
||||
# previously used Throat Chop. The first part of this would probably
|
||||
# go elsewhere (damage calc?).
|
||||
|
||||
# TODO: Prefer move if it has a high critical hit rate, critical hits are
|
||||
# possible but not certain, and target has raised defences/user has
|
||||
# lowered offences (Atk/Def or SpAtk/SpDef, whichever is relevant).
|
||||
|
||||
# TODO: Don't prefer damaging moves if target is Destiny Bonding.
|
||||
# => Also don't prefer damaging moves if user is slower than the target, move
|
||||
# is likely to be lethal, and target has previously used Destiny Bond
|
||||
|
||||
# TODO: Don't prefer a move that is stopped by Wide Guard if target has
|
||||
# previously used Wide Guard.
|
||||
|
||||
# TODO: Don't prefer Fire-type moves if target has previously used Powder.
|
||||
|
||||
# TODO: Don't prefer contact move if making contact with the target could
|
||||
# trigger an effect that's bad for the user (Static, etc.).
|
||||
# => Also check if target has previously used Spiky Shield.King's Shield/
|
||||
# Baneful Bunker, and don't prefer move if so
|
||||
|
||||
# TODO: Prefer a contact move if making contact with the target could trigger
|
||||
# an effect that's good for the user (Poison Touch/Pickpocket).
|
||||
|
||||
# TODO: Don't prefer a status move if user has a damaging move that will KO
|
||||
# the target.
|
||||
# => If target has previously used a move that will hurt the user by 30% of
|
||||
# its current HP or more, moreso don't prefer a status move.
|
||||
|
||||
|
||||
if skill_check(AILevel.medium)
|
||||
|
||||
# Prefer damaging moves if AI has no more Pokémon or AI is less clever
|
||||
if @battle.pbAbleNonActiveCount(@user.idxOwnSide) == 0
|
||||
if !(skill_check(AILevel.high) && @battle.pbAbleNonActiveCount(@target.idxOwnSide) > 0)
|
||||
if @move.statusMove?
|
||||
score *= 0.9
|
||||
elsif @target.hp <= @target.totalhp / 2
|
||||
score *= 1.1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Don't prefer attacking the target if they'd be semi-invulnerable
|
||||
if skill_check(AILevel.high) && @move.accuracy > 0 && @user_faster &&
|
||||
(@target.semiInvulnerable? || @target.effects[PBEffects::SkyDrop] >= 0)
|
||||
miss = true
|
||||
miss = false if @user.hasActiveAbility?(:NOGUARD)
|
||||
miss = false if skill_check(AILevel.best) && @target.hasActiveAbility?(:NOGUARD)
|
||||
if skill_check(AILevel.best) && miss
|
||||
# Knows what can get past semi-invulnerability
|
||||
if @target.effects[PBEffects::SkyDrop] >= 0
|
||||
@target.effects[PBEffects::SkyDrop] != @user.index
|
||||
miss = false if @move.hitsFlyingTargets?
|
||||
else
|
||||
if @target.inTwoTurnAttack?("0C9", "0CC", "0CE") # Fly, Bounce, Sky Drop
|
||||
miss = false if @move.hitsFlyingTargets?
|
||||
elsif @target.inTwoTurnAttack?("0CA") # Dig
|
||||
miss = false if @move.hitsDiggingTargets?
|
||||
elsif @target.inTwoTurnAttack?("0CB") # Dive
|
||||
miss = false if @move.hitsDivingTargets?
|
||||
end
|
||||
end
|
||||
end
|
||||
score = 0 if miss
|
||||
end
|
||||
|
||||
# Pick a good move for the Choice items
|
||||
if @user.hasActiveItem?([:CHOICEBAND, :CHOICESPECS, :CHOICESCARF])
|
||||
# Really don't prefer status moves (except Trick)
|
||||
score *= 0.1 if @move.statusMove? && @move.function != "0F2" # Trick
|
||||
# Don't prefer moves of certain types
|
||||
move_type = pbRoughType(@move)
|
||||
# Most unpreferred types are 0x effective against another type, except
|
||||
# Fire/Water/Grass
|
||||
# TODO: Actually check through the types for 0x instead of hardcoding
|
||||
# them.
|
||||
# TODO: Reborn separately doesn't prefer Fire/Water/Grass/Electric, also
|
||||
# with a 0.95x score, meaning Electric can be 0.95x twice. Why are
|
||||
# these four types not preferred? Maybe because they're all not
|
||||
# very effective against Dragon.
|
||||
unpreferred_types = [:NORMAL, :FIGHTING, :POISON, :GROUND, :GHOST,
|
||||
:FIRE, :WATER, :GRASS, :ELECTRIC, :PSYCHIC, :DRAGON]
|
||||
score *= 0.95 if unpreferred_types.include?(move_type)
|
||||
# Don't prefer moves with lower accuracy
|
||||
score *= @move.accuracy / 100.0 if @move.accuracy > 0
|
||||
# Don't prefer moves with low PP
|
||||
score *= 0.9 if @move.pp < 6
|
||||
end
|
||||
|
||||
# If user is asleep, don't prefer moves that can't be used while asleep
|
||||
if skill_check(AILevel.medium) && @user.asleep? &&
|
||||
@user.statusCount > 1 && !@move.usableWhenAsleep?
|
||||
score *= 0.2
|
||||
end
|
||||
|
||||
# If user is frozen, prefer a move that can thaw the user
|
||||
if skill_check(AILevel.medium) && @user.status == PBStatuses::FROZEN
|
||||
if @move.thawsUser?
|
||||
score += 30
|
||||
else
|
||||
@user.eachMove do |m|
|
||||
next unless m.thawsUser?
|
||||
score *= 0 # Discard this move if user knows another move that thaws
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# If target is frozen, don't prefer moves that could thaw them
|
||||
if @target.status == PBStatuses::FROZEN
|
||||
if pbRoughType(@move) == :FIRE || (NEWEST_BATTLE_MECHANICS && @move.thawsUser?)
|
||||
score *= 0.1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Don't prefer hitting a wild shiny Pokémon
|
||||
if @battle.wildBattle? && @target.opposes? && @target.shiny?
|
||||
score *= 0.15
|
||||
end
|
||||
|
||||
# TODO: Discard a move that can be Magic Coated if either opponent has Magic
|
||||
# Bounce.
|
||||
|
||||
# Account for accuracy of move
|
||||
accuracy = pbRoughAccuracy(@move, @target)
|
||||
score *= accuracy / 100.0
|
||||
|
||||
# Prefer flinching external effects (note that move effects which cause
|
||||
# flinching are dealt with in the function code part of score calculation)
|
||||
if skill_check(AILevel.medium)
|
||||
if !@target.hasActiveAbility?([:INNERFOCUS, :SHIELDDUST]) &&
|
||||
@target.effects[PBEffects::Substitute] == 0
|
||||
can_flinch = false
|
||||
if @move.canKingsRock? && @user.hasActiveItem?([:KINGSROCK, :RAZORFANG])
|
||||
can_flinch = true
|
||||
elsif @user.hasActiveAbility?(:STENCH) && !@move.flinchingMove?
|
||||
can_flinch = true
|
||||
end
|
||||
calc_damage *= 1.3 if can_flinch
|
||||
end
|
||||
end
|
||||
|
||||
score = score.to_i
|
||||
score = 0 if score < 0
|
||||
return score
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Calculate how much damage a move is likely to do to a given target (as a
|
||||
# percentage of the target's current HP)
|
||||
#=============================================================================
|
||||
def pbGetDamagingMoveBaseScore
|
||||
# Don't prefer moves that are ineffective because of abilities or effects
|
||||
return 0 if pbCheckMoveImmunity(@move, @target)
|
||||
|
||||
# Calculate how much damage the move will do (roughly)
|
||||
base_damage = pbMoveBaseDamage(@move, @target)
|
||||
calc_damage = pbRoughDamage(@move, @target, base_damage)
|
||||
|
||||
# TODO: Maybe move this check elsewhere? Note that Reborn's base score does
|
||||
# not include this halving, but the predicted damage does.
|
||||
# Two-turn attacks waste 2 turns to deal one lot of damage
|
||||
calc_damage /= 2 if @move.chargingTurnMove?
|
||||
|
||||
# TODO: Maybe move this check elsewhere?
|
||||
# Increased critical hit rate
|
||||
if skill_check(AILevel.medium)
|
||||
crit_stage = pbRoughCriticalHitStage(@move, @target)
|
||||
if crit_stage >= 0
|
||||
crit_fraction = (crit_stage > 50) ? 1 : PokeBattle_Move::CRITICAL_HIT_RATIOS[crit_stage]
|
||||
crit_mult = (NEWEST_BATTLE_MECHANICS) ? 0.5 : 1
|
||||
calc_damage *= (1 + crit_mult / crit_fraction)
|
||||
end
|
||||
end
|
||||
|
||||
# Convert damage to percentage of target's remaining HP
|
||||
damage_percentage = calc_damage * 100.0 / @target.hp
|
||||
|
||||
# Don't prefer weak attacks
|
||||
# damage_percentage /= 2 if damage_percentage < 20
|
||||
|
||||
# Prefer damaging attack if level difference is significantly high
|
||||
# damage_percentage *= 1.2 if @user.level - 10 > @target.level
|
||||
|
||||
# Adjust score
|
||||
damage_percentage = 110 if damage_percentage > 110 # Treat all lethal moves the same
|
||||
damage_percentage += 40 if damage_percentage > 100 # Prefer moves likely to be lethal
|
||||
|
||||
score = damage_percentage.to_i
|
||||
return score
|
||||
end
|
||||
|
||||
def pbGetStatusMoveBaseScore
|
||||
# TODO: Call pbCheckMoveImmunity here too, not just for damaging moves
|
||||
# (only if this status move will be affected).
|
||||
|
||||
# TODO: Make sure all status moves are accounted for.
|
||||
# TODO: Duplicates:
|
||||
# 003 cause sleep - Dark Void (15), Grass Whistle (15), Hypnosis (15), Sing (15),
|
||||
# Lovely Kiss (20), Sleep Powder (20), Spore (60)
|
||||
# 005 poisons - Poison Powder (15), Poison Gas (20)
|
||||
# 007 paralyses - Stun Spore (25), Glare (30), Thunder Wave (30)
|
||||
# 013 confuses - Teeter Dance (5), Supersonic (10), Sweet Kiss (20), Confuse Ray (25)
|
||||
# 01C user's Atk +1 - Howl (10), Sharpen (10), Medicate (15)
|
||||
# 030 user's Spd +2 - Agility (15), Rock Polish (25)
|
||||
# 042 target Atk -1 - Growl (10), Baby-Doll Eyes (15)
|
||||
# 047 target acc -1 - Sand Attack (5), Flash (10), Kinesis (10), Smokescreen (10)
|
||||
# 04B target Atk -2 - Charm (10), Feather Dance (15)
|
||||
# 04D target Spd -2 - String Shot (10), Cotton Spore (15), Scary Face (15)
|
||||
# 04F target SpDef -2 - Metal Sound (10), Fake Tears (15)
|
||||
case @move.function
|
||||
when "013", "047", "049", "052", "053", "057", "058", "059", "05E", "061",
|
||||
"062", "066", "067", "09C", "09D", "09E", "0A6", "0A7", "0A8", "0AB",
|
||||
"0AC", "0B1", "0B2", "0B8", "0BB", "0E6", "0E8", "0F6", "0F9", "10F",
|
||||
"114", "118", "119", "120", "124", "138", "13E", "13F", "143", "152",
|
||||
"15E", "161", "16A", "16B"
|
||||
return 5
|
||||
when "013", "01C", "01D", "01E", "023", "027", "028", "029", "037", "042",
|
||||
"043", "047", "04B", "04D", "04F", "051", "055", "060", "0B7", "0F8",
|
||||
"139", "13A", "13C", "148"
|
||||
return 10
|
||||
when "003", "005", "018", "01C", "021", "022", "030", "042", "04A", "04B",
|
||||
"04C", "04D", "04E", "04F", "05C", "05D", "065", "0B0", "0B5", "0DB",
|
||||
"0DF", "0E3", "0E4", "0FF", "100", "101", "102", "137", "13D", "140",
|
||||
"142", "151", "15C", "16E"
|
||||
return 15
|
||||
when "003", "004", "005", "013", "040", "041", "054", "056", "05F", "063",
|
||||
"064", "068", "069", "0AE", "0AF", "0B6", "0D9", "0DA", "0E5", "0EB",
|
||||
"0EF", "145", "146", "159"
|
||||
return 20
|
||||
when "006", "007", "00A", "013", "016", "01B", "02A", "02F", "030", "031",
|
||||
"033", "034", "038", "03A", "05A", "0AA", "0B9", "0BA", "0D5", "0D6",
|
||||
"0D7", "0D8", "0DC", "0E7", "0F2", "10C", "112", "117", "141", "160",
|
||||
"16D"
|
||||
return 25
|
||||
when "007", "024", "025", "02C", "0B3", "0B4", "0BC", "0ED", "103", "104",
|
||||
"105", "10D", "11F", "14C", "154", "155", "156", "15B", "173"
|
||||
return 30
|
||||
when "019", "02E", "032", "039", "05B", "0A2", "0A3", "149", "14B", "168"
|
||||
return 35
|
||||
when "026", "02B", "035", "036", "14E"
|
||||
return 40
|
||||
when "003", "153", "167"
|
||||
return 60
|
||||
end
|
||||
# "001", "01A", "048", "0A1", "0E2", "0EA", "0F3", "10E", "11A", "11D",
|
||||
# "11E", "14A"
|
||||
return 0
|
||||
end
|
||||
end
|
||||
@@ -1,431 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Apply additional effect chance to a move's score
|
||||
# TODO: Apply all the additional effect chance modifiers.
|
||||
#=============================================================================
|
||||
def apply_effect_chance_to_score(score)
|
||||
if @move.damagingMove?
|
||||
# TODO: Doesn't return the correct value for "014" (Chatter).
|
||||
effect_chance = @move.addlEffect
|
||||
if effect_chance > 0
|
||||
effect_chance *= 2 if @user.hasActiveAbility?(:SERENEGRACE) ||
|
||||
@user.pbOwnSide.effects[PBEffects::Rainbow] > 0
|
||||
effect_multiplier = [effect_chance.to_f, 100].min / 100
|
||||
score = ((score - 1) * effect_multiplier) + 1
|
||||
end
|
||||
end
|
||||
return score
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
# TODO: These function codes need to have an attr_reader :statUp and for them
|
||||
# to be set when the move is initialised.
|
||||
# 035 Shell Smash
|
||||
# 037 Acupressure
|
||||
# 137 Magnetic Flux
|
||||
# 15C Gear Up
|
||||
def calc_user_stat_raise_mini_score
|
||||
mini_score = 1.0
|
||||
# Determine whether the move boosts Attack, Special Attack or Speed (Bulk Up
|
||||
# is sometimes not considered a sweeping move)
|
||||
sweeping_stat = false
|
||||
offensive_stat = false
|
||||
@move.stat_up.each_with_index do |stat, idx|
|
||||
next if idx.odd?
|
||||
next if ![:ATTACK, :SPATK, :SPEED].include?(stat)
|
||||
sweeping_stat = true
|
||||
next if @move.function == "024" # Bulk Up (+Atk +Def)
|
||||
offensive_stat = true
|
||||
break
|
||||
end
|
||||
|
||||
# Prefer if user has most of its HP
|
||||
if @user.hp >= @user.totalhp * 3 / 4
|
||||
mini_score *= (sweeping_stat) ? 1.2 : 1.1
|
||||
end
|
||||
# Prefer if user hasn't been in battle for long
|
||||
if @user.turnCount < 2
|
||||
mini_score *= (sweeping_stat) ? 1.2 : 1.1
|
||||
end
|
||||
# Prefer if user has the ability Simple
|
||||
mini_score *= 2 if @user.hasActiveAbility?(:SIMPLE)
|
||||
# TODO: Prefer if user's moves won't do much damage.
|
||||
# Prefer if user has something that will limit damage taken
|
||||
mini_score *= 1.3 if @user.effects[PBEffects::Substitute] > 0 ||
|
||||
(@user.form == 0 && @user.ability_id == :DISGUISE)
|
||||
|
||||
# Don't prefer if user doesn't have much HP left
|
||||
mini_score *= 0.3 if @user.hp < @user.totalhp / 3
|
||||
# Don't prefer if user is badly poisoned
|
||||
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0 && !offensive_stat
|
||||
# Don't prefer if user is confused
|
||||
if @user.effects[PBEffects::Confusion] > 0
|
||||
# TODO: Especially don't prefer if the move raises Atk. Even more so if
|
||||
# the move raises the stat by 2+. Not quite so much if the move also
|
||||
# raises Def.
|
||||
mini_score *= 0.5
|
||||
end
|
||||
# Don't prefer if user is infatuated or Leech Seeded
|
||||
if @user.effects[PBEffects::Attract] >= 0 || @user.effects[PBEffects::LeechSeed] >= 0
|
||||
mini_score *= (offensive_stat) ? 0.6 : 0.3
|
||||
end
|
||||
# Don't prefer if user has an ability or item that will force it to switch
|
||||
# out
|
||||
if @user.hp < @user.totalhp * 3 / 4
|
||||
mini_score *= 0.3 if @user.hasActiveAbility?([:EMERGENCYEXIT, :WIMPOUT])
|
||||
mini_score *= 0.3 if @user.hasActiveItem?(:EJECTBUTTON)
|
||||
end
|
||||
|
||||
# Prefer if target has a status problem
|
||||
if @target.status != PBStatuses::NONE
|
||||
mini_score *= (sweeping_stat) ? 1.2 : 1.1
|
||||
case @target.status
|
||||
when PBStatuses::SLEEP, PBStatuses::FROZEN
|
||||
mini_score *= 1.3
|
||||
when PBStatuses::BURN
|
||||
# TODO: Prefer if the move boosts Sp Def.
|
||||
mini_score *= 1.1 if !offensive_stat
|
||||
end
|
||||
end
|
||||
# Prefer if target is yawning
|
||||
if @target.effects[PBEffects::Yawn] > 0
|
||||
mini_score *= (sweeping_stat) ? 1.7 : 1.3
|
||||
end
|
||||
# Prefer if target is recovering after Hyper Beam
|
||||
if @target.effects[PBEffects::HyperBeam] > 0
|
||||
mini_score *= (sweeping_stat) ? 1.3 : 1.2
|
||||
end
|
||||
# Prefer if target is Encored into a status move
|
||||
if @target.effects[PBEffects::Encore] > 0 &&
|
||||
GameData::Move.get(@target.effects[PBEffects::EncoreMove]).category == 2 # Status move
|
||||
# TODO: Why should this check greatly prefer raising both the user's defences?
|
||||
if sweeping_stat || @move.function == "02A" # +Def +SpDef
|
||||
mini_score *= 1.5
|
||||
else
|
||||
mini_score *= 1.3
|
||||
end
|
||||
end
|
||||
# TODO: Don't prefer if target has previously used a move that would force
|
||||
# the user to switch (or Yawn/Perish Song which encourage it). Prefer
|
||||
# instead if the move raises evasion. Note this comes after the
|
||||
# dissociation of Bulk Up from sweeping_stat.
|
||||
|
||||
if skill_check(AILevel.medium)
|
||||
# TODO: Prefer if the maximum damage the target has dealt wouldn't hurt
|
||||
# the user much.
|
||||
end
|
||||
# Don't prefer if foe's side is able to use a boosted Retaliate
|
||||
# TODO: I think this is what Reborn means. Reborn doesn't check for the
|
||||
# existence of the move Retaliate, just whether it can be boosted.
|
||||
if @user.pbOpposingSide.effects[PBEffects::LastRoundFainted] == @battle.turnCount - 1
|
||||
mini_score *= 0.3
|
||||
end
|
||||
|
||||
# Don't prefer if it's not a single battle
|
||||
if !@battle.singleBattle?
|
||||
mini_score *= (offensive_stat) ? 0.25 : 0.5
|
||||
end
|
||||
|
||||
return mini_score
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
# TODO: This method doesn't take the increment into account but should.
|
||||
def calc_user_stat_raise_one(stat, increment)
|
||||
mini_score = 1.0
|
||||
|
||||
# Ignore if user won't benefit from the stat being raised
|
||||
# TODO: Exception if user knows Baton Pass? Exception if user knows Power Trip?
|
||||
case stat
|
||||
when PBStats::ATTACK
|
||||
has_physical_move = false
|
||||
@user.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type) || m.function == "121" # Foul Play
|
||||
has_physical_move = true
|
||||
break
|
||||
end
|
||||
return mini_score if !has_physical_move
|
||||
when PBStats::SPATK
|
||||
has_special_move = false
|
||||
@user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
has_special_move = true
|
||||
break
|
||||
end
|
||||
return mini_score if !has_special_move
|
||||
end
|
||||
|
||||
case stat
|
||||
when PBStats::ATTACK
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
|
||||
mini_score *= 1.4
|
||||
end
|
||||
end
|
||||
# Prefer if user has the Sweeper role
|
||||
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
|
||||
# Don't prefer if user is burned or paralysed
|
||||
mini_score *= 0.5 if @user.status == PBStatuses::BURN || @user.status == PBStatuses::PARALYSIS
|
||||
# Don't prefer if user's Speed stat is lowered
|
||||
sum_stages = @user.stages[PBStats::SPEED]
|
||||
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
|
||||
|
||||
# TODO: Prefer if target has previously used a HP-restoring move.
|
||||
# TODO: Don't prefer if some of foes' stats are raised
|
||||
sum_stages = 0
|
||||
[PBStats::ATTACK, PBStats::SPATK, PBStats::SPEED].each do |s|
|
||||
sum_stages += @target.stages[s]
|
||||
end
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
|
||||
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round).
|
||||
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
|
||||
# TODO: Don't prefer if target has previously used a move that benefits
|
||||
# from user's Attack being boosted.
|
||||
mini_score *= 0.3 if check_for_move(@target) { |move| move.function == "121" } # Foul Play
|
||||
# TODO: Don't prefer if the target has previously used a priority move.
|
||||
|
||||
when PBStats::DEFENSE
|
||||
# Prefer if user has a healing item
|
||||
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
|
||||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
|
||||
# Prefer if user knows any healing moves
|
||||
# TODO: Is 1.2x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
# TODO: Leech Seed is 1.2x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
|
||||
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
|
||||
# Prefer if user has certain roles
|
||||
# TODO: Is 1.1x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
|
||||
# Don't prefer if user is badly poisoned
|
||||
mini_score *= 0.2 if @user.effects[PBEffects::Toxic] > 0
|
||||
# Don't prefer if user's Defense stat is raised
|
||||
sum_stages = @user.stages[PBStats::DEFENSE]
|
||||
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
|
||||
|
||||
# TODO: Prefer if foes have higher Attack than Special Attack, and user
|
||||
# doesn't have a wall role, user is faster and user has at least 75%
|
||||
# HP. Don't prefer instead if user is slower (ignore HP).
|
||||
|
||||
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
|
||||
# user much.
|
||||
|
||||
when PBStats::SPEED
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
|
||||
mini_score *= 1.4
|
||||
end
|
||||
end
|
||||
# Prefer if user's Attack/SpAtk stat (whichever is higher) is lowered
|
||||
# TODO: Why?
|
||||
if @user.attack > @user.spatk
|
||||
sum_stages = @user.stages[PBStats::ATTACK]
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
|
||||
else
|
||||
sum_stages = @user.stages[PBStats::SPATK]
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
|
||||
end
|
||||
# Prefer if user has lowered Speed
|
||||
# TODO: Is a flat 1.3x for 026 Dragon Dance (+Atk, +Spd).
|
||||
sum_stages = @user.stages[PBStats::SPEED]
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages < 0
|
||||
# Prefer if user has Moxie
|
||||
mini_score *= 1.3 if @user.hasActiveAbility?(:MOXIE)
|
||||
# Prefer if user has the Sweeper role
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
|
||||
# Don't prefer if user is burned or paralysed
|
||||
mini_score *= 0.2 if @user.status == PBStatuses::PARALYSIS
|
||||
# Don't prefer if user has Speed Boost
|
||||
mini_score *= 0.6 if @user.hasActiveAbility?(:SPEEDBOOST)
|
||||
|
||||
# TODO: Don't prefer if target has raised defenses.
|
||||
sum_stages = 0
|
||||
[PBStats::DEFENSE, PBStats::SPDEF].each { |s| sum_stages += @target.stages[s] }
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
|
||||
# TODO: Don't prefer if the target has previously used a priority move.
|
||||
# TODO: Don't prefer if Trick Room applies or any foe has previously used
|
||||
# Trick Room.
|
||||
mini_score *= 0.2 if @battle.field.effects[PBEffects::TrickRoom] > 0
|
||||
|
||||
# TODO: Don't prefer if user is already faster than the target. Exception
|
||||
# for moves that benefit from a raised user's Speed?
|
||||
# TODO: Don't prefer if user is already faster than the target and there's
|
||||
# only 1 unfainted foe (this check is done by Agility/Autotomize
|
||||
# (both +2 Spd) only in Reborn.)
|
||||
|
||||
when PBStats::SPATK
|
||||
# Prefer if user can definitely survive a hit no matter how powerful, and
|
||||
# it won't be hurt by weather
|
||||
if @user.hp == @user.totalhp &&
|
||||
(@user.hasActiveItem?(:FOCUSSASH) || @user.hasActiveAbility?(:STURDY))
|
||||
if !(@battle.pbWeather == PBWeather::Sandstorm && @user.takesSandstormDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::Hail && @user.takesHailDamage?) &&
|
||||
!(@battle.pbWeather == PBWeather::ShadowSky && @user.takesShadowSkyDamage?)
|
||||
mini_score *= 1.4
|
||||
end
|
||||
end
|
||||
# Prefer if user has the Sweeper role
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::SWEEPER)
|
||||
# Don't prefer if user's Speed stat is lowered
|
||||
sum_stages = @user.stages[PBStats::SPEED]
|
||||
mini_score *= 1 + sum_stages * 0.05 if sum_stages < 0
|
||||
|
||||
# TODO: Prefer if target has previously used a HP-restoring move.
|
||||
# TODO: Don't prefer if some of foes' stats are raised
|
||||
sum_stages = 0
|
||||
[PBStats::ATTACK, PBStats::SPATK, PBStats::SPEED].each do |s|
|
||||
sum_stages += @target.stages[s]
|
||||
end
|
||||
mini_score *= 1 - sum_stages * 0.05 if sum_stages > 0
|
||||
# TODO: Don't prefer if target has Speed Boost (+Spd at end of each round)
|
||||
mini_score *= 0.6 if @target.hasActiveAbility?(:SPEEDBOOST)
|
||||
# TODO: Don't prefer if the target has previously used a priority move.
|
||||
|
||||
when PBStats::SPDEF
|
||||
# Prefer if user has a healing item
|
||||
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
|
||||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
|
||||
# Prefer if user knows any healing moves
|
||||
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
|
||||
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
|
||||
# Prefer if user has certain roles
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
|
||||
# Don't prefer if user's Defense stat is raised
|
||||
sum_stages = @user.stages[PBStats::SPDEF]
|
||||
mini_score *= 1 - sum_stages * 0.15 if sum_stages > 0
|
||||
|
||||
# TODO: Prefer if foes have higher Special Attack than Attack.
|
||||
|
||||
# TODO: Don't prefer if previous damage done by foes wouldn't hurt the
|
||||
# user much.
|
||||
|
||||
when PBStats::ACCURACY
|
||||
|
||||
# Prefer if user knows any weaker moves
|
||||
mini_score *= 1.1 if check_for_move(@user) { |move| move.damagingMove? && move.basedamage < 95 }
|
||||
|
||||
# Prefer if target has a raised evasion
|
||||
sum_stages = @target.stages[PBStats::EVASION]
|
||||
mini_score *= 1 + sum_stages * 0.05 if sum_stages > 0
|
||||
# Prefer if target has an item that lowers foes' accuracy
|
||||
mini_score *= 1.1 if @target.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
|
||||
# Prefer if target has an ability that lowers foes' accuracy
|
||||
# TODO: Tangled Feet while user is confused?
|
||||
if (@battle.pbWeather == PBWeather::Sandstorm && @target.hasActiveAbility?(:SANDVEIL)) ||
|
||||
(@battle.pbWeather == PBWeather::Hail && @target.hasActiveAbility?(:SNOWCLOAK))
|
||||
mini_score *= 1.1
|
||||
end
|
||||
|
||||
when PBStats::EVASION
|
||||
# Prefer if user has a healing item
|
||||
mini_score *= 1.2 if @user.hasActiveItem?(:LEFTOVERS) ||
|
||||
(@user.hasActiveItem?(:BLACKSLUDGE) && @user.pbHasType?(:POISON))
|
||||
# Prefer if user has an item that lowers foes' accuracy
|
||||
mini_score *= 1.3 if @user.hasActiveItem?([:BRIGHTPOWDER, :LAXINCENSE])
|
||||
# Prefer if user has an ability that lowers foes' accuracy
|
||||
# TODO: Tangled Feet while user is confused?
|
||||
if (@battle.pbWeather == PBWeather::Sandstorm && @user.hasActiveAbility?(:SANDVEIL)) ||
|
||||
(@battle.pbWeather == PBWeather::Hail && @user.hasActiveAbility?(:SNOWCLOAK))
|
||||
mini_score *= 1.3
|
||||
end
|
||||
# Prefer if user knows any healing moves
|
||||
mini_score *= 1.3 if check_for_move(@user) { |move| move.healingMove? }
|
||||
# Prefer if user knows Pain Split or Leech Seed
|
||||
mini_score *= 1.2 if @user.pbHasMoveFunction?("05A") # Pain Split
|
||||
mini_score *= 1.3 if @user.pbHasMoveFunction?("0DC") # Leech Seed
|
||||
# Prefer if user has certain roles
|
||||
mini_score *= 1.3 if check_battler_role(@user, BattleRole::PHYSICALWALL, BattleRole::SPECIALWALL)
|
||||
# TODO: Don't prefer if user's evasion stat is raised
|
||||
|
||||
# TODO: Don't prefer if target has No Guard.
|
||||
mini_score *= 0.2 if @target.hasActiveAbility?(:NOGUARD)
|
||||
# TODO: Don't prefer if target has previously used any moves that never miss.
|
||||
|
||||
end
|
||||
|
||||
# Don't prefer if user has Contrary
|
||||
mini_score *= 0.5 if @user.hasActiveAbility?(:CONTRARY)
|
||||
# TODO: Don't prefer if target has Unaware? Reborn resets mini_score to 1.
|
||||
# This check needs more consideration. Note that @target is user for
|
||||
# status moves, so that part is wrong.
|
||||
# TODO: Is 0x for 025, 026, 026 (all moves that raise multiple stats)
|
||||
mini_score *= 0.5 if @move.statusMove? && @target.hasActiveAbility?(:UNAWARE)
|
||||
|
||||
# TODO: Don't prefer if any foe has previously used a stat stage-clearing
|
||||
# move (050, 051 Clear Smog/Haze).
|
||||
mini_score *= 0.3 if check_for_move(@target) { |move| ["050", "051"].include?(move.function) } # Clear Smog, Haze
|
||||
|
||||
# TODO: Prefer if user is faster than the target.
|
||||
# TODO: Is 1.3x for 025 Coil (+Atk, +Def, +acc).
|
||||
mini_score *= 1.5 if @user_faster
|
||||
# TODO: Don't prefer if target is a higher level than the user
|
||||
if @target.level > @user.level + 5
|
||||
mini_score *= 0.6
|
||||
if @target.level > @user.level + 10
|
||||
mini_score *= 0.2
|
||||
end
|
||||
end
|
||||
|
||||
return mini_score
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
def get_score_for_user_stat_raise(score)
|
||||
# Discard status move if user has Contrary
|
||||
return 0 if @move.statusMove? && @user.hasActiveAbility?(:CONTRARY)
|
||||
|
||||
# Discard move if it can't raise any stats
|
||||
can_change_any_stat = false
|
||||
@move.stat_up.each_with_index do |stat, idx|
|
||||
next if idx.odd?
|
||||
next if @user.statStageAtMax?(stat)
|
||||
can_change_any_stat = true
|
||||
break
|
||||
end
|
||||
if !can_change_any_stat
|
||||
return (@move.statusMove?) ? 0 : score
|
||||
end
|
||||
|
||||
# Get the main mini-score
|
||||
main_mini_score = calc_user_stat_raise_mini_score
|
||||
|
||||
# For each stat to be raised in turn, calculate a mini-score describing how
|
||||
# beneficial that stat being raised will be
|
||||
mini_score = 0
|
||||
num_stats = 0
|
||||
@move.stat_up.each_with_index do |stat, idx|
|
||||
next if idx.odd?
|
||||
next if @user.statStageAtMax?(stat)
|
||||
# TODO: Use the effective increment (e.g. 1 if the stat is raised by 2 but
|
||||
# the stat is already at +5).
|
||||
mini_score += calc_user_stat_raise_one(stat, @move.stat_up[idx + 1])
|
||||
num_stats += 1
|
||||
end
|
||||
|
||||
# Apply the average mini-score to the actual score
|
||||
score = apply_effect_chance_to_score(main_mini_score * mini_score / num_stats)
|
||||
|
||||
return score
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,746 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __b__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctions(score)
|
||||
score = __b__pbGetMoveScoreFunctions(score)
|
||||
case @move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "040"
|
||||
if !@target.pbCanConfuse?(@user,false)
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if @target.stages[PBStats::SPATK]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "041"
|
||||
if !@target.pbCanConfuse?(@user,false)
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if @target.stages[PBStats::ATTACK]<0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "042"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::ATTACK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::ATTACK]>0
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "043"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "044"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::SPEED]*10
|
||||
if skill_check(AILevel.high)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if @user.stages[PBStats::SPEED]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "045"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @user.stages[PBStats::SPATK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasSpecicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 20 if @user.stages[PBStats::SPATK]>0
|
||||
if skill_check(AILevel.medium)
|
||||
hasSpecicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "046"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPDEF,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::SPDEF]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "047"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::ACCURACY,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::ACCURACY]*10
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::ACCURACY]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "048"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::EVASION]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "049"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::EVASION]*10
|
||||
end
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::EVASION]>0
|
||||
end
|
||||
score += 30 if @target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::Mist]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
score -= 30 if @target.pbOwnSide.effects[PBEffects::Spikes]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
#---------------------------------------------------------------------------
|
||||
when "04A"
|
||||
avg = @target.stages[PBStats::ATTACK]*10
|
||||
avg += @target.stages[PBStats::DEFENSE]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "04B"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::ATTACK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if @user.turnCount==0
|
||||
score += 20 if @target.stages[PBStats::ATTACK]>0
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 20 if hasPhysicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04C"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
else
|
||||
score += 10 if @user.turnCount==0
|
||||
score += 20 if @target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04D"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 20 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::SPEED]*20
|
||||
if skill_check(AILevel.high)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if @user.turnCount==0
|
||||
score += 30 if @target.stages[PBStats::SPEED]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04E"
|
||||
if @user.gender==2 || @target.gender==2 || @user.gender==@target.gender ||
|
||||
@target.hasActiveAbility?(:OBLIVIOUS)
|
||||
score -= 90
|
||||
elsif @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::SPATK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasSpecicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
score += 10 if @user.turnCount==0
|
||||
score += 20 if @target.stages[PBStats::SPATK]>0
|
||||
if skill_check(AILevel.medium)
|
||||
hasSpecicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecicalAttack = true
|
||||
break
|
||||
end
|
||||
score += 30 if hasSpecicalAttack
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "04F"
|
||||
if @move.statusMove?
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPDEF,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::SPDEF]*20
|
||||
end
|
||||
else
|
||||
score += 10 if @user.turnCount==0
|
||||
score += 20 if @target.stages[PBStats::SPDEF]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "050"
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
else
|
||||
avg = 0; anyChange = false
|
||||
PBStats.eachBattleStat do |s|
|
||||
next if @target.stages[s]==0
|
||||
avg += @target.stages[s]
|
||||
anyChange = true
|
||||
end
|
||||
if anyChange
|
||||
score += avg*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "051"
|
||||
if skill_check(AILevel.medium)
|
||||
stages = 0
|
||||
@battle.eachBattler do |b|
|
||||
totalStages = 0
|
||||
PBStats.eachBattleStat { |s| totalStages += b.stages[s] }
|
||||
if b.opposes?(@user)
|
||||
stages += totalStages
|
||||
else
|
||||
stages -= totalStages
|
||||
end
|
||||
end
|
||||
score += stages*10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "052"
|
||||
if skill_check(AILevel.medium)
|
||||
aatk = @user.stages[PBStats::ATTACK]
|
||||
aspa = @user.stages[PBStats::SPATK]
|
||||
oatk = @target.stages[PBStats::ATTACK]
|
||||
ospa = @target.stages[PBStats::SPATK]
|
||||
if aatk>=oatk && aspa>=ospa
|
||||
score -= 80
|
||||
else
|
||||
score += (oatk-aatk)*10
|
||||
score += (ospa-aspa)*10
|
||||
end
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "053"
|
||||
if skill_check(AILevel.medium)
|
||||
adef = @user.stages[PBStats::DEFENSE]
|
||||
aspd = @user.stages[PBStats::SPDEF]
|
||||
odef = @target.stages[PBStats::DEFENSE]
|
||||
ospd = @target.stages[PBStats::SPDEF]
|
||||
if adef>=odef && aspd>=ospd
|
||||
score -= 80
|
||||
else
|
||||
score += (odef-adef)*10
|
||||
score += (ospd-aspd)*10
|
||||
end
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "054"
|
||||
if skill_check(AILevel.medium)
|
||||
userStages = 0; targetStages = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
userStages += @user.stages[s]
|
||||
targetStages += @target.stages[s]
|
||||
end
|
||||
score += (targetStages-userStages)*10
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "055"
|
||||
if skill_check(AILevel.medium)
|
||||
equal = true
|
||||
PBStats.eachBattleStat do |s|
|
||||
stagediff = @target.stages[s]-@user.stages[s]
|
||||
score += stagediff*10
|
||||
equal = false if stagediff!=0
|
||||
end
|
||||
score -= 80 if equal
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "056"
|
||||
score -= 80 if @user.pbOwnSide.effects[PBEffects::Mist]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "057"
|
||||
if skill_check(AILevel.medium)
|
||||
aatk = pbRoughStat(@user,PBStats::ATTACK)
|
||||
adef = pbRoughStat(@user,PBStats::DEFENSE)
|
||||
if aatk==adef ||
|
||||
@user.effects[PBEffects::PowerTrick] # No flip-flopping
|
||||
score -= 90
|
||||
elsif adef>aatk # Prefer a higher Attack
|
||||
score += 30
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "058"
|
||||
if skill_check(AILevel.medium)
|
||||
aatk = pbRoughStat(@user,PBStats::ATTACK)
|
||||
aspatk = pbRoughStat(@user,PBStats::SPATK)
|
||||
oatk = pbRoughStat(@target,PBStats::ATTACK)
|
||||
ospatk = pbRoughStat(@target,PBStats::SPATK)
|
||||
if aatk<oatk && aspatk<ospatk
|
||||
score += 50
|
||||
elsif aatk+aspatk<oatk+ospatk
|
||||
score += 30
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "059"
|
||||
if skill_check(AILevel.medium)
|
||||
adef = pbRoughStat(@user,PBStats::DEFENSE)
|
||||
aspdef = pbRoughStat(@user,PBStats::SPDEF)
|
||||
odef = pbRoughStat(@target,PBStats::DEFENSE)
|
||||
ospdef = pbRoughStat(@target,PBStats::SPDEF)
|
||||
if adef<odef && aspdef<ospdef
|
||||
score += 50
|
||||
elsif adef+aspdef<odef+ospdef
|
||||
score += 30
|
||||
else
|
||||
score -= 50
|
||||
end
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05A"
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif @user.hp>=(@user.hp+@target.hp)/2
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05B"
|
||||
score -= 90 if @user.pbOwnSide.effects[PBEffects::Tailwind]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "05C"
|
||||
moveBlacklist = [
|
||||
"002", # Struggle
|
||||
"014", # Chatter
|
||||
"05C", # Mimic
|
||||
"05D", # Sketch
|
||||
"0B6" # Metronome
|
||||
]
|
||||
if @user.effects[PBEffects::Transform] || !@target.lastRegularMoveUsed
|
||||
score -= 90
|
||||
else
|
||||
lastMoveData = GameData::Move.get(@target.lastRegularMoveUsed)
|
||||
if moveBlacklist.include?(lastMoveData.function_code) ||
|
||||
lastMoveData.type == :SHADOW
|
||||
score -= 90
|
||||
end
|
||||
@user.eachMove do |m|
|
||||
next if m != @target.lastRegularMoveUsed
|
||||
score -= 90
|
||||
break
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05D"
|
||||
moveBlacklist = [
|
||||
"002", # Struggle
|
||||
"014", # Chatter
|
||||
"05D" # Sketch
|
||||
]
|
||||
if @user.effects[PBEffects::Transform] || !@target.lastRegularMoveUsed
|
||||
score -= 90
|
||||
else
|
||||
lastMoveData = GameData::Move.get(@target.lastRegularMoveUsed)
|
||||
if moveBlacklist.include?(lastMoveData.function_code) ||
|
||||
lastMoveData.type == :SHADOW
|
||||
score -= 90
|
||||
end
|
||||
@user.eachMove do |m|
|
||||
next if m != @target.lastRegularMoveUsed
|
||||
score -= 90 # User already knows the move that will be Sketched
|
||||
break
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05E"
|
||||
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
|
||||
score -= 90
|
||||
else
|
||||
types = []
|
||||
@user.eachMove do |m|
|
||||
next if m.id==@id
|
||||
next if PBTypes.isPseudoType?(m.type)
|
||||
next if @user.pbHasType?(m.type)
|
||||
types.push(m.type) if !types.include?(m.type)
|
||||
end
|
||||
score -= 90 if types.length==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "05F"
|
||||
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
|
||||
score -= 90
|
||||
elsif !@target.lastMoveUsed ||
|
||||
PBTypes.isPseudoType?(GameData::Move.get(@target.lastMoveUsed).type)
|
||||
score -= 90
|
||||
else
|
||||
aType = nil
|
||||
@target.eachMove do |m|
|
||||
next if m.id!=@target.lastMoveUsed
|
||||
aType = m.pbCalcType(@user)
|
||||
break
|
||||
end
|
||||
if aType
|
||||
types = []
|
||||
GameData::Type.each do |t|
|
||||
types.push(t.id) if !@user.pbHasType?(t.id) && PBTypes.resistant?(aType, t.id)
|
||||
end
|
||||
score -= 90 if types.length==0
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "060"
|
||||
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium)
|
||||
envtypes = [
|
||||
:NORMAL, # None
|
||||
:GRASS, # Grass
|
||||
:GRASS, # Tall grass
|
||||
:WATER, # Moving water
|
||||
:WATER, # Still water
|
||||
:WATER, # Underwater
|
||||
:ROCK, # Rock
|
||||
:ROCK, # Cave
|
||||
:GROUND # Sand
|
||||
]
|
||||
type = envtypes[@battle.environment]
|
||||
score -= 90 if @user.pbHasType?(type)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "061"
|
||||
if @target.effects[PBEffects::Substitute]>0 ||
|
||||
[:MULTITYPE, :RKSSYSTEM].include?(@target.ability_id)
|
||||
score -= 90
|
||||
elsif @target.pbHasType?(:WATER)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "062"
|
||||
if [:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id)
|
||||
score -= 90
|
||||
elsif @user.pbHasType?(@target.type1) &&
|
||||
@user.pbHasType?(@target.type2) &&
|
||||
@target.pbHasType?(@user.type1) &&
|
||||
@target.pbHasType?(@user.type2)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "063"
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium)
|
||||
if [:MULTITYPE, :RKSSYSTEM, :SIMPLE, :TRUANT].include?(@target.ability_id)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "064"
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium)
|
||||
if [:INSOMNIA, :MULTITYPE, :RKSSYSTEM, :TRUANT].include?(@target.ability_id)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "065"
|
||||
score -= 40 # don't prefer this move
|
||||
if skill_check(AILevel.medium)
|
||||
if !@target.ability || @user.ability_id == @target.ability_id ||
|
||||
[:MULTITYPE, :RKSSYSTEM].include?(@user.ability_id) ||
|
||||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
|
||||
:TRACE, :WONDERGUARD, :ZENMODE].include?(@target.ability_id)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high) && @user.opposes?(@target)
|
||||
score -= 90 if [:SLOWSTART, :TRUANT].include?(@target.ability_id)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "066"
|
||||
score -= 40 # don't prefer this move
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium)
|
||||
if !@user.ability || @user.ability_id == @target.ability_id ||
|
||||
[:MULTITYPE, :RKSSYSTEM, :TRUANT].include?(@target.ability_id) ||
|
||||
[:FLOWERGIFT, :FORECAST, :ILLUSION, :IMPOSTER, :MULTITYPE, :RKSSYSTEM,
|
||||
:TRACE, :ZENMODE].include?(@user.ability_id)
|
||||
score -= 90
|
||||
end
|
||||
if skill_check(AILevel.high) && @user.opposes?(@target)
|
||||
score += 90 if [:SLOWSTART, :TRUANT].include?(@user.ability_id)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "067"
|
||||
score -= 40 # don't prefer this move
|
||||
if skill_check(AILevel.medium)
|
||||
if (!@user.ability && !@target.ability) ||
|
||||
@user.ability_id == @target.ability_id ||
|
||||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(@user.ability_id) ||
|
||||
[:ILLUSION, :MULTITYPE, :RKSSYSTEM, :WONDERGUARD].include?(@target.ability_id)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high) && @user.opposes?(@target)
|
||||
score -= 90 if [:SLOWSTART, :TRUANT].include?(@target.ability_id)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "068"
|
||||
if @target.effects[PBEffects::Substitute]>0 ||
|
||||
@target.effects[PBEffects::GastroAcid]
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90 if [:MULTITYPE, :RKSSYSTEM, :SLOWSTART, :TRUANT].include?(@target.ability_id)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "069"
|
||||
score -= 70
|
||||
#---------------------------------------------------------------------------
|
||||
when "06A"
|
||||
if @target.hp<=20
|
||||
score += 80
|
||||
elsif @target.level>=25
|
||||
score -= 60 # Not useful against high-level Pokemon
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "06B"
|
||||
score += 80 if @target.hp<=40
|
||||
#---------------------------------------------------------------------------
|
||||
when "06C"
|
||||
score -= 50
|
||||
score += @target.hp*100/@target.totalhp
|
||||
#---------------------------------------------------------------------------
|
||||
when "06D"
|
||||
score += 80 if @target.hp<=@user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "06E"
|
||||
if @user.hp>=@target.hp
|
||||
score -= 90
|
||||
elsif @user.hp<@target.hp/2
|
||||
score += 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "06F"
|
||||
score += 30 if @target.hp<=@user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "070"
|
||||
score -= 90 if @target.hasActiveAbility?(:STURDY)
|
||||
score -= 90 if @target.level>@user.level
|
||||
#---------------------------------------------------------------------------
|
||||
when "071"
|
||||
if @target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
attack = pbRoughStat(@user,PBStats::ATTACK)
|
||||
spatk = pbRoughStat(@user,PBStats::SPATK)
|
||||
if attack*1.5<spatk
|
||||
score -= 60
|
||||
elsif skill_check(AILevel.medium) && @target.lastMoveUsed
|
||||
moveData = GameData::Move.get(@target.lastMoveUsed)
|
||||
if moveData.base_damage > 0 &&
|
||||
(MOVE_CATEGORY_PER_MOVE && moveData.category == 0) ||
|
||||
(!MOVE_CATEGORY_PER_MOVE && PBTypes.isPhysicalType?(moveData.type))
|
||||
score -= 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "072"
|
||||
if @target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
attack = pbRoughStat(@user,PBStats::ATTACK)
|
||||
spatk = pbRoughStat(@user,PBStats::SPATK)
|
||||
if attack>spatk*1.5
|
||||
score -= 60
|
||||
elsif skill_check(AILevel.medium) && @target.lastMoveUsed
|
||||
moveData = GameData::Move.get(@target.lastMoveUsed)
|
||||
if moveData.base_damage > 0 &&
|
||||
(MOVE_CATEGORY_PER_MOVE && moveData.category == 1) ||
|
||||
(!MOVE_CATEGORY_PER_MOVE && !PBTypes.isSpecialType?(moveData.type))
|
||||
score -= 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "073"
|
||||
score -= 90 if @target.effects[PBEffects::HyperBeam]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "074"
|
||||
@target.eachAlly do |b|
|
||||
next if !b.near?(@target)
|
||||
score += 10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "075"
|
||||
#---------------------------------------------------------------------------
|
||||
when "076"
|
||||
#---------------------------------------------------------------------------
|
||||
when "077"
|
||||
#---------------------------------------------------------------------------
|
||||
when "078"
|
||||
if skill_check(AILevel.high)
|
||||
score += 30 if !@target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
@target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "079"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07C"
|
||||
score -= 20 if @target.status==PBStatuses::PARALYSIS # Will cure status
|
||||
#---------------------------------------------------------------------------
|
||||
when "07D"
|
||||
score -= 20 if @target.status==PBStatuses::SLEEP && # Will cure status
|
||||
@target.statusCount>1
|
||||
#---------------------------------------------------------------------------
|
||||
when "07E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "07F"
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,227 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __c__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctions(score)
|
||||
score = __c__pbGetMoveScoreFunctions(score)
|
||||
case @move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "080"
|
||||
#---------------------------------------------------------------------------
|
||||
when "081"
|
||||
attspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
oppspeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if oppspeed>attspeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "082"
|
||||
score += 20 if @battle.pbOpposingBattlerCount(@user)>1
|
||||
#---------------------------------------------------------------------------
|
||||
when "083"
|
||||
if skill_check(AILevel.medium)
|
||||
@user.eachAlly do |b|
|
||||
next if !b.pbHasMove?(@move.id)
|
||||
score += 20
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "084"
|
||||
attspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
oppspeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if oppspeed>attspeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "085"
|
||||
#---------------------------------------------------------------------------
|
||||
when "086"
|
||||
#---------------------------------------------------------------------------
|
||||
when "087"
|
||||
#---------------------------------------------------------------------------
|
||||
when "088"
|
||||
#---------------------------------------------------------------------------
|
||||
when "089"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08C"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "08F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "090"
|
||||
#---------------------------------------------------------------------------
|
||||
when "091"
|
||||
#---------------------------------------------------------------------------
|
||||
when "092"
|
||||
#---------------------------------------------------------------------------
|
||||
when "093"
|
||||
score += 25 if @user.effects[PBEffects::Rage]
|
||||
#---------------------------------------------------------------------------
|
||||
when "094"
|
||||
#---------------------------------------------------------------------------
|
||||
when "095"
|
||||
#---------------------------------------------------------------------------
|
||||
when "096"
|
||||
score -= 90 if !@user.item || !@user.item.is_berry? || !@user.itemActive?
|
||||
#---------------------------------------------------------------------------
|
||||
when "097"
|
||||
#---------------------------------------------------------------------------
|
||||
when "098"
|
||||
#---------------------------------------------------------------------------
|
||||
when "099"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "09C"
|
||||
hasAlly = false
|
||||
@user.eachAlly do |b|
|
||||
hasAlly = true
|
||||
score += 30
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "09D"
|
||||
score -= 90 if @user.effects[PBEffects::MudSport]
|
||||
#---------------------------------------------------------------------------
|
||||
when "09E"
|
||||
score -= 90 if @user.effects[PBEffects::WaterSport]
|
||||
#---------------------------------------------------------------------------
|
||||
when "09F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A1"
|
||||
score -= 90 if @user.pbOwnSide.effects[PBEffects::LuckyChant]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A2"
|
||||
score -= 90 if @user.pbOwnSide.effects[PBEffects::Reflect]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A3"
|
||||
score -= 90 if @user.pbOwnSide.effects[PBEffects::LightScreen]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A4"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A5"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A6"
|
||||
score -= 90 if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90 if @user.effects[PBEffects::LockOn]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A7"
|
||||
if @target.effects[PBEffects::Foresight]
|
||||
score -= 90
|
||||
elsif @target.pbHasType?(:GHOST)
|
||||
score += 70
|
||||
elsif @target.stages[PBStats::EVASION]<=0
|
||||
score -= 60
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A8"
|
||||
if @target.effects[PBEffects::MiracleEye]
|
||||
score -= 90
|
||||
elsif @target.pbHasType?(:DARK)
|
||||
score += 70
|
||||
elsif @target.stages[PBStats::EVASION]<=0
|
||||
score -= 60
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0A9"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AA"
|
||||
if @user.effects[PBEffects::ProtectRate]>1 ||
|
||||
@target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill_check(AILevel.medium)
|
||||
score -= @user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if @user.turnCount==0
|
||||
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AB"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AC"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AE"
|
||||
score -= 40
|
||||
if skill_check(AILevel.high)
|
||||
score -= 100 if !@target.lastRegularMoveUsed ||
|
||||
!GameData::Move.get(@target.lastRegularMoveUsed).flags[/e/] # Not copyable by Mirror Move
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0AF"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B4"
|
||||
if @user.asleep?
|
||||
score += 100 # Because it can only be used while asleep
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B5"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B6"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B7"
|
||||
score -= 90 if @target.effects[PBEffects::Torment]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B8"
|
||||
score -= 90 if @user.effects[PBEffects::Imprison]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0B9"
|
||||
score -= 90 if @target.effects[PBEffects::Disable]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BA"
|
||||
score -= 90 if @target.effects[PBEffects::Taunt]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BB"
|
||||
score -= 90 if @target.effects[PBEffects::HealBlock]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BC"
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
if @target.effects[PBEffects::Encore]>0
|
||||
score -= 90
|
||||
elsif aspeed>ospeed
|
||||
if !@target.lastRegularMoveUsed
|
||||
score -= 90
|
||||
else
|
||||
moveData = GameData::Move.get(@target.lastRegularMoveUsed)
|
||||
if moveData.category == 2 && # Status move
|
||||
[PBTargets::User, PBTargets::BothSides].include?(moveData.target)
|
||||
score += 60
|
||||
elsif moveData.category != 2 && # Damaging move
|
||||
moveData.target == PBTargets::NearOther &&
|
||||
PBTypeEffectiveness.ineffective?(pbCalcTypeMod(moveData.type, @target, @user))
|
||||
score += 60
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0BF"
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,375 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __d__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctions(score)
|
||||
score = __d__pbGetMoveScoreFunctions(score)
|
||||
case @move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C0"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C4"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C7"
|
||||
score += 20 if @user.effects[PBEffects::FocusEnergy]>0
|
||||
if skill_check(AILevel.high)
|
||||
score += 20 if !@target.hasActiveAbility?(:INNERFOCUS) &&
|
||||
@target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0C9"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CA"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CB"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CC"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CD"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CE"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0CF"
|
||||
score += 40 if @target.effects[PBEffects::Trapping]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D0"
|
||||
score += 40 if @target.effects[PBEffects::Trapping]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D2"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D3"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D4"
|
||||
if @user.hp<=@user.totalhp/4
|
||||
score -= 90
|
||||
elsif @user.hp<=@user.totalhp/2
|
||||
score -= 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D5", "0D6"
|
||||
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D7"
|
||||
score -= 90 if @battle.positions[@user.index].effects[PBEffects::Wish]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D8"
|
||||
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
case @battle.pbWeather
|
||||
when PBWeather::Sun, PBWeather::HarshSun
|
||||
score += 30
|
||||
when PBWeather::None
|
||||
else
|
||||
score -= 30
|
||||
end
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0D9"
|
||||
if @user.hp==@user.totalhp || !@user.pbCanSleep?(@user,false,nil,true)
|
||||
score -= 90
|
||||
else
|
||||
score += 70
|
||||
score -= @user.hp*140/@user.totalhp
|
||||
score += 30 if @user.status!=0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DA"
|
||||
score -= 90 if @user.effects[PBEffects::AquaRing]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DB"
|
||||
score -= 90 if @user.effects[PBEffects::Ingrain]
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DC"
|
||||
if @target.effects[PBEffects::LeechSeed]>=0
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium) && @target.pbHasType?(:GRASS)
|
||||
score -= 90
|
||||
else
|
||||
score += 60 if @user.turnCount==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DD"
|
||||
if skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 70
|
||||
else
|
||||
score += 20 if @user.hp<=@user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DE"
|
||||
if !@target.asleep?
|
||||
score -= 100
|
||||
elsif skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 70
|
||||
else
|
||||
score += 20 if @user.hp<=@user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0DF"
|
||||
if @user.opposes?(@target)
|
||||
score -= 100
|
||||
else
|
||||
score += 20 if @target.hp<@target.totalhp/2 &&
|
||||
@target.effects[PBEffects::Substitute]==0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E0"
|
||||
reserves = @battle.pbAbleNonActiveCount(@user.idxOwnSide)
|
||||
foes = @battle.pbAbleNonActiveCount(@user.idxOpposingSide)
|
||||
if @battle.pbCheckGlobalAbility(:DAMP)
|
||||
score -= 100
|
||||
elsif skill_check(AILevel.medium) && reserves==0 && foes>0
|
||||
score -= 100 # don't want to lose
|
||||
elsif skill_check(AILevel.high) && reserves==0 && foes==0
|
||||
score += 80 # want to draw
|
||||
else
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E1"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E2"
|
||||
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user) &&
|
||||
!@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
|
||||
score -= 100
|
||||
elsif @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
|
||||
score -= 100
|
||||
else
|
||||
score += @target.stages[PBStats::ATTACK]*10
|
||||
score += @target.stages[PBStats::SPATK]*10
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E3", "0E4"
|
||||
score -= 70
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E5"
|
||||
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
|
||||
score -= 90
|
||||
else
|
||||
score -= 90 if @target.effects[PBEffects::PerishSong]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E6"
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
score += 30 if @user.hp<=@user.totalhp/10
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E7"
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
score += 30 if @user.hp<=@user.totalhp/10
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E8"
|
||||
score -= 25 if @user.hp>@user.totalhp/2
|
||||
if skill_check(AILevel.medium)
|
||||
score -= 90 if @user.effects[PBEffects::ProtectRate]>1
|
||||
score -= 90 if @target.effects[PBEffects::HyperBeam]>0
|
||||
else
|
||||
score -= @user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0E9"
|
||||
if @target.hp==1
|
||||
score -= 90
|
||||
elsif @target.hp<=@target.totalhp/8
|
||||
score -= 60
|
||||
elsif @target.hp<=@target.totalhp/4
|
||||
score -= 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EA"
|
||||
score -= 100 if @battle.trainerBattle?
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EB"
|
||||
if @target.effects[PBEffects::Ingrain] ||
|
||||
(skill_check(AILevel.high) && @target.hasActiveAbility?(:SUCTIONCUPS))
|
||||
score -= 90
|
||||
else
|
||||
ch = 0
|
||||
@battle.pbParty(@target.index).each_with_index do |pkmn,i|
|
||||
ch += 1 if @battle.pbCanSwitchLax?(@target.index,i)
|
||||
end
|
||||
score -= 90 if ch==0
|
||||
end
|
||||
if score>20
|
||||
score += 50 if @target.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 50 if @target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 50 if @target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EC"
|
||||
if !@target.effects[PBEffects::Ingrain] &&
|
||||
!(skill_check(AILevel.high) && @target.hasActiveAbility?(:SUCTIONCUPS))
|
||||
score += 40 if @target.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 40 if @target.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 40 if @target.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0ED"
|
||||
if !@battle.pbCanChooseNonActive?(@user.index)
|
||||
score -= 80
|
||||
else
|
||||
score -= 40 if @user.effects[PBEffects::Confusion]>0
|
||||
total = 0
|
||||
PBStats.eachBattleStat { |s| total += @user.stages[s] }
|
||||
if total<=0 || @user.turnCount==0
|
||||
score -= 60
|
||||
else
|
||||
score += total*10
|
||||
# special case: user has no damaging moves
|
||||
hasDamagingMove = false
|
||||
@user.eachMove do |m|
|
||||
next if !m.damagingMove?
|
||||
hasDamagingMove = true
|
||||
break
|
||||
end
|
||||
score += 75 if !hasDamagingMove
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EE"
|
||||
#---------------------------------------------------------------------------
|
||||
when "0EF"
|
||||
score -= 90 if @target.effects[PBEffects::MeanLook]>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F0"
|
||||
if skill_check(AILevel.high)
|
||||
score += 20 if @target.item
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F1"
|
||||
if skill_check(AILevel.high)
|
||||
if !@user.item && @target.item
|
||||
score += 40
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
else
|
||||
score -= 80
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F2"
|
||||
if !@user.item && !@target.item
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.high) && @target.hasActiveAbility?(:STICKYHOLD)
|
||||
score -= 90
|
||||
elsif @user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
|
||||
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
|
||||
score += 50
|
||||
elsif !@user.item && @target.item
|
||||
score -= 30 if user.lastMoveUsed &&
|
||||
GameData::Move.get(@user.lastMoveUsed).function_code == "0F2" # Trick/Switcheroo
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F3"
|
||||
if !@user.item || @target.item
|
||||
score -= 90
|
||||
else
|
||||
if @user.hasActiveItem?([:FLAMEORB,:TOXICORB,:STICKYBARB,:IRONBALL,
|
||||
:CHOICEBAND,:CHOICESCARF,:CHOICESPECS])
|
||||
score += 50
|
||||
else
|
||||
score -= 80
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F4", "0F5"
|
||||
if @target.effects[PBEffects::Substitute]==0
|
||||
if skill_check(AILevel.high) && @target.item && @target.item.is_berry?
|
||||
score += 30
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F6"
|
||||
if !@user.recycleItem || @user.item
|
||||
score -= 80
|
||||
elsif @user.recycleItem
|
||||
score += 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F7"
|
||||
if !@user.item || !@user.itemActive? ||
|
||||
@user.unlosableItem?(@user.item) || @user.item.is_poke_ball?
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F8"
|
||||
score -= 90 if @target.effects[PBEffects::Embargo]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "0F9"
|
||||
if @battle.field.effects[PBEffects::MagicRoom]>0
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if !@user.item && @target.item
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FA"
|
||||
score -= 25
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FB"
|
||||
score -= 30
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FC"
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FD"
|
||||
score -= 30
|
||||
if @target.pbCanParalyze?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.medium)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
if aspeed<ospeed
|
||||
score += 30
|
||||
elsif aspeed>ospeed
|
||||
score -= 40
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FE"
|
||||
score -= 30
|
||||
if @target.pbCanBurn?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.high)
|
||||
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "0FF"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Sun
|
||||
score -= 90
|
||||
else
|
||||
@user.eachMove do |m|
|
||||
score += 20 if m.damagingMove? && m.type == :FIRE
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,497 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __e__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctions(score)
|
||||
score = __e__pbGetMoveScoreFunctions(score)
|
||||
case @move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "100"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Rain
|
||||
score -= 90
|
||||
else
|
||||
@user.eachMove do |m|
|
||||
score += 20 if m.damagingMove? && m.type == :WATER
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "101"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Sandstorm
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "102"
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::Hail
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "103"
|
||||
if @user.pbOpposingSide.effects[PBEffects::Spikes]>=3
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
@user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 10*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
|
||||
score += [40,26,13][@user.pbOpposingSide.effects[PBEffects::Spikes]]
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "104"
|
||||
if @user.pbOpposingSide.effects[PBEffects::ToxicSpikes]>=2
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
@user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 8*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
|
||||
score += [26,13][@user.pbOpposingSide.effects[PBEffects::ToxicSpikes]]
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "105"
|
||||
if @user.pbOpposingSide.effects[PBEffects::StealthRock]
|
||||
score -= 90
|
||||
else
|
||||
canChoose = false
|
||||
@user.eachOpposing do |b|
|
||||
next if !@battle.pbCanChooseNonActive?(b.index)
|
||||
canChoose = true
|
||||
break
|
||||
end
|
||||
if !canChoose
|
||||
# Opponent can't switch in any Pokemon
|
||||
score -= 90
|
||||
else
|
||||
score += 10*@battle.pbAbleNonActiveCount(@user.idxOpposingSide)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "106"
|
||||
#---------------------------------------------------------------------------
|
||||
when "107"
|
||||
#---------------------------------------------------------------------------
|
||||
when "108"
|
||||
#---------------------------------------------------------------------------
|
||||
when "109"
|
||||
#---------------------------------------------------------------------------
|
||||
when "10A"
|
||||
score += 20 if @user.pbOpposingSide.effects[PBEffects::AuroraVeil]>0
|
||||
score += 20 if @user.pbOpposingSide.effects[PBEffects::Reflect]>0
|
||||
score += 20 if @user.pbOpposingSide.effects[PBEffects::LightScreen]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "10B"
|
||||
score += 10*(@user.stages[PBStats::ACCURACY]-@target.stages[PBStats::EVASION])
|
||||
#---------------------------------------------------------------------------
|
||||
when "10C"
|
||||
if @user.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif @user.hp<=@user.totalhp/4
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "10D"
|
||||
if @user.pbHasType?(:GHOST)
|
||||
if @target.effects[PBEffects::Curse]
|
||||
score -= 90
|
||||
elsif @user.hp<=@user.totalhp/2
|
||||
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
|
||||
score -= 90
|
||||
else
|
||||
score -= 50
|
||||
score -= 30 if @battle.switchStyle
|
||||
end
|
||||
end
|
||||
else
|
||||
avg = @user.stages[PBStats::SPEED]*10
|
||||
avg -= @user.stages[PBStats::ATTACK]*10
|
||||
avg -= @user.stages[PBStats::DEFENSE]*10
|
||||
score += avg/3
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "10E"
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "10F"
|
||||
if @target.effects[PBEffects::Nightmare] ||
|
||||
@target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
elsif !@target.asleep?
|
||||
score -= 90
|
||||
else
|
||||
score -= 90 if @target.statusCount<=1
|
||||
score += 50 if @target.statusCount>3
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "110"
|
||||
score += 30 if @user.effects[PBEffects::Trapping]>0
|
||||
score += 30 if @user.effects[PBEffects::LeechSeed]>=0
|
||||
if @battle.pbAbleNonActiveCount(@user.idxOwnSide)>0
|
||||
score += 80 if @user.pbOwnSide.effects[PBEffects::Spikes]>0
|
||||
score += 80 if @user.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
|
||||
score += 80 if @user.pbOwnSide.effects[PBEffects::StealthRock]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "111"
|
||||
if @battle.positions[@target.index].effects[PBEffects::FutureSightCounter]>0
|
||||
score -= 100
|
||||
elsif @battle.pbAbleNonActiveCount(@user.idxOwnSide)==0
|
||||
# Future Sight tends to be wasteful if down to last Pokemon
|
||||
score -= 70
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "112"
|
||||
avg = 0
|
||||
avg -= @user.stages[PBStats::DEFENSE]*10
|
||||
avg -= @user.stages[PBStats::SPDEF]*10
|
||||
score += avg/2
|
||||
if @user.effects[PBEffects::Stockpile]>=3
|
||||
score -= 80
|
||||
else
|
||||
# More preferable if user also has Spit Up/Swallow
|
||||
score += 20 if @user.pbHasMoveFunction?("113","114") # Spit Up, Swallow
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "113"
|
||||
score -= 100 if @user.effects[PBEffects::Stockpile]==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "114"
|
||||
if @user.effects[PBEffects::Stockpile]==0
|
||||
score -= 90
|
||||
elsif @user.hp==@user.totalhp
|
||||
score -= 90
|
||||
else
|
||||
mult = [0,25,50,100][@user.effects[PBEffects::Stockpile]]
|
||||
score += mult
|
||||
score -= @user.hp*mult*2/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "115"
|
||||
score += 50 if @target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 35 if @target.hp<=@target.totalhp/2 # If target is weak, no
|
||||
score -= 70 if @target.hp<=@target.totalhp/4 # need to risk this move
|
||||
#---------------------------------------------------------------------------
|
||||
when "116"
|
||||
#---------------------------------------------------------------------------
|
||||
when "117"
|
||||
hasAlly = false
|
||||
@user.eachAlly do |b|
|
||||
hasAlly = true
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "118"
|
||||
if @battle.field.effects[PBEffects::Gravity]>0
|
||||
score -= 90
|
||||
elsif skill_check(AILevel.medium)
|
||||
score -= 30
|
||||
score -= 20 if @user.effects[PBEffects::SkyDrop]>=0
|
||||
score -= 20 if @user.effects[PBEffects::MagnetRise]>0
|
||||
score -= 20 if @user.effects[PBEffects::Telekinesis]>0
|
||||
score -= 20 if @user.pbHasType?(:FLYING)
|
||||
score -= 20 if @user.hasActiveAbility?(:LEVITATE)
|
||||
score -= 20 if @user.hasActiveItem?(:AIRBALLOON)
|
||||
score += 20 if @target.effects[PBEffects::SkyDrop]>=0
|
||||
score += 20 if @target.effects[PBEffects::MagnetRise]>0
|
||||
score += 20 if @target.effects[PBEffects::Telekinesis]>0
|
||||
score += 20 if @target.inTwoTurnAttack?("0C9","0CC","0CE") # Fly, Bounce, Sky Drop
|
||||
score += 20 if @target.pbHasType?(:FLYING)
|
||||
score += 20 if @target.hasActiveAbility?(:LEVITATE)
|
||||
score += 20 if @target.hasActiveItem?(:AIRBALLOON)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "119"
|
||||
if @user.effects[PBEffects::MagnetRise]>0 ||
|
||||
@user.effects[PBEffects::Ingrain] ||
|
||||
@user.effects[PBEffects::SmackDown]
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11A"
|
||||
if @target.effects[PBEffects::Telekinesis]>0 ||
|
||||
@target.effects[PBEffects::Ingrain] ||
|
||||
@target.effects[PBEffects::SmackDown]
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11B"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11C"
|
||||
if skill_check(AILevel.medium)
|
||||
score += 20 if @target.effects[PBEffects::MagnetRise]>0
|
||||
score += 20 if @target.effects[PBEffects::Telekinesis]>0
|
||||
score += 20 if @target.inTwoTurnAttack?("0C9","0CC") # Fly, Bounce
|
||||
score += 20 if @target.pbHasType?(:FLYING)
|
||||
score += 20 if @target.hasActiveAbility?(:LEVITATE)
|
||||
score += 20 if @target.hasActiveItem?(:AIRBALLOON)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "11D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11E"
|
||||
#---------------------------------------------------------------------------
|
||||
when "11F"
|
||||
#---------------------------------------------------------------------------
|
||||
when "120"
|
||||
#---------------------------------------------------------------------------
|
||||
when "121"
|
||||
#---------------------------------------------------------------------------
|
||||
when "122"
|
||||
#---------------------------------------------------------------------------
|
||||
when "123"
|
||||
if !@target.pbHasType?(@user.type1) &&
|
||||
!@target.pbHasType?(@user.type2)
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "124"
|
||||
#---------------------------------------------------------------------------
|
||||
when "125"
|
||||
#---------------------------------------------------------------------------
|
||||
when "126"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
#---------------------------------------------------------------------------
|
||||
when "127"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @target.pbCanParalyze?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.medium)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
if aspeed<ospeed
|
||||
score += 30
|
||||
elsif aspeed>ospeed
|
||||
score -= 40
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "128"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @target.pbCanBurn?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.high)
|
||||
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:QUICKFEET,:FLAREBOOST])
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "129"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @target.pbCanFreeze?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.high)
|
||||
score -= 20 if @target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12A"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @target.pbCanConfuse?(@user,false)
|
||||
score += 30
|
||||
else
|
||||
if skill_check(AILevel.medium)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12B"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if !@target.pbCanLowerStatStage?(PBStats::DEFENSE,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::DEFENSE]*20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12C"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if !@target.pbCanLowerStatStage?(PBStats::EVASION,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::EVASION]*15
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "12D"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
#---------------------------------------------------------------------------
|
||||
when "12E"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score += 20 if @target.hp>=@target.totalhp/2
|
||||
score -= 20 if @user.hp<@user.hp/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "12F"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score -= 110 if @target.effects[PBEffects::MeanLook]>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "130"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
score -= 40
|
||||
#---------------------------------------------------------------------------
|
||||
when "131"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @battle.pbCheckGlobalAbility(:AIRLOCK) ||
|
||||
@battle.pbCheckGlobalAbility(:CLOUDNINE)
|
||||
score -= 90
|
||||
elsif @battle.pbWeather==PBWeather::ShadowSky
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "132"
|
||||
score += 20 # Shadow moves are more preferable
|
||||
if @target.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
@target.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
score += 30
|
||||
score -= 90 if @user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 ||
|
||||
@user.pbOwnSide.effects[PBEffects::Reflect]>0 ||
|
||||
@user.pbOwnSide.effects[PBEffects::LightScreen]>0 ||
|
||||
@user.pbOwnSide.effects[PBEffects::Safeguard]>0
|
||||
else
|
||||
score -= 110
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "133", "134"
|
||||
score -= 95
|
||||
score = 0 if skill_check(AILevel.high)
|
||||
#---------------------------------------------------------------------------
|
||||
when "135"
|
||||
if @target.pbCanFreeze?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.high)
|
||||
score -= 20 if @target.hasActiveAbility?(:MARVELSCALE)
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "136"
|
||||
score += 20 if @user.stages[PBStats::DEFENSE]<0
|
||||
#---------------------------------------------------------------------------
|
||||
when "137"
|
||||
hasEffect = @user.statStageAtMax?(PBStats::DEFENSE) &&
|
||||
@user.statStageAtMax?(PBStats::SPDEF)
|
||||
@user.eachAlly do |b|
|
||||
next if b.statStageAtMax?(PBStats::DEFENSE) && b.statStageAtMax?(PBStats::SPDEF)
|
||||
hasEffect = true
|
||||
score -= b.stages[PBStats::DEFENSE]*10
|
||||
score -= b.stages[PBStats::SPDEF]*10
|
||||
end
|
||||
if hasEffect
|
||||
score -= @user.stages[PBStats::DEFENSE]*10
|
||||
score -= @user.stages[PBStats::SPDEF]*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "138"
|
||||
if @target.statStageAtMax?(PBStats::SPDEF)
|
||||
score -= 90
|
||||
else
|
||||
score -= @target.stages[PBStats::SPDEF]*10
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "139"
|
||||
if !@target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += @target.stages[PBStats::ATTACK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13A"
|
||||
avg = @target.stages[PBStats::ATTACK]*10
|
||||
avg += @target.stages[PBStats::SPATK]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "13B"
|
||||
if !@user.isSpecies?(:HOOPA) || @user.form!=1
|
||||
score -= 100
|
||||
else
|
||||
score += 20 if @target.stages[PBStats::DEFENSE]>0
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13C"
|
||||
score += 20 if @target.stages[PBStats::SPATK]>0
|
||||
#---------------------------------------------------------------------------
|
||||
when "13D"
|
||||
if !@target.pbCanLowerStatStage?(PBStats::SPATK,@user)
|
||||
score -= 90
|
||||
else
|
||||
score += 40 if @user.turnCount==0
|
||||
score += @target.stages[PBStats::SPATK]*20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "13E"
|
||||
count = 0
|
||||
@battle.eachBattler do |b|
|
||||
if b.pbHasType?(:GRASS) && !b.airborne? &&
|
||||
(!b.statStageAtMax?(PBStats::ATTACK) || !b.statStageAtMax?(PBStats::SPATK))
|
||||
count += 1
|
||||
if @user.opposes?(b)
|
||||
score -= 20
|
||||
else
|
||||
score -= @user.stages[PBStats::ATTACK]*10
|
||||
score -= @user.stages[PBStats::SPATK]*10
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "13F"
|
||||
count = 0
|
||||
@battle.eachBattler do |b|
|
||||
if b.pbHasType?(:GRASS) && !b.statStageAtMax?(PBStats::DEFENSE)
|
||||
count += 1
|
||||
if @user.opposes?(b)
|
||||
score -= 20
|
||||
else
|
||||
score -= @user.stages[PBStats::DEFENSE]*10
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,409 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
alias __f__pbGetMoveScoreFunctions pbGetMoveScoreFunctions
|
||||
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
def pbGetMoveScoreFunctions(score)
|
||||
score = __f__pbGetMoveScoreFunctions(score)
|
||||
case @move.function
|
||||
#---------------------------------------------------------------------------
|
||||
when "140"
|
||||
count=0
|
||||
@battle.eachBattler do |b|
|
||||
if b.poisoned? &&
|
||||
(!b.statStageAtMin?(PBStats::ATTACK) ||
|
||||
!b.statStageAtMin?(PBStats::SPATK) ||
|
||||
!b.statStageAtMin?(PBStats::SPEED))
|
||||
count += 1
|
||||
if @user.opposes?(b)
|
||||
score += @user.stages[PBStats::ATTACK]*10
|
||||
score += @user.stages[PBStats::SPATK]*10
|
||||
score += @user.stages[PBStats::SPEED]*10
|
||||
else
|
||||
score -= 20
|
||||
end
|
||||
end
|
||||
end
|
||||
score -= 95 if count==0
|
||||
#---------------------------------------------------------------------------
|
||||
when "141"
|
||||
if @target.effects[PBEffects::Substitute]>0
|
||||
score -= 90
|
||||
else
|
||||
numpos = 0; numneg = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
numpos += @target.stages[s] if @target.stages[s]>0
|
||||
numneg += @target.stages[s] if @target.stages[s]<0
|
||||
end
|
||||
if numpos!=0 || numneg!=0
|
||||
score += (numpos-numneg)*10
|
||||
else
|
||||
score -= 95
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "142"
|
||||
score -= 90 if @target.pbHasType?(:GHOST)
|
||||
#---------------------------------------------------------------------------
|
||||
when "143"
|
||||
score -= 90 if @target.pbHasType?(:GRASS)
|
||||
#---------------------------------------------------------------------------
|
||||
when "144"
|
||||
#---------------------------------------------------------------------------
|
||||
when "145"
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score -= 90 if aspeed>ospeed
|
||||
#---------------------------------------------------------------------------
|
||||
when "146"
|
||||
#---------------------------------------------------------------------------
|
||||
when "147"
|
||||
#---------------------------------------------------------------------------
|
||||
when "148"
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
if aspeed>ospeed
|
||||
score -= 90
|
||||
else
|
||||
score += 30 if @target.pbHasMoveType?(:FIRE)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "149"
|
||||
if @user.turnCount==0
|
||||
score += 30
|
||||
else
|
||||
score -= 90 # Because it will fail here
|
||||
score = 0 if skill_check(AILevel.best)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14A"
|
||||
#---------------------------------------------------------------------------
|
||||
when "14B", "14C"
|
||||
if @user.effects[PBEffects::ProtectRate]>1 ||
|
||||
@target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill_check(AILevel.medium)
|
||||
score -= @user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if @user.turnCount==0
|
||||
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14D"
|
||||
#---------------------------------------------------------------------------
|
||||
when "14E"
|
||||
if @user.statStageAtMax?(PBStats::SPATK) &&
|
||||
@user.statStageAtMax?(PBStats::SPDEF) &&
|
||||
@user.statStageAtMax?(PBStats::SPEED)
|
||||
score -= 90
|
||||
else
|
||||
score -= @user.stages[PBStats::SPATK]*10 # Only *10 isntead of *20
|
||||
score -= @user.stages[PBStats::SPDEF]*10 # because two-turn attack
|
||||
score -= @user.stages[PBStats::SPEED]*10
|
||||
if skill_check(AILevel.medium)
|
||||
hasSpecialAttack = false
|
||||
@user.eachMove do |m|
|
||||
next if !m.specialMove?(m.type)
|
||||
hasSpecialAttack = true
|
||||
break
|
||||
end
|
||||
if hasSpecialAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "14F"
|
||||
if skill_check(AILevel.high) && @target.hasActiveAbility?(:LIQUIDOOZE)
|
||||
score -= 80
|
||||
else
|
||||
score += 40 if @user.hp<=@user.totalhp/2
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "150"
|
||||
score += 20 if !@user.statStageAtMax?(PBStats::ATTACK) && @target.hp<=@target.totalhp/4
|
||||
#---------------------------------------------------------------------------
|
||||
when "151"
|
||||
avg = @target.stages[PBStats::ATTACK]*10
|
||||
avg += @target.stages[PBStats::SPATK]*10
|
||||
score += avg/2
|
||||
#---------------------------------------------------------------------------
|
||||
when "152"
|
||||
#---------------------------------------------------------------------------
|
||||
when "153"
|
||||
score -= 95 if @target.pbOwnSide.effects[PBEffects::StickyWeb]
|
||||
#---------------------------------------------------------------------------
|
||||
when "154"
|
||||
#---------------------------------------------------------------------------
|
||||
when "155"
|
||||
#---------------------------------------------------------------------------
|
||||
when "156"
|
||||
#---------------------------------------------------------------------------
|
||||
when "157"
|
||||
score -= 90
|
||||
#---------------------------------------------------------------------------
|
||||
when "158"
|
||||
score -= 90 if !@user.belched?
|
||||
#---------------------------------------------------------------------------
|
||||
when "159"
|
||||
if !@target.pbCanPoison?(@user,false) && !@target.pbCanLowerStatStage?(PBStats::SPEED,@user)
|
||||
score -= 90
|
||||
else
|
||||
if @target.pbCanPoison?(@user,false)
|
||||
score += 30
|
||||
if skill_check(AILevel.medium)
|
||||
score += 30 if @target.hp<=@target.totalhp/4
|
||||
score += 50 if @target.hp<=@target.totalhp/8
|
||||
score -= 40 if @target.effects[PBEffects::Yawn]>0
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
score += 10 if pbRoughStat(@target,PBStats::DEFENSE)>100
|
||||
score += 10 if pbRoughStat(@target,PBStats::SPDEF)>100
|
||||
score -= 40 if @target.hasActiveAbility?([:GUTS,:MARVELSCALE,:TOXICBOOST])
|
||||
end
|
||||
end
|
||||
if @target.pbCanLowerStatStage?(PBStats::SPEED,@user)
|
||||
score += @target.stages[PBStats::SPEED]*10
|
||||
if skill_check(AILevel.high)
|
||||
aspeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
ospeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
score += 30 if aspeed<ospeed && aspeed*2>ospeed
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15A"
|
||||
if @target.opposes?(@user)
|
||||
score -= 40 if @target.status==PBStatuses::BURN
|
||||
else
|
||||
score += 40 if @target.status==PBStatuses::BURN
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15B"
|
||||
if @target.status==PBStatuses::NONE
|
||||
score -= 90
|
||||
elsif @user.hp==@user.totalhp && @target.opposes?(@user)
|
||||
score -= 90
|
||||
else
|
||||
score += (@user.totalhp-@user.hp)*50/@user.totalhp
|
||||
score -= 30 if @target.opposes?(@user)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15C"
|
||||
hasEffect = @user.statStageAtMax?(PBStats::ATTACK) &&
|
||||
@user.statStageAtMax?(PBStats::SPATK)
|
||||
@user.eachAlly do |b|
|
||||
next if b.statStageAtMax?(PBStats::ATTACK) && b.statStageAtMax?(PBStats::SPATK)
|
||||
hasEffect = true
|
||||
score -= b.stages[PBStats::ATTACK]*10
|
||||
score -= b.stages[PBStats::SPATK]*10
|
||||
end
|
||||
if hasEffect
|
||||
score -= @user.stages[PBStats::ATTACK]*10
|
||||
score -= @user.stages[PBStats::SPATK]*10
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15D"
|
||||
numStages = 0
|
||||
PBStats.eachBattleStat do |s|
|
||||
next if @target.stages[s]<=0
|
||||
numStages += @target.stages[s]
|
||||
end
|
||||
score += numStages*20
|
||||
#---------------------------------------------------------------------------
|
||||
when "15E"
|
||||
if @user.effects[PBEffects::LaserFocus]>0
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "15F"
|
||||
score += @user.stages[PBStats::DEFENSE]*10
|
||||
#---------------------------------------------------------------------------
|
||||
when "160"
|
||||
if @target.statStageAtMin?(PBStats::ATTACK)
|
||||
score -= 90
|
||||
else
|
||||
if @target.pbCanLowerStatStage?(PBStats::ATTACK,@user)
|
||||
score += @target.stages[PBStats::ATTACK]*20
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
if hasPhysicalAttack
|
||||
score += 20
|
||||
elsif skill_check(AILevel.high)
|
||||
score -= 90
|
||||
end
|
||||
end
|
||||
end
|
||||
score += (@user.totalhp-@user.hp)*50/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "161"
|
||||
if skill_check(AILevel.medium)
|
||||
if @user.speed>@target.speed
|
||||
score += 50
|
||||
else
|
||||
score -= 70
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "162"
|
||||
score -= 90 if !@user.pbHasType?(:FIRE)
|
||||
#---------------------------------------------------------------------------
|
||||
when "163"
|
||||
#---------------------------------------------------------------------------
|
||||
when "164"
|
||||
#---------------------------------------------------------------------------
|
||||
when "165"
|
||||
if skill_check(AILevel.medium)
|
||||
userSpeed = pbRoughStat(@user,PBStats::SPEED)
|
||||
targetSpeed = pbRoughStat(@target,PBStats::SPEED)
|
||||
if userSpeed<targetSpeed
|
||||
score += 30
|
||||
end
|
||||
else
|
||||
score += 30
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "166"
|
||||
#---------------------------------------------------------------------------
|
||||
when "167"
|
||||
if @user.pbOwnSide.effects[PBEffects::AuroraVeil]>0 || @battle.pbWeather!=PBWeather::Hail
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "168"
|
||||
if @user.effects[PBEffects::ProtectRate]>1 ||
|
||||
@target.effects[PBEffects::HyperBeam]>0
|
||||
score -= 90
|
||||
else
|
||||
if skill_check(AILevel.medium)
|
||||
score -= @user.effects[PBEffects::ProtectRate]*40
|
||||
end
|
||||
score += 50 if @user.turnCount==0
|
||||
score += 30 if @target.effects[PBEffects::TwoTurnAttack]
|
||||
score += 20 # Because of possible poisoning
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "169"
|
||||
#---------------------------------------------------------------------------
|
||||
when "16A"
|
||||
hasAlly = false
|
||||
@target.eachAlly do |b|
|
||||
hasAlly = true
|
||||
break
|
||||
end
|
||||
score -= 90 if !hasAlly
|
||||
#---------------------------------------------------------------------------
|
||||
when "16B"
|
||||
if skill_check(AILevel.medium)
|
||||
if !@target.lastRegularMoveUsed ||
|
||||
!@target.pbHasMove?(@target.lastRegularMoveUsed) ||
|
||||
@target.usingMultiTurnAttack?
|
||||
score -= 90
|
||||
else
|
||||
# Without lots of code here to determine good/bad moves and relative
|
||||
# speeds, using this move is likely to just be a waste of a turn
|
||||
score -= 50
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16C"
|
||||
if @target.effects[PBEffects::ThroatChop]==0 && skill_check(AILevel.high)
|
||||
hasSoundMove = false
|
||||
@user.eachMove do |m|
|
||||
next if !m.soundMove?
|
||||
hasSoundMove = true
|
||||
break
|
||||
end
|
||||
score += 40 if hasSoundMove
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16D"
|
||||
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
score += 30 if @battle.pbWeather==PBWeather::Sandstorm
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16E"
|
||||
if @user.hp==@user.totalhp || (skill_check(AILevel.medium) && !@user.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= @user.hp*100/@user.totalhp
|
||||
if skill_check(AILevel.medium)
|
||||
score += 30 if @battle.field.terrain==PBBattleTerrains::Grassy
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "16F"
|
||||
if !@target.opposes?(@user)
|
||||
if @target.hp==@target.totalhp || (skill_check(AILevel.medium) && !@target.canHeal?)
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
score -= @target.hp*100/@target.totalhp
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "170"
|
||||
reserves = @battle.pbAbleNonActiveCount(@user.idxOwnSide)
|
||||
foes = @battle.pbAbleNonActiveCount(@user.idxOpposingSide)
|
||||
if @battle.pbCheckGlobalAbility(:DAMP)
|
||||
score -= 100
|
||||
elsif skill_check(AILevel.medium) && reserves==0 && foes>0
|
||||
score -= 100 # don't want to lose
|
||||
elsif skill_check(AILevel.high) && reserves==0 && foes==0
|
||||
score += 80 # want to draw
|
||||
else
|
||||
score -= (@user.total.hp-@user.hp)*75/@user.totalhp
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "171"
|
||||
if skill_check(AILevel.medium)
|
||||
hasPhysicalAttack = false
|
||||
@target.eachMove do |m|
|
||||
next if !m.physicalMove?(m.type)
|
||||
hasPhysicalAttack = true
|
||||
break
|
||||
end
|
||||
score -= 80 if !hasPhysicalAttack
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "172"
|
||||
score += 20 # Because of possible burning
|
||||
#---------------------------------------------------------------------------
|
||||
when "173"
|
||||
#---------------------------------------------------------------------------
|
||||
when "174"
|
||||
score -= 90 if @user.turnCount>0 || @user.lastRoundMoved>=0
|
||||
#---------------------------------------------------------------------------
|
||||
when "175"
|
||||
score += 30 if @target.effects[PBEffects::Minimize]
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1,725 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
def pbTargetsMultiple?(move)
|
||||
numTargets = 0
|
||||
case move.pbTarget(@user)
|
||||
when PBTargets::AllNearFoes
|
||||
@battle.eachOtherSideBattler(@user) { |b| numTargets += 1 if b.near?(@user) }
|
||||
return numTargets > 1
|
||||
when PBTargets::AllNearOthers
|
||||
@battle.eachBattler { |b| numTargets += 1 if b.near?(@user) }
|
||||
return numTargets > 1
|
||||
when PBTargets::UserAndAllies
|
||||
@battle.eachSameSideBattler(@user) { |_b| numTargets += 1 }
|
||||
return numTargets > 1
|
||||
when PBTargets::AllFoes
|
||||
@battle.eachOtherSideBattler(@user) { |_b| numTargets += 1 }
|
||||
return numTargets > 1
|
||||
when PBTargets::AllBattlers
|
||||
@battle.eachBattler { |_b| numTargets += 1 }
|
||||
return numTargets > 1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Move's type effectiveness
|
||||
#=============================================================================
|
||||
def pbCalcTypeModSingle(moveType,defType,user,target)
|
||||
ret = PBTypes.getEffectiveness(moveType,defType)
|
||||
# Ring Target
|
||||
if target.hasActiveItem?(:RINGTARGET)
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Foresight
|
||||
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :GHOST &&
|
||||
PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Miracle Eye
|
||||
if target.effects[PBEffects::MiracleEye]
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :DARK &&
|
||||
PBTypes.ineffective?(moveType,defType)
|
||||
end
|
||||
# Delta Stream's weather
|
||||
if @battle.pbWeather==PBWeather::StrongWinds
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING &&
|
||||
PBTypes.superEffective?(moveType,defType)
|
||||
end
|
||||
# Grounded Flying-type Pokémon become susceptible to Ground moves
|
||||
if !target.airborne?
|
||||
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING && moveType == :GROUND
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def pbCalcTypeMod(moveType,user,target)
|
||||
return PBTypeEffectiveness::NORMAL_EFFECTIVE if !moveType
|
||||
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType == :GROUND &&
|
||||
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
|
||||
# Determine types
|
||||
tTypes = target.pbTypes(true)
|
||||
# Get effectivenesses
|
||||
typeMods = [PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
|
||||
tTypes.each_with_index do |type,i|
|
||||
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
|
||||
end
|
||||
# Multiply all effectivenesses together
|
||||
ret = 1
|
||||
typeMods.each { |m| ret *= m }
|
||||
return ret
|
||||
end
|
||||
|
||||
# For switching. Determines the effectiveness of a potential switch-in against
|
||||
# an opposing battler.
|
||||
def pbCalcTypeModPokemon(battlerThis, _battlerOther)
|
||||
mod1 = PBTypes.getCombinedEffectiveness(battlerThis.type1, target.type1, target.type2)
|
||||
return mod1 if battlerThis.type1 == battlerThis.type2
|
||||
mod2 = PBTypes.getCombinedEffectiveness(battlerThis.type2, target.type1, target.type2)
|
||||
return mod1 * mod2.to_f / PBTypeEffectivenesss::NORMAL_EFFECTIVE
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Immunity to a move because of the target's ability, item or other effects
|
||||
#=============================================================================
|
||||
def pbCheckMoveImmunity(move, target)
|
||||
# TODO: Add consideration of user's Mold Breaker.
|
||||
move_type = pbRoughType(move)
|
||||
typeMod = pbCalcTypeMod(move_type, @user, target)
|
||||
# Type effectiveness
|
||||
return true if PBTypeEffectiveness.ineffective?(typeMod)
|
||||
# Immunity due to ability/item/other effects
|
||||
if skill_check(AILevel.medium)
|
||||
case move_type
|
||||
when :GROUND
|
||||
# TODO: Split target.airborne? into separate parts to allow different
|
||||
# skill levels to apply to each part.
|
||||
return true if target.airborne? && !move.hitsFlyingTargets?
|
||||
when :FIRE
|
||||
return true if target.hasActiveAbility?(:FLASHFIRE)
|
||||
when :WATER
|
||||
return true if target.hasActiveAbility?([:DRYSKIN, :STORMDRAIN, :WATERABSORB])
|
||||
when :GRASS
|
||||
return true if target.hasActiveAbility?(:SAPSIPPER)
|
||||
when :ELECTRIC
|
||||
return true if target.hasActiveAbility?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB])
|
||||
end
|
||||
return true if PBTypeEffectiveness.notVeryEffective?(typeMod) &&
|
||||
target.hasActiveAbility?(:WONDERGUARD)
|
||||
return true if move.damagingMove? && @user.index != target.index && !target.opposes?(@user) &&
|
||||
target.hasActiveAbility?(:TELEPATHY)
|
||||
return true if move.canMagicCoat? && target.hasActiveAbility?(:MAGICBOUNCE) &&
|
||||
target.opposes?(@user)
|
||||
return true if move.soundMove? && target.hasActiveAbility?(:SOUNDPROOF)
|
||||
return true if move.bombMove? && target.hasActiveAbility?(:BULLETPROOF)
|
||||
if move.powderMove?
|
||||
return true if target.pbHasType?(:GRASS)
|
||||
return true if skill_check(AILevel.best) && target.hasActiveAbility?(:OVERCOAT)
|
||||
return true if skill_check(AILevel.high) && target.hasActiveItem?(:SAFETYGOGGLES)
|
||||
end
|
||||
return true if target.effects[PBEffects::Substitute] > 0 && move.statusMove? &&
|
||||
!move.ignoresSubstitute?(@user) && @user.index != target.index
|
||||
return true if NEWEST_BATTLE_MECHANICS && @user.hasActiveAbility?(:PRANKSTER) &&
|
||||
target.pbHasType?(:DARK) && target.opposes?(@user)
|
||||
return true if move.priority>0 && @battle.field.terrain == PBBattleTerrains::Psychic &&
|
||||
target.affectedByTerrain? && target.opposes?(@user)
|
||||
# TODO: Dazzling/Queenly Majesty go here.
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get approximate properties for a battler
|
||||
#=============================================================================
|
||||
def pbRoughType(move)
|
||||
ret = move.type
|
||||
if skill_check(AILevel.high)
|
||||
ret = move.pbCalcType(@user)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def pbRoughStat(battler,stat)
|
||||
return battler.pbSpeed if skill_check(AILevel.high) && stat==PBStats::SPEED
|
||||
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
|
||||
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
|
||||
stage = battler.stages[stat]+6
|
||||
value = 0
|
||||
case stat
|
||||
when PBStats::ATTACK then value = battler.attack
|
||||
when PBStats::DEFENSE then value = battler.defense
|
||||
when PBStats::SPATK then value = battler.spatk
|
||||
when PBStats::SPDEF then value = battler.spdef
|
||||
when PBStats::SPEED then value = battler.speed
|
||||
end
|
||||
return (value.to_f * stageMul[stage] / stageDiv[stage]).floor
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Get a better move's base damage value
|
||||
#=============================================================================
|
||||
def pbMoveBaseDamage(move, target)
|
||||
baseDmg = move.baseDamage
|
||||
baseDmg = 60 if baseDmg == 1
|
||||
return baseDmg if !skill_check(AILevel.medium)
|
||||
# Covers all function codes which have their own def pbBaseDamage
|
||||
case move.function
|
||||
when "010" # Stomp
|
||||
baseDmg *= 2 if target.effects[PBEffects::Minimize]
|
||||
# Sonic Boom, Dragon Rage, Super Fang, Night Shade, Endeavor
|
||||
when "06A", "06B", "06C", "06D", "06E"
|
||||
baseDmg = move.pbFixedDamage(@user, target)
|
||||
when "06F" # Psywave
|
||||
baseDmg = @user.level
|
||||
when "070" # OHKO
|
||||
baseDmg = target.totalhp
|
||||
when "071", "072", "073" # Counter, Mirror Coat, Metal Burst
|
||||
# TODO: Check memory to find the move that did the most damage, and use
|
||||
# that value (if this move counters it, applying this move's
|
||||
# doubling effect if appropriate).
|
||||
baseDmg = 60
|
||||
when "075", "076", "0D0", "12D" # Surf, Earthquake, Whirlpool, Shadow Storm
|
||||
baseDmg = move.pbModifyDamage(baseDmg, @user, target)
|
||||
# Bulldoze, Gust, Twister, Venoshock, Smelling Salts, Wake-Up Slap, Facade,
|
||||
# Hex, Brine, Retaliate, Weather Ball, Return, Frustration, Eruption,
|
||||
# Crush Grip, Stored Power, Punishment, Flail, Electro Ball, Low Kick,
|
||||
# Knock Off, Spit Up, Stomping Tantrum
|
||||
when "044", "077", "078", "07B", "07C", "07D", "07E", "07F", "080", "085",
|
||||
"087", "089", "08A", "08B", "08C", "08E", "08F", "098", "099", "09A",
|
||||
"0F0", "113", "166"
|
||||
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
|
||||
when "086" # Acrobatics
|
||||
baseDmg *= 2 if !@user.item || @user.hasActiveItem?(:FLYINGGEM)
|
||||
when "08D" # Gyro Ball
|
||||
target_speed = pbRoughStat(target, PBStats::SPEED)
|
||||
user_speed = pbRoughStat(@user, PBStats::SPEED)
|
||||
baseDmg = [[(25 * target_speed / user_speed).floor, 150].min, 1].max
|
||||
when "091" # Fury Cutter
|
||||
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
|
||||
baseDmg *= 2 if baseDmg < 160 && @user.effects[PBEffects::FuryCutter] > 0
|
||||
when "092" # Echoed Voice
|
||||
factor = @user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter]
|
||||
baseDmg *= [(factor + 1), 5].min
|
||||
when "094" # Present
|
||||
baseDmg = 50
|
||||
when "095" # Magnitude
|
||||
baseDmg = 71
|
||||
baseDmg *= 2 if target.inTwoTurnAttack?("0CA") # Dig
|
||||
baseDmg /= 2 if @battle.field.terrain == PBBattleTerrains::Grassy
|
||||
when "096" # Natural Gift
|
||||
baseDmg = 0 if !@user.item || !@user.item.is_berry? || !@user.itemActive?
|
||||
baseDmg = move.pbNaturalGiftBaseDamage(@user.item_id) if baseDmg > 0
|
||||
when "097" # Trump Card
|
||||
dmgs = [200, 80, 60, 50, 40]
|
||||
pp_left = [[move.pp - 1, dmgs.length - 1].min, 0].max
|
||||
return dmgs[pp_left]
|
||||
when "09B" # Heavy Slam
|
||||
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
|
||||
baseDmg *= 2 if NEWEST_BATTLE_MECHANICS && target.effects[PBEffects::Minimize]
|
||||
when "0BD", "0BE" # Double Kick, Twineedle
|
||||
baseDmg *= 2
|
||||
when "0BF" # Triple Kick
|
||||
baseDmg *= 6 # Hits do x1, x2, x3 baseDmg in turn, for x6 in total
|
||||
when "0C0" # Fury Attack
|
||||
if @user.hasActiveAbility?(:SKILLLINK)
|
||||
baseDmg *= 5
|
||||
else
|
||||
baseDmg = (baseDmg * 19 / 6).floor # Average damage dealt
|
||||
end
|
||||
when "0C1" # Beat Up
|
||||
mult = 0
|
||||
@battle.eachInTeamFromBattlerIndex(@user.index) do |pkmn, _i|
|
||||
mult += 1 if pkmn && pkmn.able? && pkmn.status == PBStatuses::NONE
|
||||
end
|
||||
baseDmg *= mult
|
||||
when "0C4" # Solar Beam
|
||||
baseDmg = move.pbBaseDamageMultiplier(baseDmg, @user, target)
|
||||
when "0D3" # Rollout
|
||||
baseDmg *= 2 if @user.effects[PBEffects::DefenseCurl]
|
||||
when "0D4" # Bide
|
||||
# TODO: Maybe make this equal to the highest damage a foe has dealt?
|
||||
baseDmg = 40
|
||||
when "0E1" # Final Gambit
|
||||
baseDmg = @user.hp
|
||||
when "0F7" # Fling
|
||||
if !@user.item || !@user.itemActive? || @user.unlosableItem?(@user.item) ||
|
||||
(@user.item.is_berry? && @battle.pbCheckOpposingAbility(:UNNERVE, @user.index))
|
||||
baseDmg = 0
|
||||
else
|
||||
# TODO: Currently assumes a power of 10 if item is unflingable.
|
||||
baseDmg = move.pbBaseDamage(baseDmg, @user, target)
|
||||
end
|
||||
when "144" # Flying Press
|
||||
if GameData::Type.exists?(:FLYING)
|
||||
if skill_check(AILevel.high)
|
||||
targetTypes = target.pbTypes(true)
|
||||
mult = PBTypes.getCombinedEffectiveness(:FLYING,
|
||||
targetTypes[0], targetTypes[1], targetTypes[2])
|
||||
baseDmg = (baseDmg.to_f * mult / PBTypeEffectiveness::NORMAL_EFFECTIVE).round
|
||||
else
|
||||
mult = PBTypes.getCombinedEffectiveness(:FLYING,
|
||||
target.type1, target.type2, target.effects[PBEffects::Type3])
|
||||
baseDmg = (baseDmg.to_f * mult / PBTypeEffectiveness::NORMAL_EFFECTIVE).round
|
||||
end
|
||||
end
|
||||
baseDmg *= 2 if target.effects[PBEffects::Minimize]
|
||||
when "175" # Double Iron Bash
|
||||
baseDmg *= 2
|
||||
baseDmg *= 2 if target.effects[PBEffects::Minimize]
|
||||
end
|
||||
return baseDmg
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Damage calculation
|
||||
#=============================================================================
|
||||
def pbRoughDamage(move,target,baseDmg)
|
||||
# Fixed damage moves
|
||||
return baseDmg if move.is_a?(PokeBattle_FixedDamageMove)
|
||||
|
||||
# Get the move's type
|
||||
type = pbRoughType(move)
|
||||
|
||||
##### Calculate user's attack stat #####
|
||||
atk = pbRoughStat(@user,PBStats::ATTACK)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,PBStats::ATTACK)
|
||||
elsif move.specialMove?(type)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,PBStats::SPATK)
|
||||
else
|
||||
atk = pbRoughStat(@user,PBStats::SPATK)
|
||||
end
|
||||
end
|
||||
|
||||
##### Calculate target's defense stat #####
|
||||
defense = pbRoughStat(target,PBStats::DEFENSE)
|
||||
if move.specialMove?(type) && move.function!="122" # Psyshock
|
||||
defense = pbRoughStat(target,PBStats::SPDEF)
|
||||
end
|
||||
|
||||
##### Calculate all multiplier effects #####
|
||||
multipliers = [1.0, 1.0, 1.0, 1.0]
|
||||
# Ability effects that alter damage
|
||||
mold_breaker = false
|
||||
if skill_check(AILevel.high) && @user.hasMoldBreaker?
|
||||
mold_breaker = true
|
||||
end
|
||||
|
||||
if skill_check(AILevel.medium) && @user.abilityActive?
|
||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||
# round.
|
||||
if ![:ANALYTIC, :SNIPER, :TINTEDLENS, :AERILATE, :PIXILATE,
|
||||
:REFRIGERATE].include?(@user.ability_id)
|
||||
BattleHandlers.triggerDamageCalcUserAbility(@user.ability,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
|
||||
if skill_check(AILevel.medium) && !mold_breaker
|
||||
@user.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerDamageCalcUserAllyAbility(b.ability,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
|
||||
if skill_check(AILevel.best) && !mold_breaker && target.abilityActive?
|
||||
# NOTE: These abilities aren't suitable for checking at the start of the
|
||||
# round.
|
||||
if ![:FILTER, :SOLIDROCK].include?(target.ability_id)
|
||||
BattleHandlers.triggerDamageCalcTargetAbility(target.ability,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
|
||||
if skill_check(AILevel.best) && !mold_breaker
|
||||
target.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerDamageCalcTargetAllyAbility(b.ability,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
|
||||
# Item effects that alter damage
|
||||
# NOTE: Type-boosting gems aren't suitable for checking at the start of the
|
||||
# round.
|
||||
if skill_check(AILevel.medium) && @user.itemActive?
|
||||
# NOTE: These items aren't suitable for checking at the start of the
|
||||
# round.
|
||||
if ![:EXPERTBELT, :LIFEORB].include?(@user.item_id)
|
||||
BattleHandlers.triggerDamageCalcUserItem(@user.item,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
# TODO: Prefer (1.5x?) if item will be consumed and user has Unburden.
|
||||
end
|
||||
|
||||
if skill_check(AILevel.best) && target.itemActive?
|
||||
# NOTE: Type-weakening berries aren't suitable for checking at the start
|
||||
# of the round.
|
||||
if !target.item.is_berry?
|
||||
BattleHandlers.triggerDamageCalcTargetItem(target.item,
|
||||
@user,target,move,multipliers,baseDmg,type)
|
||||
end
|
||||
end
|
||||
|
||||
# Global abilities
|
||||
if skill_check(AILevel.medium)
|
||||
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
|
||||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
|
||||
if @battle.pbCheckGlobalAbility(:AURABREAK)
|
||||
multipliers[BASE_DMG_MULT] *= 2.0 / 3
|
||||
else
|
||||
multipliers[BASE_DMG_MULT] *= 4.0 / 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Parental Bond
|
||||
if skill_check(AILevel.medium) && @user.hasActiveAbility?(:PARENTALBOND)
|
||||
multipliers[BASE_DMG_MULT] *= 1.25
|
||||
end
|
||||
|
||||
# Me First
|
||||
# TODO
|
||||
|
||||
# Helping Hand - n/a
|
||||
|
||||
# Charge
|
||||
if skill_check(AILevel.medium)
|
||||
if @user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
|
||||
multipliers[BASE_DMG_MULT] *= 2
|
||||
end
|
||||
end
|
||||
|
||||
# Mud Sport and Water Sport
|
||||
if skill_check(AILevel.medium)
|
||||
if type == :ELECTRIC
|
||||
@battle.eachBattler do |b|
|
||||
next if !b.effects[PBEffects::MudSport]
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
break
|
||||
end
|
||||
if @battle.field.effects[PBEffects::MudSportField]>0
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
end
|
||||
end
|
||||
if type == :FIRE
|
||||
@battle.eachBattler do |b|
|
||||
next if !b.effects[PBEffects::WaterSport]
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
break
|
||||
end
|
||||
if @battle.field.effects[PBEffects::WaterSportField]>0
|
||||
multipliers[BASE_DMG_MULT] /= 3
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Terrain moves
|
||||
if @user.affectedByTerrain? && skill_check(AILevel.medium)
|
||||
case @battle.field.terrain
|
||||
when PBBattleTerrains::Electric
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :ELECTRIC
|
||||
when PBBattleTerrains::Grassy
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :GRASS
|
||||
when PBBattleTerrains::Psychic
|
||||
multipliers[BASE_DMG_MULT] *= 1.5 if type == :PSYCHIC
|
||||
end
|
||||
end
|
||||
if target.affectedByTerrain? && skill_check(AILevel.medium)
|
||||
if @battle.field.terrain==PBBattleTerrains::Misty && type == :DRAGON
|
||||
multipliers[BASE_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
|
||||
# Badge multipliers
|
||||
if skill_check(AILevel.high)
|
||||
if @battle.internalBattle
|
||||
# Don't need to check the Atk/Sp Atk-boosting badges because the AI
|
||||
# won't control the player's Pokémon.
|
||||
if target.pbOwnedByPlayer?
|
||||
if move.physicalMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
|
||||
multipliers[DEF_MULT] *= 1.1
|
||||
elsif move.specialMove?(type) && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
|
||||
multipliers[DEF_MULT] *= 1.1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Multi-targeting attacks
|
||||
if skill_check(AILevel.high)
|
||||
if pbTargetsMultiple?(move)
|
||||
multipliers[FINAL_DMG_MULT] *= 0.75
|
||||
end
|
||||
end
|
||||
|
||||
# Weather
|
||||
if skill_check(AILevel.medium)
|
||||
case @battle.pbWeather
|
||||
when PBWeather::Sun, PBWeather::HarshSun
|
||||
if type == :FIRE
|
||||
multipliers[FINAL_DMG_MULT] *= 1.5
|
||||
elsif type == :WATER
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
when PBWeather::Rain, PBWeather::HeavyRain
|
||||
if type == :FIRE
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
elsif type == :WATER
|
||||
multipliers[FINAL_DMG_MULT] *= 1.5
|
||||
end
|
||||
when PBWeather::Sandstorm
|
||||
if target.pbHasType?(:ROCK) && move.specialMove?(type) && move.function!="122" # Psyshock
|
||||
multipliers[DEF_MULT] *= 1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Critical hits - n/a
|
||||
|
||||
# Random variance - n/a
|
||||
|
||||
# STAB
|
||||
if skill_check(AILevel.medium)
|
||||
if type && @user.pbHasType?(type)
|
||||
if @user.hasActiveAbility?(:ADAPTABILITY)
|
||||
multipliers[FINAL_DMG_MULT] *= 2
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Type effectiveness
|
||||
if skill_check(AILevel.medium)
|
||||
typemod = pbCalcTypeMod(type,@user,target)
|
||||
multipliers[FINAL_DMG_MULT] *= typemod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
|
||||
end
|
||||
|
||||
# Burn
|
||||
if skill_check(AILevel.high)
|
||||
if @user.status==PBStatuses::BURN && move.physicalMove?(type) &&
|
||||
!@user.hasActiveAbility?(:GUTS) &&
|
||||
!(NEWEST_BATTLE_MECHANICS && move.function=="07E") # Facade
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
|
||||
# Aurora Veil, Reflect, Light Screen
|
||||
if skill_check(AILevel.high)
|
||||
if !move.ignoresReflect? && !@user.hasActiveAbility?(:INFILTRATOR)
|
||||
if target.pbOwnSide.effects[PBEffects::AuroraVeil]>0
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && move.physicalMove?(type)
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && move.specialMove?(type)
|
||||
if @battle.pbSideBattlerCount(target)>1
|
||||
multipliers[FINAL_DMG_MULT] *= 2.0 / 3
|
||||
else
|
||||
multipliers[FINAL_DMG_MULT] /= 2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Minimize
|
||||
if skill_check(AILevel.high)
|
||||
if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(2)
|
||||
multipliers[FINAL_DMG_MULT] *= 2
|
||||
end
|
||||
end
|
||||
|
||||
# Move-specific base damage modifiers
|
||||
# TODO
|
||||
|
||||
# Move-specific final damage modifiers
|
||||
# TODO
|
||||
|
||||
##### Main damage calculation #####
|
||||
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT]).round, 1].max
|
||||
atk = [(atk * multipliers[ATK_MULT]).round, 1].max
|
||||
defense = [(defense * multipliers[DEF_MULT]).round, 1].max
|
||||
damage = (((2.0 * @user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
|
||||
damage = [(damage * multipliers[FINAL_DMG_MULT]).round, 1].max
|
||||
return damage.floor
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Critical hit rate calculation
|
||||
#=============================================================================
|
||||
def pbRoughCriticalHitStage(move, target)
|
||||
return -1 if target.pbOwnSide.effects[PBEffects::LuckyChant] > 0
|
||||
mold_breaker = (skill_check(AILevel.medium) && @user.hasMoldBreaker?)
|
||||
crit_stage = 0
|
||||
# Ability effects that alter critical hit rate
|
||||
if skill_check(AILevel.medium) && @user.abilityActive?
|
||||
crit_stage = BattleHandlers.triggerCriticalCalcUserAbility(@user.ability, @user, target, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
end
|
||||
if skill_check(AILevel.best) && !mold_breaker && target.abilityActive?
|
||||
crit_stage = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability, @user, target, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
end
|
||||
# Item effects that alter critical hit rate
|
||||
if skill_check(AILevel.medium) && @user.itemActive?
|
||||
crit_stage = BattleHandlers.triggerCriticalCalcUserItem(@user.item, @user, target, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
end
|
||||
if skill_check(AILevel.high) && target.itemActive?
|
||||
crit_stage = BattleHandlers.triggerCriticalCalcTargetItem(target.item, @user, target, crit_stage)
|
||||
return -1 if crit_stage < 0
|
||||
end
|
||||
# Other effects
|
||||
case move.pbCritialOverride(@user, target)
|
||||
when 1 then return 99
|
||||
when -1 then return -1
|
||||
end
|
||||
return 99 if crit_stage > 50 # Merciless
|
||||
return 99 if @user.effects[PBEffects::LaserFocus] > 0
|
||||
crit_stage += 1 if move.highCriticalRate?
|
||||
crit_stage += @user.effects[PBEffects::FocusEnergy]
|
||||
crit_stage += 1 if @user.inHyperMode? && move.type == :SHADOW
|
||||
crit_stage = [crit_stage, PokeBattle_Move::CRITICAL_HIT_RATIOS.length - 1].min
|
||||
return crit_stage
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Accuracy calculation
|
||||
#=============================================================================
|
||||
def pbRoughAccuracy(move, target)
|
||||
# "Always hit" effects and "always hit" accuracy
|
||||
if skill_check(AILevel.medium)
|
||||
return 100 if target.effects[PBEffects::Minimize] && move.tramplesMinimize?(1)
|
||||
return 100 if target.effects[PBEffects::Telekinesis] > 0
|
||||
end
|
||||
# Get base accuracy
|
||||
baseAcc = move.accuracy
|
||||
if skill_check(AILevel.medium)
|
||||
baseAcc = move.pbBaseAccuracy(@user, target)
|
||||
end
|
||||
return 100 if baseAcc == 0 && skill_check(AILevel.medium)
|
||||
# Get the move's type
|
||||
type = pbRoughType(move)
|
||||
# Calculate all modifier effects
|
||||
modifiers = []
|
||||
modifiers[BASE_ACC] = baseAcc
|
||||
modifiers[ACC_STAGE] = @user.stages[PBStats::ACCURACY]
|
||||
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
|
||||
modifiers[ACC_MULT] = 1.0
|
||||
modifiers[EVA_MULT] = 1.0
|
||||
pbCalcAccuracyModifiers(target, modifiers, move, type)
|
||||
# Check if move certainly misses/can't miss
|
||||
return 0 if modifiers[BASE_ACC] < 0
|
||||
return 100 if modifiers[BASE_ACC] == 0
|
||||
# Calculation
|
||||
accStage = [[modifiers[ACC_STAGE], -6].max, 6].min + 6
|
||||
evaStage = [[modifiers[EVA_STAGE], -6].max, 6].min + 6
|
||||
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
|
||||
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
|
||||
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
|
||||
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
|
||||
accuracy = (accuracy * modifiers[ACC_MULT]).round
|
||||
evasion = (evasion * modifiers[EVA_MULT]).round
|
||||
evasion = 1 if evasion < 1
|
||||
return modifiers[BASE_ACC] * accuracy / evasion
|
||||
end
|
||||
|
||||
def pbCalcAccuracyModifiers(target,modifiers,move,type)
|
||||
mold_breaker = false
|
||||
if skill_check(AILevel.medium) && @user.hasMoldBreaker?
|
||||
mold_breaker = true
|
||||
end
|
||||
# Ability effects that alter accuracy calculation
|
||||
if skill_check(AILevel.medium)
|
||||
if @user.abilityActive?
|
||||
BattleHandlers.triggerAccuracyCalcUserAbility(@user.ability,
|
||||
modifiers, @user, target, move, type)
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
@user.eachAlly do |b|
|
||||
next if !b.abilityActive?
|
||||
BattleHandlers.triggerAccuracyCalcUserAllyAbility(b.ability,
|
||||
modifiers, @user, target, move, type)
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.best)
|
||||
if target.abilityActive? && !mold_breaker
|
||||
BattleHandlers.triggerAccuracyCalcTargetAbility(target.ability,
|
||||
modifiers, @user, target, move, type)
|
||||
end
|
||||
end
|
||||
# Item effects that alter accuracy calculation
|
||||
if skill_check(AILevel.medium)
|
||||
if @user.itemActive?
|
||||
# TODO: Zoom Lens needs to be checked differently (compare speeds of
|
||||
# user and target).
|
||||
BattleHandlers.triggerAccuracyCalcUserItem(@user.item,
|
||||
modifiers, @user, target, move, type)
|
||||
end
|
||||
end
|
||||
if skill_check(AILevel.high)
|
||||
if target.itemActive?
|
||||
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
|
||||
modifiers, @user, target, move, type)
|
||||
end
|
||||
end
|
||||
# Other effects, inc. ones that set ACC_MULT or EVA_STAGE to specific values
|
||||
if @battle.field.effects[PBEffects::Gravity] > 0
|
||||
modifiers[ACC_MULT] *= 5 / 3.0
|
||||
end
|
||||
if skill_check(AILevel.medium)
|
||||
if @user.effects[PBEffects::MicleBerry]
|
||||
modifiers[ACC_MULT] *= 1.2
|
||||
end
|
||||
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE] > 0
|
||||
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_STAGE] > 0
|
||||
end
|
||||
# "AI-specific calculations below"
|
||||
modifiers[EVA_STAGE] = 0 if move.function == "0A9" # Chip Away
|
||||
modifiers[BASE_ACC] = 0 if ["0A5", "139", "13A", "13B", "13C", # "Always hit"
|
||||
"147"].include?(move.function)
|
||||
if skill_check(AILevel.medium)
|
||||
modifiers[BASE_ACC] = 0 if @user.effects[PBEffects::LockOn] > 0 &&
|
||||
@user.effects[PBEffects::LockOnPos] == target.index
|
||||
end
|
||||
if skill_check(AILevel.medium)
|
||||
if move.function == "006" # Toxic
|
||||
modifiers[BASE_ACC] = 0 if NEWEST_BATTLE_MECHANICS && move.statusMove? &&
|
||||
@user.pbHasType?(:POISON)
|
||||
elsif move.function == "070" # OHKO moves
|
||||
modifiers[BASE_ACC] = move.accuracy + @user.level - target.level
|
||||
modifiers[BASE_ACC] = -1 if modifiers[BASE_ACC] <= 0 # Certain miss
|
||||
modifiers[ACC_MULT] = 0 if target.level > @user.level
|
||||
if skill_check(AILevel.best)
|
||||
modifiers[ACC_MULT] = 0 if target.hasActiveAbility?(:STURDY) && !mold_breaker
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Check if battler has a move that meets the criteria in the block provided
|
||||
#=============================================================================
|
||||
def check_for_move(battler)
|
||||
ret = false
|
||||
battler.eachMove do |move|
|
||||
next unless yield move
|
||||
ret = true
|
||||
break
|
||||
end
|
||||
return ret
|
||||
end
|
||||
end
|
||||
@@ -1,165 +0,0 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
#
|
||||
#=============================================================================
|
||||
# TODO: Reborn has the REVENGEKILLER role which compares mon's speed with
|
||||
# opponent (only when deciding whether to switch mon in) - this
|
||||
# comparison should be calculated when needed instead of being a role.
|
||||
module BattleRole
|
||||
PHAZER = 0
|
||||
CLERIC = 1
|
||||
STALLBREAKER = 2
|
||||
STATUSABSORBER = 3
|
||||
BATONPASSER = 4
|
||||
SPINNER = 5
|
||||
FIELDSETTER = 6
|
||||
WEATHERSETTER = 7
|
||||
SWEEPER = 8
|
||||
PIVOT = 9
|
||||
PHYSICALWALL = 10
|
||||
SPECIALWALL = 11
|
||||
TANK = 12
|
||||
TRAPPER = 13
|
||||
SCREENER = 14
|
||||
ACE = 15
|
||||
LEAD = 16
|
||||
SECOND = 17
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Determine the roles filled by a Pokémon on a given side at a given party
|
||||
# index.
|
||||
#=============================================================================
|
||||
def determine_roles(side, index)
|
||||
pkmn = @battle.pbParty(side)[index]
|
||||
ret = []
|
||||
return ret if !pkmn || pkmn.egg?
|
||||
|
||||
# Check for moves indicative of particular roles
|
||||
hasHealMove = false
|
||||
hasPivotMove = false
|
||||
pkmn.moves.each do |m|
|
||||
next if !m
|
||||
move = PokeBattle_Move.pbFromPBMove(@battle, m)
|
||||
hasHealMove = true if !hasHealMove && move.healingMove?
|
||||
case move.function
|
||||
when "004", "0E5", "0EB", "0EC" # Yawn, Perish Song, Roar, Circle Throw
|
||||
ret.push(BattleRole::PHAZER)
|
||||
when "019" # Aromatherapy/Heal Bell
|
||||
ret.push(BattleRole::CLERIC)
|
||||
when "0BA" # Taunt
|
||||
ret.push(BattleRole::STALLBREAKER)
|
||||
when "0D7" # Wish
|
||||
ret.push(BattleRole::CLERIC) if pkmn.ev[PBStats::HP] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
when "0D9" # Rest
|
||||
ret.push(BattleRole::STATUSABSORBER)
|
||||
when "0ED" # Baton Pass
|
||||
ret.push(BattleRole::BATONPASSER)
|
||||
when "0EE" # U-turn
|
||||
hasPivotMove = true
|
||||
when "110" # Rapid Spin
|
||||
ret.push(BattleRole::SPINNER)
|
||||
when "154", "155", "156", "173" # Terrain moves
|
||||
ret.push(BattleRole::FIELDSETTER)
|
||||
else
|
||||
ret.push(BattleRole::WEATHERSETTER) if move.is_a?(PokeBattle_WeatherMove)
|
||||
end
|
||||
end
|
||||
|
||||
# Check EVs, nature and moves for combinations indicative of particular roles
|
||||
if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
if [PBNatures::MODEST, PBNatures::ADAMANT, # SpAtk+ Atk-, Atk+ SpAtk-
|
||||
PBNatures::TIMID, PBNatures::JOLLY].include?(pkmn.nature) # Spd+ Atk-, Spd+ SpAtk-
|
||||
ret.push(BattleRole::SWEEPER)
|
||||
end
|
||||
end
|
||||
if hasHealMove
|
||||
ret.push(BattleRole::PIVOT) if hasPivotMove
|
||||
if PBNatures.getStatRaised(pkmn.nature) == PBStats::DEFENSE &&
|
||||
PBNatures.getStatLowered(pkmn.nature) != PBStats::DEFENSE
|
||||
ret.push(BattleRole::PHYSICALWALL) if pkmn.ev[PBStats::DEFENSE] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
elsif PBNatures.getStatRaised(pkmn.nature) == PBStats::SPDEF &&
|
||||
PBNatures.getStatLowered(pkmn.nature) != PBStats::SPDEF
|
||||
ret.push(BattleRole::SPECIALWALL) if pkmn.ev[PBStats::SPDEF] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
end
|
||||
else
|
||||
ret.push(BattleRole::TANK) if pkmn.ev[PBStats::HP] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
end
|
||||
|
||||
# Check for abilities indicative of particular roles
|
||||
case pkmn.ability_id
|
||||
when :REGENERATOR
|
||||
ret.push(BattleRole::PIVOT)
|
||||
when :GUTS, :QUICKFEET, :FLAREBOOST, :TOXICBOOST, :NATURALCURE, :MAGICGUARD,
|
||||
:MAGICBOUNCE, :HYDRATION
|
||||
ret.push(BattleRole::STATUSABSORBER)
|
||||
when :SHADOWTAG, :ARENATRAP, :MAGNETPULL
|
||||
ret.push(BattleRole::TRAPPER)
|
||||
when :DROUGHT, :DRIZZLE, :SANDSTREAM, :SNOWWARNING, :PRIMORDIALSEA,
|
||||
:DESOLATELAND, :DELTASTREAM
|
||||
ret.push(BattleRole::WEATHERSETTER)
|
||||
when :GRASSYSURGE, :ELECTRICSURGE, :MISTYSURGE, :PSYCHICSURGE
|
||||
ret.push(BattleRole::FIELDSETTER)
|
||||
end
|
||||
|
||||
# Check for items indicative of particular roles
|
||||
case pkmn.item_id
|
||||
when :LIGHTCLAY
|
||||
ret.push(BattleRole::SCREENER)
|
||||
when :ASSAULTVEST
|
||||
ret.push(BattleRole::TANK)
|
||||
when :CHOICEBAND, :CHOICESPECS
|
||||
ret.push(BattleRole::STALLBREAKER)
|
||||
ret.push(BattleRole::SWEEPER) if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
when :CHOICESCARF
|
||||
ret.push(BattleRole::SWEEPER) if pkmn.ev[PBStats::SPEED] == PokeBattle_Pokemon::EV_STAT_LIMIT
|
||||
when :TOXICORB, :FLAMEORB
|
||||
ret.push(BattleRole::STATUSABSORBER)
|
||||
when :TERRAINEXTENDER
|
||||
ret.push(BattleRole::FIELDSETTER)
|
||||
end
|
||||
|
||||
# Check for position in team, level relative to other levels in team
|
||||
partyStarts = @battle.pbPartyStarts(side)
|
||||
if partyStarts.include?(index + 1) || index == @battle.pbParty(side).length - 1
|
||||
ret.push(BattleRole::ACE)
|
||||
else
|
||||
ret.push(BattleRole::LEAD) if partyStarts.include?(index)
|
||||
idxTrainer = @battle.pbGetOwnerIndexFromPartyIndex(side, index)
|
||||
maxLevel = @battle.pbMaxLevelInTeam(side, idxTrainer)
|
||||
if pkmn.level >= maxLevel
|
||||
ret.push(BattleRole::SECOND)
|
||||
else
|
||||
secondHighest = true
|
||||
seenHigherLevel = false
|
||||
@battle.eachInTeam(side, @battle.pbGetOwnerIndexFromPartyIndex(side, index)).each do |p|
|
||||
next if p.level < pkmn.level
|
||||
if seenHigherLevel
|
||||
secondHighest = false
|
||||
break
|
||||
end
|
||||
seenHigherLevel = true
|
||||
end
|
||||
# NOTE: There can be multiple "second"s if all their levels are equal
|
||||
# and the highest in the team (and none are the ace).
|
||||
ret.push(BattleRole::SECOND) if secondHighest
|
||||
end
|
||||
end
|
||||
|
||||
return ret
|
||||
end
|
||||
|
||||
def check_role(side, idxBattler, *roles)
|
||||
role_array = @roles[side][idxBattler]
|
||||
roles.each do |r|
|
||||
return true if role_array.include?(r)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def check_battler_role(battler, *roles)
|
||||
side = idxParty.idxOwnSide
|
||||
idxParty = idxParty.pokemonIndex
|
||||
return check_role(side, idxParty, *roles)
|
||||
end
|
||||
end
|
||||
@@ -1,86 +0,0 @@
|
||||
class PokeBattle_StatUpMove < PokeBattle_Move
|
||||
attr_reader :statUp
|
||||
end
|
||||
|
||||
class PokeBattle_MultiStatUpMove < PokeBattle_Move
|
||||
attr_reader :statUp
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Battle Palace AI.
|
||||
#===============================================================================
|
||||
class PokeBattle_AI
|
||||
alias _battlePalace_pbEnemyShouldWithdraw? pbEnemyShouldWithdraw?
|
||||
|
||||
def pbEnemyShouldWithdraw?
|
||||
return _battlePalace_pbEnemyShouldWithdraw? if !@battlePalace
|
||||
shouldswitch = false
|
||||
if @user.effects[PBEffects::PerishSong]==1
|
||||
shouldswitch = true
|
||||
elsif !@battle.pbCanChooseAnyMove?(@user.index) &&
|
||||
@user.turnCount && @user.turnCount>5
|
||||
shouldswitch = true
|
||||
else
|
||||
hppercent = @user.hp*100/@user.totalhp
|
||||
percents = []
|
||||
maxindex = -1
|
||||
maxpercent = 0
|
||||
factor = 0
|
||||
@battle.pbParty(@user.index).each_with_index do |pkmn,i|
|
||||
if @battle.pbCanSwitch?(@user.index,i)
|
||||
percents[i] = 100*pkmn.hp/pkmn.totalhp
|
||||
if percents[i]>maxpercent
|
||||
maxindex = i
|
||||
maxpercent = percents[i]
|
||||
end
|
||||
else
|
||||
percents[i] = 0
|
||||
end
|
||||
end
|
||||
if hppercent<50
|
||||
factor = (maxpercent<hppercent) ? 20 : 40
|
||||
end
|
||||
if hppercent<25
|
||||
factor = (maxpercent<hppercent) ? 30 : 50
|
||||
end
|
||||
case @user.status
|
||||
when PBStatuses::SLEEP, PBStatuses::FROZEN
|
||||
factor += 20
|
||||
when PBStatuses::POISON, PBStatuses::BURN
|
||||
factor += 10
|
||||
when PBStatuses::PARALYSIS
|
||||
factor += 15
|
||||
end
|
||||
if @justswitched[@user.index]
|
||||
factor -= 60
|
||||
factor = 0 if factor<0
|
||||
end
|
||||
shouldswitch = (pbAIRandom(100)<factor)
|
||||
if shouldswitch && maxindex>=0
|
||||
@battle.pbRegisterSwitch(@user.index,maxindex)
|
||||
return true
|
||||
end
|
||||
end
|
||||
@justswitched[@user.index] = shouldswitch
|
||||
if shouldswitch
|
||||
@battle.pbParty(@user.index).each_with_index do |_pkmn,i|
|
||||
next if !@battle.pbCanSwitch?(@user.index,i)
|
||||
@battle.pbRegisterSwitch(@user.index,i)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Battle Arena AI.
|
||||
#===============================================================================
|
||||
class PokeBattle_AI
|
||||
alias _battleArena_pbEnemyShouldWithdraw? pbEnemyShouldWithdraw?
|
||||
|
||||
def pbEnemyShouldWithdraw?
|
||||
return _battleArena_pbEnemyShouldWithdraw? if !@battleArena
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -1,110 +0,0 @@
|
||||
=begin
|
||||
class PBStuff
|
||||
#Standardized lists of moves with similar purposes/characteristics
|
||||
#(mostly just "stuff that gets called together")
|
||||
UNFREEZEMOVE = [PBMoves::FLAMEWHEEL,PBMoves::SACREDFIRE,PBMoves::FLAREBLITZ,
|
||||
PBMoves::FUSIONFLARE,PBMoves::SCALD,PBMoves::STEAMERUPTION,PBMoves::BURNUP]
|
||||
SWITCHOUTMOVE = [PBMoves::ROAR,PBMoves::WHIRLWIND,PBMoves::CIRCLETHROW,
|
||||
PBMoves::DRAGONTAIL,PBMoves::YAWN,PBMoves::PERISHSONG]
|
||||
SETUPMOVE = [PBMoves::SWORDSDANCE,PBMoves::DRAGONDANCE,PBMoves::CALMMIND,
|
||||
PBMoves::WORKUP,PBMoves::NASTYPLOT,PBMoves::TAILGLOW,PBMoves::BELLYDRUM,
|
||||
PBMoves::BULKUP,PBMoves::COIL,PBMoves::CURSE,PBMoves::GROWTH,
|
||||
PBMoves::HONECLAWS,PBMoves::QUIVERDANCE,PBMoves::SHELLSMASH]
|
||||
PROTECTMOVE = [PBMoves::PROTECT,PBMoves::DETECT,PBMoves::KINGSSHIELD,
|
||||
PBMoves::SPIKYSHIELD,PBMoves::BANEFULBUNKER]
|
||||
PROTECTIGNORINGMOVE = [PBMoves::FEINT,PBMoves::HYPERSPACEHOLE,
|
||||
PBMoves::HYPERSPACEFURY,PBMoves::SHADOWFORCE,PBMoves::PHANTOMFORCE]
|
||||
SCREENBREAKERMOVE = [PBMoves::DEFOG,PBMoves::BRICKBREAK,PBMoves::PSYCHICFANGS]
|
||||
CONTRARYBAITMOVE = [PBMoves::SUPERPOWER,PBMoves::OVERHEAT,PBMoves::DRACOMETEOR,
|
||||
PBMoves::LEAFSTORM,PBMoves::FLEURCANNON,PBMoves::PSYCHOBOOST]
|
||||
TWOTURNAIRMOVE = [PBMoves::BOUNCE,PBMoves::FLY,PBMoves::SKYDROP]
|
||||
PIVOTMOVE = [PBMoves::UTURN,PBMoves::VOLTSWITCH,PBMoves::PARTINGSHOT]
|
||||
DANCEMOVE = [PBMoves::QUIVERDANCE,PBMoves::DRAGONDANCE,PBMoves::FIERYDANCE,
|
||||
PBMoves::FEATHERDANCE,PBMoves::PETALDANCE,PBMoves::SWORDSDANCE,
|
||||
PBMoves::TEETERDANCE,PBMoves::LUNARDANCE,PBMoves::REVELATIONDANCE]
|
||||
BULLETMOVE = [PBMoves::ACIDSPRAY,PBMoves::AURASPHERE,PBMoves::BARRAGE,
|
||||
PBMoves::BULLETSEED,PBMoves::EGGBOMB,PBMoves::ELECTROBALL,PBMoves::ENERGYBALL,
|
||||
PBMoves::FOCUSBLAST,PBMoves::GYROBALL,PBMoves::ICEBALL,PBMoves::MAGNETBOMB,
|
||||
PBMoves::MISTBALL,PBMoves::MUDBOMB,PBMoves::OCTAZOOKA,PBMoves::ROCKWRECKER,
|
||||
PBMoves::SEARINGSHOT,PBMoves::SEEDBOMB,PBMoves::SHADOWBALL,PBMoves::SLUDGEBOMB,
|
||||
PBMoves::WEATHERBALL,PBMoves::ZAPCANNON,PBMoves::BEAKBLAST]
|
||||
|
||||
BURNMOVE = [PBMoves::WILLOWISP,PBMoves::SACREDFIRE,PBMoves::INFERNO]
|
||||
PARAMOVE = [PBMoves::THUNDERWAVE,PBMoves::STUNSPORE,PBMoves::GLARE,
|
||||
PBMoves::NUZZLE,PBMoves::ZAPCANNON]
|
||||
SLEEPMOVE = [PBMoves::SPORE,PBMoves::SLEEPPOWDER,PBMoves::HYPNOSIS,PBMoves::DARKVOID,
|
||||
PBMoves::GRASSWHISTLE,PBMoves::LOVELYKISS,PBMoves::SING]
|
||||
POISONMOVE = [PBMoves::TOXIC,PBMoves::POISONPOWDER,PBMoves::POISONGAS,PBMoves::TOXICTHREAD]
|
||||
CONFUMOVE = [PBMoves::CONFUSERAY,PBMoves::SUPERSONIC,PBMoves::FLATTER,PBMoves::SWAGGER,
|
||||
PBMoves::SWEETKISS,PBMoves::TEETERDANCE,PBMoves::CHATTER,PBMoves::DYNAMICPUNCH]
|
||||
|
||||
HEALFUNCTIONS = [0xD5,0xD6,0xD7,0xD8,0xD9,0xDD,0xDE,0xDF,0xE3,0xE4,0x114,0x139,0x158,0x162,0x169,0x16C,0x172]
|
||||
|
||||
#massive arrays of stuff that no one wants to see
|
||||
NATURALGIFTDAMAGE={
|
||||
100 => [:WATMELBERRY,:DURINBERRY,:BELUEBERRY,:LIECHIBERRY,:GANLONBERRY,:SALACBERRY,
|
||||
:PETAYABERRY,:APICOTBERRY,:LANSATBERRY,:STARFBERRY,:ENIGMABERRY,:MICLEBERRY,
|
||||
:CUSTAPBERRY,:JABOCABERRY,:ROWAPBERRY],
|
||||
90 => [:BLUKBERRY,:NANABBERRY,:WEPEARBERRY,:PINAPBERRY,:POMEGBERRY,:KELPSYBERRY,
|
||||
:QUALOTBERRY,:HONDEWBERRY,:GREPABERRY,:TAMATOBERRY,:CORNNBERRY,:MAGOSTBERRY,
|
||||
:RABUTABERRY,:NOMELBERRY,:SPELONBERRY,:PAMTREBERRY],
|
||||
80 => [:CHERIBERRY,:CHESTOBERRY,:PECHABERRY,:RAWSTBERRY,:ASPEARBERRY,:LEPPABERRY,
|
||||
:ORANBERRY,:PERSIMBERRY,:LUMBERRY,:SITRUSBERRY,:FIGYBERRY,:WIKIBERRY,
|
||||
:MAGOBERRY,:AGUAVBERRY,:IAPAPABERRY,:RAZZBERRY,:OCCABERRY,:PASSHOBERRY,
|
||||
:WACANBERRY,:RINDOBERRY,:YACHEBERRY,:CHOPLEBERRY,:KEBIABERRY,:SHUCABERRY,
|
||||
:COBABERRY,:PAYAPABERRY,:TANGABERRY,:CHARTIBERRY,:KASIBBERRY,:HABANBERRY,
|
||||
:COLBURBERRY,:BABIRIBERRY,:CHILANBERRY]}
|
||||
FLINGDAMAGE={
|
||||
300 => [:MEMEONADE],
|
||||
130 => [:IRONBALL],
|
||||
100 => [:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HARDSTONE,:HELIXFOSSIL,
|
||||
:OLDAMBER,:PLUMEFOSSIL,:RAREBONE,:ROOTFOSSIL,:SKULLFOSSIL],
|
||||
90 => [:DEEPSEATOOTH,:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
|
||||
:GRIPCLAW,:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
|
||||
:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,:THICKCLUB,:TOXICPLATE,
|
||||
:ZAPPLATE],
|
||||
80 => [:DAWNSTONE,:DUSKSTONE,:ELECTIRIZER,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
|
||||
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SHINYSTONE,:STICKYBARB,:ASSAULTVEST],
|
||||
70 => [:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:DRAGONFANG,:POISONBARB,:POWERANKLET,
|
||||
:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,:POWERWEIGHT,:SHOCKDRIVE],
|
||||
60 => [:ADAMANTORB,:DAMPROCK,:HEATROCK,:LUSTROUSORB,:MACHOBRACE,:ROCKYHELMET,
|
||||
:STICK,:AMPLIFIELDROCK,:ADRENALINEORB],
|
||||
50 => [:DUBIOUSDISC,:SHARPBEAK],
|
||||
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH,:PROTECTIVEPADS],
|
||||
30 => [:ABILITYURGE,:ABSORBBULB,:AMULETCOIN,:ANTIDOTE,:AWAKENING,:BALMMUSHROOM,
|
||||
:BERRYJUICE,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:BINDINGBAND,:BLACKBELT,
|
||||
:BLACKFLUTE,:BLACKGLASSES,:BLACKSLUDGE,:BLUEFLUTE,:BLUESHARD,:BURNHEAL,
|
||||
:CALCIUM,:CARBOS,:CASTELIACONE,:CELLBATTERY,:CHARCOAL,:CLEANSETAG,
|
||||
:COMETSHARD,:DAMPMULCH,:DEEPSEASCALE,:DIREHIT,:DIREHIT2,:DIREHIT3,
|
||||
:DRAGONSCALE,:EJECTBUTTON,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ESCAPEROPE,
|
||||
:ETHER,:EVERSTONE,:EXPSHARE,:FIRESTONE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,
|
||||
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:GOOEYMULCH,:GREENSHARD,:GROWTHMULCH,
|
||||
:GUARDSPEC,:HEALPOWDER,:HEARTSCALE,:HONEY,:HPUP,:HYPERPOTION,:ICEHEAL,
|
||||
:IRON,:ITEMDROP,:ITEMURGE,:KINGSROCK,:LAVACOOKIE,:LEAFSTONE,:LEMONADE,
|
||||
:LIFEORB,:LIGHTBALL,:LIGHTCLAY,:LUCKYEGG,:MAGNET,:MAXELIXIR,:MAXETHER,
|
||||
:MAXPOTION,:MAXREPEL,:MAXREVIVE,:METALCOAT,:METRONOME,:MIRACLESEED,
|
||||
:MOOMOOMILK,:MOONSTONE,:MYSTICWATER,:NEVERMELTICE,:NUGGET,:OLDGATEAU,
|
||||
:PARLYZHEAL,:PEARL,:PEARLSTRING,:POKEDOLL,:POKETOY,:POTION,:PPMAX,:PPUP,
|
||||
:PRISMSCALE,:PROTEIN,:RAGECANDYBAR,:RARECANDY,:RAZORFANG,:REDFLUTE,
|
||||
:REDSHARD,:RELICBAND,:RELICCOPPER,:RELICCROWN,:RELICGOLD,:RELICSILVER,
|
||||
:RELICSTATUE,:RELICVASE,:REPEL,:RESETURGE,:REVIVALHERB,:REVIVE,:SACREDASH,
|
||||
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SODAPOP,:SOULDEW,
|
||||
:SPELLTAG,:STABLEMULCH,:STARDUST,:STARPIECE,:SUNSTONE,:SUPERPOTION,
|
||||
:SUPERREPEL,:SWEETHEART,:THUNDERSTONE,:TINYMUSHROOM,:TOXICORB,
|
||||
:TWISTEDSPOON,:UPGRADE,:WATERSTONE,:WHITEFLUTE,:XACCURACY,:XACCURACY2,
|
||||
:XACCURACY3,:XACCURACY6,:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,:XDEFEND,
|
||||
:XDEFEND2,:XDEFEND3,:XDEFEND6,:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,:XSPECIAL,
|
||||
:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
|
||||
:YELLOWFLUTE,:YELLOWSHARD,:ZINC,:BIGMALASADA,:ICESTONE],
|
||||
20 => [:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
|
||||
:RESISTWING,:SWIFTWING],
|
||||
10 => [:AIRBALLOON,:BIGROOT,:BLUESCARF,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
|
||||
:CHOICESPECS,:DESTINYKNOT,:EXPERTBELT,:FOCUSBAND,:FOCUSSASH,:FULLINCENSE,
|
||||
:GREENSCARF,:LAGGINGTAIL,:LAXINCENSE,:LEFTOVERS,:LUCKINCENSE,:MENTALHERB,
|
||||
:METALPOWDER,:MUSCLEBAND,:ODDINCENSE,:PINKSCARF,:POWERHERB,:PUREINCENSE,
|
||||
:QUICKPOWDER,:REAPERCLOTH,:REDCARD,:REDSCARF,:RINGTARGET,:ROCKINCENSE,
|
||||
:ROSEINCENSE,:SEAINCENSE,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
|
||||
:SOFTSAND,:SOOTHEBELL,:WAVEINCENSE,:WHITEHERB,:WIDELENS,:WISEGLASSES,
|
||||
:YELLOWSCARF,:ZOOMLENS,:BLUEMIC,:VANILLAIC,:STRAWBIC,:CHOCOLATEIC]}
|
||||
end
|
||||
=end
|
||||
@@ -1,165 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
# Legacy method that should stop being used.
|
||||
def pbGetOwner(battlerIndex)
|
||||
if opposes?(battlerIndex)
|
||||
if @opponent.is_a?(Array)
|
||||
return (battlerIndex==1) ? @opponent[0] : @opponent[1]
|
||||
else
|
||||
return @opponent
|
||||
end
|
||||
else
|
||||
if @player.is_a?(Array)
|
||||
return (battlerIndex==0) ? @player[0] : @player[1]
|
||||
else
|
||||
return @player
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Reborn method (the difference is that each element in "choices" is an array
|
||||
# in Essentials but just a number in Reborn)
|
||||
def pbStdDev(choices)
|
||||
sum = 0
|
||||
n = 0
|
||||
choices.each do |c|
|
||||
sum += c
|
||||
n += 1
|
||||
end
|
||||
return 0 if n<2
|
||||
mean = sum.to_f/n.to_f
|
||||
varianceTimesN = 0
|
||||
for i in 0...choices.length
|
||||
next if choices[i]<=0
|
||||
deviation = choices[i].to_f-mean
|
||||
varianceTimesN += deviation*deviation
|
||||
end
|
||||
# Using population standard deviation
|
||||
# [(n-1) makes it a sample std dev, would be 0 with only 1 sample]
|
||||
return Math.sqrt(varianceTimesN/n)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Choose an action.
|
||||
##############################################################################
|
||||
def pbDefaultChooseEnemyCommand(idxBattler)
|
||||
if !@battle.pbCanShowFightMenu?(idxBattler)
|
||||
return if pbEnemyShouldUseItem?(idxBattler)
|
||||
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
|
||||
return if pbShouldSwitch?(idxBattler)
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbAutoChooseMove(idxBattler)
|
||||
return
|
||||
end
|
||||
|
||||
pbBuildMoveScores(idxBattler) # Grab the array of scores/targets before doing anything else
|
||||
return if pbShouldSwitch?(idxBattler)
|
||||
# return if pbEnemyShouldWithdraw?(idxBattler) # Old Switching Method
|
||||
return if pbEnemyShouldUseItem?(idxBattler)
|
||||
return if @battle.pbAutoFightMenu(idxBattler)
|
||||
@battle.pbRegisterUltraBurst(idxBattler) if pbEnemyShouldUltraBurst?(idxBattler)
|
||||
@battle.pbRegisterMegaEvolution(idxBattler) if pbEnemyShouldMegaEvolve?(idxBattler)
|
||||
if pbEnemyShouldZMove?(idxBattler)
|
||||
return pbChooseEnemyZMove(idxBattler)
|
||||
end
|
||||
pbChooseMoves(idxBattler)
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
#
|
||||
##############################################################################
|
||||
def pbChooseEnemyZMove(index) #Put specific cases for trainers using status Z-Moves
|
||||
chosenmove=false
|
||||
chosenindex=-1
|
||||
attacker = @battlers[index]
|
||||
opponent=attacker.pbOppositeOpposing
|
||||
otheropp=opponent.pbPartner
|
||||
skill=pbGetOwner(attacker.index).skill || 0
|
||||
for i in 0..3
|
||||
move=@battlers[index].moves[i]
|
||||
if @battlers[index].pbCompatibleZMoveFromMove?(move)
|
||||
if move.id == (PBMoves::CONVERSION) || move.id == (PBMoves::SPLASH)
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,i,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
return
|
||||
end
|
||||
if !chosenmove
|
||||
chosenindex = i
|
||||
chosenmove=move
|
||||
else
|
||||
if move.basedamage>chosenmove.basedamage
|
||||
chosenindex=i
|
||||
chosenmove=move
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
#oppeff1 = chosenmove.pbTypeModifier(chosenmove.type,attacker,opponent)
|
||||
oppeff1 = pbTypeModNoMessages(chosenmove.type,attacker,opponent,chosenmove,skill)
|
||||
#oppeff2 = chosenmove.pbTypeModifier(chosenmove.type,attacker,otheropp)
|
||||
oppeff2 = pbTypeModNoMessages(chosenmove.type,attacker,otheropp,chosenmove,skill)
|
||||
oppeff1 = 0 if opponent.hp<(opponent.totalhp/2.0).round
|
||||
oppeff1 = 0 if (opponent.effects[PBEffects::Substitute]>0 || opponent.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
|
||||
oppeff2 = 0 if otheropp.hp<(otheropp.totalhp/2.0).round
|
||||
oppeff2 = 0 if (otheropp.effects[PBEffects::Substitute]>0 || otheropp.effects[PBEffects::Disguise]) && attacker.item!=(PBItems::KOMMONIUMZ2)
|
||||
oppmult=0
|
||||
for i in 1..7 #iterates through all the stats
|
||||
oppmult+=opponent.stages[i] if opponent.stages[i]>0
|
||||
end
|
||||
othermult=0
|
||||
for i in 1..7
|
||||
othermult+=otheropp.stages[i] if otheropp.stages[i]>0
|
||||
end
|
||||
if (oppeff1<4) && ((oppeff2<4) || otheropp.hp==0)
|
||||
pbChooseMoves(index)
|
||||
elsif oppeff1>oppeff2
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
elsif oppeff1<oppeff2
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
elsif oppeff1==oppeff2
|
||||
if oppmult > othermult
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
elsif oppmult < othermult
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
else
|
||||
if otheropp.hp > opponent.hp
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,otheropp.index)
|
||||
else
|
||||
pbRegisterZMove(index)
|
||||
pbRegisterMove(index,chosenindex,false)
|
||||
pbRegisterTarget(index,opponent.index)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
##############################################################################
|
||||
# Decide whether the opponent should use a Z-Move.
|
||||
##############################################################################
|
||||
def pbEnemyShouldZMove?(index)
|
||||
return pbCanZMove?(index) #Conditions based on effectiveness and type handled later
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Decide whether the opponent should Ultra Burst their Pokémon.
|
||||
#=============================================================================
|
||||
def pbEnemyShouldUltraBurst?(idxBattler)
|
||||
battler = @battlers[idxBattler]
|
||||
if pbCanUltraBurst?(idxBattler) # Simple "always should if possible"
|
||||
PBDebug.log("[AI] #{battler.pbThis} (#{idxBattler}) will Ultra Burst")
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
end
|
||||
@@ -1,495 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
################################################################################
|
||||
# Decide whether the opponent should use an item on the Pokémon.
|
||||
################################################################################
|
||||
def pbEnemyShouldUseItem?(index)
|
||||
item=pbEnemyItemToUse(index)
|
||||
if item>0 && @battlers[index].effects[PBEffects::Embargo]==0
|
||||
pbRegisterItem(index,item,nil)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def pbEnemyItemAlreadyUsed?(index,item,items)
|
||||
if @choices[1][0]==3 && @choices[1][1]==item
|
||||
qty=0
|
||||
for i in items
|
||||
qty+=1 if i==item
|
||||
end
|
||||
return true if qty<=1
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def pbEnemyItemToUse(index)
|
||||
return 0 if !@opponent
|
||||
return 0 if !@internalbattle
|
||||
items=pbGetOwnerItems(index)
|
||||
return 0 if !items
|
||||
skill=pbGetOwner(index).skill || 0
|
||||
battler=@battlers[index]
|
||||
party = pbParty(index)
|
||||
opponent1 = battler.pbOppositeOpposing
|
||||
opponent2 = opponent1.pbPartner
|
||||
currentroles = pbGetMonRole(battler,opponent1,skill)
|
||||
return 0 if battler.isFainted?
|
||||
highscore = 0
|
||||
movecount = -1
|
||||
maxplaypri = -1
|
||||
partynumber = 0
|
||||
aimem = getAIMemory(skill,opponent1.pokemonIndex)
|
||||
for i in party
|
||||
next if i.nil?
|
||||
next if i.hp == 0
|
||||
partynumber+=1
|
||||
end
|
||||
itemnumber = 0
|
||||
for i in items
|
||||
next if pbEnemyItemAlreadyUsed?(index,i,items)
|
||||
itemnumber+=1
|
||||
end
|
||||
#highest score
|
||||
for i in battler.moves
|
||||
scorearray = 0
|
||||
scorearray = @scores[i] if @scores[i]
|
||||
if scorearray>100 && i.priority>maxplaypri
|
||||
maxplaypri = i.priority
|
||||
end
|
||||
end
|
||||
highscore = @scores.max
|
||||
highdamage = -1
|
||||
maxopppri = -1
|
||||
pridam = -1
|
||||
bestid = -1
|
||||
#expected damage
|
||||
#if battler.pbSpeed<pbRoughStat(opponent1,PBStats::SPEED,skill)
|
||||
if aimem.length > 0
|
||||
for i in aimem
|
||||
tempdam = pbRoughDamage(i,opponent1,battler,skill,i.basedamage)
|
||||
if tempdam>highdamage
|
||||
highdamage = tempdam
|
||||
bestid = i.id
|
||||
end
|
||||
if i.priority > maxopppri
|
||||
maxopppri = i.priority
|
||||
pridam = tempdam
|
||||
end
|
||||
end
|
||||
end
|
||||
highratio = -1
|
||||
#expected damage percentage
|
||||
if battler.hp!=0
|
||||
highratio = highdamage*(1.0/battler.hp)
|
||||
end
|
||||
scorearray = []
|
||||
arraycount = -1
|
||||
PBDebug.log(sprintf("Beginning AI Item use check.")) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
for i in items
|
||||
arraycount+=1
|
||||
scorearray.push(0)
|
||||
itemscore=100
|
||||
ishpitem = false
|
||||
isstatusitem = false
|
||||
next if pbEnemyItemAlreadyUsed?(index,i,items)
|
||||
if (i== PBItems::POTION) ||
|
||||
(i== PBItems::ULTRAPOTION) ||
|
||||
(i== PBItems::SUPERPOTION) ||
|
||||
(i== PBItems::HYPERPOTION) ||
|
||||
(i== PBItems::MAXPOTION) ||
|
||||
(i== PBItems::FULLRESTORE) ||
|
||||
(i== PBItems::FRESHWATER) ||
|
||||
(i== PBItems::SODAPOP) ||
|
||||
(i== PBItems::LEMONADE) ||
|
||||
(i== PBItems::MOOMOOMILK) ||
|
||||
(i== PBItems::MEMEONADE) ||
|
||||
(i== PBItems::STRAWBIC) ||
|
||||
(i== PBItems::CHOCOLATEIC) ||
|
||||
(i== PBItems::BLUEMIC)
|
||||
ishpitem=true
|
||||
end
|
||||
if (i== PBItems::FULLRESTORE) ||
|
||||
(i== PBItems::FULLHEAL) ||
|
||||
(i== PBItems::RAGECANDYBAR) ||
|
||||
(i== PBItems::LAVACOOKIE) ||
|
||||
(i== PBItems::OLDGATEAU) ||
|
||||
(i== PBItems::CASTELIACONE) ||
|
||||
(i== PBItems::LUMIOSEGALETTE) ||
|
||||
(i== PBItems::BIGMALASADA)
|
||||
isstatusitem=true
|
||||
end
|
||||
if ishpitem
|
||||
PBDebug.log(sprintf("This is a HP-healing item.")) if $INTERNAL
|
||||
restoreamount=0
|
||||
if (i== PBItems::POTION)
|
||||
restoreamount=20
|
||||
elsif (i== PBItems::ULTRAPOTION)
|
||||
restoreamount=200
|
||||
elsif (i== PBItems::SUPERPOTION)
|
||||
restoreamount=60
|
||||
elsif (i== PBItems::HYPERPOTION)
|
||||
restoreamount=120
|
||||
elsif (i== PBItems::MAXPOTION) || (i== PBItems::FULLRESTORE)
|
||||
restoreamount=battler.totalhp
|
||||
elsif (i== PBItems::FRESHWATER)
|
||||
restoreamount=30
|
||||
elsif (i== PBItems::SODAPOP)
|
||||
restoreamount=50
|
||||
elsif (i== PBItems::LEMONADE)
|
||||
restoreamount=70
|
||||
elsif (i== PBItems::MOOMOOMILK)
|
||||
restoreamount=110
|
||||
elsif (i== PBItems::MEMEONADE)
|
||||
restoreamount=103
|
||||
elsif (i== PBItems::STRAWBIC)
|
||||
restoreamount=90
|
||||
elsif (i== PBItems::CHOCOLATEIC)
|
||||
restoreamount=70
|
||||
elsif (i== PBItems::BLUEMIC)
|
||||
restoreamount=200
|
||||
end
|
||||
resratio=restoreamount*(1.0/battler.totalhp)
|
||||
itemscore*= (2 - (2*(battler.hp*(1.0/battler.totalhp))))
|
||||
if highdamage>=battler.hp
|
||||
if highdamage > [battler.hp+restoreamount,battler.totalhp].min
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.2
|
||||
end
|
||||
healmove = false
|
||||
for j in battler.moves
|
||||
if j.isHealingMove?
|
||||
healmove=true
|
||||
end
|
||||
end
|
||||
if healmove
|
||||
if battler.pbSpeed < opponent1.pbSpeed
|
||||
if highdamage>=battler.hp
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.6
|
||||
if resratio<0.55
|
||||
itemscore*=0.2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
itemscore*=0.4
|
||||
end
|
||||
if highdamage > restoreamount
|
||||
itemscore*=0
|
||||
else
|
||||
if restoreamount-highdamage < 15
|
||||
itemscore*=0.5
|
||||
end
|
||||
end
|
||||
if battler.pbSpeed > opponent1.pbSpeed
|
||||
itemscore*=0.8
|
||||
if highscore >=110
|
||||
if maxopppri > maxplaypri
|
||||
itemscore*=1.3
|
||||
if pridam>battler.hp
|
||||
if pridam>(battler.hp/2.0)
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=2
|
||||
end
|
||||
end
|
||||
elsif !(!opponent1.abilitynulled && opponent1.ability == PBAbilities::STURDY)
|
||||
itemscore*=0
|
||||
end
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SWEEPER)
|
||||
itemscore*=1.1
|
||||
end
|
||||
else
|
||||
if highdamage*2 > [battler.hp+restoreamount,battler.totalhp].min
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.5
|
||||
if highscore >=110
|
||||
itemscore*=1.5
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.hp == battler.totalhp
|
||||
itemscore*=0
|
||||
elsif battler.hp >= (battler.totalhp*0.8)
|
||||
itemscore*=0.2
|
||||
elsif battler.hp >= (battler.totalhp*0.6)
|
||||
itemscore*=0.3
|
||||
elsif battler.hp >= (battler.totalhp*0.5)
|
||||
itemscore*=0.5
|
||||
end
|
||||
minipot = (partynumber-1)
|
||||
minimini = -1
|
||||
for j in items
|
||||
next if pbEnemyItemAlreadyUsed?(index,j,items)
|
||||
next if !((j== PBItems::POTION) || (j== PBItems::ULTRAPOTION) ||
|
||||
(j== PBItems::SUPERPOTION) || (j== PBItems::HYPERPOTION) ||
|
||||
(j== PBItems::MAXPOTION) || (j== PBItems::FULLRESTORE) ||
|
||||
(j== PBItems::FRESHWATER) || (j== PBItems::SODAPOP) ||
|
||||
(j== PBItems::LEMONADE) || (j== PBItems::MOOMOOMILK) ||
|
||||
(j== PBItems::MEMEONADE) || (j== PBItems::STRAWBIC) ||
|
||||
(j== PBItems::CHOCOLATEIC) || (j== PBItems::BLUEMIC))
|
||||
minimini+=1
|
||||
end
|
||||
if minipot>minimini
|
||||
itemscore*=(0.9**(minipot-minimini))
|
||||
minipot=minimini
|
||||
elsif minimini>minipot
|
||||
itemscore*=(1.1**(minimini-minipot))
|
||||
minimini=minipot
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::LEAD) || currentroles.include?(PBMonRoles::SCREENER)
|
||||
itemscore*=0.6
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::TANK)
|
||||
itemscore*=1.1
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SECOND)
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.hasWorkingItem(:LEFTOVERS) || (battler.hasWorkingItem(:BLACKSLUDGE) && battler.pbHasType?(:POISON))
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.status!=0 && !(i== PBItems::FULLRESTORE)
|
||||
itemscore*=0.7
|
||||
if battler.effects[PBEffects::Toxic]>0 && partynumber>1
|
||||
itemscore*=0.2
|
||||
end
|
||||
end
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)>4
|
||||
itemscore*=0.7
|
||||
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
|
||||
itemscore*=1.1
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
|
||||
itemscore*=1.2
|
||||
end
|
||||
end
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type2,battler.type1,battler.type2)>4
|
||||
itemscore*=0.6
|
||||
elsif PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)<4
|
||||
itemscore*=1.1
|
||||
if PBTypes.getCombinedEffectiveness(opponent1.type1,battler.type1,battler.type2)==0
|
||||
itemscore*=1.2
|
||||
end
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::REGENERATOR) && partynumber>1
|
||||
itemscore*=0.7
|
||||
end
|
||||
end
|
||||
if isstatusitem
|
||||
PBDebug.log(sprintf("This is a status-curing item.")) if $INTERNAL
|
||||
if !(i== PBItems::FULLRESTORE)
|
||||
if battler.status==0
|
||||
itemscore*=0
|
||||
else
|
||||
if highdamage>battler.hp
|
||||
if (bestid==106 && battler.status==PBStatuses::SLEEP) || (bestid==298 && battler.status==PBStatuses::PARALYSIS) || bestid==179
|
||||
if highdamage*0.5>battler.hp
|
||||
itemscore*=0
|
||||
else
|
||||
itemscore*=1.4
|
||||
end
|
||||
else
|
||||
itemscore*=0
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::SLEEP
|
||||
if battler.pbHasMove?((PBMoves::SLEEPTALK)) ||
|
||||
battler.pbHasMove?((PBMoves::SNORE)) ||
|
||||
battler.pbHasMove?((PBMoves::REST)) ||
|
||||
(!battler.abilitynulled && battler.ability == PBAbilities::COMATOSE)
|
||||
itemscore*=0.6
|
||||
end
|
||||
if checkAImoves([PBMoves::DREAMEATER,PBMoves::NIGHTMARE],aimem) || (!opponent1.abilitynulled && opponent1.ability == PBAbilities::BADDREAMS)
|
||||
itemscore*=1.3
|
||||
end
|
||||
if highdamage*(1.0/battler.hp)>0.2
|
||||
itemscore*=1.3
|
||||
else
|
||||
itemscore*=0.7
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::PARALYSIS
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::QUICKFEET) || (!battler.abilitynulled && battler.ability == PBAbilities::GUTS)
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.pbSpeed>opponent1.pbSpeed && (battler.pbSpeed*0.5)<opponent1.pbSpeed
|
||||
itemscore*=1.3
|
||||
end
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.status==PBStatuses::BURN
|
||||
itemscore*=1.1
|
||||
if battler.attack>battler.spatk
|
||||
itemscore*=1.2
|
||||
else
|
||||
itemscore*=0.8
|
||||
end
|
||||
if !battler.abilitynulled
|
||||
itemscore*=0.6 if battler.ability == PBAbilities::GUTS
|
||||
itemscore*=0.7 if battler.ability == PBAbilities::MAGICGUARD
|
||||
itemscore*=0.8 if battler.ability == PBAbilities::FLAREBOOST
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::POISON
|
||||
itemscore*=1.1
|
||||
if !battler.abilitynulled
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::GUTS
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::MAGICGUARD
|
||||
itemscore*=0.5 if battler.ability == PBAbilities::TOXICBOOST
|
||||
itemscore*=0.4 if battler.ability == PBAbilities::POISONHEAL
|
||||
end
|
||||
if battler.effects[PBEffects::Toxic]>0
|
||||
itemscore*=1.1
|
||||
if battler.effects[PBEffects::Toxic]>3
|
||||
itemscore*=1.3
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.status==PBStatuses::FROZEN
|
||||
itemscore*=1.3
|
||||
thawmove=false
|
||||
for j in battler.moves
|
||||
if j.canThawUser?
|
||||
thawmove=true
|
||||
end
|
||||
end
|
||||
if thawmove
|
||||
itemscore*=0.5
|
||||
end
|
||||
if highdamage*(1.0/battler.hp)>0.15
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.9
|
||||
end
|
||||
end
|
||||
end
|
||||
if battler.pbHasMove?((PBMoves::REFRESH)) ||
|
||||
battler.pbHasMove?((PBMoves::REST)) ||
|
||||
battler.pbHasMove?((PBMoves::PURIFY))
|
||||
itemscore*=0.5
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::NATURALCURE) && partynumber>1
|
||||
itemscore*=0.2
|
||||
end
|
||||
if (!battler.abilitynulled && battler.ability == PBAbilities::SHEDSKIN)
|
||||
itemscore*=0.3
|
||||
end
|
||||
end
|
||||
if partynumber==1 || currentroles.include?(PBMonRoles::ACE)
|
||||
itemscore*=1.2
|
||||
else
|
||||
itemscore*=0.8
|
||||
if battler.itemUsed2
|
||||
itemscore*=0.6
|
||||
end
|
||||
end
|
||||
if battler.effects[PBEffects::Confusion]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.effects[PBEffects::Attract]>=0
|
||||
itemscore*=0.6
|
||||
end
|
||||
if battler.effects[PBEffects::Substitute]>0
|
||||
itemscore*=1.1
|
||||
end
|
||||
if battler.effects[PBEffects::LeechSeed]>=0
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.effects[PBEffects::Curse]
|
||||
itemscore*=0.5
|
||||
end
|
||||
if battler.effects[PBEffects::PerishSong]>0
|
||||
itemscore*=0.2
|
||||
end
|
||||
minipot=0
|
||||
for s in [PBStats::ATTACK,PBStats::DEFENSE,PBStats::SPEED,
|
||||
PBStats::SPATK,PBStats::SPDEF,PBStats::ACCURACY,PBStats::EVASION]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::PHYSICALWALL) || currentroles.include?(PBMonRoles::SPECIALWALL)
|
||||
for s in [PBStats::DEFENSE,PBStats::SPDEF]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
end
|
||||
if currentroles.include?(PBMonRoles::SWEEPER)
|
||||
for s in [PBStats::SPEED]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
if battler.attack>battler.spatk
|
||||
for s in [PBStats::ATTACK]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
else
|
||||
for s in [PBStats::SPATK]
|
||||
minipot+=battler.stages[s]
|
||||
end
|
||||
end
|
||||
end
|
||||
minipot*=5
|
||||
minipot+=100
|
||||
minipot*=0.01
|
||||
itemscore*=minipot
|
||||
if opponent1.effects[PBEffects::TwoTurnAttack]>0 || opponent1.effects[PBEffects::HyperBeam]>0
|
||||
itemscore*=1.2
|
||||
end
|
||||
if highscore>70
|
||||
itemscore*=1.1
|
||||
else
|
||||
itemscore*=0.9
|
||||
end
|
||||
fielddisrupt = getFieldDisruptScore(battler,opponent1,skill)
|
||||
if fielddisrupt <= 0
|
||||
fielddisrupt=0.6
|
||||
end
|
||||
itemscore*= (1.0/fielddisrupt)
|
||||
if @trickroom > 0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::Tailwind]>0
|
||||
itemscore*=0.6
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::Reflect]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::LightScreen]>0
|
||||
itemscore*=0.9
|
||||
end
|
||||
if battler.pbOwnSide.effects[PBEffects::AuroraVeil]>0
|
||||
itemscore*=0.8
|
||||
end
|
||||
if @doublebattle
|
||||
itemscore*=0.8
|
||||
end
|
||||
itemscore-=100
|
||||
PBDebug.log(sprintf("Score for %s: %d",PBItems.getName(i),itemscore)) if $INTERNAL
|
||||
scorearray[arraycount] = itemscore
|
||||
end
|
||||
bestitem=-1
|
||||
bestscore=-10000
|
||||
counter=-1
|
||||
for k in scorearray
|
||||
counter+=1
|
||||
if k>bestscore
|
||||
bestscore = k
|
||||
bestitem = items[counter]
|
||||
end
|
||||
end
|
||||
PBDebug.log(sprintf("Highest item score: %d",bestscore)) if $INTERNAL
|
||||
PBDebug.log(sprintf("Highest move score: %d",highscore)) if $INTERNAL
|
||||
if highscore<bestscore
|
||||
PBDebug.log(sprintf("Using %s",PBItems.getName(bestitem))) if $INTERNAL
|
||||
return bestitem
|
||||
else
|
||||
PBDebug.log(sprintf("Not using an item.")) if $INTERNAL
|
||||
PBDebug.log(sprintf(" ")) if $INTERNAL
|
||||
return 0
|
||||
end
|
||||
end
|
||||
end
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,121 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
attr_accessor :aiMoveMemory
|
||||
|
||||
alias __ai__initialize initialize
|
||||
def initialize(scene,p1,p2,player,opponent)
|
||||
__ai__initialize(scene,p1,p2,player,opponent)
|
||||
@aiMoveMemory = [[],
|
||||
[],
|
||||
[[], [], [], [], [], [], [], [], [], [], [], []] # One array for each party index
|
||||
]
|
||||
end
|
||||
|
||||
################################################################################
|
||||
# AI Memory utility functions
|
||||
################################################################################
|
||||
def getAIMemory(skill,index=0)
|
||||
if skill>=PBTrainerAI.bestSkill
|
||||
return @aiMoveMemory[2][index]
|
||||
elsif skill>=PBTrainerAI.highSkill
|
||||
return @aiMoveMemory[1]
|
||||
elsif skill>=PBTrainerAI.mediumSkill
|
||||
return @aiMoveMemory[0]
|
||||
else
|
||||
return []
|
||||
end
|
||||
end
|
||||
|
||||
def checkAImoves(moveID,memory)
|
||||
#basic "does the other mon have x"
|
||||
return false if memory.length == 0
|
||||
for i in moveID
|
||||
for j in memory
|
||||
j = pbChangeMove(j,nil)#doesn't matter that i'm passing nil, won't get used
|
||||
return true if i == j.id #i should already be an ID here
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIhealing(memory)
|
||||
#less basic "can the other mon heal"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
return true if j.isHealingMove?
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIpriority(memory)
|
||||
#"does the other mon have priority"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
return true if j.priority>0
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIaccuracy(memory)
|
||||
#"does the other mon have moves that don't miss"
|
||||
return false if memory.length == 0
|
||||
for j in memory
|
||||
j = pbChangeMove(j,nil)
|
||||
return true if j.accuracy==0
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def checkAIdamage(memory,attacker,opponent,skill)
|
||||
#returns how much damage the AI expects to take
|
||||
return -1 if memory.length == 0
|
||||
maxdam=0
|
||||
for j in memory
|
||||
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
|
||||
maxdam=tempdam if tempdam>maxdam
|
||||
end
|
||||
return maxdam
|
||||
end
|
||||
|
||||
def checkAIbest(memory,modifier,type=[],usepower=true,attacker=nil,opponent=nil,skill=nil)
|
||||
return false if memory.length == 0
|
||||
#had to split this because switching ai uses power
|
||||
bestmove = 0
|
||||
if usepower
|
||||
biggestpower = 0
|
||||
for j in memory
|
||||
if j.basedamage>biggestpower
|
||||
biggestpower=j.basedamage
|
||||
bestmove=j
|
||||
end
|
||||
end
|
||||
else #maxdam
|
||||
maxdam=0
|
||||
for j in memory
|
||||
tempdam = pbRoughDamage(j,opponent,attacker,skill,j.basedamage)
|
||||
if tempdam>maxdam
|
||||
maxdam=tempdam
|
||||
bestmove=j
|
||||
end
|
||||
end
|
||||
end
|
||||
return false if bestmove==0
|
||||
#i don't want to make multiple functions for rare cases
|
||||
#we're doing it in one and you're gonna like it
|
||||
case modifier
|
||||
when 1 #type mod. checks types from a list.
|
||||
return true if type.include?(bestmove.type)
|
||||
when 2 #physical mod.
|
||||
return true if bestmove.pbIsPhysical?(bestmove.type)
|
||||
when 3 #special mod.
|
||||
return true if bestmove.pbIsSpecial?(bestmove.type)
|
||||
when 4 #contact mod.
|
||||
return true if bestmove.isContactMove?
|
||||
when 5 #sound mod.
|
||||
return true if bestmove.isSoundBased?
|
||||
when 6 #why.
|
||||
return true if (PBStuff::BULLETMOVE).include?(bestmove.id)
|
||||
end
|
||||
return false #you're still here? it's over! go home.
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,974 +0,0 @@
|
||||
class PokeBattle_Battle
|
||||
=begin
|
||||
# Added to Essentials
|
||||
def pbStatusDamage(move)
|
||||
if (move.id == PBMoves::AFTERYOU || move.id == PBMoves::BESTOW || # 11D, 0F3
|
||||
move.id == PBMoves::CRAFTYSHIELD || move.id == PBMoves::LUCKYCHANT || # 14A, 0A1
|
||||
move.id == PBMoves::MEMENTO || move.id == PBMoves::QUASH || # 0E2, 11E
|
||||
move.id == PBMoves::SAFEGUARD || move.id == PBMoves::SPITE || # 01A, 10E
|
||||
move.id == PBMoves::SPLASH || move.id == PBMoves::SWEETSCENT || # 001, 048
|
||||
move.id == PBMoves::TELEKINESIS || move.id == PBMoves::TELEPORT) # 11A, 0EA
|
||||
# "001", "01A", "048", "0A1", "0E2", "0EA", "0F3", "10E", "11A", "11D", "11E", "14A"
|
||||
return 0
|
||||
elsif (move.id == PBMoves::ALLYSWITCH || move.id == PBMoves::AROMATICMIST ||
|
||||
move.id == PBMoves::CONVERSION || move.id == PBMoves::ENDURE ||
|
||||
move.id == PBMoves::ENTRAINMENT || move.id == PBMoves::FLOWERSHIELD ||
|
||||
move.id == PBMoves::FORESIGHT || move.id == PBMoves::FORESTSCURSE ||
|
||||
move.id == PBMoves::GRAVITY || move.id == PBMoves::DEFOG ||
|
||||
move.id == PBMoves::GUARDSWAP || move.id == PBMoves::HEALBLOCK ||
|
||||
move.id == PBMoves::IMPRISON || move.id == PBMoves::INSTRUCT ||
|
||||
move.id == PBMoves::FAIRYLOCK || move.id == PBMoves::LASERFOCUS ||
|
||||
move.id == PBMoves::HELPINGHAND || move.id == PBMoves::MAGICROOM ||
|
||||
move.id == PBMoves::MAGNETRISE || move.id == PBMoves::SOAK ||
|
||||
move.id == PBMoves::LOCKON || move.id == PBMoves::MINDREADER ||
|
||||
move.id == PBMoves::MIRACLEEYE || move.id == PBMoves::MUDSPORT ||
|
||||
move.id == PBMoves::NIGHTMARE || move.id == PBMoves::ODORSLEUTH ||
|
||||
move.id == PBMoves::POWERSPLIT || move.id == PBMoves::POWERSWAP ||
|
||||
move.id == PBMoves::GRUDGE || move.id == PBMoves::GUARDSPLIT ||
|
||||
move.id == PBMoves::POWERTRICK || move.id == PBMoves::QUICKGUARD ||
|
||||
move.id == PBMoves::RECYCLE || move.id == PBMoves::REFLECTTYPE ||
|
||||
move.id == PBMoves::ROTOTILLER || move.id == PBMoves::SANDATTACK ||
|
||||
move.id == PBMoves::SKILLSWAP || move.id == PBMoves::SNATCH ||
|
||||
move.id == PBMoves::MAGICCOAT || move.id == PBMoves::SPEEDSWAP ||
|
||||
move.id == PBMoves::SPOTLIGHT || move.id == PBMoves::SWALLOW ||
|
||||
move.id == PBMoves::TEETERDANCE || move.id == PBMoves::WATERSPORT ||
|
||||
move.id == PBMoves::WIDEGUARD || move.id == PBMoves::WONDERROOM)
|
||||
# "013", "047", "049", "052", "053", "057", "058", "059", "05E", "061",
|
||||
# "062", "066", "067", "09C", "09D", "09E", "0A6", "0A6", "0A7", "0A7",
|
||||
# "0A8", "0AB", "0AC", "0B1", "0B2", "0B8", "0BB", "0E6", "0E8", "0F6",
|
||||
# "0F9", "10F", "114", "118", "119", "120", "124", "138", "13E", "13F",
|
||||
# "143", "152", "15E", "161", "16A", "16B"
|
||||
return 5
|
||||
elsif (move.id == PBMoves::ACUPRESSURE || move.id == PBMoves::CAMOUFLAGE ||
|
||||
move.id == PBMoves::CHARM || move.id == PBMoves::CONFIDE ||
|
||||
move.id == PBMoves::DEFENSECURL || move.id == PBMoves::GROWTH ||
|
||||
move.id == PBMoves::EMBARGO || move.id == PBMoves::FLASH ||
|
||||
move.id == PBMoves::FOCUSENERGY || move.id == PBMoves::GROWL ||
|
||||
move.id == PBMoves::HARDEN || move.id == PBMoves::HAZE ||
|
||||
move.id == PBMoves::HONECLAWS || move.id == PBMoves::HOWL ||
|
||||
move.id == PBMoves::KINESIS || move.id == PBMoves::LEER ||
|
||||
move.id == PBMoves::METALSOUND || move.id == PBMoves::NOBLEROAR ||
|
||||
move.id == PBMoves::PLAYNICE || move.id == PBMoves::POWDER ||
|
||||
move.id == PBMoves::PSYCHUP || move.id == PBMoves::SHARPEN ||
|
||||
move.id == PBMoves::SMOKESCREEN || move.id == PBMoves::STRINGSHOT ||
|
||||
move.id == PBMoves::SUPERSONIC || move.id == PBMoves::TAILWHIP ||
|
||||
move.id == PBMoves::TEARFULLOOK || move.id == PBMoves::TORMENT ||
|
||||
move.id == PBMoves::WITHDRAW || move.id == PBMoves::WORKUP)
|
||||
# "013", "01C", "01C", "01D", "01D", "01E", "023", "027", "028", "029",
|
||||
# "037", "042", "043", "043", "047", "047", "047", "04B", "04D", "04F",
|
||||
# "051", "055", "060", "0B7", "0F8", "139", "13A", "13A", "13C", "148"
|
||||
return 10
|
||||
elsif (move.id == PBMoves::ASSIST || move.id == PBMoves::BABYDOLLEYES ||
|
||||
move.id == PBMoves::CAPTIVATE || move.id == PBMoves::COTTONSPORE ||
|
||||
move.id == PBMoves::DARKVOID || move.id == PBMoves::AGILITY ||
|
||||
move.id == PBMoves::DOUBLETEAM || move.id == PBMoves::EERIEIMPULSE ||
|
||||
move.id == PBMoves::FAKETEARS || move.id == PBMoves::FEATHERDANCE ||
|
||||
move.id == PBMoves::FLORALHEALING || move.id == PBMoves::GRASSWHISTLE ||
|
||||
move.id == PBMoves::HEALPULSE || move.id == PBMoves::HEALINGWISH ||
|
||||
move.id == PBMoves::HYPNOSIS || move.id == PBMoves::INGRAIN ||
|
||||
move.id == PBMoves::LUNARDANCE || move.id == PBMoves::MEFIRST ||
|
||||
move.id == PBMoves::MEDITATE || move.id == PBMoves::MIMIC ||
|
||||
move.id == PBMoves::PARTINGSHOT || move.id == PBMoves::POISONPOWDER ||
|
||||
move.id == PBMoves::REFRESH || move.id == PBMoves::ROLEPLAY ||
|
||||
move.id == PBMoves::SCARYFACE || move.id == PBMoves::SCREECH ||
|
||||
move.id == PBMoves::SING || move.id == PBMoves::SKETCH ||
|
||||
move.id == PBMoves::TICKLE || move.id == PBMoves::CHARGE ||
|
||||
move.id == PBMoves::TRICKORTREAT || move.id == PBMoves::VENOMDRENCH ||
|
||||
move.id == PBMoves::GEARUP || move.id == PBMoves::MAGNETICFLUX ||
|
||||
move.id == PBMoves::SANDSTORM || move.id == PBMoves::HAIL ||
|
||||
move.id == PBMoves::SUNNYDAY || move.id == PBMoves::RAINDANCE)
|
||||
# "003", "003", "003", "003", "005", "018", "01C", "021", "022", "030",
|
||||
# "042", "04A", "04B", "04C", "04D", "04D", "04E", "04F", "05C", "05D",
|
||||
# "065", "0B0", "0B5", "0DB", "0DF", "0E3", "0E4", "0FF", "100", "101",
|
||||
# "102", "137", "13D", "140", "142", "151", "15C", "16E"
|
||||
return 15
|
||||
elsif (move.id == PBMoves::AQUARING || move.id == PBMoves::BLOCK ||
|
||||
move.id == PBMoves::CONVERSION2 || move.id == PBMoves::ELECTRIFY ||
|
||||
move.id == PBMoves::FLATTER || move.id == PBMoves::GASTROACID ||
|
||||
move.id == PBMoves::HEARTSWAP || move.id == PBMoves::IONDELUGE ||
|
||||
move.id == PBMoves::MEANLOOK || move.id == PBMoves::LOVELYKISS ||
|
||||
move.id == PBMoves::METRONOME || move.id == PBMoves::COPYCAT ||
|
||||
move.id == PBMoves::MIRRORMOVE || move.id == PBMoves::MIST ||
|
||||
move.id == PBMoves::PERISHSONG || move.id == PBMoves::REST ||
|
||||
move.id == PBMoves::ROAR || move.id == PBMoves::SIMPLEBEAM ||
|
||||
move.id == PBMoves::SLEEPPOWDER || move.id == PBMoves::SPIDERWEB ||
|
||||
move.id == PBMoves::SWAGGER || move.id == PBMoves::SWEETKISS ||
|
||||
move.id == PBMoves::POISONGAS || move.id == PBMoves::TOXICTHREAD ||
|
||||
move.id == PBMoves::TRANSFORM || move.id == PBMoves::WHIRLWIND ||
|
||||
move.id == PBMoves::WORRYSEED || move.id == PBMoves::YAWN)
|
||||
# "003", "003", "004", "005", "013", "040", "041", "054", "056", "05F",
|
||||
# "063", "064", "068", "069", "0AE", "0AF", "0B6", "0D9", "0DA", "0E5",
|
||||
# "0EB", "0EB", "0EF", "0EF", "0EF", "145", "146", "159"
|
||||
return 20
|
||||
elsif (move.id == PBMoves::AMNESIA || move.id == PBMoves::ATTRACT ||
|
||||
move.id == PBMoves::BARRIER || move.id == PBMoves::BELLYDRUM ||
|
||||
move.id == PBMoves::CONFUSERAY || move.id == PBMoves::DESTINYBOND ||
|
||||
move.id == PBMoves::DETECT || move.id == PBMoves::DISABLE ||
|
||||
move.id == PBMoves::ACIDARMOR || move.id == PBMoves::COSMICPOWER ||
|
||||
move.id == PBMoves::COTTONGUARD || move.id == PBMoves::DEFENDORDER ||
|
||||
move.id == PBMoves::FOLLOWME || move.id == PBMoves::AUTOTOMIZE ||
|
||||
move.id == PBMoves::HEALORDER || move.id == PBMoves::IRONDEFENSE ||
|
||||
move.id == PBMoves::LEECHSEED || move.id == PBMoves::MILKDRINK ||
|
||||
move.id == PBMoves::MINIMIZE || move.id == PBMoves::MOONLIGHT ||
|
||||
move.id == PBMoves::MORNINGSUN || move.id == PBMoves::PAINSPLIT ||
|
||||
move.id == PBMoves::PROTECT || move.id == PBMoves::PSYCHOSHIFT ||
|
||||
move.id == PBMoves::RAGEPOWDER || move.id == PBMoves::ROOST ||
|
||||
move.id == PBMoves::RECOVER || move.id == PBMoves::ROCKPOLISH ||
|
||||
move.id == PBMoves::SHOREUP || move.id == PBMoves::SLACKOFF ||
|
||||
move.id == PBMoves::SOFTBOILED || move.id == PBMoves::STRENGTHSAP ||
|
||||
move.id == PBMoves::STOCKPILE || move.id == PBMoves::STUNSPORE ||
|
||||
move.id == PBMoves::SUBSTITUTE ||
|
||||
move.id == PBMoves::SWITCHEROO || move.id == PBMoves::SYNTHESIS ||
|
||||
move.id == PBMoves::TAUNT || move.id == PBMoves::TOPSYTURVY ||
|
||||
move.id == PBMoves::TOXIC || move.id == PBMoves::TRICK ||
|
||||
move.id == PBMoves::WILLOWISP || move.id == PBMoves::WISH)
|
||||
# "006", "007", "00A", "013", "016", "01B", "02A", "02A", "02F", "02F",
|
||||
# "02F", "030", "031", "033", "034", "038", "03A", "05A", "0AA", "0AA",
|
||||
# "0B9", "0BA", "0D5", "0D5", "0D5", "0D5", "0D5", "0D6", "0D7", "0D8",
|
||||
# "0D8", "0D8", "0DC", "0E7", "0F2", "0F2", "10C", "112", "117", "117",
|
||||
# "141", "160", "16D"
|
||||
return 25
|
||||
elsif (move.id == PBMoves::BATONPASS || move.id == PBMoves::BULKUP ||
|
||||
move.id == PBMoves::CALMMIND || move.id == PBMoves::COIL ||
|
||||
move.id == PBMoves::CURSE || move.id == PBMoves::ELECTRICTERRAIN ||
|
||||
move.id == PBMoves::ENCORE || move.id == PBMoves::GLARE ||
|
||||
move.id == PBMoves::GRASSYTERRAIN || move.id == PBMoves::MISTYTERRAIN ||
|
||||
move.id == PBMoves::NATUREPOWER || move.id == PBMoves::PSYCHICTERRAIN ||
|
||||
move.id == PBMoves::PURIFY || move.id == PBMoves::SLEEPTALK ||
|
||||
move.id == PBMoves::SPIKES || move.id == PBMoves::STEALTHROCK ||
|
||||
move.id == PBMoves::SPIKYSHIELD || move.id == PBMoves::THUNDERWAVE ||
|
||||
move.id == PBMoves::TOXICSPIKES || move.id == PBMoves::TRICKROOM)
|
||||
# "007", "007", "024", "025", "02C", "0B3", "0B4", "0BC", "0ED", "103",
|
||||
# "104", "105", "10D", "11F", "14C", "154", "155", "156", "15B", "173"
|
||||
return 30
|
||||
elsif (move.id == PBMoves::AROMATHERAPY || move.id == PBMoves::BANEFULBUNKER ||
|
||||
move.id == PBMoves::HEALBELL || move.id == PBMoves::KINGSSHIELD ||
|
||||
move.id == PBMoves::LIGHTSCREEN || move.id == PBMoves::MATBLOCK ||
|
||||
move.id == PBMoves::NASTYPLOT || move.id == PBMoves::REFLECT ||
|
||||
move.id == PBMoves::SWORDSDANCE || move.id == PBMoves::TAILGLOW ||
|
||||
move.id == PBMoves::TAILWIND)
|
||||
# "019", "019", "02E", "032", "039", "05B", "0A2", "0A3", "149", "14B", "168"
|
||||
return 35
|
||||
elsif (move.id == PBMoves::DRAGONDANCE || move.id == PBMoves::GEOMANCY ||
|
||||
move.id == PBMoves::QUIVERDANCE || move.id == PBMoves::SHELLSMASH ||
|
||||
move.id == PBMoves::SHIFTGEAR)
|
||||
# "026", "02B", "035", "036", "14E"
|
||||
return 40
|
||||
elsif (move.id == PBMoves::AURORAVEIL || move.id == PBMoves::STICKYWEB ||
|
||||
move.id == PBMoves::SPORE)
|
||||
# "003", "153", "167"
|
||||
return 60
|
||||
end
|
||||
end
|
||||
=end
|
||||
|
||||
def pbAegislashStats(aegi)
|
||||
if aegi.form==1
|
||||
return aegi
|
||||
else
|
||||
bladecheck = aegi.clone
|
||||
bladecheck.form = 1
|
||||
return bladecheck
|
||||
end
|
||||
end
|
||||
|
||||
def pbMegaStats(mon)
|
||||
if mon.isMega?
|
||||
return mon
|
||||
else
|
||||
megacheck = mon.clone
|
||||
megacheck.stages = mon.stages.clone
|
||||
megacheck.form = mon.getMegaForm
|
||||
return megacheck
|
||||
end
|
||||
end
|
||||
|
||||
def pbChangeMove(move,attacker)
|
||||
move = PokeBattle_Move.pbFromPBMove(self,PBMove.new(move.id),attacker)
|
||||
case move.id
|
||||
when PBMoves::WEATHERBALL
|
||||
weather=pbWeather
|
||||
move.type=(PBTypes::NORMAL)
|
||||
move.type=PBTypes::FIRE if (weather==PBWeather::SUNNYDAY && !attacker.hasWorkingItem(:UTILITYUMBRELLA))
|
||||
move.type=PBTypes::WATER if (weather==PBWeather::RAINDANCE && !attacker.hasWorkingItem(:UTILITYUMBRELLA))
|
||||
move.type=PBTypes::ROCK if weather==PBWeather::SANDSTORM
|
||||
move.type=PBTypes::ICE if weather==PBWeather::HAIL
|
||||
if pbWeather !=0
|
||||
move.basedamage*=2 if move.basedamage == 50
|
||||
end
|
||||
|
||||
when PBMoves::HIDDENPOWER
|
||||
if attacker
|
||||
move.type = move.pbType(type,attacker,nil)
|
||||
end
|
||||
|
||||
when PBMoves::NATUREPOWER
|
||||
move=0
|
||||
if $fefieldeffect > 0
|
||||
naturemoves = FieldEffects::NATUREMOVES
|
||||
move= naturemoves[$fefieldeffect] # Combination of environment and Terrain
|
||||
else
|
||||
move=PBMoves::TRIATTACK
|
||||
end
|
||||
move = PokeBattle_Move.pbFromPBMove(self,PBMove.new(move),attacker)
|
||||
end
|
||||
return move
|
||||
end
|
||||
|
||||
def getAbilityDisruptScore(move,attacker,opponent,skill)
|
||||
abilityscore=100.0
|
||||
return abilityscore if !opponent.abilitynulled == false #if the ability doesn't work, then nothing here matters
|
||||
if opponent.ability == PBAbilities::SPEEDBOOST
|
||||
PBDebug.log(sprintf("Speedboost Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.1
|
||||
if opponent.stages[PBStats::SPEED]<2
|
||||
abilityscore*=1.3
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::SANDVEIL
|
||||
PBDebug.log(sprintf("Sand veil Disrupt")) if $INTERNAL
|
||||
if @weather==PBWeather::SANDSTORM
|
||||
abilityscore*=1.3
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::VOLTABSORB ||
|
||||
opponent.ability == PBAbilities::LIGHTNINGROD ||
|
||||
opponent.ability == PBAbilities::MOTORDRIVE
|
||||
PBDebug.log(sprintf("Volt Absorb Disrupt")) if $INTERNAL
|
||||
elecvar = false
|
||||
totalelec=true
|
||||
elecmove=nil
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::ELECTRIC)
|
||||
totalelec=false
|
||||
end
|
||||
if (i.type == PBTypes::ELECTRIC)
|
||||
elecvar=true
|
||||
elecmove=i
|
||||
end
|
||||
end
|
||||
if elecvar
|
||||
if totalelec
|
||||
abilityscore*=3
|
||||
end
|
||||
if pbTypeModNoMessages(elecmove.type,attacker,opponent,elecmove,skill)>4
|
||||
abilityscore*=2
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::WATERABSORB ||
|
||||
opponent.ability == PBAbilities::STORMDRAIN ||
|
||||
opponent.ability == PBAbilities::DRYSKIN
|
||||
PBDebug.log(sprintf("Water Absorb Disrupt")) if $INTERNAL
|
||||
watervar = false
|
||||
totalwater=true
|
||||
watermove=nil
|
||||
firevar=false
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::WATER)
|
||||
totalwater=false
|
||||
end
|
||||
if (i.type == PBTypes::WATER)
|
||||
watervar=true
|
||||
watermove=i
|
||||
end
|
||||
if (i.type == PBTypes::FIRE)
|
||||
firevar=true
|
||||
end
|
||||
end
|
||||
if watervar
|
||||
if totalwater
|
||||
abilityscore*=3
|
||||
end
|
||||
if pbTypeModNoMessages(watermove.type,attacker,opponent,watermove,skill)>4
|
||||
abilityscore*=2
|
||||
end
|
||||
end
|
||||
if opponent.ability == PBAbilities::DRYSKIN
|
||||
if firevar
|
||||
abilityscore*=0.5
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::FLASHFIRE
|
||||
PBDebug.log(sprintf("Flash Fire Disrupt")) if $INTERNAL
|
||||
firevar = false
|
||||
totalfire=true
|
||||
firemove=nil
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::FIRE)
|
||||
totalfire=false
|
||||
end
|
||||
if (i.type == PBTypes::FIRE)
|
||||
firevar=true
|
||||
firemove=i
|
||||
end
|
||||
end
|
||||
if firevar
|
||||
if totalfire
|
||||
abilityscore*=3
|
||||
end
|
||||
if pbTypeModNoMessages(firemove.type,attacker,opponent,firemove,skill)>4
|
||||
abilityscore*=2
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::LEVITATE
|
||||
PBDebug.log(sprintf("Levitate Disrupt")) if $INTERNAL
|
||||
groundvar = false
|
||||
totalground=true
|
||||
groundmove=nil
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::GROUND)
|
||||
totalground=false
|
||||
end
|
||||
if (i.type == PBTypes::GROUND)
|
||||
groundvar=true
|
||||
groundmove=i
|
||||
end
|
||||
end
|
||||
if groundvar
|
||||
if totalground
|
||||
abilityscore*=3
|
||||
end
|
||||
if pbTypeModNoMessages(groundmove.type,attacker,opponent,groundmove,skill)>4
|
||||
abilityscore*=2
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::SHADOWTAG
|
||||
PBDebug.log(sprintf("Shadow Tag Disrupt")) if $INTERNAL
|
||||
if !attacker.hasType?(PBTypes::GHOST)
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::ARENATRAP
|
||||
PBDebug.log(sprintf("Arena Trap Disrupt")) if $INTERNAL
|
||||
if attacker.isAirborne?
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::WONDERGUARD
|
||||
PBDebug.log(sprintf("Wonder Guard Disrupt")) if $INTERNAL
|
||||
wondervar=false
|
||||
for i in attacker.moves
|
||||
if pbTypeModNoMessages(i.type,attacker,opponent,i,skill)>4
|
||||
wondervar=true
|
||||
end
|
||||
end
|
||||
if !wondervar
|
||||
abilityscore*=5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::SERENEGRACE
|
||||
PBDebug.log(sprintf("Serene Grace Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.3
|
||||
elsif opponent.ability == PBAbilities::PUREPOWER || opponent.ability == PBAbilities::HUGEPOWER
|
||||
PBDebug.log(sprintf("Pure Power Disrupt")) if $INTERNAL
|
||||
abilityscore*=2
|
||||
elsif opponent.ability == PBAbilities::SOUNDPROOF
|
||||
PBDebug.log(sprintf("Soundproof Disrupt")) if $INTERNAL
|
||||
soundvar=false
|
||||
for i in attacker.moves
|
||||
if i.isSoundBased?
|
||||
soundvar=true
|
||||
end
|
||||
end
|
||||
if !soundvar
|
||||
abilityscore*=3
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::THICKFAT
|
||||
PBDebug.log(sprintf("Thick Fat Disrupt")) if $INTERNAL
|
||||
totalguard=true
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::FIRE) && !(i.type == PBTypes::ICE)
|
||||
totalguard=false
|
||||
end
|
||||
end
|
||||
if totalguard
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::TRUANT
|
||||
PBDebug.log(sprintf("Truant Disrupt")) if $INTERNAL
|
||||
abilityscore*=0.1
|
||||
elsif opponent.ability == PBAbilities::GUTS ||
|
||||
opponent.ability == PBAbilities::QUICKFEET ||
|
||||
opponent.ability == PBAbilities::MARVELSCALE
|
||||
PBDebug.log(sprintf("Guts Disrupt")) if $INTERNAL
|
||||
if opponent.status!=0
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::LIQUIDOOZE
|
||||
PBDebug.log(sprintf("Liquid Ooze Disrupt")) if $INTERNAL
|
||||
if opponent.effects[PBEffects::LeechSeed]>=0 || attacker.pbHasMove?((PBMoves::LEECHSEED))
|
||||
abilityscore*=2
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::AIRLOCK || opponent.ability == PBAbilities::CLOUDNINE
|
||||
PBDebug.log(sprintf("Airlock Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.1
|
||||
elsif opponent.ability == PBAbilities::HYDRATION
|
||||
PBDebug.log(sprintf("Hydration Disrupt")) if $INTERNAL
|
||||
if @weather==PBWeather::RAINDANCE
|
||||
abilityscore*=1.3
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::ADAPTABILITY
|
||||
PBDebug.log(sprintf("Adaptability Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.3
|
||||
elsif opponent.ability == PBAbilities::SKILLLINK
|
||||
PBDebug.log(sprintf("Skill Link Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.5
|
||||
elsif opponent.ability == PBAbilities::POISONHEAL
|
||||
PBDebug.log(sprintf("Poison Heal Disrupt")) if $INTERNAL
|
||||
if opponent.status==PBStatuses::POISON
|
||||
abilityscore*=2
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::NORMALIZE
|
||||
PBDebug.log(sprintf("Normalize Disrupt")) if $INTERNAL
|
||||
abilityscore*=0.6
|
||||
elsif opponent.ability == PBAbilities::MAGICGUARD
|
||||
PBDebug.log(sprintf("Magic Guard Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.4
|
||||
elsif opponent.ability == PBAbilities::STALL
|
||||
PBDebug.log(sprintf("Stall Disrupt")) if $INTERNAL
|
||||
abilityscore*=0.5
|
||||
elsif opponent.ability == PBAbilities::TECHNICIAN
|
||||
PBDebug.log(sprintf("Technician Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.3
|
||||
elsif opponent.ability == PBAbilities::MOLDBREAKER
|
||||
PBDebug.log(sprintf("Mold Breaker Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.1
|
||||
elsif opponent.ability == PBAbilities::UNAWARE
|
||||
PBDebug.log(sprintf("Unaware Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.7
|
||||
elsif opponent.ability == PBAbilities::SLOWSTART
|
||||
PBDebug.log(sprintf("Slow Start Disrupt")) if $INTERNAL
|
||||
abilityscore*=0.3
|
||||
elsif opponent.ability == PBAbilities::MULTITYPE || opponent.ability == PBAbilities::STANCECHANGE ||
|
||||
opponent.ability == PBAbilities::SCHOOLING || opponent.ability == PBAbilities::SHIELDSDOWN ||
|
||||
opponent.ability == PBAbilities::DISGUISE || opponent.ability == PBAbilities::RKSSYSTEM ||
|
||||
opponent.ability == PBAbilities::POWERCONSTRUCT
|
||||
PBDebug.log(sprintf("Multitype Disrupt")) if $INTERNAL
|
||||
abilityscore*=0
|
||||
elsif opponent.ability == PBAbilities::SHEERFORCE
|
||||
PBDebug.log(sprintf("Sheer Force Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.2
|
||||
elsif opponent.ability == PBAbilities::CONTRARY
|
||||
PBDebug.log(sprintf("Contrary Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.4
|
||||
if opponent.stages[PBStats::ATTACK]>0 || opponent.stages[PBStats::SPATK]>0 ||
|
||||
opponent.stages[PBStats::DEFENSE]>0 || opponent.stages[PBStats::SPDEF]>0 ||
|
||||
opponent.stages[PBStats::SPEED]>0
|
||||
abilityscore*=2
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::DEFEATIST
|
||||
PBDebug.log(sprintf("Defeatist Disrupt")) if $INTERNAL
|
||||
abilityscore*=0.5
|
||||
elsif opponent.ability == PBAbilities::MULTISCALE
|
||||
PBDebug.log(sprintf("Multiscale Disrupt")) if $INTERNAL
|
||||
if opponent.hp==opponent.totalhp
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::HARVEST
|
||||
PBDebug.log(sprintf("Harvest Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.2
|
||||
elsif opponent.ability == PBAbilities::MOODY
|
||||
PBDebug.log(sprintf("Moody Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.8
|
||||
elsif opponent.ability == PBAbilities::SAPSIPPER
|
||||
PBDebug.log(sprintf("Sap Sipper Disrupt")) if $INTERNAL
|
||||
grassvar = false
|
||||
totalgrass=true
|
||||
grassmove=nil
|
||||
for i in attacker.moves
|
||||
if !(i.type == PBTypes::GRASS)
|
||||
totalgrass=false
|
||||
end
|
||||
if (i.type == PBTypes::GRASS)
|
||||
grassvar=true
|
||||
grassmove=i
|
||||
end
|
||||
end
|
||||
if grassvar
|
||||
if totalgrass
|
||||
abilityscore*=3
|
||||
end
|
||||
if pbTypeModNoMessages(grassmove.type,attacker,opponent,grassmove,skill)>4
|
||||
abilityscore*=2
|
||||
end
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::PRANKSTER
|
||||
PBDebug.log(sprintf("Prankster Disrupt")) if $INTERNAL
|
||||
if attacker.speed>opponent.speed
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::SNOWCLOAK
|
||||
PBDebug.log(sprintf("Snow Cloak Disrupt")) if $INTERNAL
|
||||
if @weather==PBWeather::HAIL
|
||||
abilityscore*=1.1
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::FURCOAT
|
||||
PBDebug.log(sprintf("Fur Coat Disrupt")) if $INTERNAL
|
||||
if attacker.attack>attacker.spatk
|
||||
abilityscore*=1.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::PARENTALBOND
|
||||
PBDebug.log(sprintf("Parental Bond Disrupt")) if $INTERNAL
|
||||
abilityscore*=3
|
||||
elsif opponent.ability == PBAbilities::PROTEAN
|
||||
PBDebug.log(sprintf("Protean Disrupt")) if $INTERNAL
|
||||
abilityscore*=3
|
||||
elsif opponent.ability == PBAbilities::TOUGHCLAWS
|
||||
PBDebug.log(sprintf("Tough Claws Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.2
|
||||
elsif opponent.ability == PBAbilities::BEASTBOOST
|
||||
PBDebug.log(sprintf("Beast Boost Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.1
|
||||
elsif opponent.ability == PBAbilities::COMATOSE
|
||||
PBDebug.log(sprintf("Comatose Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.3
|
||||
elsif opponent.ability == PBAbilities::FLUFFY
|
||||
PBDebug.log(sprintf("Fluffy Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.5
|
||||
firevar = false
|
||||
for i in attacker.moves
|
||||
if (i.type == PBTypes::FIRE)
|
||||
firevar=true
|
||||
end
|
||||
end
|
||||
if firevar
|
||||
abilityscore*=0.5
|
||||
end
|
||||
elsif opponent.ability == PBAbilities::MERCILESS
|
||||
PBDebug.log(sprintf("Merciless Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.3
|
||||
elsif opponent.ability == PBAbilities::WATERBUBBLE
|
||||
PBDebug.log(sprintf("Water Bubble Disrupt")) if $INTERNAL
|
||||
abilityscore*=1.5
|
||||
firevar = false
|
||||
for i in attacker.moves
|
||||
if (i.type == PBTypes::FIRE)
|
||||
firevar=true
|
||||
end
|
||||
end
|
||||
if firevar
|
||||
abilityscore*=1.3
|
||||
end
|
||||
elsif attacker.pbPartner==opponent
|
||||
if abilityscore!=0
|
||||
if abilityscore>200
|
||||
abilityscore=200
|
||||
end
|
||||
tempscore = abilityscore
|
||||
abilityscore = 200 - tempscore
|
||||
end
|
||||
end
|
||||
abilityscore*=0.01
|
||||
return abilityscore
|
||||
end
|
||||
|
||||
def getFieldDisruptScore(attacker,opponent,skill)
|
||||
fieldscore=100.0
|
||||
aroles = pbGetMonRole(attacker,opponent,skill)
|
||||
oroles = pbGetMonRole(opponent,attacker,skill)
|
||||
aimem = getAIMemory(skill,opponent.pokemonIndex)
|
||||
if $fefieldeffect==1 # Electric Terrain
|
||||
PBDebug.log(sprintf("Electric Terrain Disrupt")) if $INTERNAL
|
||||
if opponent.pbHasType?(:ELECTRIC) || opponent.pbPartner.pbHasType?(:ELECTRIC)
|
||||
fieldscore*=1.5
|
||||
end
|
||||
if attacker.pbHasType?(:ELECTRIC)
|
||||
fieldscore*=0.5
|
||||
end
|
||||
partyelec=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:ELECTRIC)
|
||||
partyelec=true
|
||||
end
|
||||
end
|
||||
if partyelec
|
||||
fieldscore*=0.5
|
||||
end
|
||||
if (!opponent.abilitynulled && opponent.ability == PBAbilities::SURGESURFER)
|
||||
fieldscore*=1.3
|
||||
end
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::SURGESURFER)
|
||||
fieldscore*=0.7
|
||||
end
|
||||
end
|
||||
if $fefieldeffect==2 # Grassy Terrain
|
||||
PBDebug.log(sprintf("Grassy Terrain Disrupt")) if $INTERNAL
|
||||
if opponent.pbHasType?(:GRASS) || opponent.pbPartner.pbHasType?(:GRASS)
|
||||
fieldscore*=1.5
|
||||
end
|
||||
if attacker.pbHasType?(:GRASS)
|
||||
fieldscore*=0.5
|
||||
end
|
||||
if opponent.pbHasType?(:FIRE) || opponent.pbPartner.pbHasType?(:FIRE)
|
||||
fieldscore*=1.8
|
||||
end
|
||||
if attacker.pbHasType?(:FIRE)
|
||||
fieldscore*=0.2
|
||||
end
|
||||
partygrass=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:GRASS)
|
||||
partygrass=true
|
||||
end
|
||||
end
|
||||
if partygrass
|
||||
fieldscore*=0.5
|
||||
end
|
||||
partyfire=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:FIRE)
|
||||
partyfire=true
|
||||
end
|
||||
end
|
||||
if partyfire
|
||||
fieldscore*=0.2
|
||||
end
|
||||
if aroles.include?(PBMonRoles::SPECIALWALL) || aroles.include?(PBMonRoles::PHYSICALWALL)
|
||||
fieldscore*=0.8
|
||||
end
|
||||
if oroles.include?(PBMonRoles::SPECIALWALL) || oroles.include?(PBMonRoles::PHYSICALWALL)
|
||||
fieldscore*=1.2
|
||||
end
|
||||
end
|
||||
if $fefieldeffect==3 # Misty Terrain
|
||||
PBDebug.log(sprintf("Misty Terrain Disrupt")) if $INTERNAL
|
||||
if attacker.spatk>attacker.attack
|
||||
if opponent.pbHasType?(:FAIRY) || opponent.pbPartner.pbHasType?(:FAIRY)
|
||||
fieldscore*=1.3
|
||||
end
|
||||
end
|
||||
if opponent.spatk>opponent.attack
|
||||
if attacker.pbHasType?(:FAIRY)
|
||||
fieldscore*=0.7
|
||||
end
|
||||
end
|
||||
if opponent.pbHasType?(:DRAGON) || opponent.pbPartner.pbHasType?(:DRAGON)
|
||||
fieldscore*=0.5
|
||||
end
|
||||
if attacker.pbHasType?(:DRAGON)
|
||||
fieldscore*=1.5
|
||||
end
|
||||
partyfairy=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:FAIRY)
|
||||
partyfairy=true
|
||||
end
|
||||
end
|
||||
if partyfairy
|
||||
fieldscore*=0.7
|
||||
end
|
||||
partydragon=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:DRAGON)
|
||||
partydragon=true
|
||||
end
|
||||
end
|
||||
if partydragon
|
||||
fieldscore*=1.5
|
||||
end
|
||||
if !(attacker.pbHasType?(:POISON) || attacker.pbHasType?(:STEEL))
|
||||
if $fecounter==1
|
||||
fieldscore*=1.8
|
||||
end
|
||||
end
|
||||
end
|
||||
if $fefieldeffect==37 # Psychic Terrain
|
||||
PBDebug.log(sprintf("Psychic Terrain Disrupt")) if $INTERNAL
|
||||
if opponent.pbHasType?(:PSYCHIC) || opponent.pbPartner.pbHasType?(:PSYCHIC)
|
||||
fieldscore*=1.7
|
||||
end
|
||||
if attacker.pbHasType?(:PSYCHIC)
|
||||
fieldscore*=0.3
|
||||
end
|
||||
partypsy=false
|
||||
for k in pbParty(attacker.index)
|
||||
next if k.nil?
|
||||
if k.hasType?(:PSYCHIC)
|
||||
partypsy=true
|
||||
end
|
||||
end
|
||||
if partypsy
|
||||
fieldscore*=0.3
|
||||
end
|
||||
if (!opponent.abilitynulled && opponent.ability == PBAbilities::TELEPATHY)
|
||||
fieldscore*=1.3
|
||||
end
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::TELEPATHY)
|
||||
fieldscore*=0.7
|
||||
end
|
||||
end
|
||||
fieldscore*=0.01
|
||||
return fieldscore
|
||||
end
|
||||
|
||||
# Used by all moves that raise the user's stat(s)
|
||||
def setupminiscore(attacker,opponent,skill,move,sweep,code,double,initialscores,scoreindex)
|
||||
aimem = getAIMemory(skill,opponent.pokemonIndex)
|
||||
miniscore=100
|
||||
#hi we are going in the comments for this one because it is in dire need of explanation
|
||||
#up until this point, most of the key differences between different set up moves has
|
||||
#been whether they are good for setting up to sweep or not.
|
||||
#this is not the case past here.
|
||||
#there are some really obnoxious differences between moves, and the way i'm dealing
|
||||
#with it is through binary strings.
|
||||
#this string is passed as a single number and is then processed by the function as such:
|
||||
# 00001 = attack 00010 = defense 00100 = sp.attack 01000 = sp.defense 10000 = speed
|
||||
#cosmic power would be 01010 in binary or 10 in normal, bulk up would be 00011 or 3, etc
|
||||
#evasion has a code of 0
|
||||
#this way new moves can be added and still use this function without any loss in
|
||||
#the overall scoring precision of the AI
|
||||
if initialscores.length>0
|
||||
miniscore*=1.3 if hasbadmoves(initialscores,scoreindex,20)
|
||||
end
|
||||
if skill>=PBTrainerAI.mediumSkill
|
||||
if aimem.length > 0
|
||||
maxdam = checkAIdamage(aimem,attacker,opponent,skill)
|
||||
if maxdam<(attacker.hp/4.0) && sweep
|
||||
miniscore*=1.2
|
||||
elsif maxdam<(attacker.hp/3.0) && !sweep
|
||||
miniscore*=1.1
|
||||
elsif maxdam<(attacker.hp/4.0) && code == 10
|
||||
miniscore*=1.5
|
||||
else
|
||||
if move.basedamage==0
|
||||
miniscore*=0.8
|
||||
if maxdam>attacker.hp
|
||||
miniscore*=0.1
|
||||
end
|
||||
end
|
||||
end
|
||||
else
|
||||
if move.basedamage==0
|
||||
effcheck = PBTypes.getCombinedEffectiveness(opponent.type1,attacker.type1,attacker.type2)
|
||||
if effcheck > 4
|
||||
miniscore*=0.5
|
||||
end
|
||||
effcheck2 = PBTypes.getCombinedEffectiveness(opponent.type2,attacker.type1,attacker.type2)
|
||||
if effcheck2 > 4
|
||||
miniscore*=0.5
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if attacker.effects[PBEffects::Confusion]>0
|
||||
if code & 0b1 == 0b1 #if move boosts attack
|
||||
miniscore*=0.2
|
||||
miniscore*=0.5 if double #using swords dance or shell smash while confused is Extra Bad
|
||||
miniscore*=1.5 if code & 0b11 == 0b11 #adds a correction for moves that boost attack and defense
|
||||
else
|
||||
miniscore*=0.5
|
||||
end
|
||||
end
|
||||
if !sweep
|
||||
miniscore*=1.1 if opponent.status==PBStatuses::BURN && code & 0b1000 == 0b1000 #sp.def boosting
|
||||
end
|
||||
if checkAImoves(PBStuff::SWITCHOUTMOVE,aimem)
|
||||
miniscore*=0.5 if sweep
|
||||
miniscore*=0.2 if !sweep
|
||||
miniscore*=1.5 if code == 0 #correction for evasion moves
|
||||
end
|
||||
=begin
|
||||
if attacker.effects[PBEffects::Substitute]>0 || attacker.effects[PBEffects::Disguise]
|
||||
miniscore*=1.3
|
||||
end
|
||||
if (attacker.hp.to_f)/attacker.totalhp<0.33
|
||||
miniscore*=0.3
|
||||
end
|
||||
if (attacker.hp.to_f)/attacker.totalhp<0.75 &&
|
||||
(!attacker.abilitynulled && (attacker.ability == PBAbilities::EMERGENCYEXIT || attacker.ability == PBAbilities::WIMPOUT) ||
|
||||
(attacker.itemWorks? && attacker.item == PBItems::EJECTBUTTON))
|
||||
miniscore*=0.3
|
||||
end
|
||||
if attacker.pbOpposingSide.effects[PBEffects::Retaliate]
|
||||
miniscore*=0.3
|
||||
end
|
||||
if opponent.status==PBStatuses::SLEEP || opponent.status==PBStatuses::FROZEN
|
||||
miniscore*=1.3
|
||||
end
|
||||
if (!attacker.abilitynulled && attacker.ability == PBAbilities::SIMPLE)
|
||||
miniscore*=2
|
||||
end
|
||||
if (attacker.hp.to_f)/attacker.totalhp>0.75
|
||||
miniscore*=1.2 if sweep
|
||||
miniscore*=1.1 if !sweep
|
||||
end
|
||||
if opponent.effects[PBEffects::HyperBeam]>0
|
||||
miniscore*=1.3 if sweep
|
||||
miniscore*=1.2 if !sweep
|
||||
end
|
||||
if opponent.effects[PBEffects::Yawn]>0
|
||||
miniscore*=1.7 if sweep
|
||||
miniscore*=1.3 if !sweep
|
||||
end
|
||||
if attacker.turncount<2
|
||||
miniscore*=1.2 if sweep
|
||||
miniscore*=1.1 if !sweep
|
||||
end
|
||||
if opponent.status!=0
|
||||
miniscore*=1.2 if sweep
|
||||
miniscore*=1.1 if !sweep
|
||||
end
|
||||
if opponent.effects[PBEffects::Encore]>0
|
||||
if opponent.moves[(opponent.effects[PBEffects::EncoreIndex])].basedamage==0
|
||||
if sweep || code == 10 #cosmic power
|
||||
miniscore*=1.5
|
||||
else
|
||||
miniscore*=1.3
|
||||
end
|
||||
end
|
||||
end
|
||||
sweep = false if code == 3 #from here on out, bulk up is not a sweep move
|
||||
if attacker.effects[PBEffects::LeechSeed]>=0 || attacker.effects[PBEffects::Attract]>=0
|
||||
miniscore*=0.6 if sweep
|
||||
miniscore*=0.3 if !sweep
|
||||
end
|
||||
miniscore*=0.2 if attacker.effects[PBEffects::Toxic]>0 && !sweep
|
||||
if @doublebattle
|
||||
miniscore*=0.5
|
||||
miniscore*=0.5 if !sweep #drop is doubled
|
||||
end
|
||||
=end
|
||||
|
||||
return miniscore
|
||||
end
|
||||
|
||||
# General processing for stat-dropping moves
|
||||
def unsetupminiscore(attacker,opponent,skill,move,roles,type,physical,greatmoves=false)
|
||||
#attack stat = type 1 defense stat = type 2 speed = 3 evasion = no
|
||||
miniscore = 100
|
||||
aimem = getAIMemory(skill,opponent.pokemonIndex)
|
||||
if type == 3 #speed stuff
|
||||
if (pbRoughStat(opponent,PBStats::SPEED,skill)*0.66)<attacker.pbSpeed
|
||||
if greatmoves
|
||||
miniscore*=1.5 if greatmoves
|
||||
else
|
||||
miniscore*=1.1
|
||||
end
|
||||
end
|
||||
else #non-speed stuff
|
||||
count=-1
|
||||
party=pbParty(attacker.index)
|
||||
sweepvar=false
|
||||
for i in 0...party.length
|
||||
count+=1
|
||||
next if (count==attacker.pokemonIndex || party[i].nil?)
|
||||
temproles = pbGetMonRole(party[i],opponent,skill,count,party)
|
||||
if temproles.include?(PBMonRoles::SWEEPER)
|
||||
sweepvar=true
|
||||
end
|
||||
end
|
||||
if sweepvar
|
||||
miniscore*=1.1
|
||||
end
|
||||
end
|
||||
if type == 2 #defense stuff
|
||||
miniscore*=1.5 if checkAIhealing(aimem)
|
||||
miniscore*=1.5 if move.function == 0x4C
|
||||
else
|
||||
if roles.include?(PBMonRoles::PHYSICALWALL) || roles.include?(PBMonRoles::SPECIALWALL)
|
||||
miniscore*=1.3 if type == 1
|
||||
miniscore*=1.1 if type == 3
|
||||
end
|
||||
end
|
||||
livecount1=0
|
||||
for i in pbParty(attacker.index)
|
||||
next if i.nil?
|
||||
livecount1+=1 if i.hp!=0
|
||||
end
|
||||
livecount2=0
|
||||
for i in pbParty(opponent.index)
|
||||
next if i.nil?
|
||||
livecount2+=1 if i.hp!=0
|
||||
end
|
||||
if livecount2==1 || (!attacker.abilitynulled && attacker.ability == PBAbilities::SHADOWTAG) || opponent.effects[PBEffects::MeanLook]>0
|
||||
miniscore*=1.4
|
||||
end
|
||||
#status section
|
||||
if type == 2 || !physical
|
||||
miniscore*=1.2 if opponent.status==PBStatuses::POISON || opponent.status==PBStatuses::BURN
|
||||
elsif type == 1
|
||||
miniscore*=1.2 if opponent.status==PBStatuses::POISON
|
||||
miniscore*=0.5 if opponent.status==PBStatuses::BURN
|
||||
end
|
||||
#move checks
|
||||
if type == 1 && physical
|
||||
miniscore*=0.5 if attacker.pbHasMove?(PBMoves::FOULPLAY)
|
||||
elsif type == 3
|
||||
miniscore*=0.5 if attacker.pbHasMove?(PBMoves::GYROBALL)
|
||||
miniscore*=1.5 if attacker.pbHasMove?(PBMoves::ELECTROBALL)
|
||||
miniscore*=1.3 if checkAImoves([PBMoves::ELECTROBALL],aimem)
|
||||
miniscore*=0.5 if checkAImoves([PBMoves::GYROBALL],aimem)
|
||||
miniscore*=0.1 if @trickroom!=0 || checkAImoves([PBMoves::TRICKROOM],aimem)
|
||||
end
|
||||
#final things
|
||||
if type == 3
|
||||
miniscore*=0.1 if opponent.itemWorks? && (opponent.item == PBItems::LAGGINGTAIL || opponent.item == PBItems::IRONBALL)
|
||||
miniscore*=0.2 if !opponent.abilitynulled && [PBAbilities::COMPETITIVE, PBAbilities::DEFIANT, PBAbilities::CONTRARY].include?(opponent.ability)
|
||||
else
|
||||
miniscore*=0.1 if !opponent.abilitynulled && [PBAbilities::UNAWARE, PBAbilities::COMPETITIVE, PBAbilities::DEFIANT, PBAbilities::CONTRARY].include?(opponent.ability)
|
||||
end
|
||||
if move.basedamage>0
|
||||
miniscore-=100
|
||||
if move.addlEffect.to_f != 100
|
||||
miniscore*=(move.addlEffect.to_f/100)
|
||||
if !attacker.abilitynulled && attacker.ability == PBAbilities::SERENEGRACE
|
||||
miniscore*=2
|
||||
end
|
||||
end
|
||||
miniscore+=100
|
||||
else
|
||||
if livecount1==1
|
||||
miniscore*=0.5
|
||||
end
|
||||
if attacker.status!=0
|
||||
miniscore*=0.7
|
||||
end
|
||||
end
|
||||
miniscore /= 100
|
||||
return miniscore
|
||||
end
|
||||
|
||||
def hasgreatmoves(initialscores,scoreindex,skill)
|
||||
#slight variance in precision based on trainer skill
|
||||
threshold = 100
|
||||
threshold = 105 if skill>=PBTrainerAI.highSkill
|
||||
threshold = 110 if skill>=PBTrainerAI.bestSkill
|
||||
for i in 0...initialscores.length
|
||||
next if i==scoreindex
|
||||
if initialscores[i]>=threshold
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def hasbadmoves(initialscores,scoreindex,threshold)
|
||||
for i in 0...initialscores.length
|
||||
next if i==scoreindex
|
||||
if initialscores[i]>threshold
|
||||
return false
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def statchangecounter(mon,initial,final,limiter=0)
|
||||
count = 0
|
||||
case limiter
|
||||
when 0 #all stats
|
||||
for i in initial..final
|
||||
count += mon.stages[i]
|
||||
end
|
||||
when 1 #increases only
|
||||
for i in initial..final
|
||||
count += mon.stages[i] if mon.stages[i]>0
|
||||
end
|
||||
when -1 #decreases only
|
||||
for i in initial..final
|
||||
count += mon.stages[i] if mon.stages[i]<0
|
||||
end
|
||||
end
|
||||
return count
|
||||
end
|
||||
|
||||
end
|
||||
@@ -1,327 +0,0 @@
|
||||
=begin
|
||||
class PokeBattle_Battle
|
||||
def pbGetMonRole(mon,opponent,skill,position=0,party=nil)
|
||||
#PBDebug.log(sprintf("Beginning role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
monRoles=[]
|
||||
monability = mon.ability.to_i
|
||||
curemove=false
|
||||
healingmove=false
|
||||
wishmove=false
|
||||
phasemove=false
|
||||
priorityko=false
|
||||
pivotmove=false
|
||||
spinmove=false
|
||||
batonmove=false
|
||||
tauntmove=false
|
||||
restmove=false
|
||||
weathermove=false
|
||||
fieldmove=false
|
||||
|
||||
if mon.class == PokeBattle_Battler
|
||||
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
|
||||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
|
||||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
|
||||
monRoles.push(PBMonRoles::SWEEPER)
|
||||
end
|
||||
|
||||
for i in mon.moves
|
||||
next if i.nil?
|
||||
next if i.id == 0
|
||||
# Unused as only counts for REVENGEKILLER, which is only used if mon is
|
||||
# a Pokémon and not a battler (used in switching calculation)
|
||||
if i.priority>0
|
||||
dam=pbRoughDamage(i,mon,opponent,skill,i.basedamage)
|
||||
if opponent.hp>0
|
||||
percentage=(dam*100.0)/opponent.hp
|
||||
priorityko=true if percentage>100
|
||||
end
|
||||
end
|
||||
if i.isHealingMove?
|
||||
healingmove=true
|
||||
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
|
||||
curemove=true
|
||||
elsif (i.id == (PBMoves::WISH))
|
||||
wishmove=true
|
||||
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
|
||||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
|
||||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
|
||||
phasemove=true
|
||||
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
|
||||
pivotmove=true
|
||||
elsif (i.id == (PBMoves::RAPIDSPIN))
|
||||
spinmove=true
|
||||
elsif (i.id == (PBMoves::BATONPASS))
|
||||
batonmove=true
|
||||
elsif (i.id == (PBMoves::TAUNT))
|
||||
tauntmove=true
|
||||
elsif (i.id == (PBMoves::REST))
|
||||
restmove=true
|
||||
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
|
||||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
|
||||
weathermove=true
|
||||
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
|
||||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
|
||||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
|
||||
i.id == (PBMoves::TOPSYTURVY))
|
||||
fieldmove=true
|
||||
end
|
||||
end
|
||||
|
||||
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
|
||||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
|
||||
mon.nature==PBNatures::LAX))
|
||||
monRoles.push(PBMonRoles::PHYSICALWALL)
|
||||
end
|
||||
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
|
||||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
|
||||
mon.nature==PBNatures::CAREFUL))
|
||||
monRoles.push(PBMonRoles::SPECIALWALL)
|
||||
end
|
||||
if mon.pokemonIndex==0
|
||||
monRoles.push(PBMonRoles::LEAD)
|
||||
end
|
||||
if curemove || (wishmove && mon.ev[0]>251)
|
||||
monRoles.push(PBMonRoles::CLERIC)
|
||||
end
|
||||
if phasemove == true
|
||||
monRoles.push(PBMonRoles::PHAZER)
|
||||
end
|
||||
if mon.item==(PBItems::LIGHTCLAY)
|
||||
monRoles.push(PBMonRoles::SCREENER)
|
||||
end
|
||||
|
||||
# Unused
|
||||
if priorityko || (mon.speed>opponent.speed)
|
||||
monRoles.push(PBMonRoles::REVENGEKILLER)
|
||||
end
|
||||
|
||||
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
|
||||
monRoles.push(PBMonRoles::PIVOT)
|
||||
end
|
||||
if spinmove
|
||||
monRoles.push(PBMonRoles::SPINNER)
|
||||
end
|
||||
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
|
||||
monRoles.push(PBMonRoles::TANK)
|
||||
end
|
||||
if batonmove
|
||||
monRoles.push(PBMonRoles::BATONPASSER)
|
||||
end
|
||||
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS)
|
||||
monRoles.push(PBMonRoles::STALLBREAKER)
|
||||
end
|
||||
if restmove || (monability == PBAbilities::COMATOSE) ||
|
||||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
|
||||
(monability == PBAbilities::GUTS) ||
|
||||
(monability == PBAbilities::QUICKFEET)||
|
||||
(monability == PBAbilities::FLAREBOOST) ||
|
||||
(monability == PBAbilities::TOXICBOOST) ||
|
||||
(monability == PBAbilities::NATURALCURE) ||
|
||||
(monability == PBAbilities::MAGICGUARD) ||
|
||||
(monability == PBAbilities::MAGICBOUNCE) ||
|
||||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
|
||||
monRoles.push(PBMonRoles::STATUSABSORBER)
|
||||
end
|
||||
if (monability == PBAbilities::SHADOWTAG) ||
|
||||
(monability == PBAbilities::ARENATRAP) ||
|
||||
(monability == PBAbilities::MAGNETPULL)
|
||||
monRoles.push(PBMonRoles::TRAPPER)
|
||||
end
|
||||
if weathermove || (monability == PBAbilities::DROUGHT) ||
|
||||
(monability == PBAbilities::SANDSTREAM) ||
|
||||
(monability == PBAbilities::DRIZZLE) ||
|
||||
(monability == PBAbilities::SNOWWARNING) ||
|
||||
(monability == PBAbilities::PRIMORDIALSEA) ||
|
||||
(monability == PBAbilities::DESOLATELAND) ||
|
||||
(monability == PBAbilities::DELTASTREAM)
|
||||
monRoles.push(PBMonRoles::WEATHERSETTER)
|
||||
end
|
||||
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
|
||||
(monability == PBAbilities::ELECTRICSURGE) ||
|
||||
(monability == PBAbilities::MISTYSURGE) ||
|
||||
(monability == PBAbilities::PSYCHICSURGE) ||
|
||||
mon.item==(PBItems::AMPLIFIELDROCK)
|
||||
monRoles.push(PBMonRoles::FIELDSETTER)
|
||||
end
|
||||
#if $game_switches[525] && mon.pokemonIndex==(pbParty(mon.index).length-1)
|
||||
if mon.pokemonIndex==(pbParty(mon.index).length-1)
|
||||
monRoles.push(PBMonRoles::ACE)
|
||||
end
|
||||
|
||||
secondhighest=true
|
||||
if pbParty(mon.index).length>2
|
||||
for i in 0..(pbParty(mon.index).length-2)
|
||||
next if pbParty(mon.index)[i].nil?
|
||||
if mon.level<pbParty(mon.index)[i].level
|
||||
secondhighest=false
|
||||
end
|
||||
end
|
||||
end
|
||||
#if $game_switches[525]&& secondhighest
|
||||
if secondhighest
|
||||
monRoles.push(PBMonRoles::SECOND)
|
||||
end
|
||||
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
|
||||
|
||||
|
||||
elsif mon.class == PokeBattle_Pokemon
|
||||
movelist = []
|
||||
for i in mon.moves
|
||||
next if i.nil?
|
||||
next if i.id == 0
|
||||
movedummy = PokeBattle_Move.pbFromPBMove(self,i,mon)
|
||||
movelist.push(movedummy)
|
||||
end
|
||||
if mon.ev[3]>251 && (mon.nature==PBNatures::MODEST ||
|
||||
mon.nature==PBNatures::JOLLY || mon.nature==PBNatures::TIMID ||
|
||||
mon.nature==PBNatures::ADAMANT) || (mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS) || mon.item==(PBItems::CHOICESCARF))
|
||||
monRoles.push(PBMonRoles::SWEEPER)
|
||||
end
|
||||
for i in movelist
|
||||
next if i.nil?
|
||||
if i.isHealingMove?
|
||||
healingmove=true
|
||||
elsif (i.id == (PBMoves::HEALBELL) || i.id == (PBMoves::AROMATHERAPY))
|
||||
curemove=true
|
||||
elsif (i.id == (PBMoves::WISH))
|
||||
wishmove=true
|
||||
elsif (i.id == (PBMoves::YAWN) || i.id == (PBMoves::PERISHSONG) ||
|
||||
i.id == (PBMoves::DRAGONTAIL) || i.id == (PBMoves::CIRCLETHROW) ||
|
||||
i.id == (PBMoves::WHIRLWIND) || i.id == (PBMoves::ROAR))
|
||||
phasemove=true
|
||||
elsif (i.id == (PBMoves::UTURN) || i.id == (PBMoves::VOLTSWITCH))
|
||||
pivotmove=true
|
||||
elsif (i.id == (PBMoves::RAPIDSPIN))
|
||||
spinmove=true
|
||||
elsif (i.id == (PBMoves::BATONPASS))
|
||||
batonmove=true
|
||||
elsif(i.id == (PBMoves::TAUNT))
|
||||
tauntmove=true
|
||||
elsif (i.id == (PBMoves::REST))
|
||||
restmove=true
|
||||
elsif (i.id == (PBMoves::SUNNYDAY) || i.id == (PBMoves::RAINDANCE) ||
|
||||
i.id == (PBMoves::HAIL) || i.id == (PBMoves::SANDSTORM))
|
||||
weathermove=true
|
||||
elsif (i.id == (PBMoves::GRASSYTERRAIN) || i.id == (PBMoves::ELECTRICTERRAIN) ||
|
||||
i.id == (PBMoves::MISTYTERRAIN) || i.id == (PBMoves::PSYCHICTERRAIN) ||
|
||||
i.id == (PBMoves::MIST) || i.id == (PBMoves::IONDELUGE) ||
|
||||
i.id == (PBMoves::TOPSYTURVY))
|
||||
fieldmove=true
|
||||
end
|
||||
end
|
||||
if healingmove && (mon.ev[2]>251 && (mon.nature==PBNatures::BOLD ||
|
||||
mon.nature==PBNatures::RELAXED || mon.nature==PBNatures::IMPISH ||
|
||||
mon.nature==PBNatures::LAX))
|
||||
monRoles.push(PBMonRoles::PHYSICALWALL)
|
||||
end
|
||||
if healingmove && (mon.ev[5]>251 && (mon.nature==PBNatures::CALM ||
|
||||
mon.nature==PBNatures::GENTLE || mon.nature==PBNatures::SASSY ||
|
||||
mon.nature==PBNatures::CAREFUL))
|
||||
monRoles.push(PBMonRoles::SPECIALWALL)
|
||||
end
|
||||
if position==0
|
||||
monRoles.push(PBMonRoles::LEAD)
|
||||
end
|
||||
if curemove || (wishmove && mon.ev[0]>251)
|
||||
monRoles.push(PBMonRoles::CLERIC)
|
||||
end
|
||||
if (phasemove)
|
||||
monRoles.push(PBMonRoles::PHAZER)
|
||||
end
|
||||
if mon.item==(PBItems::LIGHTCLAY)
|
||||
monRoles.push(PBMonRoles::SCREENER)
|
||||
end
|
||||
# pbRoughDamage does not take Pokemon objects, this will cause issues
|
||||
priorityko=false
|
||||
for i in movelist
|
||||
next if i.priority<1
|
||||
next if i.basedamage<10
|
||||
priorityko=true
|
||||
end
|
||||
if priorityko || (mon.speed>opponent.speed)
|
||||
monRoles.push(PBMonRoles::REVENGEKILLER)
|
||||
end
|
||||
if (pivotmove && healingmove) || (monability == PBAbilities::REGENERATOR)
|
||||
monRoles.push(PBMonRoles::PIVOT)
|
||||
end
|
||||
if spinmove
|
||||
monRoles.push(PBMonRoles::SPINNER)
|
||||
end
|
||||
if (mon.ev[0]>251 && !healingmove) || mon.item==(PBItems::ASSAULTVEST)
|
||||
monRoles.push(PBMonRoles::TANK)
|
||||
end
|
||||
if batonmove
|
||||
monRoles.push(PBMonRoles::BATONPASSER)
|
||||
end
|
||||
if tauntmove || mon.item==(PBItems::CHOICEBAND) ||
|
||||
mon.item==(PBItems::CHOICESPECS)
|
||||
monRoles.push(PBMonRoles::STALLBREAKER)
|
||||
end
|
||||
if restmove || (monability == PBAbilities::COMATOSE) ||
|
||||
mon.item==(PBItems::TOXICORB) || mon.item==(PBItems::FLAMEORB) ||
|
||||
(monability == PBAbilities::GUTS) ||
|
||||
(monability == PBAbilities::QUICKFEET) ||
|
||||
(monability == PBAbilities::FLAREBOOST) ||
|
||||
(monability == PBAbilities::TOXICBOOST) ||
|
||||
(monability == PBAbilities::NATURALCURE) ||
|
||||
(monability == PBAbilities::MAGICGUARD) ||
|
||||
(monability == PBAbilities::MAGICBOUNCE) ||
|
||||
# TODO: Reference to the weather here.
|
||||
((monability == PBAbilities::HYDRATION) && pbWeather==PBWeather::RAINDANCE)
|
||||
monRoles.push(PBMonRoles::STATUSABSORBER)
|
||||
end
|
||||
if (monability == PBAbilities::SHADOWTAG) ||
|
||||
(monability == PBAbilities::ARENATRAP) ||
|
||||
(monability == PBAbilities::MAGNETPULL)
|
||||
monRoles.push(PBMonRoles::TRAPPER)
|
||||
end
|
||||
if weathermove || (monability == PBAbilities::DROUGHT) ||
|
||||
(monability == PBAbilities::SANDSTREAM) ||
|
||||
(monability == PBAbilities::DRIZZLE) ||
|
||||
(monability == PBAbilities::SNOWWARNING) ||
|
||||
(monability == PBAbilities::PRIMORDIALSEA) ||
|
||||
(monability == PBAbilities::DESOLATELAND) ||
|
||||
(monability == PBAbilities::DELTASTREAM)
|
||||
monRoles.push(PBMonRoles::WEATHERSETTER)
|
||||
end
|
||||
if fieldmove || (monability == PBAbilities::GRASSYSURGE) ||
|
||||
(monability == PBAbilities::ELECTRICSURGE) ||
|
||||
(monability == PBAbilities::MISTYSURGE) ||
|
||||
(monability == PBAbilities::PSYCHICSURGE) ||
|
||||
mon.item==(PBItems::AMPLIFIELDROCK)
|
||||
monRoles.push(PBMonRoles::FIELDSETTER)
|
||||
end
|
||||
if position==(party.length-1)
|
||||
#if $game_switches[525] && position==(party.length-1)
|
||||
monRoles.push(PBMonRoles::ACE)
|
||||
end
|
||||
secondhighest=true
|
||||
if party.length>2
|
||||
for i in 0...(party.length-1)
|
||||
next if party[i].nil?
|
||||
if mon.level<party[i].level
|
||||
secondhighest=false
|
||||
end
|
||||
end
|
||||
end
|
||||
#if $game_switches[525]&& secondhighest
|
||||
if secondhighest
|
||||
monRoles.push(PBMonRoles::SECOND)
|
||||
end
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
end
|
||||
#PBDebug.log(sprintf("Ending role assignment for %s",PBSpecies.getName(mon.species))) if $INTERNAL
|
||||
#PBDebug.log(sprintf("")) if $INTERNAL
|
||||
return monRoles
|
||||
end
|
||||
end
|
||||
=end
|
||||
@@ -233,6 +233,7 @@ class Scene_Map
|
||||
if $game_temp.title_screen_calling
|
||||
pbMapInterpreter.command_end if pbMapInterpreterRunning?
|
||||
$game_temp.title_screen_calling = false
|
||||
pbBGMFade(1.0)
|
||||
Graphics.transition
|
||||
Graphics.freeze
|
||||
end
|
||||
|
||||
@@ -47,7 +47,7 @@ class Window_UnformattedTextPokemon < SpriteWindow_Base
|
||||
return ret
|
||||
end
|
||||
|
||||
def resizeToFitInternal(text, maxwidth) # maxwidth is maximum acceptable window width
|
||||
def resizeToFitInternal(text, maxwidth) # maxwidth is maximum acceptable window width
|
||||
dims = [0, 0]
|
||||
cwidth = maxwidth < 0 ? Graphics.width : maxwidth
|
||||
getLineBrokenChunks(self.contents, text,
|
||||
@@ -173,7 +173,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
|
||||
moveCursor
|
||||
end
|
||||
|
||||
def lineHeight(value)
|
||||
def lineHeight=(value)
|
||||
@lineHeight = value
|
||||
self.text = self.text
|
||||
end
|
||||
@@ -296,7 +296,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
|
||||
width = 1
|
||||
height = 1
|
||||
numlines = 0
|
||||
visiblelines = (self.height - self.borderY) / 32
|
||||
visiblelines = (self.height - self.borderY) / @lineHeight
|
||||
if value.length == 0
|
||||
@fmtchars = []
|
||||
@bitmapwidth = width
|
||||
@@ -307,7 +307,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
|
||||
@fmtchars = []
|
||||
fmt = getFormattedText(self.contents, 0, 0,
|
||||
self.width - self.borderX - SpriteWindow_Base::TEXT_PADDING, -1,
|
||||
shadowc3tag(@baseColor, @shadowColor) + value, 32, true)
|
||||
shadowc3tag(@baseColor, @shadowColor) + value, @lineHeight, true)
|
||||
@oldfont = self.contents.font.clone
|
||||
fmt.each do |ch|
|
||||
chx = ch[1] + ch[3]
|
||||
@@ -334,7 +334,7 @@ class Window_AdvancedTextPokemon < SpriteWindow_Base
|
||||
else
|
||||
@fmtchars = getFormattedText(self.contents, 0, 0,
|
||||
self.width - self.borderX - SpriteWindow_Base::TEXT_PADDING, -1,
|
||||
shadowc3tag(@baseColor, @shadowColor) + value, 32, true)
|
||||
shadowc3tag(@baseColor, @shadowColor) + value, @lineHeight, true)
|
||||
@oldfont = self.contents.font.clone
|
||||
@fmtchars.each do |ch|
|
||||
chx = ch[1] + ch[3]
|
||||
|
||||
@@ -61,7 +61,7 @@ class Battle::Battler
|
||||
end
|
||||
end
|
||||
# Taunt
|
||||
if @effects[PBEffects::Taunt] > 0 && move.statusMove?
|
||||
if @effects[PBEffects::Taunt] > 0 && move.statusMove? && !specialUsage
|
||||
if showMessages
|
||||
msg = _INTL("{1} can't use {2} after the taunt!", pbThis, move.name)
|
||||
(commandPhase) ? @battle.pbDisplayPaused(msg) : @battle.pbDisplay(msg)
|
||||
@@ -69,7 +69,7 @@ class Battle::Battler
|
||||
return false
|
||||
end
|
||||
# Torment
|
||||
if @effects[PBEffects::Torment] && !@effects[PBEffects::Instructed] &&
|
||||
if @effects[PBEffects::Torment] && !@effects[PBEffects::Instructed] && !specialUsage &&
|
||||
@lastMoveUsed && move.id == @lastMoveUsed && move.id != @battle.struggle.id
|
||||
if showMessages
|
||||
msg = _INTL("{1} can't use the same move twice in a row due to the torment!", pbThis)
|
||||
|
||||
@@ -536,6 +536,8 @@ end
|
||||
# Power is also doubled if user has curled up. (Ice Ball, Rollout)
|
||||
#===============================================================================
|
||||
class Battle::Move::MultiTurnAttackPowersUpEachTurn < Battle::Move
|
||||
def pbNumHits(user, targets); return 1; end
|
||||
|
||||
def pbBaseDamage(baseDmg, user, target)
|
||||
shift = (5 - user.effects[PBEffects::Rollout]) # 0-4, where 0 is most powerful
|
||||
shift = 0 if user.effects[PBEffects::Rollout] == 0 # For first turn
|
||||
|
||||
@@ -756,6 +756,9 @@ end
|
||||
|
||||
#===============================================================================
|
||||
# The target can no longer use the same move twice in a row. (Torment)
|
||||
# NOTE: Torment is only supposed to start applying at the end of the round in
|
||||
# which it is used, unlike Taunt which starts applying immediately. I've
|
||||
# decided to make Torment apply immediately.
|
||||
#===============================================================================
|
||||
class Battle::Move::DisableTargetUsingSameMoveConsecutively < Battle::Move
|
||||
def ignoresSubstitute?(user); return true; end
|
||||
|
||||
Reference in New Issue
Block a user