def pbProcessMoveAgainstTarget(thismove,user,target,numhits,turneffects,nocheck=false,alltargets=nil,showanimation=true,dancercheck=false)
realnumhits=0
totaldamage=0
destinybond=false
originalTarget=target
for i in 0...numhits
target.damagestate.reset
#for i in 0...numhits
#target.damagestate.reset
if thismove.function==0x180 && @battle.doublebattle && target!=user.pbPartner && # Dragon Darts
!target.pbPartner.fainted?
changetarget=false
for i in @battle.pbPriority
next if !user.pbIsOpposing?(i.index)
changetarget=true if i.effects[PBEffects::FollowMe]>0 || i.effects[PBEffects::RagePowder]>0 ||
i.effects[PBEffects::Spotlight]
end
if (thismove.pbTypeModifier(thismove.pbType(thismove.type,user,originalTarget),user,originalTarget)==0 ||
thismove.pbTypeImmunityByAbility(thismove.pbType(thismove.type,user,originalTarget),user,originalTarget) ||
(originalTarget.effects[PBEffects::Protect] ||
(originalTarget.pbOwnSide.effects[PBEffects::QuickGuard] && thismove.priority>0) ||
originalTarget.effects[PBEffects::SpikyShield] ||
originalTarget.effects[PBEffects::BanefulBunker] ||
originalTarget.effects[PBEffects::Obstruct]) ||
originalTarget.effects[PBEffects::TwoTurnAttack]>0 ||
!thismove.pbAccuracyCheck(user,originalTarget)) && !changetarget
target=originalTarget.pbPartner
end
end
# Check success (accuracy/evasion calculation)
# Check success (accuracy/evasion calculation)
if !nocheck &&
!pbSuccessCheck(thismove,user,target,turneffects,i==0 || thismove.successCheckPerHit?)
if thismove.function==0xBF && realnumhits>0 # Triple Kick
break # Considered a success if Triple Kick hits at least once
elsif thismove.function==0x10B # Hi Jump Kick, Jump Kick
if !user.hasWorkingAbility(:MAGICGUARD)
PBDebug.log("[Move effect triggered] #{user.pbThis} took crash damage")
# TODO: Not shown if message is "It doesn't affect XXX..."
@battle.pbDisplay(_INTL("{1} kept going and crashed!",user.pbThis))
damage=(user.totalhp/2).floor
if damage>0
@battle.scene.pbDamageAnimation(user,0)
user.pbReduceHP(damage)
end
user.pbFaint if user.fainted?
end
end
user.effects[PBEffects::Outrage]=0 if thismove.function==0xD2 # Outrage
user.effects[PBEffects::Rollout]=0 if thismove.function==0xD3 # Rollout
user.effects[PBEffects::FuryCutter]=0 if thismove.function==0x91 # Fury Cutter
user.effects[PBEffects::Stockpile]=0 if thismove.function==0x113 # Spit Up
return
end
# Add to counters for moves which increase them when used in succession
if thismove.function==0x91 # Fury Cutter
user.effects[PBEffects::FuryCutter]+=1 if user.effects[PBEffects::FuryCutter]<4
else
user.effects[PBEffects::FuryCutter]=0
end
if thismove.function==0x92 # Echoed Voice
if !user.pbOwnSide.effects[PBEffects::EchoedVoiceUsed] &&
user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter]<5
user.pbOwnSide.effects[PBEffects::EchoedVoiceCounter]+=1
end
user.pbOwnSide.effects[PBEffects::EchoedVoiceUsed]=true
end
# Count a hit for Parental Bond if it applies
user.effects[PBEffects::ParentalBond]-=1 if user.effects[PBEffects::ParentalBond]>0
# Count a hit for Dragon Darts if it hits first time
if thismove.function==0x180 && @battle.doublebattle && realnumhits>0
secondTarget=target.pbPartner
changetarget=false
for i in @battle.pbPriority
next if !user.pbIsOpposing?(i.index)
changetarget=true if i.effects[PBEffects::FollowMe]>0 || i.effects[PBEffects::RagePowder]>0 ||
i.effects[PBEffects::Spotlight]
end
if (thismove.pbTypeModifier(thismove.pbType(thismove.type,user,secondTarget),user,secondTarget)==0 ||
thismove.pbTypeImmunityByAbility(thismove.pbType(thismove.type,user,secondTarget),user,secondTarget) ||
(secondTarget.effects[PBEffects::Protect] ||
(secondTarget.pbOwnSide.effects[PBEffects::QuickGuard] && thismove.priority>0) ||
secondTarget.effects[PBEffects::SpikyShield] ||
secondTarget.effects[PBEffects::BanefulBunker] ||
secondTarget.effects[PBEffects::Obstruct]) ||
secondTarget.effects[PBEffects::TwoTurnAttack]>0 ||
!thismove.pbAccuracyCheck(user,secondTarget)) && !changetarget
target=secondTarget.pbPartner if secondTarget.pbPartner!=user.pbPartner
else
target=secondTarget.pbPartner if secondTarget.pbPartner!=user.pbPartner
if target.hasWorkingAbility(:PRESSURE) && !originalTarget.hasWorkingAbility(:PRESSURE)
PBDebug.log("[Ability triggered] #{target.pbThis}'s Pressure (in pbChangeTarget)")
user.pbReducePP(thismove) # Reduce PP
end
end
end
# This hit will happen; count it
realnumhits+=1
# Damage calculation and/or main effect
damage=thismove.pbEffect(user,target,i,alltargets,showanimation) # Recoil/drain, etc. are applied here
totaldamage+=damage if damage>0
# Message and consume for type-weakening berries
if target.damagestate.berryweakened
@battle.pbDisplay(_INTL("The {1} weakened the damage to {2}!",
PBItems.getName(target.item),target.pbThis(true)))
target.pbConsumeItem
end
# Illusion
if target.effects[PBEffects::Illusion] && target.hasWorkingAbility(:ILLUSION) &&
damage>0 && !target.damagestate.substitute
PBDebug.log("[Ability triggered] #{target.pbThis}'s Illusion ended")
target.effects[PBEffects::Illusion]=nil
@battle.scene.pbChangePokemon(target,target.pokemon)
@battle.pbDisplay(_INTL("{1}'s {2} wore off!",target.pbThis,
PBAbilities.getName(target.ability)))
end
# Disguise
if target.hasWorkingAbility(:DISGUISE) &&
isConst?(target.species,PBSpecies,:MIMIKYU) && target.form==0 &&
thismove.pbIsDamaging? && !target.damagestate.substitute &&
!user.hasMoldBreaker #&& !thismove.doesBypassIgnorableAbilities?
PBDebug.log("[Ability triggered] #{target.pbThis}'s Disguise ended")
@battle.pbDisplay(_INTL("Its disguise served it as a decoy!"))
target.form=1
target.pbUpdate(true)
@battle.scene.pbChangePokemon(target,target.pokemon)
@battle.pbDisplay(_INTL("{1}'s disguise was busted!",target.pbThis))
if target.hasWorkingItem(:AIRBALLOON,true)
PBDebug.log("[Item triggered] #{target.pbThis}'s Air Balloon popped")
@battle.pbDisplay(_INTL("{1}'s Air Balloon popped!",target.pbThis))
target.pbConsumeItem(true,false)
end
end
user.pbFaint if user.fainted? # no return
return if numhits>1 && target.damagestate.calcdamage<=0
@battle.pbJudgeCheckpoint(user,thismove)
# Additional effect
if target.damagestate.calcdamage>0 &&
!user.hasWorkingAbility(:SHEERFORCE) &&
(user.hasMoldBreaker || !target.hasWorkingAbility(:SHIELDDUST))
addleffect=thismove.addlEffect
addleffect*=2 if (user.hasWorkingAbility(:SERENEGRACE) ||
user.pbOwnSide.effects[PBEffects::Rainbow]>0) &&
thismove.function!=0xA4 # Secret Power
addleffect=100 if $DEBUG && Input.press?(Input::CTRL)
if @battle.pbRandom(100)<addleffect
PBDebug.log("[Move effect triggered] #{thismove.name}'s added effect")
thismove.pbAdditionalEffect(user,target)
end
end
# Ability effects
pbEffectsOnDealingDamage(thismove,user,target,damage)
# Grudge
if !user.fainted? && target.fainted?
if target.effects[PBEffects::Grudge] && target.pbIsOpposing?(user.index)
thismove.pp=0
@battle.pbDisplay(_INTL("{1}'s {2} lost all its PP due to the grudge!",
user.pbThis,thismove.name))
PBDebug.log("[Lingering effect triggered] #{target.pbThis}'s Grudge made #{thismove.name} lose all its PP")
end
end
if target.fainted?
destinybond=destinybond || target.effects[PBEffects::DestinyBond]
end
user.pbFaint if user.fainted? # no return
break if user.fainted?
break if target.fainted?
# Make the target flinch
if target.damagestate.calcdamage>0 && !target.damagestate.substitute
if user.hasMoldBreaker || !target.hasWorkingAbility(:SHIELDDUST)
canflinch=false
if (user.hasWorkingItem(:KINGSROCK) || user.hasWorkingItem(:RAZORFANG)) &&
thismove.canKingsRock?
canflinch=true
end
if user.hasWorkingAbility(:STENCH) &&
thismove.function!=0x09 && # Thunder Fang
thismove.function!=0x0B && # Fire Fang
thismove.function!=0x0E && # Ice Fang
thismove.function!=0x0F && # flinch-inducing moves
thismove.function!=0x10 && # Stomp
thismove.function!=0x11 && # Snore
thismove.function!=0x12 && # Fake Out
thismove.function!=0x78 && # Twister
thismove.function!=0xC7 # Sky Attack
canflinch=true
end
if canflinch && @battle.pbRandom(10)==0
PBDebug.log("[Item/ability triggered] #{user.pbThis}'s King's Rock/Razor Fang or Stench")
target.pbFlinch(user)
end
end
end
pbEffectsOnMoveEnd(thismove,user,target,damage)
if target.damagestate.calcdamage>0 && !target.fainted?
# Defrost
if target.status==PBStatuses::FROZEN &&
(isConst?(thismove.pbType(thismove.type,user,target),PBTypes,:FIRE) ||
(USENEWBATTLEMECHANICS && isConst?(thismove.id,PBMoves,:SCALD)))
target.pbCureStatus
end
# Rage
if target.effects[PBEffects::Rage] && target.pbIsOpposing?(user.index)
# TODO: Apparently triggers if opposing Pokémon uses Future Sight after a Future Sight attack
if target.pbIncreaseStatWithCause(PBStats::ATTACK,1,target,"",true,false)
PBDebug.log("[Lingering effect triggered] #{target.pbThis}'s Rage")
@battle.pbDisplay(_INTL("{1}'s rage is building!",target.pbThis))
end
end
end
target.pbFaint if target.fainted? # no return
user.pbFaint if user.fainted? # no return
break if user.fainted? || target.fainted?
# Dancer using damaging moves
if thismove.isDanceMove? && !dancercheck
if @battle.doublebattle
for k in @battle.pbPriority(true)
if k!=user && !k.fainted?
if !k.effects[PBEffects::Dancer] &&
k.hasWorkingAbility(:DANCER)
@battle.battlers[user.index].effects[PBEffects::Dancer]=true
if k==user.pbPartner
if !target.fainted?
if target==user.pbPartner
if !user.pbOpposing1.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user.pbOpposing1,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.pbOpposing2.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user.pbOpposing2,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.fainted?
@battle.pbDisplay(_INTL("{1} wants to dance, but will not attack its ally!",user.pbPartner.pbThis))
else
@battle.pbDisplay(_INTL("What a pity! {1} wanted to dance...",user.pbPartner.pbThis))
end
else
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,target,numhits,turneffects,nocheck,alltargets,showanimation,true)
end
elsif !target.pbPartner.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,target.pbPartner,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.fainted?
@battle.pbDisplay(_INTL("{1} wants to dance, but will not attack its ally!",user.pbPartner.pbThis))
else
@battle.pbDisplay(_INTL("What a pity! {1} wanted to dance...",user.pbPartner.pbThis))
end
elsif k==user.pbOpposing1
if !user.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.pbPartner.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user.pbPartner,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.pbOpposing2.fainted?
@battle.pbDisplay(_INTL("{1} wants to dance, but will not attack its ally!",user.pbOpposing1.pbThis))
else
@battle.pbDisplay(_INTL("What a pity! {1} wanted to dance...",user.pbOpposing1.pbThis))
end
elsif k==user.pbOpposing2
if !user.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.pbPartner.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",k.pbThis))
k.effects[PBEffects::Dancer]=true
pbProcessMoveAgainstTarget(thismove,k,user.pbPartner,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif !user.pbOpposing1.fainted?
@battle.pbDisplay(_INTL("{1} wants to dance, but will not attack its ally!",user.pbOpposing1.pbThis))
else
@battle.pbDisplay(_INTL("What a pity! {1} wanted to dance...",user.pbOpposing2.pbThis))
end
end
end
end
end
elsif target.hasWorkingAbility(:DANCER) && !target.fainted? && !user.fainted?
@battle.pbDisplay(_INTL("{1} also dances!",target.pbThis))
pbProcessMoveAgainstTarget(thismove,target,user,numhits,turneffects,nocheck,alltargets,showanimation,true)
elsif target.hasWorkingAbility(:DANCER) && !target.fainted? && user.fainted?
@battle.pbDisplay(_INTL("What a pity! {1} wanted to dance...",target.pbThis))
end
end
# Berry check (maybe just called by ability effect, since only necessary Berries are checked)
for j in 0...4
@battle.battlers[j].pbBerryCureCheck
end
break if user.fainted? || target.fainted?
target.pbUpdateTargetedMove(thismove,user)
break if target.damagestate.calcdamage<=0
end
turneffects[PBEffects::TotalDamage]+=totaldamage if totaldamage>0
# Battle Arena only - attack is successful
@battle.successStates[user.index].useState=2
@battle.successStates[user.index].typemod=target.damagestate.typemod
# Type effectiveness
if numhits>1
if target.damagestate.typemod>8
if alltargets.length>1
@battle.pbDisplay(_INTL("It's super effective on {1}!",target.pbThis(true)))
else
@battle.pbDisplay(_INTL("It's super effective!"))
end
elsif target.damagestate.typemod>=1 && target.damagestate.typemod<8
if alltargets.length>1
@battle.pbDisplay(_INTL("It's not very effective on {1}...",target.pbThis(true)))
else
@battle.pbDisplay(_INTL("It's not very effective..."))
end
end
if realnumhits==1
@battle.pbDisplay(_INTL("Hit {1} time!",realnumhits))
else
@battle.pbDisplay(_INTL("Hit {1} times!",realnumhits)) if !isConst?(thismove.id,PBMoves,:DRAGONDARTS)
end
end
PBDebug.log("Move did #{numhits} hit(s), total damage=#{turneffects[PBEffects::TotalDamage]}")
# Faint if 0 HP
target.pbFaint if target.fainted? # no return
user.pbFaint if user.fainted? # no return
thismove.pbEffectAfterHit(user,target,turneffects)
target.pbFaint if target.fainted? # no return
user.pbFaint if user.fainted? # no return
# Innards Out
if target.ability==PBAbilities::INNARDSOUT && target.fainted? &&
thismove.pbIsDamaging? && !target.effects[PBEffects::GastroAcid]
PBDebug.log("[Ability triggered] #{target.pbThis}'s Innards Out")
@battle.pbDisplay(_INTL("{1} was hurt by {2}'s {3}!",user.pbThis,
target.pbThis,PBAbilities.getName(target.ability)))
user.pbReduceHP(turneffects[PBEffects::TotalDamage])
end
# Destiny Bond
if !user.fainted? && target.fainted?
if destinybond && target.pbIsOpposing?(user.index)
PBDebug.log("[Lingering effect triggered] #{target.pbThis}'s Destiny Bond")
@battle.pbDisplay(_INTL("{1} took its attacker down with it!",target.pbThis))
user.pbReduceHP(user.hp)
user.pbFaint # no return
@battle.pbJudgeCheckpoint(user)
end
end
pbEffectsAfterHit(user,target,thismove,turneffects)
# Berry check
for j in 0...4
@battle.battlers[j].pbBerryCureCheck
end
target.pbUpdateTargetedMove(thismove,user)
end