mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Rewrote AI for move function codes for counters, protection removal, Wonder Room, Substitute. Fixed Counters working with damage absorbed by a substitute.
This commit is contained in:
@@ -374,6 +374,7 @@ class Battle::Move
|
||||
# code.
|
||||
moveType = nil
|
||||
moveType = :NORMAL if @function == "TypeDependsOnUserIVs" # Hidden Power
|
||||
if !target.damageState.substitute
|
||||
if physicalMove?(moveType)
|
||||
target.effects[PBEffects::Counter] = damage
|
||||
target.effects[PBEffects::CounterTarget] = user.index
|
||||
@@ -381,6 +382,7 @@ class Battle::Move
|
||||
target.effects[PBEffects::MirrorCoat] = damage
|
||||
target.effects[PBEffects::MirrorCoatTarget] = user.index
|
||||
end
|
||||
end
|
||||
if target.effects[PBEffects::Bide] > 0
|
||||
target.effects[PBEffects::BideDamage] += damage
|
||||
target.effects[PBEffects::BideTarget] = user.index
|
||||
|
||||
@@ -991,20 +991,8 @@ end
|
||||
#===============================================================================
|
||||
# Ends target's protections immediately. (Hyperspace Hole)
|
||||
#===============================================================================
|
||||
class Battle::Move::RemoveProtectionsBypassSubstitute < Battle::Move
|
||||
class Battle::Move::RemoveProtectionsBypassSubstitute < Battle::Move::RemoveProtections
|
||||
def ignoresSubstitute?(user); return true; end
|
||||
|
||||
def pbEffectAgainstTarget(user, target)
|
||||
target.effects[PBEffects::BanefulBunker] = false
|
||||
target.effects[PBEffects::KingsShield] = false
|
||||
target.effects[PBEffects::Obstruct] = false
|
||||
target.effects[PBEffects::Protect] = false
|
||||
target.effects[PBEffects::SpikyShield] = false
|
||||
target.pbOwnSide.effects[PBEffects::CraftyShield] = false
|
||||
target.pbOwnSide.effects[PBEffects::MatBlock] = false
|
||||
target.pbOwnSide.effects[PBEffects::QuickGuard] = false
|
||||
target.pbOwnSide.effects[PBEffects::WideGuard] = false
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
|
||||
@@ -601,7 +601,7 @@ Battle::AI::Handlers::MoveEffectScore.add("SwapSideEffects",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
|
||||
proc { |move, user, ai, battle|
|
||||
@@ -612,7 +612,11 @@ Battle::AI::Handlers::MoveFailureCheck.add("UserMakeSubstitute",
|
||||
Battle::AI::Handlers::MoveEffectScore.add("UserMakeSubstitute",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# Prefer more the higher the user's HP
|
||||
score += 8.0 * user.hp / user.totalhp
|
||||
score += (8 * user.hp.to_f / user.totalhp).round
|
||||
# Prefer if foes don't know any moves that can bypass a substitute
|
||||
ai.each_battler do |b, i|
|
||||
score += 4 if !b.check_for_move { |m| m.ignoresSubstitute?(b.battler) }
|
||||
end
|
||||
# TODO: Predict incoming damage, and prefer if it's greater than
|
||||
# user.totalhp / 4?
|
||||
next score
|
||||
|
||||
@@ -1323,7 +1323,6 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserCopyTargetStatStages
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
# TODO: Account for stat theft before damage calculation. This would be complex,
|
||||
# involving pbCanRaiseStatStage? and Contrary and Simple; do I want to
|
||||
# account for all that or simplify things?
|
||||
@@ -1507,57 +1506,56 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtk
|
||||
target_atk = target.base_stat(:ATTACK)
|
||||
target_spatk = target.base_stat(:SPECIAL_ATTACK)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user_atk >= target_atk && user_spatk >= target_spatk
|
||||
change_matters = false
|
||||
# Score based on changes to Attack
|
||||
atk_change_matters = false
|
||||
if target_atk > user_atk
|
||||
# User's Attack will be raised
|
||||
if ai.stat_raise_worthwhile?(user, :ATTACK, true)
|
||||
score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i
|
||||
atk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Attack will be lowered
|
||||
if ai.stat_drop_worthwhile?(target, :ATTACK, true)
|
||||
score += (20 * ((target_atk.to_f / user_atk) - 1)).to_i
|
||||
atk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
elsif target_atk < user_atk
|
||||
# User's Attack will be lowered
|
||||
if ai.stat_drop_worthwhile?(user, :ATTACK, true)
|
||||
score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i
|
||||
atk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Attack will be raised
|
||||
if ai.stat_raise_worthwhile?(target, :ATTACK, true)
|
||||
score -= (20 * ((user_atk.to_f / target_atk) - 1)).to_i
|
||||
atk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
end
|
||||
# Score based on changes to Special Attack
|
||||
spatk_change_matters = false
|
||||
if target_spatk > user_spatk
|
||||
# User's Special Attack will be raised
|
||||
if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true)
|
||||
score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i
|
||||
spatk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Special Attack will be lowered
|
||||
if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||
score += (20 * ((target_spatk.to_f / user_spatk) - 1)).to_i
|
||||
spatk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
elsif target_spatk < user_spatk
|
||||
# User's Special Attack will be lowered
|
||||
if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true)
|
||||
score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i
|
||||
spatk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Special Attack will be raised
|
||||
if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||
score -= (20 * ((user_spatk.to_f / target_spatk) - 1)).to_i
|
||||
spatk_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
end
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !atk_change_matters && !spatk_change_matters
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !change_matters
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -1572,57 +1570,56 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDef
|
||||
target_def = target.base_stat(:DEFENSE)
|
||||
target_spdef = target.base_stat(:SPECIAL_DEFENSE)
|
||||
next Battle::AI::MOVE_USELESS_SCORE if user_def >= target_def && user_spdef >= target_spdef
|
||||
change_matters = false
|
||||
# Score based on changes to Defense
|
||||
def_change_matters = false
|
||||
if target_def > user_def
|
||||
# User's Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(user, :ATTACK, true)
|
||||
if ai.stat_raise_worthwhile?(user, :DEFENSE, true)
|
||||
score += (20 * ((target_def.to_f / user_def) - 1)).to_i
|
||||
def_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(target, :ATTACK, true)
|
||||
if ai.stat_drop_worthwhile?(target, :DEFENSE, true)
|
||||
score += (20 * ((target_def.to_f / user_def) - 1)).to_i
|
||||
def_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
elsif target_def < user_def
|
||||
# User's Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(user, :ATTACK, true)
|
||||
if ai.stat_drop_worthwhile?(user, :DEFENSE, true)
|
||||
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i
|
||||
def_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(target, :ATTACK, true)
|
||||
if ai.stat_raise_worthwhile?(target, :DEFENSE, true)
|
||||
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i
|
||||
def_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
end
|
||||
# Score based on changes to Special Defense
|
||||
spdef_change_matters = false
|
||||
if target_spdef > user_spdef
|
||||
# User's Special Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(user, :SPECIAL_ATTACK, true)
|
||||
if ai.stat_raise_worthwhile?(user, :SPECIAL_DEFENSE, true)
|
||||
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i
|
||||
spdef_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Special Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||
if ai.stat_drop_worthwhile?(target, :SPECIAL_DEFENSE, true)
|
||||
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i
|
||||
spdef_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
elsif target_spdef < user_spdef
|
||||
# User's Special Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(user, :SPECIAL_ATTACK, true)
|
||||
if ai.stat_drop_worthwhile?(user, :SPECIAL_DEFENSE, true)
|
||||
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i
|
||||
spdef_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
# Target's Special Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||
if ai.stat_raise_worthwhile?(target, :SPECIAL_DEFENSE, true)
|
||||
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i
|
||||
spdef_change_matters = true
|
||||
change_matters = true
|
||||
end
|
||||
end
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !def_change_matters && !spdef_change_matters
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !change_matters
|
||||
next score
|
||||
}
|
||||
)
|
||||
@@ -1673,7 +1670,43 @@ Battle::AI::Handlers::MoveEffectScore.add("StartUserSideDoubleSpeed",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
# TODO: This code shouldn't make use of target.
|
||||
#
|
||||
#===============================================================================
|
||||
# StartSwapAllBattlersBaseDefensiveStats
|
||||
Battle::AI::Handlers::MoveEffectScore.add("StartSwapAllBattlersBaseDefensiveStats",
|
||||
proc { |score, move, user, ai, battle|
|
||||
any_change_matters = false
|
||||
ai.each_battler do |b, i|
|
||||
b_def = b.base_stat(:DEFENSE)
|
||||
b_spdef = b.base_stat(:SPECIAL_DEFENSE)
|
||||
next if b_def == b_spdef
|
||||
score_change = 0
|
||||
if b_def > b_spdef
|
||||
# Battler's Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(b, :DEFENSE, true)
|
||||
score_change -= (20 * ((b_def.to_f / b_spdef) - 1)).to_i
|
||||
any_change_matters = true
|
||||
end
|
||||
# Battler's Special Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(b, :SPECIAL_DEFENSE, true)
|
||||
score_change += (20 * ((b_def.to_f / b_spdef) - 1)).to_i
|
||||
any_change_matters = true
|
||||
end
|
||||
else
|
||||
# Battler's Special Defense will be lowered
|
||||
if ai.stat_drop_worthwhile?(b, :SPECIAL_DEFENSE, true)
|
||||
score_change -= (20 * ((b_spdef.to_f / b_def) - 1)).to_i
|
||||
any_change_matters = true
|
||||
end
|
||||
# Battler's Defense will be raised
|
||||
if ai.stat_raise_worthwhile?(b, :DEFENSE, true)
|
||||
score_change += (20 * ((b_spdef.to_f / b_def) - 1)).to_i
|
||||
any_change_matters = true
|
||||
end
|
||||
end
|
||||
score += (b.opposes?(user)) ? -score_change : score_change
|
||||
end
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !any_change_matters
|
||||
next Battle::AI::MOVE_USELESS_SCORE if score <= Battle::AI::MOVE_BASE_SCORE
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
@@ -1138,17 +1138,28 @@ Battle::AI::Handlers::MoveEffectScore.add("ProtectUserSideFromMultiTargetDamagin
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
# RemoveProtections
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("RemoveProtections",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
if target.check_for_move { |m| (m.is_a?(Battle::Move::ProtectMove) ||
|
||||
m.is_a?(Battle::Move::ProtectUserSideFromStatusMoves) ||
|
||||
m.is_a?(Battle::Move::ProtectUserSideFromDamagingMovesIfUserFirstTurn)) &&
|
||||
!m.is_a?(Battle::Move::UserEnduresFaintingThisTurn) }
|
||||
score += 5
|
||||
end
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
# RemoveProtectionsBypassSubstitute
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("RemoveProtectionsBypassSubstitute",
|
||||
"RemoveProtections")
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
|
||||
proc { |move, user, ai, battle|
|
||||
@@ -1157,6 +1168,8 @@ Battle::AI::Handlers::MoveFailureCheck.add("HoopaRemoveProtectionsBypassSubstitu
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("HoopaRemoveProtectionsBypassSubstituteLowerUserDef1",
|
||||
proc { |score, move, user, target, ai, battle|
|
||||
score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections",
|
||||
score, move, user, target, ai, battle)
|
||||
next ai.get_score_for_target_stat_drop(score, user, move.move.statDown, false)
|
||||
}
|
||||
)
|
||||
|
||||
@@ -241,8 +241,7 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("PowerUpAllyMove",
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
# TODO: This code shouldn't make use of target.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
|
||||
proc { |power, move, user, target, ai, battle|
|
||||
@@ -251,22 +250,30 @@ Battle::AI::Handlers::MoveBasePower.add("CounterPhysicalDamage",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("CounterPhysicalDamage",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
|
||||
attack = user.rough_stat(:ATTACK)
|
||||
spatk = user.rough_stat(:SPECIAL_ATTACK)
|
||||
if attack * 1.5 < spatk
|
||||
score -= 60
|
||||
# elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed
|
||||
# moveData = GameData::Move.get(target.battler.lastMoveUsed)
|
||||
# score += 60 if moveData.physical?
|
||||
has_physical_move = false
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.physicalMove?(m.type) &&
|
||||
(user.effects[PBEffects::Substitute] == 0 ||
|
||||
m.ignoresSubstitute?(b.battler)) }
|
||||
has_physical_move = true
|
||||
# Prefer if foe has a higher Attack than Special Attack
|
||||
score += 5 if b.rough_stat(:ATTACK) > b.rough_stat(:SPECIAL_ATTACK)
|
||||
# Prefer if the last move the foe used was physical
|
||||
if ai.trainer.medium_skill? && b.battler.lastMoveUsed
|
||||
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).physical?
|
||||
end
|
||||
# Prefer if the foe is taunted into using a damaging move
|
||||
score += 4 if b.effects[PBEffects::Taunt] > 0
|
||||
end
|
||||
# Useless if no foes have a physical move to counter
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_physical_move
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
# TODO: This code shouldn't make use of target.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
|
||||
proc { |power, move, user, target, ai, battle|
|
||||
@@ -275,22 +282,30 @@ Battle::AI::Handlers::MoveBasePower.add("CounterSpecialDamage",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("CounterSpecialDamage",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
|
||||
attack = user.rough_stat(:ATTACK)
|
||||
spatk = user.rough_stat(:SPECIAL_ATTACK)
|
||||
if attack > spatk * 1.5
|
||||
score -= 60
|
||||
# elsif ai.trainer.medium_skill? && target.battler.lastMoveUsed
|
||||
# moveData = GameData::Move.get(target.battler.lastMoveUsed)
|
||||
# score += 60 if moveData.special?
|
||||
has_special_move = false
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack?
|
||||
next if !b.check_for_move { |m| m.specialMove?(m.type) &&
|
||||
(user.effects[PBEffects::Substitute] == 0 ||
|
||||
m.ignoresSubstitute?(b.battler)) }
|
||||
has_special_move = true
|
||||
# Prefer if foe has a higher Special Attack than Attack
|
||||
score += 5 if b.rough_stat(:SPECIAL_ATTACK) > b.rough_stat(:ATTACK)
|
||||
# Prefer if the last move the foe used was special
|
||||
if ai.trainer.medium_skill? && b.battler.lastMoveUsed
|
||||
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).special?
|
||||
end
|
||||
# Prefer if the foe is taunted into using a damaging move
|
||||
score += 4 if b.effects[PBEffects::Taunt] > 0
|
||||
end
|
||||
# Useless if no foes have a special move to counter
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_special_move
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# TODO: Review score modifiers.
|
||||
# TODO: This code shouldn't make use of target.
|
||||
#
|
||||
#===============================================================================
|
||||
Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
|
||||
proc { |power, move, user, target, ai, battle|
|
||||
@@ -299,7 +314,23 @@ Battle::AI::Handlers::MoveBasePower.add("CounterDamagePlusHalf",
|
||||
)
|
||||
Battle::AI::Handlers::MoveEffectScore.add("CounterDamagePlusHalf",
|
||||
proc { |score, move, user, ai, battle|
|
||||
# next Battle::AI::MOVE_USELESS_SCORE if target.effects[PBEffects::HyperBeam] > 0
|
||||
has_damaging_move = false
|
||||
ai.each_foe_battler(user.side) do |b, i|
|
||||
next if !b.can_attack? || user.faster_than?(b)
|
||||
next if !b.check_for_move { |m| m.damagingMove? &&
|
||||
(user.effects[PBEffects::Substitute] == 0 ||
|
||||
m.ignoresSubstitute?(b.battler)) }
|
||||
has_damaging_move = true
|
||||
# Prefer if the last move the foe used was damaging
|
||||
if ai.trainer.medium_skill? && b.battler.lastMoveUsed
|
||||
score += 5 if GameData::Move.get(b.battler.lastMoveUsed).damaging?
|
||||
end
|
||||
# Prefer if the foe is taunted into using a damaging move
|
||||
score += 6 if b.effects[PBEffects::Taunt] > 0
|
||||
end
|
||||
# Useless if no foes have a damaging move to counter
|
||||
next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move
|
||||
next score
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user