mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 06:04:59 +00:00
AI function code rewrites for base stat changes, electrifying moves and multi-turn moves
This commit is contained in:
@@ -1424,88 +1424,205 @@ Battle::AI::Handlers::MoveEffectScore.add("ResetAllBattlersStatStages",
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowering",
|
Battle::AI::Handlers::MoveFailureCheck.add("StartUserSideImmunityToStatStageLowering",
|
||||||
proc { |move, user, ai, battle|
|
proc { |move, user, ai, battle|
|
||||||
next user.pbOwnSide.effects[PBEffects::Mist] > 0
|
next user.pbOwnSide.effects[PBEffects::Mist] > 0
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectScore.add("StartUserSideImmunityToStatStageLowering",
|
||||||
|
proc { |score, move, user, ai, battle|
|
||||||
|
has_move = false
|
||||||
|
ai.each_foe_battler(user.side) do |b, i|
|
||||||
|
if b.check_for_move { |m| m.is_a?(Battle::Move::TargetStatDownMove) ||
|
||||||
|
m.is_a?(Battle::Move::TargetMultiStatDownMove) ||
|
||||||
|
["LowerPoisonedTargetAtkSpAtkSpd1",
|
||||||
|
"PoisonTargetLowerTargetSpeed1",
|
||||||
|
"HealUserByTargetAttackLowerTargetAttack1"].include?(m.function) }
|
||||||
|
score += 10
|
||||||
|
has_move = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !has_move
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef",
|
Battle::AI::Handlers::MoveEffectScore.add("UserSwapBaseAtkDef",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
aatk = user.rough_stat(:ATTACK)
|
# No flip-flopping
|
||||||
adef = user.rough_stat(:DEFENSE)
|
next Battle::AI::MOVE_USELESS_SCORE if user.effects[PBEffects::PowerTrick]
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if aatk == adef || user.effects[PBEffects::PowerTrick] # No flip-flopping
|
# Check stats
|
||||||
if adef > aatk # Prefer a higher Attack
|
user_atk = user.base_stat(:ATTACK)
|
||||||
score += 20
|
user_def = user.base_stat(:DEFENSE)
|
||||||
else
|
next Battle::AI::MOVE_USELESS_SCORE if user_atk == user_def
|
||||||
score -= 20
|
# NOTE: Prefer to raise Attack regardless of the drop to Defense. Only
|
||||||
|
# prefer to raise Defense if Attack is useless.
|
||||||
|
if user_def > user_atk # Attack will be raised
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !ai.stat_raise_worthwhile?(user, :ATTACK, true)
|
||||||
|
score += (40 * ((user_def.to_f / user_atk) - 1)).to_i
|
||||||
|
score += 5 if !ai.stat_drop_worthwhile?(user, :DEFENSE, true) # No downside
|
||||||
|
else # Defense will be raised
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !ai.stat_raise_worthwhile?(user, :DEFENSE, true)
|
||||||
|
# Don't want to lower user's Attack if it can make use of it
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if ai.stat_drop_worthwhile?(user, :ATTACK, true)
|
||||||
|
score += (40 * ((user_atk.to_f / user_def) - 1)).to_i
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
# TODO: target should probably be treated as an enemy when deciding the score,
|
|
||||||
# since the score will be inverted elsewhere due to the target being an
|
|
||||||
# ally.
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapBaseSpeed",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetSwapBaseSpeed",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
if user.speed > target.speed
|
user_speed = user.base_stat(:SPEED)
|
||||||
score += 25
|
target_speed = target.base_stat(:SPEED)
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if user_speed == target_speed
|
||||||
|
if battle.field.effects[PBEffects::TrickRoom] > 1
|
||||||
|
# User wants to be slower so it can move first
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if target_speed > user_speed
|
||||||
|
score += (40 * ((user_speed.to_f / target_speed) - 1)).to_i
|
||||||
else
|
else
|
||||||
score -= 25
|
# User wants to be faster so it can move first
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if user_speed > target_speed
|
||||||
|
score += (40 * ((target_speed.to_f / user_speed) - 1)).to_i
|
||||||
end
|
end
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
# TODO: target should probably be treated as an enemy when deciding the score,
|
|
||||||
# since the score will be inverted elsewhere due to the target being an
|
|
||||||
# ally.
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtkSpAtk",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseAtkSpAtk",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
user_atk = user.battler.attack
|
user_atk = user.base_stat(:ATTACK)
|
||||||
user_spatk = user.battler.spatk
|
user_spatk = user.base_stat(:SPECIAL_ATTACK)
|
||||||
target_atk = target.battler.attack
|
target_atk = target.base_stat(:ATTACK)
|
||||||
target_spatk = target.battler.spatk
|
target_spatk = target.base_stat(:SPECIAL_ATTACK)
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if user_atk > target_atk && user_spatk > target_spatk
|
next Battle::AI::MOVE_USELESS_SCORE if user_atk >= target_atk && user_spatk >= target_spatk
|
||||||
if user_atk + user_spatk < target_atk + target_spatk
|
# Score based on changes to Attack
|
||||||
score += 20
|
atk_change_matters = false
|
||||||
else
|
if target_atk > user_atk
|
||||||
score -= 20
|
# 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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
end
|
||||||
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
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
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !atk_change_matters && !spatk_change_matters
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
# TODO: target should probably be treated as an enemy when deciding the score,
|
|
||||||
# since the score will be inverted elsewhere due to the target being an
|
|
||||||
# ally.
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDefSpDef",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDefSpDef",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
user_def = user.rough_stat(:DEFENSE)
|
user_def = user.base_stat(:DEFENSE)
|
||||||
user_spdef = user.rough_stat(:SPECIAL_DEFENSE)
|
user_spdef = user.base_stat(:SPECIAL_DEFENSE)
|
||||||
target_def = target.rough_stat(:DEFENSE)
|
target_def = target.base_stat(:DEFENSE)
|
||||||
target_spdef = target.rough_stat(:SPECIAL_DEFENSE)
|
target_spdef = target.base_stat(:SPECIAL_DEFENSE)
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if user_def > target_def && user_spdef > target_spdef
|
next Battle::AI::MOVE_USELESS_SCORE if user_def >= target_def && user_spdef >= target_spdef
|
||||||
if user_def + user_spdef < target_def + target_spdef
|
# Score based on changes to Defense
|
||||||
score += 20
|
def_change_matters = false
|
||||||
else
|
if target_def > user_def
|
||||||
score -= 20
|
# User's Defense will be raised
|
||||||
|
if ai.stat_raise_worthwhile?(user, :ATTACK, true)
|
||||||
|
score += (20 * ((target_def.to_f / user_def) - 1)).to_i
|
||||||
|
def_change_matters = true
|
||||||
|
end
|
||||||
|
# Target's Defense will be lowered
|
||||||
|
if ai.stat_drop_worthwhile?(target, :ATTACK, true)
|
||||||
|
score += (20 * ((target_def.to_f / user_def) - 1)).to_i
|
||||||
|
def_change_matters = true
|
||||||
|
end
|
||||||
|
elsif target_def < user_def
|
||||||
|
# User's Defense will be lowered
|
||||||
|
if ai.stat_drop_worthwhile?(user, :ATTACK, true)
|
||||||
|
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i
|
||||||
|
def_change_matters = true
|
||||||
|
end
|
||||||
|
# Target's Defense will be raised
|
||||||
|
if ai.stat_raise_worthwhile?(target, :ATTACK, true)
|
||||||
|
score -= (20 * ((user_def.to_f / target_def) - 1)).to_i
|
||||||
|
def_change_matters = true
|
||||||
|
end
|
||||||
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)
|
||||||
|
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i
|
||||||
|
spdef_change_matters = true
|
||||||
|
end
|
||||||
|
# Target's Special Defense will be lowered
|
||||||
|
if ai.stat_drop_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||||
|
score += (20 * ((target_spdef.to_f / user_spdef) - 1)).to_i
|
||||||
|
spdef_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)
|
||||||
|
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i
|
||||||
|
spdef_change_matters = true
|
||||||
|
end
|
||||||
|
# Target's Special Defense will be raised
|
||||||
|
if ai.stat_raise_worthwhile?(target, :SPECIAL_ATTACK, true)
|
||||||
|
score -= (20 * ((user_spdef.to_f / target_spdef) - 1)).to_i
|
||||||
|
spdef_change_matters = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !def_change_matters && !spdef_change_matters
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -1515,9 +1632,9 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageBaseDef
|
|||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageHP",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("UserTargetAverageHP",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if user.hp >= (user.hp + target.hp) / 2
|
next Battle::AI::MOVE_USELESS_SCORE if user.hp >= target.hp
|
||||||
mult = (user.hp + target.hp) / (2.0 * user.hp)
|
mult = (user.hp + target.hp) / (2.0 * user.hp)
|
||||||
score += 10 * mult if mult >= 1.2
|
score += (10 * mult).to_i if mult >= 1.2
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1138,18 +1138,82 @@ Battle::AI::Handlers::MoveBasePower.copy("TypeAndPowerDependOnWeather",
|
|||||||
"TypeAndPowerDependOnTerrain")
|
"TypeAndPowerDependOnTerrain")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TargetMovesBecomeElectric",
|
||||||
|
proc { |move, user, target, ai, battle|
|
||||||
|
next !user.faster_than?(target)
|
||||||
|
}
|
||||||
|
)
|
||||||
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric",
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TargetMovesBecomeElectric",
|
||||||
proc { |score, move, user, target, ai, battle|
|
proc { |score, move, user, target, ai, battle|
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if !user.faster_than?(target)
|
# Get Electric's effectiveness against the user
|
||||||
|
electric_eff = user.effectiveness_of_type_against_battler(:ELECTRIC, target)
|
||||||
|
electric_eff *= 1.5 if target.has_type?(:ELECTRIC) # STAB
|
||||||
|
electric_eff = 0 if user.has_active_ability?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB])
|
||||||
|
# For each of target's moves, get its effectiveness against the user and
|
||||||
|
# decide whether it is better or worse than Electric's effectiveness
|
||||||
|
old_type_better = 0
|
||||||
|
electric_type_better = 0
|
||||||
|
target.battler.eachMove do |m|
|
||||||
|
next if !m.damagingMove?
|
||||||
|
m_type = m.pbCalcType(target.battler)
|
||||||
|
next if m_type == :ELECTRIC
|
||||||
|
eff = user.effectiveness_of_type_against_battler(m_type, target)
|
||||||
|
eff *= 1.5 if target.has_type?(m_type) # STAB
|
||||||
|
case m_type
|
||||||
|
when :FIRE
|
||||||
|
eff = 0 if user.has_active_ability?(:FLASHFIRE)
|
||||||
|
when :GRASS
|
||||||
|
eff = 0 if user.has_active_ability?(:SAPSIPPER)
|
||||||
|
when :WATER
|
||||||
|
eff = 0 if user.has_active_ability?([:STORMDRAIN, :WATERABSORB])
|
||||||
|
end
|
||||||
|
if eff > electric_eff
|
||||||
|
electric_type_better += 1
|
||||||
|
elsif eff < electric_eff
|
||||||
|
old_type_better += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if electric_type_better == 0
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if electric_type_better < old_type_better
|
||||||
|
score += 10 * (electric_type_better - old_type_better)
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
# TODO: This could check all other battlers, not just foes. It could check the
|
||||||
# TODO: This code can be called with a single target and with no targets. Make
|
# effectivenesses of their Normal and Electric moves on all their foes,
|
||||||
# sure it doesn't assume that there is a target.
|
# not just on the user. I think this is overkill, particularly as the
|
||||||
|
# effect only lasts for one round.
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# NormalMovesBecomeElectric
|
Battle::AI::Handlers::MoveEffectScore.add("NormalMovesBecomeElectric",
|
||||||
|
proc { |score, move, user, ai, battle|
|
||||||
|
# Get Electric's effectiveness against the user
|
||||||
|
electric_eff = user.effectiveness_of_type_against_battler(:ELECTRIC, target)
|
||||||
|
electric_eff *= 1.5 if target.has_type?(:ELECTRIC) # STAB
|
||||||
|
electric_eff = 0 if user.has_active_ability?([:LIGHTNINGROD, :MOTORDRIVE, :VOLTABSORB])
|
||||||
|
# Check all affected foe battlers for Normal moves, get their effectiveness
|
||||||
|
# against the user and decide whether it is better or worse than Electric's
|
||||||
|
# effectiveness
|
||||||
|
normal_type_better = 0
|
||||||
|
electric_type_better = 0
|
||||||
|
ai.each_foe_battler(user.side) do |b, i|
|
||||||
|
next if move.pbPriority(b.battler) <= 0 && b.faster_than?(user)
|
||||||
|
next if !b.has_damaging_move_of_type?(:NORMAL)
|
||||||
|
eff = user.effectiveness_of_type_against_battler(:NORMAL, b)
|
||||||
|
eff *= 1.5 if b.has_type?(:NORMAL) # STAB
|
||||||
|
if eff > electric_eff
|
||||||
|
electric_type_better += 1
|
||||||
|
elsif eff < electric_eff
|
||||||
|
normal_type_better += 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if electric_type_better == 0 || electric_type_better < normal_type_better
|
||||||
|
next (move.statusMove?) ? Battle::AI::MOVE_USELESS_SCORE : score
|
||||||
|
end
|
||||||
|
score += 10 * (electric_type_better - normal_type_better)
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|||||||
@@ -206,10 +206,12 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttack",
|
|||||||
next score if user.has_active_item?(:POWERHERB)
|
next score if user.has_active_item?(:POWERHERB)
|
||||||
# Treat as a failure if user has Truant (the charging turn has no effect)
|
# Treat as a failure if user has Truant (the charging turn has no effect)
|
||||||
next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:TRUANT)
|
next Battle::AI::MOVE_USELESS_SCORE if user.has_active_ability?(:TRUANT)
|
||||||
|
# Useless if user will faint from EoR damage before finishing this attack
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if user.rough_end_of_round_damage >= user.hp
|
||||||
# Don't prefer because it uses up two turns
|
# Don't prefer because it uses up two turns
|
||||||
score -= 15
|
score -= 10
|
||||||
# Don't prefer if user is at a low HP (time is better spent on quicker moves)
|
# Don't prefer if user is at a low HP (time is better spent on quicker moves)
|
||||||
score -= 10 if user.hp < user.totalhp / 2
|
score -= 8 if user.hp < user.totalhp / 2
|
||||||
# Don't prefer if target has a protecting move
|
# Don't prefer if target has a protecting move
|
||||||
if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?)
|
if ai.trainer.high_skill? && !(user.has_active_ability?(:UNSEENFIST) && move.move.contactMove?)
|
||||||
has_protect_move = false
|
has_protect_move = false
|
||||||
@@ -356,27 +358,82 @@ Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackChargeRaise
|
|||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttackInvulnerableUnderground
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableUnderground",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Score for being a two turn attack
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Score for being semi-invulnerable underground
|
||||||
|
user.each_foe_battler(user.side) do |b, i|
|
||||||
|
if b.check_for_move { |m| m.hitsDiggingTargets? }
|
||||||
|
score -= 8
|
||||||
|
else
|
||||||
|
score += 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttackInvulnerableUnderwater
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableUnderwater",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Score for being a two turn attack
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Score for being semi-invulnerable underwater
|
||||||
|
user.each_foe_battler(user.side) do |b, i|
|
||||||
|
if b.check_for_move { |m| m.hitsDivingTargets? }
|
||||||
|
score -= 8
|
||||||
|
else
|
||||||
|
score += 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttackInvulnerableInSky
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableInSky",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Score for being a two turn attack
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Score for being semi-invulnerable in the sky
|
||||||
|
user.each_foe_battler(user.side) do |b, i|
|
||||||
|
if b.check_for_move { |m| m.hitsFlyingTargets? }
|
||||||
|
score -= 8
|
||||||
|
else
|
||||||
|
score += 5
|
||||||
|
end
|
||||||
|
end
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttackInvulnerableInSkyParalyzeTarget
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableInSkyParalyzeTarget",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
|
# Score for being a two turn attack and semi-invulnerable in the sky
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttackInvulnerableInSky",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
# Score for paralyzing the target
|
||||||
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("ParalyzeTarget",
|
||||||
|
score, move, user, target, ai, battle)
|
||||||
|
next score
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
|
Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerableInSkyTargetCannotAct",
|
||||||
proc { |move, user, target, ai, battle|
|
proc { |move, user, target, ai, battle|
|
||||||
@@ -387,34 +444,51 @@ Battle::AI::Handlers::MoveFailureAgainstTargetCheck.add("TwoTurnAttackInvulnerab
|
|||||||
next false
|
next false
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.copy("TwoTurnAttackInvulnerableInSky",
|
||||||
|
"TwoTurnAttackInvulnerableInSkyTargetCannotAct")
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TwoTurnAttackInvulnerableRemoveProtections
|
Battle::AI::Handlers::MoveEffectAgainstTargetScore.add("TwoTurnAttackInvulnerableRemoveProtections",
|
||||||
|
proc { |score, move, user, target, ai, battle|
|
||||||
#===============================================================================
|
# Score for being a two turn attack
|
||||||
# TODO: Review score modifiers.
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("TwoTurnAttack",
|
||||||
#===============================================================================
|
score, move, user, target, ai, battle)
|
||||||
# MultiTurnAttackPreventSleeping
|
# Score for being invulnerable
|
||||||
|
score += 5
|
||||||
#===============================================================================
|
# Score for removing protections
|
||||||
# TODO: Review score modifiers.
|
score = Battle::AI::Handlers.apply_move_effect_against_target_score("RemoveProtections",
|
||||||
#===============================================================================
|
score, move, user, target, ai, battle)
|
||||||
# MultiTurnAttackConfuseUserAtEnd
|
next score
|
||||||
|
|
||||||
#===============================================================================
|
|
||||||
# TODO: Review score modifiers.
|
|
||||||
#===============================================================================
|
|
||||||
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
|
|
||||||
proc { |power, move, user, target, ai, battle|
|
|
||||||
next move.move.pbBaseDamage(power, user.battler, target.battler)
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
# TODO: Review score modifiers.
|
#
|
||||||
# TODO: This code shouldn't make use of target.
|
#===============================================================================
|
||||||
|
# MultiTurnAttackPreventSleeping
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
# MultiTurnAttackConfuseUserAtEnd
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
|
#===============================================================================
|
||||||
|
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackPowersUpEachTurn",
|
||||||
|
proc { |power, move, user, target, ai, battle|
|
||||||
|
# NOTE: The * 2 (roughly) incorporates the higher damage done in subsequent
|
||||||
|
# rounds. It is nearly the average damage this move will do per round,
|
||||||
|
# assuming it hits for 3 rounds (hoping for hits in all 5 rounds is
|
||||||
|
# optimistic).
|
||||||
|
next move.move.pbBaseDamage(power, user.battler, target.battler) * 2
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
#===============================================================================
|
||||||
|
#
|
||||||
#===============================================================================
|
#===============================================================================
|
||||||
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
||||||
proc { |power, move, user, target, ai, battle|
|
proc { |power, move, user, target, ai, battle|
|
||||||
@@ -423,11 +497,19 @@ Battle::AI::Handlers::MoveBasePower.add("MultiTurnAttackBideThenReturnDoubleDama
|
|||||||
)
|
)
|
||||||
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
Battle::AI::Handlers::MoveEffectScore.add("MultiTurnAttackBideThenReturnDoubleDamage",
|
||||||
proc { |score, move, user, ai, battle|
|
proc { |score, move, user, ai, battle|
|
||||||
if user.hp <= user.totalhp / 4
|
# Useless if no foe has any damaging moves
|
||||||
score -= 90
|
has_damaging_move = false
|
||||||
elsif user.hp <= user.totalhp / 2
|
ai.each_foe_battler(user.side) do |b, i|
|
||||||
score -= 50
|
next if b.status == :SLEEP && b.statusCount > 2
|
||||||
|
next if b.status == :FROZEN
|
||||||
|
has_damaging_move = true if b.check_for_move { |m| m.damagingMove? }
|
||||||
|
break if has_damaging_move
|
||||||
end
|
end
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if !has_damaging_move
|
||||||
|
# Don't prefer if the user isn't at high HP
|
||||||
|
next Battle::AI::MOVE_USELESS_SCORE if user.hp <= user.totalhp / 4
|
||||||
|
score -= 15 if user.hp <= user.totalhp / 2
|
||||||
|
score -= 8 if user.hp <= user.totalhp * 3 / 4
|
||||||
next score
|
next score
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -168,20 +168,25 @@ class Battle::AI::AIBattler
|
|||||||
|
|
||||||
def speed; return @battler.speed; end
|
def speed; return @battler.speed; end
|
||||||
|
|
||||||
|
def base_stat(stat)
|
||||||
|
ret = 0
|
||||||
|
case stat
|
||||||
|
when :ATTACK then ret = @battler.attack
|
||||||
|
when :DEFENSE then ret = @battler.defense
|
||||||
|
when :SPECIAL_ATTACK then ret = @battler.spatk
|
||||||
|
when :SPECIAL_DEFENSE then ret = @battler.spdef
|
||||||
|
when :SPEED then ret = @battler.speed
|
||||||
|
end
|
||||||
|
return ret
|
||||||
|
end
|
||||||
|
|
||||||
# TODO: Cache calculated rough stats? Forget them in def refresh_battler.
|
# TODO: Cache calculated rough stats? Forget them in def refresh_battler.
|
||||||
def rough_stat(stat)
|
def rough_stat(stat)
|
||||||
return @battler.pbSpeed if stat == :SPEED && @ai.trainer.high_skill?
|
return @battler.pbSpeed if stat == :SPEED && @ai.trainer.high_skill?
|
||||||
stageMul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8]
|
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]
|
stageDiv = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2]
|
||||||
stage = @battler.stages[stat] + 6
|
stage = @battler.stages[stat] + 6
|
||||||
value = 0
|
value = base_stat(stat)
|
||||||
case stat
|
|
||||||
when :ATTACK then value = @battler.attack
|
|
||||||
when :DEFENSE then value = @battler.defense
|
|
||||||
when :SPECIAL_ATTACK then value = @battler.spatk
|
|
||||||
when :SPECIAL_DEFENSE then value = @battler.spdef
|
|
||||||
when :SPEED then value = @battler.speed
|
|
||||||
end
|
|
||||||
return (value.to_f * stageMul[stage] / stageDiv[stage]).floor
|
return (value.to_f * stageMul[stage] / stageDiv[stage]).floor
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user