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:
Golisopod-User
2021-08-03 03:26:55 +05:30
committed by GitHub
parent ec84d581ad
commit c6da16409e
16 changed files with 543 additions and 77 deletions

View File

@@ -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
#=============================================================================

View File

@@ -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
#=============================================================================

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
#===============================================================================

View File

@@ -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

View File

@@ -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)

View 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

View File

@@ -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
}

View File

@@ -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

View File

@@ -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

View File

@@ -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.

View File

@@ -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.
#-------------------------------