class PokeBattle_Move #============================================================================= # Effect methods per move usage #============================================================================= def pbCanChooseMove?(user,commandPhase,showMessages); return true; end # For Belch def pbDisplayChargeMessage(user); end # For Focus Punch/shell Trap/Beak Blast def pbOnStartUse(user,targets); end def pbAddTarget(targets,user); end # For Counter, etc. and Bide # Reset move usage counters (child classes can increment them). def pbChangeUsageCounters(user,specialUsage) user.effects[PBEffects::FuryCutter] = 0 user.effects[PBEffects::ParentalBond] = 0 user.effects[PBEffects::ProtectRate] = 1 @battle.field.effects[PBEffects::FusionBolt] = false @battle.field.effects[PBEffects::FusionFlare] = false end def pbDisplayUseMessage(user) @battle.pbDisplayBrief(_INTL("{1} used {2}!",user.pbThis,@name)) end def pbMissMessage(user,target); return false; end #============================================================================= # #============================================================================= # Whether the move is currently in the "charging" turn of a two turn attack. # Is false if Power Herb or another effect lets a two turn move charge and # attack in the same turn. # user.effects[PBEffects::TwoTurnAttack] is set to the move's ID during the # charging turn, and is 0 during the attack turn. def pbIsChargingTurn?(user); return false; end def pbDamagingMove?; return damagingMove?; end def pbContactMove?(user) return false if user.hasActiveAbility?(:LONGREACH) return contactMove? end # The maximum number of hits in a round this move will actually perform. This # can be 1 for Beat Up, and can be 2 for any moves affected by Parental Bond. def pbNumHits(user,targets) if user.hasActiveAbility?(:PARENTALBOND) && pbDamagingMove? && !chargingTurnMove? && targets.length==1 # Record that Parental Bond applies, to weaken the second attack user.effects[PBEffects::ParentalBond] = 3 return 2 end return 1 end #============================================================================= # Effect methods per hit #============================================================================= def pbOverrideSuccessCheckPerHit(user,target); return false; end def pbCrashDamage(user); end def pbInitialEffect(user,targets,hitNum); end def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true) return if !showAnimation if user.effects[PBEffects::ParentalBond]==1 @battle.pbCommonAnimation("ParentalBond",user,targets) else @battle.pbAnimation(id,user,targets,hitNum) end end def pbSelfKO(user); end def pbEffectWhenDealingDamage(user,target); end def pbEffectAgainstTarget(user,target); end def pbEffectGeneral(user); end def pbAdditionalEffect(user,target); end def pbEffectAfterAllHits(user,target); end # Move effects that occur after all hits def pbSwitchOutTargetsEffect(user,targets,numHits,switchedBattlers); end def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers); end #============================================================================= # Check if target is immune to the move because of its ability #============================================================================= def pbImmunityByAbility(user,target) return false if @battle.moldBreaker ret = false if target.abilityActive? ret = BattleHandlers.triggerMoveImmunityTargetAbility(target.ability, user,target,self,@calcType,@battle) end return ret end #============================================================================= # Move failure checks #============================================================================= # Check whether the move fails completely due to move-specific requirements. def pbMoveFailed?(user,targets); return false; end # Checks whether the move will be ineffective against the target. def pbFailsAgainstTarget?(user,target); return false; end def pbMoveFailedLastInRound?(user) unmoved = false @battle.eachBattler do |b| next if b.index==user.index next if @battle.choices[b.index][0]!=:UseMove && @battle.choices[b.index][0]!=:Shift next if b.movedThisRound? unmoved = true break end if !unmoved @battle.pbDisplay(_INTL("But it failed!")) return true end return false end def pbMoveFailedTargetAlreadyMoved?(target) if (@battle.choices[target.index][0]!=:UseMove && @battle.choices[target.index][0]!=:Shift) || target.movedThisRound? @battle.pbDisplay(_INTL("But it failed!")) return true end return false end def pbMoveFailedAromaVeil?(user,target,showMessage=true) return false if @battle.moldBreaker if target.hasActiveAbility?(:AROMAVEIL) if showMessage @battle.pbShowAbilitySplash(target) if PokeBattle_SceneConstants::USE_ABILITY_SPLASH @battle.pbDisplay(_INTL("{1} is unaffected!",target.pbThis)) else @battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!", target.pbThis,target.abilityName)) end @battle.pbHideAbilitySplash(target) end return true end target.eachAlly do |b| next if !b.hasActiveAbility?(:AROMAVEIL) if showMessage @battle.pbShowAbilitySplash(target) if PokeBattle_SceneConstants::USE_ABILITY_SPLASH @battle.pbDisplay(_INTL("{1} is unaffected!",target.pbThis)) else @battle.pbDisplay(_INTL("{1} is unaffected because of {2}'s {3}!", target.pbThis,b.pbThis(true),b.abilityName)) end @battle.pbHideAbilitySplash(target) end return true end return false end #============================================================================= # Weaken the damage dealt (doesn't actually change a battler's HP) #============================================================================= def pbCheckDamageAbsorption(user,target) # Substitute will take the damage if target.effects[PBEffects::Substitute]>0 && !ignoresSubstitute?(user) && (!user || user.index!=target.index) target.damageState.substitute = true return end # Disguise will take the damage if !@battle.moldBreaker && isConst?(target.species,PBSpecies,:MIMIKYU) && target.form==0 && isConst?(target.ability,PBAbilities,:DISGUISE) target.damageState.disguise = true return end end def pbReduceDamage(user,target) damage = target.damageState.calcDamage # Substitute takes the damage if target.damageState.substitute damage = target.effects[PBEffects::Substitute] if damage>target.effects[PBEffects::Substitute] target.damageState.hpLost = damage target.damageState.totalHPLost += damage return end # Disguise takes the damage return if target.damageState.disguise # Target takes the damage if damage>=target.hp damage = target.hp # Survive a lethal hit with 1 HP effects if nonLethal?(user,target) damage -= 1 elsif target.effects[PBEffects::Endure] target.damageState.endured = true damage -= 1 elsif damage==target.totalhp if target.hasActiveAbility?(:STURDY) && !@battle.moldBreaker target.damageState.sturdy = true damage -= 1 elsif target.hasActiveItem?(:FOCUSSASH) && target.hp==target.totalhp target.damageState.focusSash = true damage -= 1 elsif target.hasActiveItem?(:FOCUSBAND) && @battle.pbRandom(100)<10 target.damageState.focusBand = true damage -= 1 end end end damage = 0 if damage<0 target.damageState.hpLost = damage target.damageState.totalHPLost += damage end #============================================================================= # Change the target's HP by the amount calculated above #============================================================================= def pbInflictHPDamage(target) if target.damageState.substitute target.effects[PBEffects::Substitute] -= target.damageState.hpLost else target.hp -= target.damageState.hpLost end end #============================================================================= # Animate the damage dealt, including lowering the HP #============================================================================= # Animate being damaged and losing HP (by a move) def pbAnimateHitAndHPLost(user,targets) # Animate allies first, then foes animArray = [] for side in 0...2 # side here means "allies first, then foes" targets.each do |b| next if b.damageState.unaffected || b.damageState.hpLost==0 next if (side==0 && b.opposes?(user)) || (side==1 && !b.opposes?(user)) oldHP = b.hp+b.damageState.hpLost PBDebug.log("[Move damage] #{b.pbThis} lost #{b.damageState.hpLost} HP (#{oldHP}=>#{b.hp})") effectiveness = 0 if PBTypes.resistant?(b.damageState.typeMod); effectiveness = 1 elsif PBTypes.superEffective?(b.damageState.typeMod); effectiveness = 2 end animArray.push([b,oldHP,effectiveness]) end if animArray.length>0 @battle.scene.pbHitAndHPLossAnimation(animArray) animArray.clear end end end #============================================================================= # Messages upon being hit #============================================================================= def pbEffectivenessMessage(user,target,numTargets=1) return if target.damageState.disguise if PBTypes.superEffective?(target.damageState.typeMod) if numTargets>1 @battle.pbDisplay(_INTL("It's super effective on {1}!",target.pbThis(true))) else @battle.pbDisplay(_INTL("It's super effective!")) end elsif PBTypes.notVeryEffective?(target.damageState.typeMod) if numTargets>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 end def pbHitEffectivenessMessages(user,target,numTargets=1) return if target.damageState.disguise if target.damageState.substitute @battle.pbDisplay(_INTL("The substitute took damage for {1}!",target.pbThis(true))) end if target.damageState.critical if numTargets>1 @battle.pbDisplay(_INTL("A critical hit on {1}!",target.pbThis(true))) else @battle.pbDisplay(_INTL("A critical hit!")) end end # Effectiveness message, for moves with 1 hit if !multiHitMove? && user.effects[PBEffects::ParentalBond]==0 pbEffectivenessMessage(user,target,numTargets) end if target.damageState.substitute && target.effects[PBEffects::Substitute]==0 target.effects[PBEffects::Substitute] = 0 @battle.pbDisplay(_INTL("{1}'s substitute faded!",target.pbThis)) end end def pbEndureKOMessage(target) if target.damageState.disguise @battle.pbShowAbilitySplash(target) if PokeBattle_SceneConstants::USE_ABILITY_SPLASH @battle.pbDisplay(_INTL("Its disguise served it as a decoy!")) else @battle.pbDisplay(_INTL("{1}'s disguise served it as a decoy!",target.pbThis)) end @battle.pbHideAbilitySplash(target) target.pbChangeForm(1,_INTL("{1}'s disguise was busted!",target.pbThis)) elsif target.damageState.endured @battle.pbDisplay(_INTL("{1} endured the hit!",target.pbThis)) elsif target.damageState.sturdy @battle.pbShowAbilitySplash(target) if PokeBattle_SceneConstants::USE_ABILITY_SPLASH @battle.pbDisplay(_INTL("{1} endured the hit!",target.pbThis)) else @battle.pbDisplay(_INTL("{1} hung on with Sturdy!",target.pbThis)) end @battle.pbHideAbilitySplash(target) elsif target.damageState.focusSash @battle.pbCommonAnimation("UseItem",target) @battle.pbDisplay(_INTL("{1} hung on using its Focus Sash!",target.pbThis)) target.pbConsumeItem elsif target.damageState.focusBand @battle.pbCommonAnimation("UseItem",target) @battle.pbDisplay(_INTL("{1} hung on using its Focus Band!",target.pbThis)) end end # Used by Counter/Mirror Coat/Metal Burst/Revenge/Focus Punch/Bide/Assurance. def pbRecordDamageLost(user,target) damage = target.damageState.hpLost # NOTE: In Gen 3 where a move's category depends on its type, Hidden Power # is for some reason countered by Counter rather than Mirror Coat, # regardless of its calculated type. Hence the following two lines of # code. moveType = nil moveType = getID(PBTypes,:NORMAL) if @function=="090" # Hidden Power if physicalMove?(moveType) target.effects[PBEffects::Counter] = damage target.effects[PBEffects::CounterTarget] = user.index elsif specialMove?(moveType) target.effects[PBEffects::MirrorCoat] = damage target.effects[PBEffects::MirrorCoatTarget] = user.index end if target.effects[PBEffects::Bide]>0 target.effects[PBEffects::BideDamage] += damage target.effects[PBEffects::BideTarget] = user.index end target.damageState.fainted = true if target.fainted? target.lastHPLost = damage # For Focus Punch target.tookDamage = true if damage>0 # For Assurance target.lastAttacker.push(user.index) # For Revenge if target.opposes?(user) target.lastHPLostFromFoe = damage # For Metal Burst target.lastFoeAttacker.push(user.index) # For Metal Burst end end end