mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
AI and other Gen 8 Effects (#123)
* Added Rattled being triggered by Intimidate in Gen 8 * Added Rapid Spin speed boost effect * Added basic AI for Gen 8 * Tweaked Leppa berry's effect * Added Ability Patch's exemption for Zygarde * Added Curse's Gen 8 targeting change * Added Teleport's Gen 8 effect * Added check for Choice items in Instruct and Dancer * Added Quash's Gen 8 change to the order that multiple Quashed Pokémon move in Co-authored-by: Maruno17 <serialcolour@hotmail.com>
This commit is contained in:
@@ -14,7 +14,7 @@ module Settings
|
||||
# Note that this isn't perfect. Essentials doesn't accurately replicate every
|
||||
# single generation's mechanics. It's considered to be good enough. Only
|
||||
# generations 5 and later are reasonably supported.
|
||||
MECHANICS_GENERATION = 7
|
||||
MECHANICS_GENERATION = 8
|
||||
|
||||
#=============================================================================
|
||||
|
||||
|
||||
@@ -91,6 +91,12 @@ class PokeBattle_Battler
|
||||
end
|
||||
end
|
||||
|
||||
# Used for Rattled's Gen 8 effect. Called when Intimidate is triggered.
|
||||
def pbAbilitiesOnIntimidated
|
||||
return if !abilityActive?
|
||||
BattleHandlers.triggerAbilityOnIntimidated(self.ability, self, @battle)
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Ability curing
|
||||
#=============================================================================
|
||||
|
||||
@@ -522,14 +522,16 @@ class PokeBattle_Battler
|
||||
next if idxMove<0
|
||||
oldLastRoundMoved = b.lastRoundMoved
|
||||
@battle.pbDisplay(_INTL("{1} used the move instructed by {2}!",b.pbThis,user.pbThis(true)))
|
||||
PBDebug.logonerr{
|
||||
b.effects[PBEffects::Instructed] = true
|
||||
b.pbUseMoveSimple(b.lastMoveUsed,b.lastRegularMoveTarget,idxMove,false)
|
||||
b.effects[PBEffects::Instructed] = false
|
||||
}
|
||||
b.lastRoundMoved = oldLastRoundMoved
|
||||
@battle.pbJudge
|
||||
return if @battle.decision>0
|
||||
b.effects[PBEffects::Instructed] = true
|
||||
if b.pbCanChooseMove?(@moves[idxMove], false)
|
||||
PBDebug.logonerr{
|
||||
b.pbUseMoveSimple(b.lastMoveUsed,b.lastRegularMoveTarget,idxMove,false)
|
||||
}
|
||||
b.lastRoundMoved = oldLastRoundMoved
|
||||
@battle.pbJudge
|
||||
return if @battle.decision>0
|
||||
end
|
||||
b.effects[PBEffects::Instructed] = false
|
||||
end
|
||||
# Dancer
|
||||
if !@effects[PBEffects::Dancer] && !user.lastMoveFailed && realNumHits>0 &&
|
||||
@@ -556,16 +558,18 @@ class PokeBattle_Battler
|
||||
@battle.pbDisplay(_INTL("{1} kept the dance going with {2}!",
|
||||
nextUser.pbThis,nextUser.abilityName))
|
||||
end
|
||||
PBDebug.logonerr{
|
||||
nextUser.effects[PBEffects::Dancer] = true
|
||||
nextUser.pbUseMoveSimple(move.id,preTarget)
|
||||
nextUser.effects[PBEffects::Dancer] = false
|
||||
}
|
||||
nextUser.lastRoundMoved = oldLastRoundMoved
|
||||
nextUser.effects[PBEffects::Outrage] = oldOutrage
|
||||
nextUser.currentMove = oldCurrentMove
|
||||
@battle.pbJudge
|
||||
return if @battle.decision>0
|
||||
nextUser.effects[PBEffects::Dancer] = true
|
||||
if nextUser.pbCanChooseMove?(move, false)
|
||||
PBDebug.logonerr{
|
||||
nextUser.pbUseMoveSimple(move.id,preTarget)
|
||||
}
|
||||
nextUser.lastRoundMoved = oldLastRoundMoved
|
||||
nextUser.effects[PBEffects::Outrage] = oldOutrage
|
||||
nextUser.currentMove = oldCurrentMove
|
||||
@battle.pbJudge
|
||||
return if @battle.decision>0
|
||||
end
|
||||
nextUser.effects[PBEffects::Dancer] = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -90,6 +90,7 @@ module BattleHandlers
|
||||
AbilityOnSwitchOut = AbilityHandlerHash.new
|
||||
AbilityChangeOnBattlerFainting = AbilityHandlerHash.new
|
||||
AbilityOnBattlerFainting = AbilityHandlerHash.new # Soul-Heart
|
||||
AbilityOnIntimidated = AbilityHandlerHash.new # Rattled (Gen 8)
|
||||
# Running from battle
|
||||
RunFromBattleAbility = AbilityHandlerHash.new # Run Away
|
||||
RunFromBattleItem = ItemHandlerHash.new # Smoke Ball
|
||||
@@ -463,6 +464,10 @@ module BattleHandlers
|
||||
AbilityOnBattlerFainting.trigger(ability,battler,fainted,battle)
|
||||
end
|
||||
|
||||
def self.triggerAbilityOnIntimidated(ability,battler,battle)
|
||||
AbilityOnIntimidated.trigger(ability,battler,battle)
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
def self.triggerRunFromBattleAbility(ability,battler)
|
||||
|
||||
@@ -2983,20 +2983,43 @@ end
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# User flees from battle. Fails in trainer battles. (Teleport)
|
||||
# User flees from battle (but in Gen 8+, only when user is a wild Pokémon).
|
||||
# In Gen 8+, user switches out (except if user is a wild Pokémon). (Teleport)
|
||||
#===============================================================================
|
||||
class PokeBattle_Move_0EA < PokeBattle_Move
|
||||
def pbMoveFailed?(user,targets)
|
||||
if !@battle.pbCanRun?(user.index)
|
||||
if Settings::MECHANICS_GENERATION < 8 || (@battle.wildBattle? && user.opposes?)
|
||||
if !@battle.pbCanRun?(user.index)
|
||||
@battle.pbDisplay(_INTL("But it failed!"))
|
||||
return true
|
||||
end
|
||||
elsif !@battle.pbCanChooseNonActive?(user.index)
|
||||
@battle.pbDisplay(_INTL("But it failed!"))
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
|
||||
return if Settings::MECHANICS_GENERATION < 8 || (@battle.wildBattle? && user.opposes?)
|
||||
@battle.pbDisplay(_INTL("{1} went back to {2}!",user.pbThis,
|
||||
@battle.pbGetOwnerName(user.index)))
|
||||
@battle.pbPursuit(user.index)
|
||||
return if user.fainted?
|
||||
newPkmn = @battle.pbGetReplacementPokemonIndex(user.index) # Owner chooses
|
||||
return if newPkmn<0
|
||||
@battle.pbRecallAndReplace(user.index,newPkmn)
|
||||
@battle.pbClearChoice(user.index) # Replacement Pokémon does nothing this round
|
||||
@battle.moldBreaker = false
|
||||
switchedBattlers.push(user.index)
|
||||
user.pbEffectsOnSwitchIn(true)
|
||||
end
|
||||
|
||||
def pbEffectGeneral(user)
|
||||
@battle.pbDisplay(_INTL("{1} fled from battle!",user.pbThis))
|
||||
@battle.decision = 3 # Escaped
|
||||
if Settings::MECHANICS_GENERATION < 8 || (@battle.wildBattle? && user.opposes?)
|
||||
@battle.pbDisplay(_INTL("{1} fled from battle!",user.pbThis))
|
||||
@battle.decision = 3 # Escaped
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -269,7 +269,10 @@ class PokeBattle_Move_10D < PokeBattle_Move
|
||||
def ignoresSubstitute?(user); return true; end
|
||||
|
||||
def pbTarget(user)
|
||||
return GameData::Target.get(:NearFoe) if user.pbHasType?(:GHOST)
|
||||
if user.pbHasType?(:GHOST)
|
||||
ghost_target = (Settings::MECHANICS_GENERATION >= 8) ? :RandomNearFoe : :NearFoe
|
||||
return GameData::Target.get(ghost_target)
|
||||
end
|
||||
return super
|
||||
end
|
||||
|
||||
@@ -375,9 +378,14 @@ end
|
||||
|
||||
#===============================================================================
|
||||
# Removes trapping moves, entry hazards and Leech Seed on user/user's side.
|
||||
# (Rapid Spin)
|
||||
# Raises user's Speed by 1 stage (Gen 8+). (Rapid Spin)
|
||||
#===============================================================================
|
||||
class PokeBattle_Move_110 < PokeBattle_Move
|
||||
class PokeBattle_Move_110 < PokeBattle_StatUpMove
|
||||
def initialize(battle,move)
|
||||
super
|
||||
@statUp = [:SPEED, 1]
|
||||
end
|
||||
|
||||
def pbEffectAfterAllHits(user,target)
|
||||
return if user.fainted? || target.damageState.unaffected
|
||||
if user.effects[PBEffects::Trapping]>0
|
||||
@@ -409,6 +417,10 @@ class PokeBattle_Move_110 < PokeBattle_Move
|
||||
@battle.pbDisplay(_INTL("{1} blew away sticky webs!",user.pbThis))
|
||||
end
|
||||
end
|
||||
|
||||
def pbAdditionalEffect(user,target)
|
||||
super if Settings::MECHANICS_GENERATION >= 8
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
@@ -129,19 +129,29 @@ class PokeBattle_Battle
|
||||
return if @decision>0
|
||||
next if advance
|
||||
# Quashed
|
||||
quashLevel = 0
|
||||
loop do
|
||||
quashLevel += 1
|
||||
moreQuash = false
|
||||
if Settings::MECHANICS_GENERATION >= 8
|
||||
priority.each do |b|
|
||||
moreQuash = true if b.effects[PBEffects::Quash]>quashLevel
|
||||
next unless b.effects[PBEffects::Quash]==quashLevel && !b.fainted?
|
||||
next unless b.effects[PBEffects::Quash] > 0 && !b.fainted?
|
||||
next unless @choices[b.index][0]==:UseMove || @choices[b.index][0]==:Shift
|
||||
next if b.movedThisRound?
|
||||
advance = b.pbProcessTurn(@choices[b.index])
|
||||
break
|
||||
break if advance
|
||||
end
|
||||
else
|
||||
quashLevel = 0
|
||||
loop do
|
||||
quashLevel += 1
|
||||
moreQuash = false
|
||||
priority.each do |b|
|
||||
moreQuash = true if b.effects[PBEffects::Quash]>quashLevel
|
||||
next unless b.effects[PBEffects::Quash]==quashLevel && !b.fainted?
|
||||
next unless @choices[b.index][0]==:UseMove || @choices[b.index][0]==:Shift
|
||||
next if b.movedThisRound?
|
||||
advance = b.pbProcessTurn(@choices[b.index])
|
||||
break
|
||||
end
|
||||
break if advance || !moreQuash
|
||||
end
|
||||
break if advance || !moreQuash
|
||||
end
|
||||
return if @decision>0
|
||||
next if advance
|
||||
|
||||
@@ -2285,7 +2285,8 @@ BattleHandlers::AbilityOnSwitchIn.add(:INTIMIDATE,
|
||||
else
|
||||
check_item = false if b.statStageAtMin?(:ATTACK)
|
||||
end
|
||||
b.pbLowerAttackStatStageIntimidate(battler)
|
||||
check_ability = b.pbLowerAttackStatStageIntimidate(battler)
|
||||
b.pbAbilitiesOnIntimidated if check_ability
|
||||
b.pbItemOnIntimidatedCheck if check_item
|
||||
end
|
||||
battle.pbHideAbilitySplash(battler)
|
||||
@@ -2474,6 +2475,17 @@ BattleHandlers::AbilityOnBattlerFainting.add(:SOULHEART,
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# AbilityOnIntimidated handlers
|
||||
#===============================================================================
|
||||
|
||||
BattleHandlers::AbilityOnIntimidated.add(:RATTLED,
|
||||
proc { |ability,battler,battle|
|
||||
next if Settings::MECHANICS_GENERATION < 8
|
||||
battler.pbRaiseStatStageByAbility(:SPEED, 1, battler)
|
||||
}
|
||||
)
|
||||
|
||||
#===============================================================================
|
||||
# RunFromBattleAbility handlers
|
||||
#===============================================================================
|
||||
|
||||
@@ -191,7 +191,8 @@ class PokeBattle_AI
|
||||
score -= 80 if miss
|
||||
end
|
||||
# Pick a good move for the Choice items
|
||||
if user.hasActiveItem?([:CHOICEBAND,:CHOICESPECS,:CHOICESCARF])
|
||||
if user.hasActiveItem?([:CHOICEBAND,:CHOICESPECS,:CHOICESCARF]) ||
|
||||
user.hasActiveAbility?(:GORILLATACTICS)
|
||||
if move.baseDamage>=60; score += 60
|
||||
elsif move.damagingMove?; score += 30
|
||||
elsif move.function=="0F2"; score += 70 # Trick
|
||||
|
||||
@@ -269,6 +269,8 @@ class PokeBattle_AI
|
||||
atk = pbRoughStat(user,:ATTACK,skill)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,:ATTACK,skill)
|
||||
elsif move.function=="197" # Body Press
|
||||
atk = pbRoughStat(user,:DEFENSE,skill)
|
||||
elsif move.specialMove?(type)
|
||||
if move.function=="121" # Foul Play
|
||||
atk = pbRoughStat(target,:SPECIAL_ATTACK,skill)
|
||||
|
||||
373
Data/Scripts/011_Battle/004_AI/007_AI_Move_EffectScores_Gen8.rb
Normal file
373
Data/Scripts/011_Battle/004_AI/007_AI_Move_EffectScores_Gen8.rb
Normal file
@@ -0,0 +1,373 @@
|
||||
class PokeBattle_AI
|
||||
#=============================================================================
|
||||
# Get a score for the given move based on its effect
|
||||
#=============================================================================
|
||||
alias gen8_pbGetMoveScoreFunctionCode pbGetMoveScoreFunctionCode
|
||||
def pbGetMoveScoreFunctionCode(score,move,user,target,skill = 100)
|
||||
score = gen8_pbGetMoveScoreFunctionCode(score,move,user,target,skill)
|
||||
case move.function
|
||||
when "176"
|
||||
score += 5 if target.pbCanPoison?(user, false)
|
||||
#---------------------------------------------------------------------------
|
||||
when "177"
|
||||
if target.pbCanBurn?(user, false)
|
||||
score += 40
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
score -= 40 if target.hasActiveAbility?([:GUTS, :MARVELSCALE, :QUICKFEET, :FLAREBOOST])
|
||||
end
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "178"
|
||||
score += 20 if user.stages[:SPEED] <= 0
|
||||
#---------------------------------------------------------------------------
|
||||
when "179"
|
||||
if user.effects[PBEffects::NoRetreat]
|
||||
score -= 100
|
||||
elsif user.hasActiveAbility?(:CONTRARY)
|
||||
score -= 100
|
||||
else
|
||||
stats_maxed = true
|
||||
GameData::Stat.each_main_battle do |s|
|
||||
next if user.statStageAtMax?(s.id)
|
||||
stats_maxed = false
|
||||
break
|
||||
end
|
||||
if stats_maxed
|
||||
score -= 100
|
||||
else
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
score -= 50 if user.hp <= user.totalhp / 2
|
||||
score += 30 if user.trappedInBattle?
|
||||
end
|
||||
GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] <= 0 }
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
hasDamagingAttack = user.moves.any? { |m| next m && m.damagingMove? }
|
||||
score += 20 if hasDamagingAttack
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "17A"
|
||||
if user.hp <= user.totalhp / 2
|
||||
score -= 100
|
||||
elsif user.hasActiveAbility?(:CONTRARY)
|
||||
score -= 100
|
||||
else
|
||||
stats_maxed = true
|
||||
GameData::Stat.each_main_battle do |s|
|
||||
next if user.statStageAtMax?(s.id)
|
||||
stats_maxed = false
|
||||
break
|
||||
end
|
||||
if stats_maxed
|
||||
score -= 100
|
||||
else
|
||||
if skill >= PBTrainerAI.highSkill && user.hp >= user.totalhp * 0.75
|
||||
score += 30
|
||||
end
|
||||
GameData::Stat.each_main_battle { |s| score += 10 if user.stages[s.id] <= 0 }
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
hasDamagingAttack = user.moves.any? { |m| next m && m.damagingMove? }
|
||||
score += 20 if hasDamagingAttack
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "17B"
|
||||
has_ally = false
|
||||
user.eachAlly do |b|
|
||||
next if !b.pbCanLowerStatStage?(:ATTACK, user) &&
|
||||
!b.pbCanLowerStatStage?(:SPECIAL_ATTACK, user)
|
||||
has_ally = true
|
||||
if skill >= PBTrainerAI.mediumSkill && b.hasActiveAbility?(:CONTRARY)
|
||||
score -= 90
|
||||
else
|
||||
score += 40
|
||||
score -= b.stages[:ATTACK] * 20
|
||||
score -= b.stages[:SPECIAL_ATTACK] * 20
|
||||
end
|
||||
end
|
||||
score = 0 if !has_ally
|
||||
#---------------------------------------------------------------------------
|
||||
when "17C"
|
||||
if target.opposes?(user)
|
||||
score -= 100
|
||||
elsif skill >= PBTrainerAI.mediumSkill && target.hasActiveAbility?(:CONTRARY)
|
||||
score -= 90
|
||||
else
|
||||
score -= target.stages[:ATTACK] * 20
|
||||
score -= target.stages[:SPECIAL_ATTACK] * 20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "17D"
|
||||
if !target.pbCanLowerStatStage?(:DEFENSE, user)
|
||||
score -= 90
|
||||
else
|
||||
score += 20
|
||||
score += target.stages[:DEFENSE] * 20
|
||||
end
|
||||
score += 30 if @battle.field.effects[PBEffects::Gravity] > 0
|
||||
#---------------------------------------------------------------------------
|
||||
when "17E"
|
||||
if !target.pbCanLowerStatStage?(:SPEED, user) && target.effects[PBEffects::TarShot]
|
||||
score -= 100
|
||||
else
|
||||
score += target.stages[:SPEED] * 10
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
aspeed = pbRoughStat(user, :SPEED, skill)
|
||||
ospeed = pbRoughStat(target, :SPEED, skill)
|
||||
score += 50 if aspeed < ospeed && aspeed * 2 > ospeed
|
||||
end
|
||||
end
|
||||
score += 20 if user.moves.any? { |m| m.damagingMove? && m.pbCalcType(user) == :FIRE }
|
||||
#---------------------------------------------------------------------------
|
||||
when "17F"
|
||||
if target.pbHasOtherType?(:PSYCHIC)
|
||||
score -= 90
|
||||
elsif !target.canChangeType?
|
||||
score -= 90
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "180"
|
||||
score += 40 if @battle.field.terrain == :Electric && target.affectedByTerrain?
|
||||
#---------------------------------------------------------------------------
|
||||
when "181"
|
||||
score += 40 if @battle.field.terrain == :Psychic && user.affectedByTerrain?
|
||||
#---------------------------------------------------------------------------
|
||||
when "182"
|
||||
score += 40 if @battle.field.terrain != :None
|
||||
#---------------------------------------------------------------------------
|
||||
when "183"
|
||||
#---------------------------------------------------------------------------
|
||||
when "184"
|
||||
#---------------------------------------------------------------------------
|
||||
when "185"
|
||||
if skill >= PBTrainerAI.mediumSkill && @battle.field.terrain == :Grassy
|
||||
aspeed = pbRoughStat(user, :SPEED, skill)
|
||||
ospeed = pbRoughStat(target, :SPEED, skill)
|
||||
score += 40 if aspeed < ospeed
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "186"
|
||||
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]
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "187"
|
||||
redirection = false
|
||||
user.eachOpposing do |b|
|
||||
next if b.index == target.index
|
||||
if b.effects[PBEffects::RagePowder] ||
|
||||
b.effects[PBEffects::Spotlight] > 0 ||
|
||||
b.effects[PBEffects::FollowMe] > 0 ||
|
||||
(b.hasActiveAbility?(:LIGHTNINGROD) && move.pbCalcType == :ELECTRIC) ||
|
||||
(b.hasActiveAbility?(:STORMDRAIN) && move.pbCalcType == :WATER)
|
||||
redirection = true
|
||||
break
|
||||
end
|
||||
end
|
||||
score += 50 if redirection && skill >= PBTrainerAI.mediumSkill
|
||||
#---------------------------------------------------------------------------
|
||||
when "188"
|
||||
#---------------------------------------------------------------------------
|
||||
when "189"
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
stat = (move.physicalMove?)? :DEFENSE : :SPECIAL_DEFENSE
|
||||
score += 50 if targets.stages[stat] > 1
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "18A"
|
||||
aspeed = pbRoughStat(user, :SPEED, skill)
|
||||
ospeed = pbRoughStat(target, :SPEED, skill)
|
||||
if aspeed > ospeed && aspeed * 2 / 3 < ospeed
|
||||
score -= 50
|
||||
elsif aspeed < ospeed && aspeed * 1.5 > ospeed
|
||||
score += 50
|
||||
end
|
||||
score += user.stages[:DEFENSE] * 30
|
||||
#---------------------------------------------------------------------------
|
||||
when "18B"
|
||||
aspeed = pbRoughStat(user, :SPEED, skill)
|
||||
ospeed = pbRoughStat(target, :SPEED, skill)
|
||||
if (aspeed > ospeed && user.hp > user.totalhp / 3) || user.hp > user.totalhp / 2
|
||||
score += 60
|
||||
else
|
||||
score -= 90
|
||||
end
|
||||
score += user.stages[:SPECIAL_ATTACK] * 20
|
||||
#---------------------------------------------------------------------------
|
||||
when "18C"
|
||||
ally_amt = 30
|
||||
@battle.eachSameSideBattler(user.index) do |b|
|
||||
if b.hp == b.totalhp || (skill >= PBTrainerAI.mediumSkill && !b.canHeal?)
|
||||
score -= ally_amt / 2
|
||||
elsif b.hp < b.totalhp * 3 / 4
|
||||
score += ally_amt
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "18D"
|
||||
ally_amt = 80 / @battle.pbSideSize(user.index)
|
||||
@battle.eachSameSideBattler(user.index) do |b|
|
||||
if b.hp == b.totalhp || (skill >= PBTrainerAI.mediumSkill && !b.canHeal?)
|
||||
score -= ally_amt
|
||||
elsif b.hp < b.totalhp * 3 / 4
|
||||
score += ally_amt
|
||||
end
|
||||
score += ally_amt / 2 if b.pbHasAnyStatus?
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "18E"
|
||||
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 += 40 # want to draw
|
||||
score += 40 if @battle.field.terrain == :Misty
|
||||
else
|
||||
score -= user.hp * 100 / user.totalhp
|
||||
score += 20 if @battle.field.terrain == :Misty
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "18F"
|
||||
if target.effects[PBEffects::Octolock] >= 0
|
||||
score -= 100
|
||||
else
|
||||
score += 30 if !target.trappedInBattle?
|
||||
score -= 100 if !target.pbCanLowerStatStage?(:DEFENSE, user, move) &&
|
||||
!target.pbCanLowerStatStage?(:SPECIAL_DEFENSE, user, move)
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "190"
|
||||
if target.effects[PBEffects::JawLock] < 0
|
||||
score += 40 if !user.trappedInBattle? && !target.trappedInBattle?
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "191"
|
||||
if !user.item || !user.item.is_berry? || !user.itemActive?
|
||||
score -= 100
|
||||
else
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
useful_berries = [
|
||||
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
|
||||
:CHESTOBERRY, :FIGYBERRY, :GANLONBERRY, :IAPAPABERRY, :KEEBERRY,
|
||||
:LANSATBERRY, :LEPPABERRY, :LIECHIBERRY, :LUMBERRY, :MAGOBERRY,
|
||||
:MARANGABERRY, :PECHABERRY, :PERSIMBERRY, :PETAYABERRY, :RAWSTBERRY,
|
||||
:SALACBERRY, :STARFBERRY, :WIKIBERRY
|
||||
]
|
||||
score += 30 if useful_berries.include?(user.item_id)
|
||||
end
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
score += 20 if user.canHeal? && user.hp < user.totalhp / 3 && user.hasActiveAbility?(:CHEEKPOUCH)
|
||||
score += 20 if user.hasActiveAbility?([:HARVEST, :RIPEN]) ||
|
||||
user.pbHasMoveFunction?("0F6") # Recycle
|
||||
score += 20 if !user.canConsumeBerry?
|
||||
end
|
||||
score -= user.stages[:DEFENSE] * 20
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "192"
|
||||
useful_berries = [
|
||||
:ORANBERRY, :SITRUSBERRY, :AGUAVBERRY, :APICOTBERRY, :CHERIBERRY,
|
||||
:CHESTOBERRY, :FIGYBERRY, :GANLONBERRY, :IAPAPABERRY, :KEEBERRY,
|
||||
:LANSATBERRY, :LEPPABERRY, :LIECHIBERRY, :LUMBERRY, :MAGOBERRY,
|
||||
:MARANGABERRY, :PECHABERRY, :PERSIMBERRY, :PETAYABERRY,
|
||||
:RAWSTBERRY, :SALACBERRY, :STARFBERRY, :WIKIBERRY
|
||||
]
|
||||
@battle.eachSameSideBattler(user.index) do |b|
|
||||
if !b.item || !b.item.is_berry? || !b.itemActive?
|
||||
score -= 100 / @battle.pbSideSize(user.index)
|
||||
else
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
amt = 30 / @battle.pbSideSize(user.index)
|
||||
score += amt if useful_berries.include?(b.item_id)
|
||||
end
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
amt = 20 / @battle.pbSideSize(user.index)
|
||||
score += amt if b.canHeal? && b.hp < b.totalhp / 3 && b.hasActiveAbility?(:CHEEKPOUCH)
|
||||
score += amt if b.hasActiveAbility?([:HARVEST, :RIPEN]) ||
|
||||
b.pbHasMoveFunction?("0F6") # Recycle
|
||||
score += amt if !b.canConsumeBerry?
|
||||
end
|
||||
end
|
||||
end
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
@battle.eachOtherSideBattler(user.index) do |b|
|
||||
amt = 10 / @battle.pbSideSize(target.index)
|
||||
score -= amt if b.hasActiveItem?(useful_berries)
|
||||
score -= amt if b.canHeal? && b.hp < b.totalhp / 3 && b.hasActiveAbility?(:CHEEKPOUCH)
|
||||
score -= amt if b.hasActiveAbility?([:HARVEST, :RIPEN]) ||
|
||||
b.pbHasMoveFunction?("0F6") # Recycle
|
||||
score -= amt if !b.canConsumeBerry?
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "193"
|
||||
if @battle.corrosiveGas[target.index % 2][target.pokemonIndex]
|
||||
score -= 100
|
||||
elsif !target.item || !target.itemActive? || target.unlosableItem?(target.item) ||
|
||||
target.hasActiveAbility?(:STICKYHOLD)
|
||||
score -= 90
|
||||
elsif target.effects[PBEffects::Substitute] > 0
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "194"
|
||||
score -= 100 if user.hp <= user.totalhp / 2
|
||||
#---------------------------------------------------------------------------
|
||||
when "195"
|
||||
last_move = target.pbGetMoveWithID(target.lastRegularMoveUsed)
|
||||
if last_move && last_move.total_pp > 0 && last_move.pp <= 3
|
||||
score += 50
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "196"
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
if !target.item || !target.itemActive?
|
||||
score -= 90
|
||||
else
|
||||
score += 50
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "197"
|
||||
#---------------------------------------------------------------------------
|
||||
when "198"
|
||||
if skill >= PBTrainerAI.mediumSkill
|
||||
good_effects = [:Reflect, :LightScreen, :AuroraVeil, :SeaOfFire,
|
||||
:Swamp, :Rainbow, :Mist, :Safeguard,
|
||||
:Tailwind].map! { |e| PBEffects.const_get(e) }
|
||||
bad_effects = [:Spikes, :StickyWeb, :ToxicSpikes, :StealthRock].map! { |e| PBEffects.const_get(e) }
|
||||
bad_effects.each do |e|
|
||||
score += 10 if ![0, false, nil].include?(user.pbOwnSide.effects[e])
|
||||
score -= 10 if ![0, 1, false, nil].include?(user.pbOpposingSide.effects[e])
|
||||
end
|
||||
if skill >= PBTrainerAI.highSkill
|
||||
good_effects.each do |e|
|
||||
score += 10 if ![0, 1, false, nil].include?(user.pbOpposingSide.effects[e])
|
||||
score -= 10 if ![0, false, nil].include?(user.pbOwnSide.effects[e])
|
||||
end
|
||||
end
|
||||
end
|
||||
#---------------------------------------------------------------------------
|
||||
when "199"
|
||||
score -= 100 if @battle.field.terrain == :None
|
||||
#---------------------------------------------------------------------------
|
||||
end
|
||||
return score
|
||||
end
|
||||
end
|
||||
@@ -1283,26 +1283,27 @@ BattleHandlers::UserItemAfterMoveUse.add(:SHELLBELL,
|
||||
BattleHandlers::EndOfMoveItem.add(:LEPPABERRY,
|
||||
proc { |item,battler,battle,forced|
|
||||
next false if !forced && !battler.canConsumeBerry?
|
||||
found = []
|
||||
battler.pokemon.moves.each_with_index do |m,i|
|
||||
next if m.total_pp<=0 || m.pp==m.total_pp
|
||||
next if !forced && m.pp>0
|
||||
found.push(i)
|
||||
found_empty_moves = []
|
||||
found_partial_moves = []
|
||||
battler.pokemon.moves.each_with_index do |move, i|
|
||||
next if move.total_pp <= 0 || move.pp == move.total_pp
|
||||
(move.pp == 0) ? found_empty_moves.push(i) : found_partial_moves.push(i)
|
||||
end
|
||||
next false if found.length==0
|
||||
next false if found_empty_moves.empty? && (!forced || found_partial_moves.empty?)
|
||||
itemName = GameData::Item.get(item).name
|
||||
PBDebug.log("[Item triggered] #{battler.pbThis}'s #{itemName}") if forced
|
||||
battle.pbCommonAnimation("EatBerry",battler) if !forced
|
||||
choice = found[battle.pbRandom(found.length)]
|
||||
battle.pbCommonAnimation("EatBerry", battler) if !forced
|
||||
choice = found_empty_moves.first
|
||||
choice = found_partial_moves.first if forced && choice.nil?
|
||||
pkmnMove = battler.pokemon.moves[choice]
|
||||
pkmnMove.pp += 10
|
||||
pkmnMove.pp = pkmnMove.total_pp if pkmnMove.pp>pkmnMove.total_pp
|
||||
pkmnMove.pp = pkmnMove.total_pp if pkmnMove.pp > pkmnMove.total_pp
|
||||
battler.moves[choice].pp = pkmnMove.pp
|
||||
moveName = pkmnMove.name
|
||||
if forced
|
||||
battle.pbDisplay(_INTL("{1} restored its {2}'s PP.",battler.pbThis,moveName))
|
||||
battle.pbDisplay(_INTL("{1} restored its {2}'s PP.", battler.pbThis, moveName))
|
||||
else
|
||||
battle.pbDisplay(_INTL("{1}'s {2} restored its {3}'s PP!",battler.pbThis,itemName,moveName))
|
||||
battle.pbDisplay(_INTL("{1}'s {2} restored its {3}'s PP!", battler.pbThis, itemName, moveName))
|
||||
end
|
||||
next true
|
||||
}
|
||||
|
||||
@@ -272,7 +272,7 @@ ItemHandlers::UseOnPokemon.add(:ABILITYPATCH, proc { |item, pkmn, scene|
|
||||
abils = pkmn.getAbilityList
|
||||
new_ability_id = nil
|
||||
abils.each { |a| new_ability_id = a[0] if a[1] == 2 }
|
||||
if !new_ability_id || pkmn.hasHiddenAbility?
|
||||
if !new_ability_id || pkmn.hasHiddenAbility? || pkmn.isSpecies?(:ZYGARDE)
|
||||
scene.pbDisplay(_INTL("It won't have any effect."))
|
||||
next false
|
||||
end
|
||||
|
||||
@@ -7,32 +7,22 @@
|
||||
The game records, for each species, how many have been caught or defeated
|
||||
(counts both wild and trainer battles), and the shiny chance increases for that
|
||||
species because of this. This value is also shown in the Pokédex entry screen.
|
||||
(Will be implemented by me in the next PR)
|
||||
|
||||
Some moves have changed properties/effects:
|
||||
- Rapid Spin now raises the user's Speed by 1 stage (100% additional effect
|
||||
chance).
|
||||
- Howl's target changed to UserAndAllies, and is now a sound move. It is now
|
||||
blocked by Soundproof (I don't know if it should be checking the allies for
|
||||
pbImmunityByAbility, but leaning towards yes; will Volt Absorb block an
|
||||
Electrified Howl?). Needs a new function code, since it now affects targets
|
||||
rather than the user.
|
||||
- Teleport switches the user out. If the user is a wild Pokémon, ends the battle
|
||||
instead.
|
||||
- Curse's Ghost effect now targets a random foe (don't know if it can be non-
|
||||
adjacent); the target cannot be chosen by the player (it appears to target the
|
||||
user).
|
||||
- Look at the moves Nature Power turns into.
|
||||
- Healing Wish's effect and Lunar Dance's effect are no longer used up if a
|
||||
Pokémon that switches to the targeted position can't make use of it. Each
|
||||
position can only have one of each effect applied at once.
|
||||
- Multiple Quashed Pokémon now move in order from fastest to slowest, rather
|
||||
than the order in which they were Quashed.
|
||||
position can only have one of each effect applied at once. (Will be implemented by me in the next PR)
|
||||
- Parting Shot is able to make the user switch out if its effect is redirected
|
||||
by Mirror Armor. Throat Spray is triggered and applies before the switch.
|
||||
(The Throat Spray part is done by default)
|
||||
|
||||
Some abilities have changed effects:
|
||||
- Intimidate now triggers Rattled. Rattled needs a new ability handler just for
|
||||
triggering this way.
|
||||
- If another Pokémon faints before a Pokémon with Analytic makes its move,
|
||||
Analytic calculates whether it would have moved before or after the fainted
|
||||
Pokémon. In Gen 8, speed- and priority-modifying effects aren't considered,
|
||||
@@ -40,23 +30,15 @@ Some abilities have changed effects:
|
||||
|
||||
Some items have changed properties/effects:
|
||||
- Zygarde Cube now changes a Zygarde's ability.
|
||||
- Ability Capsule/Ability Patch should fail if used on Zygarde.
|
||||
- If Leppa Berry is forced to be consumed, it will first try to work on a move
|
||||
with 0 PP left (preferring the earliest such move in the list of moves), and
|
||||
failing that, the earliest move in the list of moves which has any PP missing
|
||||
(no matter how much).
|
||||
- Ensure that Choice items cause different moves to fail (without subtracting
|
||||
PP) if they were forced to be used by Instruct/Dancer.
|
||||
- Iron Ball shouldn't modify the effectiveness of Ground moves against a Flying
|
||||
holder if the holder is grounded by another effect that isn't Iron Ball.
|
||||
|
||||
Other notes:
|
||||
- In Gen 7+, Shaymin/Hoopa revert their form when withdrawn from storage rather
|
||||
than when deposited. It still also reverts under other conditions. Shaymin
|
||||
reverts its form when deposited in the Day Care (all Gens).
|
||||
- Look at Sweet Scent's out of battle effect, namely whether it should try to
|
||||
cause a horde battle (and what does that mean in Essentials?).
|
||||
- Maybe have multiple sets of Pickup items for multiple Gens.
|
||||
cause a horde battle (and what does that mean in Essentials? Maybe 1v3).
|
||||
- Maybe have multiple sets of Pickup items for multiple Gens. Probably not.
|
||||
Gens 7+ seem to have different item probability calculations - investigate.
|
||||
- Add a newer type of berry tree mechanics? Have a separate setting that
|
||||
prevents deterioration?
|
||||
- If a battle ends because of Rocky Helmet damage, the side that the Rocky
|
||||
@@ -68,14 +50,10 @@ Other notes:
|
||||
is probably fine.
|
||||
|
||||
Can use Fly from within the Town Map if possible. (Good QoL, add if possible.)
|
||||
(Will be implemented by me in the next PR)
|
||||
|
||||
Make example event that combines the Gen 8 fossils.
|
||||
|
||||
Add AI for new moves/items/abilities.
|
||||
|
||||
What happens to the PP of Iron Head when turned into/from Behemoth Blade/Bash
|
||||
for Zacian/Zamazenta?
|
||||
|
||||
#===============================================================================
|
||||
# Low priority or ignorable
|
||||
#===============================================================================
|
||||
@@ -131,6 +109,37 @@ Escape Rope's code now supports both consumable and non-consumable versions,
|
||||
depending on whether it is a key item. All it needs is a proper definition in
|
||||
items.txt.
|
||||
|
||||
Add AI for new moves/items/abilities.
|
||||
|
||||
Ability Effect Changes
|
||||
- Intimidate now triggers Rattled. Rattled needs a new ability handler just for
|
||||
triggering this way.
|
||||
|
||||
Move Effect Changes
|
||||
- Teleport switches the user out. If the user is a wild Pokémon, ends the battle
|
||||
instead.
|
||||
- Look at the moves Nature Power turns into. (Unchanged since Gen 7)
|
||||
- Curse's Ghost effect now targets a random foe (don't know if it can be non-
|
||||
adjacent); the target cannot be chosen by the player (it appears to target the
|
||||
user).
|
||||
- Multiple Quashed Pokémon now move in order from fastest to slowest, rather
|
||||
than the order in which they were Quashed.
|
||||
- Ensure that Choice items cause different moves to fail (without subtracting
|
||||
PP) if they were forced to be used by Instruct/Dancer.
|
||||
- Rapid Spin now raises the user's Speed by 1 stage (100% additional effect
|
||||
chance).
|
||||
|
||||
Item Effect Changes
|
||||
- If Leppa Berry is forced to be consumed, it will first try to work on a move
|
||||
with 0 PP left (preferring the earliest such move in the list of moves), and
|
||||
failing that, the earliest move in the list of moves which has any PP missing
|
||||
(no matter how much).
|
||||
- Ability Capsule/Ability Patch should fail if used on Zygarde.
|
||||
- Iron Ball shouldn't modify the effectiveness of Ground moves against a Flying
|
||||
holder if the holder is grounded by another effect that isn't Iron Ball.
|
||||
Opted to ignore this effect, and to modify the holder's effectiveness no matter
|
||||
what.
|
||||
|
||||
- Multi-Attack's power changed to 120.
|
||||
- Rapid Spin's power changed to 50.
|
||||
- Vice Grip renamed to Vise Grip.
|
||||
@@ -151,4 +160,8 @@ items.txt.
|
||||
- Changes to evolutions due to removal of moss rock/ice rock/magnetic field.
|
||||
- Form differences.
|
||||
|
||||
What happens to the PP of Iron Head when turned into/from Behemoth Blade/Bash
|
||||
for Zacian/Zamazenta? It gets decreased to the total PP if it is higher than the
|
||||
total PP of the new move, but cannot increase. This is already what happens.
|
||||
|
||||
=end
|
||||
|
||||
@@ -5389,6 +5389,7 @@ TotalPP = 40
|
||||
Target = NearOther
|
||||
FunctionCode = 110
|
||||
Flags = Contact,CanProtect,CanMirrorMove
|
||||
EffectChance = 100
|
||||
Description = A spin attack that can also eliminate such moves as Bind, Wrap, Leech Seed, and Spikes.
|
||||
#-------------------------------
|
||||
[SPIKECANNON]
|
||||
@@ -7682,6 +7683,7 @@ Type = PSYCHIC
|
||||
Category = Status
|
||||
Accuracy = 0
|
||||
TotalPP = 20
|
||||
Priority = -6
|
||||
Target = User
|
||||
FunctionCode = 0EA
|
||||
Description = Use it to flee from any wild Pokémon. It can also warp to the last Pokémon Center visited.
|
||||
|
||||
@@ -5388,6 +5388,7 @@ Accuracy = 100
|
||||
TotalPP = 40
|
||||
Target = NearOther
|
||||
FunctionCode = 110
|
||||
EffectChance = 100
|
||||
Flags = Contact,CanProtect,CanMirrorMove
|
||||
Description = A spin attack that can also eliminate such moves as Bind, Wrap, Leech Seed, and Spikes.
|
||||
#-------------------------------
|
||||
@@ -7683,6 +7684,7 @@ Category = Status
|
||||
Accuracy = 0
|
||||
TotalPP = 20
|
||||
Target = User
|
||||
Priority = -6
|
||||
FunctionCode = 0EA
|
||||
Description = Use it to flee from any wild Pokémon. It can also warp to the last Pokémon Center visited.
|
||||
#-------------------------------
|
||||
|
||||
Reference in New Issue
Block a user