#=============================================================================== # #=============================================================================== module Battle::AbilityEffects SpeedCalc = AbilityHandlerHash.new WeightCalc = AbilityHandlerHash.new # Battler's HP/stat changed OnHPDroppedBelowHalf = AbilityHandlerHash.new # Battler's status problem StatusCheckNonIgnorable = AbilityHandlerHash.new # Comatose StatusImmunity = AbilityHandlerHash.new StatusImmunityNonIgnorable = AbilityHandlerHash.new StatusImmunityFromAlly = AbilityHandlerHash.new OnStatusInflicted = AbilityHandlerHash.new # Synchronize StatusCure = AbilityHandlerHash.new # Battler's stat stages StatLossImmunity = AbilityHandlerHash.new StatLossImmunityNonIgnorable = AbilityHandlerHash.new # Full Metal Body StatLossImmunityFromAlly = AbilityHandlerHash.new # Flower Veil OnStatGain = AbilityHandlerHash.new # None! OnStatLoss = AbilityHandlerHash.new # Priority and turn order PriorityChange = AbilityHandlerHash.new PriorityBracketChange = AbilityHandlerHash.new # Stall PriorityBracketUse = AbilityHandlerHash.new # None! # Move usage failures OnFlinch = AbilityHandlerHash.new # Steadfast MoveBlocking = AbilityHandlerHash.new MoveImmunity = AbilityHandlerHash.new # Move usage ModifyMoveBaseType = AbilityHandlerHash.new # Accuracy calculation AccuracyCalcFromUser = AbilityHandlerHash.new AccuracyCalcFromAlly = AbilityHandlerHash.new # Victory Star AccuracyCalcFromTarget = AbilityHandlerHash.new # Damage calculation DamageCalcFromUser = AbilityHandlerHash.new DamageCalcFromAlly = AbilityHandlerHash.new DamageCalcFromTarget = AbilityHandlerHash.new DamageCalcFromTargetNonIgnorable = AbilityHandlerHash.new DamageCalcFromTargetAlly = AbilityHandlerHash.new CriticalCalcFromUser = AbilityHandlerHash.new CriticalCalcFromTarget = AbilityHandlerHash.new # Upon a move hitting a target OnBeingHit = AbilityHandlerHash.new OnDealingHit = AbilityHandlerHash.new # Poison Touch # Abilities that trigger at the end of using a move OnEndOfUsingMove = AbilityHandlerHash.new AfterMoveUseFromTarget = AbilityHandlerHash.new # End Of Round EndOfRoundWeather = AbilityHandlerHash.new EndOfRoundHealing = AbilityHandlerHash.new EndOfRoundEffect = AbilityHandlerHash.new EndOfRoundGainItem = AbilityHandlerHash.new # Switching and fainting CertainSwitching = AbilityHandlerHash.new # None! TrappingByTarget = AbilityHandlerHash.new OnSwitchIn = AbilityHandlerHash.new OnSwitchOut = AbilityHandlerHash.new ChangeOnBattlerFainting = AbilityHandlerHash.new OnBattlerFainting = AbilityHandlerHash.new # Soul-Heart OnTerrainChange = AbilityHandlerHash.new # Mimicry OnIntimidated = AbilityHandlerHash.new # Rattled (Gen 8) # Running from battle CertainEscapeFromBattle = AbilityHandlerHash.new # Run Away #============================================================================= def self.trigger(hash, *args, ret: false) new_ret = hash.trigger(*args) return (new_ret != nil) ? new_ret : ret end #============================================================================= def self.triggerSpeedCalc(ability, battler, mult) return trigger(SpeedCalc, ability, battler, mult, ret: mult) end def self.triggerWeightCalc(ability, battler, weight) return trigger(WeightCalc, ability, battler, weight, ret: weight) end #============================================================================= def self.triggerOnHPDroppedBelowHalf(ability, user, move_user, battle) return trigger(OnHPDroppedBelowHalf, ability, user, move_user, battle) end #============================================================================= def self.triggerStatusCheckNonIgnorable(ability, battler, status) return trigger(StatusCheckNonIgnorable, ability, battler, status) end def self.triggerStatusImmunity(ability, battler, status) return trigger(StatusImmunity, ability, battler, status) end def self.triggerStatusImmunityNonIgnorable(ability, battler, status) return trigger(StatusImmunityNonIgnorable, ability, battler, status) end def self.triggerStatusImmunityFromAlly(ability, battler, status) return trigger(StatusImmunityFromAlly, ability, battler, status) end def self.triggerOnStatusInflicted(ability, battler, user, status) OnStatusInflicted.trigger(ability, battler, user, status) end def self.triggerStatusCure(ability, battler) return trigger(StatusCure, ability, battler) end #============================================================================= def self.triggerStatLossImmunity(ability, battler, stat, battle, show_messages) return trigger(StatLossImmunity, ability, battler, stat, battle, show_messages) end def self.triggerStatLossImmunityNonIgnorable(ability, battler, stat, battle, show_messages) return trigger(StatLossImmunityNonIgnorable, ability, battler, stat, battle, show_messages) end def self.triggerStatLossImmunityFromAlly(ability, bearer, battler, stat, battle, show_messages) return trigger(StatLossImmunityFromAlly, ability, bearer, battler, stat, battle, show_messages) end def self.triggerOnStatGain(ability, battler, stat, user) OnStatGain.trigger(ability, battler, stat, user) end def self.triggerOnStatLoss(ability, battler, stat, user) OnStatLoss.trigger(ability, battler, stat, user) end #============================================================================= def self.triggerPriorityChange(ability, battler, move, priority) return trigger(PriorityChange, ability, battler, move, priority, ret: priority) end def self.triggerPriorityBracketChange(ability, battler, sub_priority, battle) return trigger(PriorityBracketChange, ability, battler, sub_priority, battle, ret: sub_priority) end def self.triggerPriorityBracketUse(ability, battler, battle) PriorityBracketUse.trigger(ability, battler, battle) end #============================================================================= def self.triggerOnFlinch(ability, battler, battle) OnFlinch.trigger(ability, battler, battle) end def self.triggerMoveBlocking(ability, bearer, user, targets, move, battle) return trigger(MoveBlocking, ability, bearer, user, targets, move, battle) end def self.triggerMoveImmunity(ability, user, target, move, type, battle, show_message) return trigger(MoveImmunity, ability, user, target, move, type, battle, show_message) end #============================================================================= def self.triggerModifyMoveBaseType(ability, user, move, type) return trigger(ModifyMoveBaseType, ability, user, move, type, ret: type) end #============================================================================= def self.triggerAccuracyCalcFromUser(ability, mods, user, target, move, type) AccuracyCalcFromUser.trigger(ability, mods, user, target, move, type) end def self.triggerAccuracyCalcFromAlly(ability, mods, user, target, move, type) AccuracyCalcFromAlly.trigger(ability, mods, user, target, move, type) end def self.triggerAccuracyCalcFromTarget(ability, mods, user, target, move, type) AccuracyCalcFromTarget.trigger(ability, mods, user, target, move, type) end #============================================================================= def self.triggerDamageCalcFromUser(ability, user, target, move, mults, base_damage, type) DamageCalcFromUser.trigger(ability, user, target, move, mults, base_damage, type) end def self.triggerDamageCalcFromAlly(ability, user, target, move, mults, base_damage, type) DamageCalcFromAlly.trigger(ability, user, target, move, mults, base_damage, type) end def self.triggerDamageCalcFromTarget(ability, user, target, move, mults, base_damage, type) DamageCalcFromTarget.trigger(ability, user, target, move, mults, base_damage, type) end def self.triggerDamageCalcFromTargetNonIgnorable(ability, user, target, move, mults, base_damage, type) DamageCalcFromTargetNonIgnorable.trigger(ability, user, target, move, mults, base_damage, type) end def self.triggerDamageCalcFromTargetAlly(ability, user, target, move, mults, base_damage, type) DamageCalcFromTargetAlly.trigger(ability, user, target, move, mults, base_damage, type) end def self.triggerCriticalCalcFromUser(ability, user, target, crit_stage) return trigger(CriticalCalcFromUser, ability, user, target, crit_stage, ret: crit_stage) end def self.triggerCriticalCalcFromTarget(ability, user, target, crit_stage) return trigger(CriticalCalcFromTarget, ability, user, target, crit_stage, ret: crit_stage) end #============================================================================= def self.triggerOnBeingHit(ability, user, target, move, battle) OnBeingHit.trigger(ability, user, target, move, battle) end def self.triggerOnDealingHit(ability, user, target, move, battle) OnDealingHit.trigger(ability, user, target, move, battle) end #============================================================================= def self.triggerOnEndOfUsingMove(ability, user, targets, move, battle) OnEndOfUsingMove.trigger(ability, user, targets, move, battle) end def self.triggerAfterMoveUseFromTarget(ability, target, user, move, switched_battlers, battle) AfterMoveUseFromTarget.trigger(ability, target, user, move, switched_battlers, battle) end #============================================================================= def self.triggerEndOfRoundWeather(ability, weather, battler, battle) EndOfRoundWeather.trigger(ability, weather, battler, battle) end def self.triggerEndOfRoundHealing(ability, battler, battle) EndOfRoundHealing.trigger(ability, battler, battle) end def self.triggerEndOfRoundEffect(ability, battler, battle) EndOfRoundEffect.trigger(ability, battler, battle) end def self.triggerEndOfRoundGainItem(ability, battler, battle) EndOfRoundGainItem.trigger(ability, battler, battle) end #============================================================================= def self.triggerCertainSwitching(ability, switcher, battle) return trigger(CertainSwitching, ability, switcher, battle) end def self.triggerTrappingByTarget(ability, switcher, bearer, battle) return trigger(TrappingByTarget, ability, switcher, bearer, battle) end def self.triggerOnSwitchIn(ability, battler, battle, switch_in = false) OnSwitchIn.trigger(ability, battler, battle, switch_in) end def self.triggerOnSwitchOut(ability, battler, end_of_battle) OnSwitchOut.trigger(ability, battler, end_of_battle) end def self.triggerChangeOnBattlerFainting(ability, battler, fainted, battle) ChangeOnBattlerFainting.trigger(ability, battler, fainted, battle) end def self.triggerOnBattlerFainting(ability, battler, fainted, battle) OnBattlerFainting.trigger(ability, battler, fainted, battle) end def self.triggerOnTerrainChange(ability, battler, battle, ability_changed) OnTerrainChange.trigger(ability, battler, battle, ability_changed) end def self.triggerOnIntimidated(ability, battler, battle) OnIntimidated.trigger(ability, battler, battle) end #============================================================================= def self.triggerCertainEscapeFromBattle(ability, battler) return trigger(CertainEscapeFromBattle, ability, battler) end end #=============================================================================== # SpeedCalc handlers #=============================================================================== Battle::AbilityEffects::SpeedCalc.add(:CHLOROPHYLL, proc { |ability,battler,mult| next mult * 2 if [:Sun, :HarshSun].include?(battler.effectiveWeather) } ) Battle::AbilityEffects::SpeedCalc.add(:QUICKFEET, proc { |ability,battler,mult| next mult*1.5 if battler.pbHasAnyStatus? } ) Battle::AbilityEffects::SpeedCalc.add(:SANDRUSH, proc { |ability,battler,mult| next mult * 2 if [:Sandstorm].include?(battler.effectiveWeather) } ) Battle::AbilityEffects::SpeedCalc.add(:SLOWSTART, proc { |ability,battler,mult| next mult/2 if battler.effects[PBEffects::SlowStart]>0 } ) Battle::AbilityEffects::SpeedCalc.add(:SLUSHRUSH, proc { |ability,battler,mult| next mult * 2 if [:Hail].include?(battler.effectiveWeather) } ) Battle::AbilityEffects::SpeedCalc.add(:SURGESURFER, proc { |ability,battler,mult| next mult*2 if battler.battle.field.terrain == :Electric } ) Battle::AbilityEffects::SpeedCalc.add(:SWIFTSWIM, proc { |ability,battler,mult| next mult * 2 if [:Rain, :HeavyRain].include?(battler.effectiveWeather) } ) Battle::AbilityEffects::SpeedCalc.add(:UNBURDEN, proc { |ability,battler,mult| next mult*2 if battler.effects[PBEffects::Unburden] && !battler.item } ) #=============================================================================== # WeightCalcy handlers #=============================================================================== Battle::AbilityEffects::WeightCalc.add(:HEAVYMETAL, proc { |ability,battler,w| next w*2 } ) Battle::AbilityEffects::WeightCalc.add(:LIGHTMETAL, proc { |ability,battler,w| next [w/2,1].max } ) #=============================================================================== # OnHPDroppedBelowHalf handlers #=============================================================================== Battle::AbilityEffects::OnHPDroppedBelowHalf.add(:EMERGENCYEXIT, proc { |ability, battler, move_user, battle| next false if battler.effects[PBEffects::SkyDrop]>=0 || battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSkyTargetCannotAct") # Sky Drop # In wild battles if battle.wildBattle? next false if battler.opposes? && battle.pbSideBattlerCount(battler.index)>1 next false if !battle.pbCanRun?(battler.index) battle.pbShowAbilitySplash(battler,true) battle.pbHideAbilitySplash(battler) pbSEPlay("Battle flee") battle.pbDisplay(_INTL("{1} fled from battle!",battler.pbThis)) battle.decision = 3 # Escaped next true end # In trainer battles next false if battle.pbAllFainted?(battler.idxOpposingSide) next false if !battle.pbCanSwitch?(battler.index) # Battler can't switch out next false if !battle.pbCanChooseNonActive?(battler.index) # No Pokémon can switch in battle.pbShowAbilitySplash(battler,true) battle.pbHideAbilitySplash(battler) if !Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} activated!",battler.pbThis,battler.abilityName)) end battle.pbDisplay(_INTL("{1} went back to {2}!", battler.pbThis,battle.pbGetOwnerName(battler.index))) if battle.endOfRound # Just switch out battle.scene.pbRecall(battler.index) if !battler.fainted? battler.pbAbilitiesOnSwitchOut # Inc. primordial weather check next true end newPkmn = battle.pbGetReplacementPokemonIndex(battler.index) # Owner chooses next false if newPkmn<0 # Shouldn't ever do this battle.pbRecallAndReplace(battler.index,newPkmn) battle.pbClearChoice(battler.index) # Replacement Pokémon does nothing this round battle.moldBreaker = false if move_user && battler.index == move_user.index battle.pbOnBattlerEnteringBattle(battler.index) next true } ) Battle::AbilityEffects::OnHPDroppedBelowHalf.copy(:EMERGENCYEXIT,:WIMPOUT) #=============================================================================== # StatusCheckNonIgnorable handlers #=============================================================================== Battle::AbilityEffects::StatusCheckNonIgnorable.add(:COMATOSE, proc { |ability,battler,status| next false if !battler.isSpecies?(:KOMALA) next true if status.nil? || status == :SLEEP } ) #=============================================================================== # StatusImmunity handlers #=============================================================================== Battle::AbilityEffects::StatusImmunity.add(:FLOWERVEIL, proc { |ability,battler,status| next true if battler.pbHasType?(:GRASS) } ) Battle::AbilityEffects::StatusImmunity.add(:IMMUNITY, proc { |ability,battler,status| next true if status == :POISON } ) Battle::AbilityEffects::StatusImmunity.copy(:IMMUNITY, :PASTELVEIL) Battle::AbilityEffects::StatusImmunity.add(:INSOMNIA, proc { |ability,battler,status| next true if status == :SLEEP } ) Battle::AbilityEffects::StatusImmunity.copy(:INSOMNIA, :SWEETVEIL, :VITALSPIRIT) Battle::AbilityEffects::StatusImmunity.add(:LEAFGUARD, proc { |ability,battler,status| next true if [:Sun, :HarshSun].include?(battler.effectiveWeather) } ) Battle::AbilityEffects::StatusImmunity.add(:LIMBER, proc { |ability,battler,status| next true if status == :PARALYSIS } ) Battle::AbilityEffects::StatusImmunity.add(:MAGMAARMOR, proc { |ability,battler,status| next true if status == :FROZEN } ) Battle::AbilityEffects::StatusImmunity.add(:WATERVEIL, proc { |ability,battler,status| next true if status == :BURN } ) Battle::AbilityEffects::StatusImmunity.copy(:WATERVEIL,:WATERBUBBLE) #=============================================================================== # StatusImmunityNonIgnorable handlers #=============================================================================== Battle::AbilityEffects::StatusImmunityNonIgnorable.add(:COMATOSE, proc { |ability,battler,status| next true if battler.isSpecies?(:KOMALA) } ) Battle::AbilityEffects::StatusImmunityNonIgnorable.add(:SHIELDSDOWN, proc { |ability,battler,status| next true if battler.isSpecies?(:MINIOR) && battler.form<7 } ) #=============================================================================== # StatusImmunityFromAlly handlers #=============================================================================== Battle::AbilityEffects::StatusImmunityFromAlly.add(:FLOWERVEIL, proc { |ability,battler,status| next true if battler.pbHasType?(:GRASS) } ) Battle::AbilityEffects::StatusImmunityFromAlly.add(:SWEETVEIL, proc { |ability,battler,status| next true if status == :SLEEP } ) #=============================================================================== # OnStatusInflicted handlers #=============================================================================== Battle::AbilityEffects::OnStatusInflicted.add(:SYNCHRONIZE, proc { |ability,battler,user,status| next if !user || user.index==battler.index case status when :POISON if user.pbCanPoisonSynchronize?(battler) battler.battle.pbShowAbilitySplash(battler) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} poisoned {3}!",battler.pbThis,battler.abilityName,user.pbThis(true)) end user.pbPoison(nil,msg,(battler.statusCount>0)) battler.battle.pbHideAbilitySplash(battler) end when :BURN if user.pbCanBurnSynchronize?(battler) battler.battle.pbShowAbilitySplash(battler) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} burned {3}!",battler.pbThis,battler.abilityName,user.pbThis(true)) end user.pbBurn(nil,msg) battler.battle.pbHideAbilitySplash(battler) end when :PARALYSIS if user.pbCanParalyzeSynchronize?(battler) battler.battle.pbShowAbilitySplash(battler) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} paralyzed {3}! It may be unable to move!", battler.pbThis,battler.abilityName,user.pbThis(true)) end user.pbParalyze(nil,msg) battler.battle.pbHideAbilitySplash(battler) end end } ) #=============================================================================== # StatusCure handlers #=============================================================================== Battle::AbilityEffects::StatusCure.add(:IMMUNITY, proc { |ability,battler| next if battler.status != :POISON battler.battle.pbShowAbilitySplash(battler) battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s {2} cured its poisoning!",battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.add(:INSOMNIA, proc { |ability,battler| next if battler.status != :SLEEP battler.battle.pbShowAbilitySplash(battler) battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s {2} woke it up!",battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.copy(:INSOMNIA, :VITALSPIRIT) Battle::AbilityEffects::StatusCure.add(:LIMBER, proc { |ability,battler| next if battler.status != :PARALYSIS battler.battle.pbShowAbilitySplash(battler) battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s {2} cured its paralysis!",battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.add(:MAGMAARMOR, proc { |ability,battler| next if battler.status != :FROZEN battler.battle.pbShowAbilitySplash(battler) battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s {2} defrosted it!",battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.add(:OBLIVIOUS, proc { |ability,battler| next if battler.effects[PBEffects::Attract]<0 && (battler.effects[PBEffects::Taunt]==0 || Settings::MECHANICS_GENERATION <= 5) battler.battle.pbShowAbilitySplash(battler) if battler.effects[PBEffects::Attract]>=0 battler.pbCureAttract if Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1} got over its infatuation.",battler.pbThis)) else battler.battle.pbDisplay(_INTL("{1}'s {2} cured its infatuation status!", battler.pbThis,battler.abilityName)) end end if battler.effects[PBEffects::Taunt]>0 && Settings::MECHANICS_GENERATION >= 6 battler.effects[PBEffects::Taunt] = 0 if Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s Taunt wore off!",battler.pbThis)) else battler.battle.pbDisplay(_INTL("{1}'s {2} made its taunt wear off!", battler.pbThis,battler.abilityName)) end end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.add(:OWNTEMPO, proc { |ability,battler| next if battler.effects[PBEffects::Confusion]==0 battler.battle.pbShowAbilitySplash(battler) battler.pbCureConfusion if Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1} snapped out of its confusion.",battler.pbThis)) else battler.battle.pbDisplay(_INTL("{1}'s {2} snapped it out of its confusion!", battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.add(:WATERVEIL, proc { |ability,battler| next if battler.status != :BURN battler.battle.pbShowAbilitySplash(battler) battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH battler.battle.pbDisplay(_INTL("{1}'s {2} healed its burn!",battler.pbThis,battler.abilityName)) end battler.battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::StatusCure.copy(:WATERVEIL, :WATERBUBBLE) #=============================================================================== # StatLossImmunity handlers #=============================================================================== Battle::AbilityEffects::StatLossImmunity.add(:BIGPECKS, proc { |ability,battler,stat,battle,showMessages| next false if stat!=:DEFENSE if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} cannot be lowered!",battler.pbThis,GameData::Stat.get(stat).name)) else battle.pbDisplay(_INTL("{1}'s {2} prevents {3} loss!",battler.pbThis, battler.abilityName,GameData::Stat.get(stat).name)) end battle.pbHideAbilitySplash(battler) end next true } ) Battle::AbilityEffects::StatLossImmunity.add(:CLEARBODY, proc { |ability,battler,stat,battle,showMessages| if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s stats cannot be lowered!",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} prevents stat loss!",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) end next true } ) Battle::AbilityEffects::StatLossImmunity.copy(:CLEARBODY, :WHITESMOKE) Battle::AbilityEffects::StatLossImmunity.add(:FLOWERVEIL, proc { |ability,battler,stat,battle,showMessages| next false if !battler.pbHasType?(:GRASS) if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s stats cannot be lowered!",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} prevents stat loss!",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) end next true } ) Battle::AbilityEffects::StatLossImmunity.add(:HYPERCUTTER, proc { |ability,battler,stat,battle,showMessages| next false if stat!=:ATTACK if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} cannot be lowered!",battler.pbThis,GameData::Stat.get(stat).name)) else battle.pbDisplay(_INTL("{1}'s {2} prevents {3} loss!",battler.pbThis, battler.abilityName,GameData::Stat.get(stat).name)) end battle.pbHideAbilitySplash(battler) end next true } ) Battle::AbilityEffects::StatLossImmunity.add(:KEENEYE, proc { |ability,battler,stat,battle,showMessages| next false if stat!=:ACCURACY if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} cannot be lowered!",battler.pbThis,GameData::Stat.get(stat).name)) else battle.pbDisplay(_INTL("{1}'s {2} prevents {3} loss!",battler.pbThis, battler.abilityName,GameData::Stat.get(stat).name)) end battle.pbHideAbilitySplash(battler) end next true } ) #=============================================================================== # StatLossImmunityNonIgnorable handlers #=============================================================================== Battle::AbilityEffects::StatLossImmunityNonIgnorable.add(:FULLMETALBODY, proc { |ability,battler,stat,battle,showMessages| if showMessages battle.pbShowAbilitySplash(battler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s stats cannot be lowered!",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} prevents stat loss!",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) end next true } ) #=============================================================================== # StatLossImmunityFromAlly handlers #=============================================================================== Battle::AbilityEffects::StatLossImmunityFromAlly.add(:FLOWERVEIL, proc { |ability,bearer,battler,stat,battle,showMessages| next false if !battler.pbHasType?(:GRASS) if showMessages battle.pbShowAbilitySplash(bearer) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s stats cannot be lowered!",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} prevents {3}'s stat loss!", bearer.pbThis,bearer.abilityName,battler.pbThis(true))) end battle.pbHideAbilitySplash(bearer) end next true } ) #=============================================================================== # OnStatGain handlers #=============================================================================== # There aren't any! #=============================================================================== # OnStatLoss handlers #=============================================================================== Battle::AbilityEffects::OnStatLoss.add(:COMPETITIVE, proc { |ability,battler,stat,user| next if user && !user.opposes?(battler) battler.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,2,battler) } ) Battle::AbilityEffects::OnStatLoss.add(:DEFIANT, proc { |ability,battler,stat,user| next if user && !user.opposes?(battler) battler.pbRaiseStatStageByAbility(:ATTACK,2,battler) } ) #=============================================================================== # PriorityChange handlers #=============================================================================== Battle::AbilityEffects::PriorityChange.add(:GALEWINGS, proc { |ability,battler,move,pri| next pri + 1 if (Settings::MECHANICS_GENERATION <= 6 || battler.hp == battler.totalhp) && move.type == :FLYING } ) Battle::AbilityEffects::PriorityChange.add(:PRANKSTER, proc { |ability,battler,move,pri| if move.statusMove? battler.effects[PBEffects::Prankster] = true next pri+1 end } ) Battle::AbilityEffects::PriorityChange.add(:TRIAGE, proc { |ability,battler,move,pri| next pri+3 if move.healingMove? } ) #=============================================================================== # PriorityBracketChange handlers #=============================================================================== Battle::AbilityEffects::PriorityBracketChange.add(:QUICKDRAW, proc { |ability, battler, subPri, battle| next 1 if subPri == 0 && battle.pbRandom(100) < 30 } ) Battle::AbilityEffects::PriorityBracketChange.add(:STALL, proc { |ability,battler,subPri,battle| next -1 if subPri==0 } ) #=============================================================================== # PriorityBracketUse handlers #=============================================================================== Battle::AbilityEffects::PriorityBracketUse.add(:QUICKDRAW, proc { |ability, battler, battle| battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} made {2} move faster!", battler.abilityName, battler.pbThis(true))) battle.pbHideAbilitySplash(battler) } ) #=============================================================================== # OnFlinch handlers #=============================================================================== Battle::AbilityEffects::OnFlinch.add(:STEADFAST, proc { |ability,battler,battle| battler.pbRaiseStatStageByAbility(:SPEED,1,battler) } ) #=============================================================================== # MoveBlocking handlers #=============================================================================== Battle::AbilityEffects::MoveBlocking.add(:DAZZLING, proc { |ability,bearer,user,targets,move,battle| next false if battle.choices[user.index][4]<=0 next false if !bearer.opposes?(user) ret = false targets.each do |b| next if !b.opposes?(user) ret = true end next ret } ) Battle::AbilityEffects::MoveBlocking.copy(:DAZZLING, :QUEENLYMAJESTY) #=============================================================================== # MoveImmunity handlers #=============================================================================== Battle::AbilityEffects::MoveImmunity.add(:BULLETPROOF, proc { |ability, user, target, move, type, battle, show_message| next false if !move.bombMove? if show_message battle.pbShowAbilitySplash(target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) else battle.pbDisplay(_INTL("{1}'s {2} made {3} ineffective!", target.pbThis, target.abilityName, move.name)) end battle.pbHideAbilitySplash(target) end next true } ) Battle::AbilityEffects::MoveImmunity.add(:FLASHFIRE, proc { |ability, user, target, move, type, battle, show_message| next false if user.index==target.index next false if type != :FIRE if show_message battle.pbShowAbilitySplash(target) if !target.effects[PBEffects::FlashFire] target.effects[PBEffects::FlashFire] = true if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("The power of {1}'s Fire-type moves rose!", target.pbThis(true))) else battle.pbDisplay(_INTL("The power of {1}'s Fire-type moves rose because of its {2}!", target.pbThis(true), target.abilityName)) end else if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) else battle.pbDisplay(_INTL("{1}'s {2} made {3} ineffective!", target.pbThis, target.abilityName, move.name)) end end battle.pbHideAbilitySplash(target) end next true } ) Battle::AbilityEffects::MoveImmunity.add(:LIGHTNINGROD, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityStatRaisingAbility(user, move, type, :ELECTRIC, :SPECIAL_ATTACK, 1, show_message) } ) Battle::AbilityEffects::MoveImmunity.add(:MOTORDRIVE, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityStatRaisingAbility(user, move, type, :ELECTRIC, :SPEED, 1, show_message) } ) Battle::AbilityEffects::MoveImmunity.add(:SAPSIPPER, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityStatRaisingAbility(user, move, type, :GRASS, :ATTACK, 1, show_message) } ) Battle::AbilityEffects::MoveImmunity.add(:SOUNDPROOF, proc { |ability, user, target, move, type, battle, show_message| next false if !move.soundMove? next false if Settings::MECHANICS_GENERATION >= 8 && user.index == target.index if show_message battle.pbShowAbilitySplash(target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) else battle.pbDisplay(_INTL("{1}'s {2} blocks {3}!", target.pbThis, target.abilityName, move.name)) end battle.pbHideAbilitySplash(target) end next true } ) Battle::AbilityEffects::MoveImmunity.add(:STORMDRAIN, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityStatRaisingAbility(user, move, type, :WATER, :SPECIAL_ATTACK, 1, show_message) } ) Battle::AbilityEffects::MoveImmunity.add(:TELEPATHY, proc { |ability, user, target, move, type, battle, show_message| next false if move.statusMove? next false if user.index==target.index || target.opposes?(user) if show_message battle.pbShowAbilitySplash(target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} avoids attacks by its ally Pokémon!", target.pbThis(true))) else battle.pbDisplay(_INTL("{1} avoids attacks by its ally Pokémon with {2}!", target.pbThis, target.abilityName)) end battle.pbHideAbilitySplash(target) end next true } ) Battle::AbilityEffects::MoveImmunity.add(:VOLTABSORB, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityHealingAbility(user, move, type, :ELECTRIC, show_message) } ) Battle::AbilityEffects::MoveImmunity.add(:WATERABSORB, proc { |ability, user, target, move, type, battle, show_message| next target.pbMoveImmunityHealingAbility(user, move, type, :WATER, show_message) } ) Battle::AbilityEffects::MoveImmunity.copy(:WATERABSORB, :DRYSKIN) Battle::AbilityEffects::MoveImmunity.add(:WONDERGUARD, proc { |ability, user, target, move, type, battle, show_message| next false if move.statusMove? next false if !type || Effectiveness.super_effective?(target.damageState.typeMod) if show_message battle.pbShowAbilitySplash(target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) else battle.pbDisplay(_INTL("{1} avoided damage with {2}!", target.pbThis, target.abilityName)) end battle.pbHideAbilitySplash(target) end next true } ) #=============================================================================== # ModifyMoveBaseType handlers #=============================================================================== Battle::AbilityEffects::ModifyMoveBaseType.add(:AERILATE, proc { |ability,user,move,type| next if type != :NORMAL || !GameData::Type.exists?(:FLYING) move.powerBoost = true next :FLYING } ) Battle::AbilityEffects::ModifyMoveBaseType.add(:GALVANIZE, proc { |ability,user,move,type| next if type != :NORMAL || !GameData::Type.exists?(:ELECTRIC) move.powerBoost = true next :ELECTRIC } ) Battle::AbilityEffects::ModifyMoveBaseType.add(:LIQUIDVOICE, proc { |ability,user,move,type| next :WATER if GameData::Type.exists?(:WATER) && move.soundMove? } ) Battle::AbilityEffects::ModifyMoveBaseType.add(:NORMALIZE, proc { |ability,user,move,type| next if !GameData::Type.exists?(:NORMAL) move.powerBoost = true if Settings::MECHANICS_GENERATION >= 7 next :NORMAL } ) Battle::AbilityEffects::ModifyMoveBaseType.add(:PIXILATE, proc { |ability,user,move,type| next if type != :NORMAL || !GameData::Type.exists?(:FAIRY) move.powerBoost = true next :FAIRY } ) Battle::AbilityEffects::ModifyMoveBaseType.add(:REFRIGERATE, proc { |ability,user,move,type| next if type != :NORMAL || !GameData::Type.exists?(:ICE) move.powerBoost = true next :ICE } ) #=============================================================================== # AccuracyCalcFromUser handlers #=============================================================================== Battle::AbilityEffects::AccuracyCalcFromUser.add(:COMPOUNDEYES, proc { |ability,mods,user,target,move,type| mods[:accuracy_multiplier] *= 1.3 } ) Battle::AbilityEffects::AccuracyCalcFromUser.add(:HUSTLE, proc { |ability,mods,user,target,move,type| mods[:accuracy_multiplier] *= 0.8 if move.physicalMove? } ) Battle::AbilityEffects::AccuracyCalcFromUser.add(:KEENEYE, proc { |ability,mods,user,target,move,type| mods[:evasion_stage] = 0 if mods[:evasion_stage] > 0 && Settings::MECHANICS_GENERATION >= 6 } ) Battle::AbilityEffects::AccuracyCalcFromUser.add(:NOGUARD, proc { |ability,mods,user,target,move,type| mods[:base_accuracy] = 0 } ) Battle::AbilityEffects::AccuracyCalcFromUser.add(:UNAWARE, proc { |ability,mods,user,target,move,type| mods[:evasion_stage] = 0 if move.damagingMove? } ) Battle::AbilityEffects::AccuracyCalcFromUser.add(:VICTORYSTAR, proc { |ability,mods,user,target,move,type| mods[:accuracy_multiplier] *= 1.1 } ) #=============================================================================== # AccuracyCalcFromAlly handlers #=============================================================================== Battle::AbilityEffects::AccuracyCalcFromAlly.add(:VICTORYSTAR, proc { |ability,mods,user,target,move,type| mods[:accuracy_multiplier] *= 1.1 } ) #=============================================================================== # AccuracyCalcFromTarget handlers #=============================================================================== Battle::AbilityEffects::AccuracyCalcFromTarget.add(:LIGHTNINGROD, proc { |ability,mods,user,target,move,type| mods[:base_accuracy] = 0 if type == :ELECTRIC } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:NOGUARD, proc { |ability,mods,user,target,move,type| mods[:base_accuracy] = 0 } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:SANDVEIL, proc { |ability,mods,user,target,move,type| mods[:evasion_multiplier] *= 1.25 if target.effectiveWeather == :Sandstorm } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:SNOWCLOAK, proc { |ability,mods,user,target,move,type| mods[:evasion_multiplier] *= 1.25 if target.effectiveWeather == :Hail } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:STORMDRAIN, proc { |ability,mods,user,target,move,type| mods[:base_accuracy] = 0 if type == :WATER } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:TANGLEDFEET, proc { |ability,mods,user,target,move,type| mods[:accuracy_multiplier] /= 2 if target.effects[PBEffects::Confusion] > 0 } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:UNAWARE, proc { |ability,mods,user,target,move,type| mods[:accuracy_stage] = 0 if move.damagingMove? } ) Battle::AbilityEffects::AccuracyCalcFromTarget.add(:WONDERSKIN, proc { |ability,mods,user,target,move,type| if move.statusMove? && user.opposes?(target) mods[:base_accuracy] = 50 if mods[:base_accuracy] > 50 end } ) #=============================================================================== # DamageCalcFromUser handlers #=============================================================================== Battle::AbilityEffects::DamageCalcFromUser.add(:AERILATE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.2 if move.powerBoost } ) Battle::AbilityEffects::DamageCalcFromUser.copy(:AERILATE, :PIXILATE, :REFRIGERATE, :GALVANIZE, :NORMALIZE) Battle::AbilityEffects::DamageCalcFromUser.add(:ANALYTIC, proc { |ability,user,target,move,mults,baseDmg,type| # NOTE: If another battler faints earlier in the round, but it would have # moved after the user, then Analytic would not power up the move. # However, this makes the determination so much more complicated # (involving pbPriority and counting or not counting speed/priority # modifiers depending on which Generation's mechanics are being used), # so I'm choosing to ignore it. The effect is thus: "power up the move # if all other battlers on the field right now have already moved". if move.pbMoveFailedLastInRound?(user, false) mults[:base_damage_multiplier] *= 1.3 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:BLAZE, proc { |ability,user,target,move,mults,baseDmg,type| if user.hp <= user.totalhp / 3 && type == :FIRE mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:DEFEATIST, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] /= 2 if user.hp <= user.totalhp / 2 } ) Battle::AbilityEffects::DamageCalcFromUser.add(:DRAGONSMAW, proc { |ability, user, target, move, mults, baseDmg, type| mults[:attack_multiplier] *= 1.5 if type == :DRAGON } ) Battle::AbilityEffects::DamageCalcFromUser.add(:FLAREBOOST, proc { |ability,user,target,move,mults,baseDmg,type| if user.burned? && move.specialMove? mults[:base_damage_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:FLASHFIRE, proc { |ability,user,target,move,mults,baseDmg,type| if user.effects[PBEffects::FlashFire] && type == :FIRE mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:FLOWERGIFT, proc { |ability,user,target,move,mults,baseDmg,type| if move.physicalMove? && [:Sun, :HarshSun].include?(user.effectiveWeather) mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:GORILLATACTICS, proc { |ability, user, target, move, mults, baseDmg, type| mults[:attack_multiplier] *= 1.5 } ) Battle::AbilityEffects::DamageCalcFromUser.add(:GUTS, proc { |ability,user,target,move,mults,baseDmg,type| if user.pbHasAnyStatus? && move.physicalMove? mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:HUGEPOWER, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] *= 2 if move.physicalMove? } ) Battle::AbilityEffects::DamageCalcFromUser.copy(:HUGEPOWER, :PUREPOWER) Battle::AbilityEffects::DamageCalcFromUser.add(:HUSTLE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] *= 1.5 if move.physicalMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:IRONFIST, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.2 if move.punchingMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:MEGALAUNCHER, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.5 if move.pulseMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:MINUS, proc { |ability,user,target,move,mults,baseDmg,type| next if !move.specialMove? if user.allAllies.any? { |b| b.hasActiveAbility?([:MINUS, :PLUS]) } mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.copy(:MINUS, :PLUS) Battle::AbilityEffects::DamageCalcFromUser.add(:NEUROFORCE, proc { |ability,user,target,move,mults,baseDmg,type| if Effectiveness.super_effective?(target.damageState.typeMod) mults[:final_damage_multiplier] *= 1.25 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:OVERGROW, proc { |ability,user,target,move,mults,baseDmg,type| if user.hp <= user.totalhp / 3 && type == :GRASS mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:PUNKROCK, proc { |ability, user, target, move, mults, baseDmg, type| mults[:attack_multiplier] *= 1.3 if move.soundMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:RECKLESS, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.2 if move.recoilMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:RIVALRY, proc { |ability,user,target,move,mults,baseDmg,type| if user.gender!=2 && target.gender!=2 if user.gender==target.gender mults[:base_damage_multiplier] *= 1.25 else mults[:base_damage_multiplier] *= 0.75 end end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SANDFORCE, proc { |ability,user,target,move,mults,baseDmg,type| if user.effectiveWeather == :Sandstorm && [:ROCK, :GROUND, :STEEL].include?(type) mults[:base_damage_multiplier] *= 1.3 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SHEERFORCE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.3 if move.addlEffect > 0 } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SLOWSTART, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] /= 2 if user.effects[PBEffects::SlowStart] > 0 && move.physicalMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SOLARPOWER, proc { |ability,user,target,move,mults,baseDmg,type| if move.specialMove? && [:Sun, :HarshSun].include?(user.effectiveWeather) mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SNIPER, proc { |ability,user,target,move,mults,baseDmg,type| if target.damageState.critical mults[:final_damage_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:STAKEOUT, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] *= 2 if target.battle.choices[target.index][0] == :SwitchOut } ) Battle::AbilityEffects::DamageCalcFromUser.add(:STEELWORKER, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] *= 1.5 if type == :STEEL } ) Battle::AbilityEffects::DamageCalcFromUser.add(:STEELYSPIRIT, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] *= 1.5 if type == :STEEL } ) Battle::AbilityEffects::DamageCalcFromUser.add(:STRONGJAW, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.5 if move.bitingMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:SWARM, proc { |ability,user,target,move,mults,baseDmg,type| if user.hp <= user.totalhp / 3 && type == :BUG mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TECHNICIAN, proc { |ability,user,target,move,mults,baseDmg,type| if user.index != target.index && move && move.id != :STRUGGLE && baseDmg * mults[:base_damage_multiplier] <= 60 mults[:base_damage_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TINTEDLENS, proc { |ability,user,target,move,mults,baseDmg,type| mults[:final_damage_multiplier] *= 2 if Effectiveness.resistant?(target.damageState.typeMod) } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TORRENT, proc { |ability,user,target,move,mults,baseDmg,type| if user.hp <= user.totalhp / 3 && type == :WATER mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TOUGHCLAWS, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 4 / 3.0 if move.contactMove? } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TOXICBOOST, proc { |ability,user,target,move,mults,baseDmg,type| if user.poisoned? && move.physicalMove? mults[:base_damage_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromUser.add(:TRANSISTOR, proc { |ability, user, target, move, mults, baseDmg, type| mults[:attack_multiplier] *= 1.5 if type == :ELECTRIC } ) Battle::AbilityEffects::DamageCalcFromUser.add(:WATERBUBBLE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:attack_multiplier] *= 2 if type == :WATER } ) #=============================================================================== # DamageCalcFromAlly handlers #=============================================================================== Battle::AbilityEffects::DamageCalcFromAlly.add(:BATTERY, proc { |ability,user,target,move,mults,baseDmg,type| next if !move.specialMove? mults[:final_damage_multiplier] *= 1.3 } ) Battle::AbilityEffects::DamageCalcFromAlly.add(:FLOWERGIFT, proc { |ability,user,target,move,mults,baseDmg,type| if move.physicalMove? && [:Sun, :HarshSun].include?(user.effectiveWeather) mults[:attack_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromAlly.add(:POWERSPOT, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] *= 1.3 } ) Battle::AbilityEffects::DamageCalcFromAlly.add(:STEELYSPIRIT, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] *= 1.5 if type == :STEEL } ) #=============================================================================== # DamageCalcFromTarget handlers #=============================================================================== Battle::AbilityEffects::DamageCalcFromTarget.add(:DRYSKIN, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] *= 1.25 if type == :FIRE } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:FILTER, proc { |ability,user,target,move,mults,baseDmg,type| if Effectiveness.super_effective?(target.damageState.typeMod) mults[:final_damage_multiplier] *= 0.75 end } ) Battle::AbilityEffects::DamageCalcFromTarget.copy(:FILTER, :SOLIDROCK) Battle::AbilityEffects::DamageCalcFromTarget.add(:FLOWERGIFT, proc { |ability,user,target,move,mults,baseDmg,type| if move.specialMove? && [:Sun, :HarshSun].include?(target.effectiveWeather) mults[:defense_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:FLUFFY, proc { |ability,user,target,move,mults,baseDmg,type| mults[:final_damage_multiplier] *= 2 if move.calcType == :FIRE mults[:final_damage_multiplier] /= 2 if move.pbContactMove? } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:FURCOAT, proc { |ability,user,target,move,mults,baseDmg,type| mults[:defense_multiplier] *= 2 if move.physicalMove? || move.function == "UseTargetDefenseInsteadOfTargetSpDef" # Psyshock } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:GRASSPELT, proc { |ability,user,target,move,mults,baseDmg,type| if user.battle.field.terrain == :Grassy mults[:defense_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:HEATPROOF, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] /= 2 if type == :FIRE } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:ICESCALES, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] /= 2 if move.specialMove? } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:MARVELSCALE, proc { |ability,user,target,move,mults,baseDmg,type| if target.pbHasAnyStatus? && move.physicalMove? mults[:defense_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:MULTISCALE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:final_damage_multiplier] /= 2 if target.hp == target.totalhp } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:PUNKROCK, proc { |ability, user, target, move, mults, baseDmg, type| mults[:final_damage_multiplier] /= 2 if move.soundMove? } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:THICKFAT, proc { |ability,user,target,move,mults,baseDmg,type| mults[:base_damage_multiplier] /= 2 if type == :FIRE || type == :ICE } ) Battle::AbilityEffects::DamageCalcFromTarget.add(:WATERBUBBLE, proc { |ability,user,target,move,mults,baseDmg,type| mults[:final_damage_multiplier] /= 2 if type == :FIRE } ) #=============================================================================== # DamageCalcFromTargetNonIgnorable handlers #=============================================================================== Battle::AbilityEffects::DamageCalcFromTargetNonIgnorable.add(:PRISMARMOR, proc { |ability,user,target,move,mults,baseDmg,type| if Effectiveness.super_effective?(target.damageState.typeMod) mults[:final_damage_multiplier] *= 0.75 end } ) Battle::AbilityEffects::DamageCalcFromTargetNonIgnorable.add(:SHADOWSHIELD, proc { |ability,user,target,move,mults,baseDmg,type| if target.hp==target.totalhp mults[:final_damage_multiplier] /= 2 end } ) #=============================================================================== # DamageCalcFromTargetAlly handlers #=============================================================================== Battle::AbilityEffects::DamageCalcFromTargetAlly.add(:FLOWERGIFT, proc { |ability,user,target,move,mults,baseDmg,type| if move.specialMove? && [:Sun, :HarshSun].include?(target.effectiveWeather) mults[:defense_multiplier] *= 1.5 end } ) Battle::AbilityEffects::DamageCalcFromTargetAlly.add(:FRIENDGUARD, proc { |ability,user,target,move,mults,baseDmg,type| mults[:final_damage_multiplier] *= 0.75 } ) #=============================================================================== # CriticalCalcFromUser handlers #=============================================================================== Battle::AbilityEffects::CriticalCalcFromUser.add(:MERCILESS, proc { |ability,user,target,c| next 99 if target.poisoned? } ) Battle::AbilityEffects::CriticalCalcFromUser.add(:SUPERLUCK, proc { |ability,user,target,c| next c+1 } ) #=============================================================================== # CriticalCalcFromTarget handlers #=============================================================================== Battle::AbilityEffects::CriticalCalcFromTarget.add(:BATTLEARMOR, proc { |ability,user,target,c| next -1 } ) Battle::AbilityEffects::CriticalCalcFromTarget.copy(:BATTLEARMOR, :SHELLARMOR) #=============================================================================== # OnBeingHit handlers #=============================================================================== Battle::AbilityEffects::OnBeingHit.add(:AFTERMATH, proc { |ability,user,target,move,battle| next if !target.fainted? next if !move.pbContactMove?(user) battle.pbShowAbilitySplash(target) if !battle.moldBreaker dampBattler = battle.pbCheckGlobalAbility(:DAMP) if dampBattler battle.pbShowAbilitySplash(dampBattler) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} cannot use {2}!",target.pbThis,target.abilityName)) else battle.pbDisplay(_INTL("{1} cannot use {2} because of {3}'s {4}!", target.pbThis,target.abilityName,dampBattler.pbThis(true),dampBattler.abilityName)) end battle.pbHideAbilitySplash(dampBattler) battle.pbHideAbilitySplash(target) next end end if user.takesIndirectDamage?(Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) battle.scene.pbDamageAnimation(user) user.pbReduceHP(user.totalhp/4,false) battle.pbDisplay(_INTL("{1} was caught in the aftermath!",user.pbThis)) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:ANGERPOINT, proc { |ability,user,target,move,battle| next if !target.damageState.critical next if !target.pbCanRaiseStatStage?(:ATTACK,target) battle.pbShowAbilitySplash(target) target.stages[:ATTACK] = 6 target.statsRaisedThisRound = true battle.pbCommonAnimation("StatUp",target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} maxed its {2}!",target.pbThis,GameData::Stat.get(:ATTACK).name)) else battle.pbDisplay(_INTL("{1}'s {2} maxed its {3}!", target.pbThis,target.abilityName,GameData::Stat.get(:ATTACK).name)) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:COTTONDOWN, proc { |ability, user, target, move, battle| next if battle.allBattlers.none? { |b| b.pbCanLowerStatStage?(:DEFENSE, target) } battle.pbShowAbilitySplash(battler) battle.allBattlers.each do |b| b.pbLowerStatStageByAbility(:SPEED, 1, target, false) end battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnBeingHit.add(:CURSEDBODY, proc { |ability,user,target,move,battle| next if user.fainted? next if user.effects[PBEffects::Disable]>0 regularMove = nil user.eachMove do |m| next if m.id!=user.lastRegularMoveUsed regularMove = m break end next if !regularMove || (regularMove.pp==0 && regularMove.total_pp>0) next if battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(target) if !move.pbMoveFailedAromaVeil?(target,user,Battle::Scene::USE_ABILITY_SPLASH) user.effects[PBEffects::Disable] = 3 user.effects[PBEffects::DisableMove] = regularMove.id if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} was disabled!",user.pbThis,regularMove.name)) else battle.pbDisplay(_INTL("{1}'s {2} was disabled by {3}'s {4}!", user.pbThis,regularMove.name,target.pbThis(true),target.abilityName)) end battle.pbHideAbilitySplash(target) user.pbItemStatusCureCheck end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:CUTECHARM, proc { |ability,user,target,move,battle| next if target.fainted? next if !move.pbContactMove?(user) next if battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(target) if user.pbCanAttract?(target,Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} made {3} fall in love!",target.pbThis, target.abilityName,user.pbThis(true)) end user.pbAttract(target,msg) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:EFFECTSPORE, proc { |ability,user,target,move,battle| # NOTE: This ability has a 30% chance of triggering, not a 30% chance of # inflicting a status condition. It can try (and fail) to inflict a # status condition that the user is immune to. next if !move.pbContactMove?(user) next if battle.pbRandom(100)>=30 r = battle.pbRandom(3) next if r==0 && user.asleep? next if r==1 && user.poisoned? next if r==2 && user.paralyzed? battle.pbShowAbilitySplash(target) if user.affectedByPowder?(Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) case r when 0 if user.pbCanSleep?(target,Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} made {3} fall asleep!",target.pbThis, target.abilityName,user.pbThis(true)) end user.pbSleep(msg) end when 1 if user.pbCanPoison?(target,Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} poisoned {3}!",target.pbThis, target.abilityName,user.pbThis(true)) end user.pbPoison(target,msg) end when 2 if user.pbCanParalyze?(target,Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} paralyzed {3}! It may be unable to move!", target.pbThis,target.abilityName,user.pbThis(true)) end user.pbParalyze(target,msg) end end end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:FLAMEBODY, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) next if user.burned? || battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(target) if user.pbCanBurn?(target,Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} burned {3}!",target.pbThis,target.abilityName,user.pbThis(true)) end user.pbBurn(target,msg) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:GOOEY, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) user.pbLowerStatStageByAbility(:SPEED,1,target,true,true) } ) Battle::AbilityEffects::OnBeingHit.copy(:GOOEY, :TANGLINGHAIR) Battle::AbilityEffects::OnBeingHit.add(:ILLUSION, proc { |ability,user,target,move,battle| # NOTE: This intentionally doesn't show the ability splash. next if !target.effects[PBEffects::Illusion] target.effects[PBEffects::Illusion] = nil battle.scene.pbChangePokemon(target,target.pokemon) battle.pbDisplay(_INTL("{1}'s illusion wore off!",target.pbThis)) battle.pbSetSeen(target) } ) Battle::AbilityEffects::OnBeingHit.add(:INNARDSOUT, proc { |ability,user,target,move,battle| next if !target.fainted? || user.dummy battle.pbShowAbilitySplash(target) if user.takesIndirectDamage?(Battle::Scene::USE_ABILITY_SPLASH) battle.scene.pbDamageAnimation(user) user.pbReduceHP(target.damageState.hpLost,false) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} is hurt!",user.pbThis)) else battle.pbDisplay(_INTL("{1} is hurt by {2}'s {3}!",user.pbThis, target.pbThis(true),target.abilityName)) end end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:IRONBARBS, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) battle.pbShowAbilitySplash(target) if user.takesIndirectDamage?(Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) battle.scene.pbDamageAnimation(user) user.pbReduceHP(user.totalhp/8,false) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} is hurt!",user.pbThis)) else battle.pbDisplay(_INTL("{1} is hurt by {2}'s {3}!",user.pbThis, target.pbThis(true),target.abilityName)) end end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.copy(:IRONBARBS, :ROUGHSKIN) Battle::AbilityEffects::OnBeingHit.add(:JUSTIFIED, proc { |ability,user,target,move,battle| next if move.calcType != :DARK target.pbRaiseStatStageByAbility(:ATTACK,1,target) } ) Battle::AbilityEffects::OnBeingHit.add(:MUMMY, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) next if user.fainted? next if user.unstoppableAbility? || user.ability == ability oldAbil = nil battle.pbShowAbilitySplash(target) if user.opposes?(target) if user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) oldAbil = user.ability battle.pbShowAbilitySplash(user,true,false) if user.opposes?(target) user.ability = ability battle.pbReplaceAbilitySplash(user) if user.opposes?(target) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s Ability became {2}!",user.pbThis,user.abilityName)) else battle.pbDisplay(_INTL("{1}'s Ability became {2} because of {3}!", user.pbThis,user.abilityName,target.pbThis(true))) end battle.pbHideAbilitySplash(user) if user.opposes?(target) end battle.pbHideAbilitySplash(target) if user.opposes?(target) user.pbOnLosingAbility(oldAbil) user.pbTriggerAbilityOnGainingIt } ) Battle::AbilityEffects::OnBeingHit.add(:PERISHBODY, proc { |ability, user, target, move, battle| next if !move.pbContactMove?(user) next if user.fainted? next if user.effects[PBEffects::PerishSong] > 0 || target.effects[PBEffects::PerishSong] > 0 battle.pbShowAbilitySplash(target) if user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) user.effects[PBEffects::PerishSong] = 4 user.effects[PBEffects::PerishSongUser] = target.index target.effects[PBEffects::PerishSong] = 4 target.effects[PBEffects::PerishSongUser] = target.index if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("Both Pokémon will faint in three turns!")) else battle.pbDisplay(_INTL("Both Pokémon will faint in three turns because of {1}'s {2}!", target.pbThis(true), target.abilityName)) end end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:POISONPOINT, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) next if user.poisoned? || battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(target) if user.pbCanPoison?(target,Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} poisoned {3}!",target.pbThis,target.abilityName,user.pbThis(true)) end user.pbPoison(target,msg) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:RATTLED, proc { |ability,user,target,move,battle| next if ![:BUG, :DARK, :GHOST].include?(move.calcType) target.pbRaiseStatStageByAbility(:SPEED,1,target) } ) Battle::AbilityEffects::OnBeingHit.add(:SANDSPIT, proc { |ability, user, target, move, battle| battle.pbStartWeatherAbility(:Sandstorm, battler) } ) Battle::AbilityEffects::OnBeingHit.add(:STAMINA, proc { |ability,user,target,move,battle| target.pbRaiseStatStageByAbility(:DEFENSE,1,target) } ) Battle::AbilityEffects::OnBeingHit.add(:STATIC, proc { |ability,user,target,move,battle| next if !move.pbContactMove?(user) next if user.paralyzed? || battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(target) if user.pbCanParalyze?(target,Battle::Scene::USE_ABILITY_SPLASH) && user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} paralyzed {3}! It may be unable to move!", target.pbThis,target.abilityName,user.pbThis(true)) end user.pbParalyze(target,msg) end battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::OnBeingHit.add(:WANDERINGSPIRIT, proc { |ability, user, target, move, battle| next if !move.pbContactMove?(user) next if user.ungainableAbility? || [:RECEIVER, :WONDERGUARD].include?(user.ability_id) oldUserAbil = nil oldTargetAbil = nil battle.pbShowAbilitySplash(target) if user.opposes?(target) if user.affectedByContactEffect?(Battle::Scene::USE_ABILITY_SPLASH) battle.pbShowAbilitySplash(user, true, false) if user.opposes?(target) oldUserAbil = user.ability oldTargetAbil = target.ability user.ability = oldTargetAbil target.ability = oldUserAbil if user.opposes?(target) battle.pbReplaceAbilitySplash(user) battle.pbReplaceAbilitySplash(target) end if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} swapped Abilities with {2}!", target.pbThis, user.pbThis(true))) else battle.pbDisplay(_INTL("{1} swapped its {2} Ability with {3}'s {4} Ability!", target.pbThis, user.abilityName, user.pbThis(true), target.abilityName)) end if user.opposes?(target) battle.pbHideAbilitySplash(user) battle.pbHideAbilitySplash(target) end end battle.pbHideAbilitySplash(target) if user.opposes?(target) user.pbOnLosingAbility(oldUserAbil) target.pbOnLosingAbility(oldTargetAbil) user.pbTriggerAbilityOnGainingIt target.pbTriggerAbilityOnGainingIt } ) Battle::AbilityEffects::OnBeingHit.add(:WATERCOMPACTION, proc { |ability,user,target,move,battle| next if move.calcType != :WATER target.pbRaiseStatStageByAbility(:DEFENSE,2,target) } ) Battle::AbilityEffects::OnBeingHit.add(:WEAKARMOR, proc { |ability,user,target,move,battle| next if !move.physicalMove? next if !target.pbCanLowerStatStage?(:DEFENSE, target) && !target.pbCanRaiseStatStage?(:SPEED, target) battle.pbShowAbilitySplash(target) target.pbLowerStatStageByAbility(:DEFENSE, 1, target, false) target.pbRaiseStatStageByAbility(:SPEED, (Settings::MECHANICS_GENERATION >= 7) ? 2 : 1, target, false) battle.pbHideAbilitySplash(target) } ) #=============================================================================== # OnDealingHit handlers #=============================================================================== Battle::AbilityEffects::OnDealingHit.add(:POISONTOUCH, proc { |ability,user,target,move,battle| next if !move.contactMove? next if battle.pbRandom(100)>=30 battle.pbShowAbilitySplash(user) if target.hasActiveAbility?(:SHIELDDUST) && !battle.moldBreaker battle.pbShowAbilitySplash(target) if !Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} is unaffected!",target.pbThis)) end battle.pbHideAbilitySplash(target) elsif target.pbCanPoison?(user,Battle::Scene::USE_ABILITY_SPLASH) msg = nil if !Battle::Scene::USE_ABILITY_SPLASH msg = _INTL("{1}'s {2} poisoned {3}!",user.pbThis,user.abilityName,target.pbThis(true)) end target.pbPoison(user,msg) end battle.pbHideAbilitySplash(user) } ) #=============================================================================== # OnEndOfUsingMove handlers #=============================================================================== Battle::AbilityEffects::OnEndOfUsingMove.add(:BEASTBOOST, proc { |ability,user,targets,move,battle| next if battle.pbAllFainted?(user.idxOpposingSide) numFainted = 0 targets.each { |b| numFainted += 1 if b.damageState.fainted } next if numFainted == 0 userStats = user.plainStats highestStatValue = 0 userStats.each_value { |value| highestStatValue = value if highestStatValue < value } GameData::Stat.each_main_battle do |s| next if userStats[s.id] < highestStatValue if user.pbCanRaiseStatStage?(s.id, user) user.pbRaiseStatStageByAbility(s.id, numFainted, user) end break end } ) Battle::AbilityEffects::OnEndOfUsingMove.add(:CHILLINGNEIGH, proc { |ability, user, targets, move, battle| next if battle.pbAllFainted?(user.idxOpposingSide) numFainted = 0 targets.each { |b| numFainted += 1 if b.damageState.fainted } next if numFainted == 0 || !user.pbCanRaiseStatStage?(:ATTACK, user) user.ability_id = :CHILLINGNEIGH # So the As One abilities can just copy this user.pbRaiseStatStageByAbility(:ATTACK, 1, user) user.ability_id = ability } ) Battle::AbilityEffects::OnEndOfUsingMove.copy(:CHILLINGNEIGH, :ASONECHILLINGNEIGH) Battle::AbilityEffects::OnEndOfUsingMove.add(:GRIMNEIGH, proc { |ability, user, targets, move, battle| next if battle.pbAllFainted?(user.idxOpposingSide) numFainted = 0 targets.each { |b| numFainted += 1 if b.damageState.fainted } next if numFainted == 0 || !user.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user) user.ability_id = :GRIMNEIGH # So the As One abilities can just copy this user.pbRaiseStatStageByAbility(:SPECIAL_ATTACK, 1, user) user.ability_id = ability } ) Battle::AbilityEffects::OnEndOfUsingMove.copy(:GRIMNEIGH, :ASONEGRIMNEIGH) Battle::AbilityEffects::OnEndOfUsingMove.add(:MAGICIAN, proc { |ability,user,targets,move,battle| next if battle.futureSight next if !move.pbDamagingMove? next if user.item next if user.wild? targets.each do |b| next if b.damageState.unaffected || b.damageState.substitute next if !b.item next if b.unlosableItem?(b.item) || user.unlosableItem?(b.item) battle.pbShowAbilitySplash(user) if b.hasActiveAbility?(:STICKYHOLD) battle.pbShowAbilitySplash(b) if user.opposes?(b) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s item cannot be stolen!",b.pbThis)) end battle.pbHideAbilitySplash(b) if user.opposes?(b) next end user.item = b.item b.item = nil b.effects[PBEffects::Unburden] = true if b.hasActiveAbility?(:UNBURDEN) if battle.wildBattle? && !user.initialItem && user.item == b.initialItem user.setInitialItem(user.item) b.setInitialItem(nil) end if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} stole {2}'s {3}!",user.pbThis, b.pbThis(true),user.itemName)) else battle.pbDisplay(_INTL("{1} stole {2}'s {3} with {4}!",user.pbThis, b.pbThis(true),user.itemName,user.abilityName)) end battle.pbHideAbilitySplash(user) user.pbHeldItemTriggerCheck break end } ) Battle::AbilityEffects::OnEndOfUsingMove.add(:MOXIE, proc { |ability,user,targets,move,battle| next if battle.pbAllFainted?(user.idxOpposingSide) numFainted = 0 targets.each { |b| numFainted += 1 if b.damageState.fainted } next if numFainted==0 || !user.pbCanRaiseStatStage?(:ATTACK,user) user.pbRaiseStatStageByAbility(:ATTACK,numFainted,user) } ) #=============================================================================== # AfterMoveUseFromTarget handlers #=============================================================================== Battle::AbilityEffects::AfterMoveUseFromTarget.add(:BERSERK, proc { |ability, target, user, move, switched_battlers, battle| next if !move.damagingMove? next if !target.droppedBelowHalfHP next if !target.pbCanRaiseStatStage?(:SPECIAL_ATTACK,target) target.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,target) } ) Battle::AbilityEffects::AfterMoveUseFromTarget.add(:COLORCHANGE, proc { |ability, target, user, move, switched_battlers, battle| next if target.damageState.calcDamage==0 || target.damageState.substitute next if !move.calcType || GameData::Type.get(move.calcType).pseudo_type next if target.pbHasType?(move.calcType) && !target.pbHasOtherType?(move.calcType) typeName = GameData::Type.get(move.calcType).name battle.pbShowAbilitySplash(target) target.pbChangeTypes(move.calcType) battle.pbDisplay(_INTL("{1}'s type changed to {2} because of its {3}!", target.pbThis, typeName, target.abilityName)) battle.pbHideAbilitySplash(target) } ) Battle::AbilityEffects::AfterMoveUseFromTarget.add(:PICKPOCKET, proc { |ability, target, user, move, switched_battlers, battle| # NOTE: According to Bulbapedia, this can still trigger to steal the user's # item even if it was switched out by a Red Card. This doesn't make # sense, so this code doesn't do it. next if target.wild? next if switched_battlers.include?(user.index) # User was switched out next if !move.contactMove? next if user.effects[PBEffects::Substitute]>0 || target.damageState.substitute next if target.item || !user.item next if user.unlosableItem?(user.item) || target.unlosableItem?(user.item) battle.pbShowAbilitySplash(target) if user.hasActiveAbility?(:STICKYHOLD) battle.pbShowAbilitySplash(user) if target.opposes?(user) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s item cannot be stolen!",user.pbThis)) end battle.pbHideAbilitySplash(user) if target.opposes?(user) battle.pbHideAbilitySplash(target) next end target.item = user.item user.item = nil user.effects[PBEffects::Unburden] = true if user.hasActiveAbility?(:UNBURDEN) if battle.wildBattle? && !target.initialItem && target.item == user.initialItem target.setInitialItem(target.item) user.setInitialItem(nil) end battle.pbDisplay(_INTL("{1} pickpocketed {2}'s {3}!",target.pbThis, user.pbThis(true),target.itemName)) battle.pbHideAbilitySplash(target) target.pbHeldItemTriggerCheck } ) #=============================================================================== # EndOfRoundWeather handlers #=============================================================================== Battle::AbilityEffects::EndOfRoundWeather.add(:DRYSKIN, proc { |ability,weather,battler,battle| case weather when :Sun, :HarshSun battle.pbShowAbilitySplash(battler) battle.scene.pbDamageAnimation(battler) battler.pbReduceHP(battler.totalhp/8,false) battle.pbDisplay(_INTL("{1} was hurt by the sunlight!",battler.pbThis)) battle.pbHideAbilitySplash(battler) battler.pbItemHPHealCheck when :Rain, :HeavyRain next if !battler.canHeal? battle.pbShowAbilitySplash(battler) battler.pbRecoverHP(battler.totalhp/8) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s HP was restored.",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} restored its HP.",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) end } ) Battle::AbilityEffects::EndOfRoundWeather.add(:ICEBODY, proc { |ability,weather,battler,battle| next unless weather == :Hail next if !battler.canHeal? battle.pbShowAbilitySplash(battler) battler.pbRecoverHP(battler.totalhp/16) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s HP was restored.",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} restored its HP.",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::EndOfRoundWeather.add(:ICEFACE, proc { |ability, weather, battler, battle| next if weather != :Hail next if !battler.canRestoreIceFace || battler.form != 1 battle.pbShowAbilitySplash(battler) if !Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s {2} activated!", battler.pbThis, battler.abilityName)) end battler.pbChangeForm(0, _INTL("{1} transformed!", battler.pbThis)) battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::EndOfRoundWeather.add(:RAINDISH, proc { |ability,weather,battler,battle| next unless [:Rain, :HeavyRain].include?(weather) next if !battler.canHeal? battle.pbShowAbilitySplash(battler) battler.pbRecoverHP(battler.totalhp/16) if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s HP was restored.",battler.pbThis)) else battle.pbDisplay(_INTL("{1}'s {2} restored its HP.",battler.pbThis,battler.abilityName)) end battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::EndOfRoundWeather.add(:SOLARPOWER, proc { |ability,weather,battler,battle| next unless [:Sun, :HarshSun].include?(weather) battle.pbShowAbilitySplash(battler) battle.scene.pbDamageAnimation(battler) battler.pbReduceHP(battler.totalhp/8,false) battle.pbDisplay(_INTL("{1} was hurt by the sunlight!",battler.pbThis)) battle.pbHideAbilitySplash(battler) battler.pbItemHPHealCheck } ) #=============================================================================== # EndOfRoundHealing handlers #=============================================================================== Battle::AbilityEffects::EndOfRoundHealing.add(:HEALER, proc { |ability,battler,battle| next unless battle.pbRandom(100)<30 battler.allAllies.each do |b| next if b.status == :NONE battle.pbShowAbilitySplash(battler) oldStatus = b.status b.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH case oldStatus when :SLEEP battle.pbDisplay(_INTL("{1}'s {2} woke its partner up!",battler.pbThis,battler.abilityName)) when :POISON battle.pbDisplay(_INTL("{1}'s {2} cured its partner's poison!",battler.pbThis,battler.abilityName)) when :BURN battle.pbDisplay(_INTL("{1}'s {2} healed its partner's burn!",battler.pbThis,battler.abilityName)) when :PARALYSIS battle.pbDisplay(_INTL("{1}'s {2} cured its partner's paralysis!",battler.pbThis,battler.abilityName)) when :FROZEN battle.pbDisplay(_INTL("{1}'s {2} defrosted its partner!",battler.pbThis,battler.abilityName)) end end battle.pbHideAbilitySplash(battler) end } ) Battle::AbilityEffects::EndOfRoundHealing.add(:HYDRATION, proc { |ability,battler,battle| next if battler.status == :NONE next if ![:Rain, :HeavyRain].include?(battler.effectiveWeather) battle.pbShowAbilitySplash(battler) oldStatus = battler.status battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH case oldStatus when :SLEEP battle.pbDisplay(_INTL("{1}'s {2} woke it up!",battler.pbThis,battler.abilityName)) when :POISON battle.pbDisplay(_INTL("{1}'s {2} cured its poison!",battler.pbThis,battler.abilityName)) when :BURN battle.pbDisplay(_INTL("{1}'s {2} healed its burn!",battler.pbThis,battler.abilityName)) when :PARALYSIS battle.pbDisplay(_INTL("{1}'s {2} cured its paralysis!",battler.pbThis,battler.abilityName)) when :FROZEN battle.pbDisplay(_INTL("{1}'s {2} defrosted it!",battler.pbThis,battler.abilityName)) end end battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::EndOfRoundHealing.add(:SHEDSKIN, proc { |ability,battler,battle| next if battler.status == :NONE next unless battle.pbRandom(100)<30 battle.pbShowAbilitySplash(battler) oldStatus = battler.status battler.pbCureStatus(Battle::Scene::USE_ABILITY_SPLASH) if !Battle::Scene::USE_ABILITY_SPLASH case oldStatus when :SLEEP battle.pbDisplay(_INTL("{1}'s {2} woke it up!",battler.pbThis,battler.abilityName)) when :POISON battle.pbDisplay(_INTL("{1}'s {2} cured its poison!",battler.pbThis,battler.abilityName)) when :BURN battle.pbDisplay(_INTL("{1}'s {2} healed its burn!",battler.pbThis,battler.abilityName)) when :PARALYSIS battle.pbDisplay(_INTL("{1}'s {2} cured its paralysis!",battler.pbThis,battler.abilityName)) when :FROZEN battle.pbDisplay(_INTL("{1}'s {2} defrosted it!",battler.pbThis,battler.abilityName)) end end battle.pbHideAbilitySplash(battler) } ) #=============================================================================== # EndOfRoundEffect handlers #=============================================================================== Battle::AbilityEffects::EndOfRoundEffect.add(:BADDREAMS, proc { |ability,battler,battle| battle.allOtherSideBattlers(battler.index).each do |b| next if !b.near?(battler) || !b.asleep? battle.pbShowAbilitySplash(battler) next if !b.takesIndirectDamage?(Battle::Scene::USE_ABILITY_SPLASH) b.pbTakeEffectDamage(b.totalhp / 8) { |hp_lost| if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} is tormented!", b.pbThis)) else battle.pbDisplay(_INTL("{1} is tormented by {2}'s {3}!", b.pbThis, battler.pbThis(true), battler.abilityName)) end battle.pbHideAbilitySplash(battler) } end } ) Battle::AbilityEffects::EndOfRoundEffect.add(:MOODY, proc { |ability,battler,battle| randomUp = [] randomDown = [] if Settings::MECHANICS_GENERATION >= 8 GameData::Stat.each_main_battle do |s| randomUp.push(s.id) if battler.pbCanRaiseStatStage?(s.id, battler) randomDown.push(s.id) if battler.pbCanLowerStatStage?(s.id, battler) end else GameData::Stat.each_battle do |s| randomUp.push(s.id) if battler.pbCanRaiseStatStage?(s.id, battler) randomDown.push(s.id) if battler.pbCanLowerStatStage?(s.id, battler) end end next if randomUp.length==0 && randomDown.length==0 battle.pbShowAbilitySplash(battler) if randomUp.length>0 r = battle.pbRandom(randomUp.length) battler.pbRaiseStatStageByAbility(randomUp[r],2,battler,false) randomDown.delete(randomUp[r]) end if randomDown.length>0 r = battle.pbRandom(randomDown.length) battler.pbLowerStatStageByAbility(randomDown[r],1,battler,false) end battle.pbHideAbilitySplash(battler) battler.pbItemStatRestoreCheck if randomDown.length>0 battler.pbItemOnStatDropped } ) Battle::AbilityEffects::EndOfRoundEffect.add(:SPEEDBOOST, proc { |ability,battler,battle| # A Pokémon's turnCount is 0 if it became active after the beginning of a # round if battler.turnCount > 0 && battle.choices[battler.index][0] != :Run && battler.pbCanRaiseStatStage?(:SPEED, battler) battler.pbRaiseStatStageByAbility(:SPEED,1,battler) end } ) #=============================================================================== # EndOfRoundGainItem handlers #=============================================================================== Battle::AbilityEffects::EndOfRoundGainItem.add(:BALLFETCH, proc { |ability, battler, battle| next if battler.item next if battle.first_poke_ball.nil? battle.pbShowAbilitySplash(battler) battler.item = battle.first_poke_ball battler.setInitialItem(battler.item) if !battler.initialItem battle.first_poke_ball = nil battle.pbDisplay(_INTL("{1} retrieved the thrown {2}!", battler.pbThis, battler.itemName)) battle.pbHideAbilitySplash(battler) battler.pbHeldItemTriggerCheck } ) Battle::AbilityEffects::EndOfRoundGainItem.add(:HARVEST, proc { |ability,battler,battle| next if battler.item next if !battler.recycleItem || !GameData::Item.get(battler.recycleItem).is_berry? if ![:Sun, :HarshSun].include?(battler.effectiveWeather) next unless battle.pbRandom(100)<50 end battle.pbShowAbilitySplash(battler) battler.item = battler.recycleItem battler.setRecycleItem(nil) battler.setInitialItem(battler.item) if !battler.initialItem battle.pbDisplay(_INTL("{1} harvested one {2}!",battler.pbThis,battler.itemName)) battle.pbHideAbilitySplash(battler) battler.pbHeldItemTriggerCheck } ) Battle::AbilityEffects::EndOfRoundGainItem.add(:PICKUP, proc { |ability,battler,battle| next if battler.item foundItem = nil fromBattler = nil use = 0 battle.allBattlers.each do |b| next if b.index==battler.index next if b.effects[PBEffects::PickupUse]<=use foundItem = b.effects[PBEffects::PickupItem] fromBattler = b use = b.effects[PBEffects::PickupUse] end next if !foundItem battle.pbShowAbilitySplash(battler) battler.item = foundItem fromBattler.effects[PBEffects::PickupItem] = nil fromBattler.effects[PBEffects::PickupUse] = 0 fromBattler.setRecycleItem(nil) if fromBattler.recycleItem==foundItem if battle.wildBattle? && !battler.initialItem && fromBattler.initialItem==foundItem battler.setInitialItem(foundItem) fromBattler.setInitialItem(nil) end battle.pbDisplay(_INTL("{1} found one {2}!",battler.pbThis,battler.itemName)) battle.pbHideAbilitySplash(battler) battler.pbHeldItemTriggerCheck } ) #=============================================================================== # CertainSwitching handlers #=============================================================================== # There aren't any! #=============================================================================== # TrappingByTarget handlers #=============================================================================== Battle::AbilityEffects::TrappingByTarget.add(:ARENATRAP, proc { |ability,switcher,bearer,battle| next true if !switcher.airborne? } ) Battle::AbilityEffects::TrappingByTarget.add(:MAGNETPULL, proc { |ability,switcher,bearer,battle| next true if switcher.pbHasType?(:STEEL) } ) Battle::AbilityEffects::TrappingByTarget.add(:SHADOWTAG, proc { |ability,switcher,bearer,battle| next true if !switcher.hasActiveAbility?(:SHADOWTAG) } ) #=============================================================================== # OnSwitchIn handlers #=============================================================================== Battle::AbilityEffects::OnSwitchIn.add(:AIRLOCK, proc { |ability, battler, battle, switch_in| battle.pbShowAbilitySplash(battler) if !Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1} has {2}!",battler.pbThis,battler.abilityName)) end battle.pbDisplay(_INTL("The effects of the weather disappeared.")) battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnSwitchIn.copy(:AIRLOCK, :CLOUDNINE) Battle::AbilityEffects::OnSwitchIn.add(:ANTICIPATION, proc { |ability, battler, battle, switch_in| next if !battler.pbOwnedByPlayer? battlerTypes = battler.pbTypes(true) types = battlerTypes found = false battle.allOtherSideBattlers(battler.index).each do |b| b.eachMove do |m| next if m.statusMove? if types.length > 0 moveType = m.type if Settings::MECHANICS_GENERATION >= 6 && m.function == "TypeDependsOnUserIVs" # Hidden Power moveType = pbHiddenPower(b.pokemon)[0] end eff = Effectiveness.calculate(moveType, types[0], types[1], types[2]) next if Effectiveness.ineffective?(eff) next if !Effectiveness.super_effective?(eff) && !["OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"].include?(m.function) else next if !["OHKO", "OHKOIce", "OHKOHitsUndergroundTarget"].include?(m.function) end found = true break end break if found end if found battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} shuddered with anticipation!",battler.pbThis)) battle.pbHideAbilitySplash(battler) end } ) Battle::AbilityEffects::OnSwitchIn.add(:ASONECHILLINGNEIGH, proc { |ability, battler, battle, switch_in| battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} has two Abilities!", battler.pbThis)) battle.pbHideAbilitySplash(battler) battler.ability_id = :UNNERVE battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} is too nervous to eat Berries!", battler.pbOpposingTeam)) battle.pbHideAbilitySplash(battler) battler.ability_id = ability } ) Battle::AbilityEffects::OnSwitchIn.copy(:ASONECHILLINGNEIGH, :ASONEGRIMNEIGH) Battle::AbilityEffects::OnSwitchIn.add(:AURABREAK, proc { |ability, battler, battle, switch_in| battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} reversed all other Pokémon's auras!",battler.pbThis)) battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnSwitchIn.add(:COMATOSE, proc { |ability, battler, battle, switch_in| battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} is drowsing!",battler.pbThis)) battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnSwitchIn.add(:CURIOUSMEDICINE, proc { |ability, battler, battle, switch_in| next if battler.allAllies.none? { |b| b.hasAlteredStatStages? } battle.pbShowAbilitySplash(battler) battler.allAllies.each do |b| next if !b.hasAlteredStatStages? b.pbResetStatStages if Battle::Scene::USE_ABILITY_SPLASH battle.pbDisplay(_INTL("{1}'s stat changes were removed!", b.pbThis)) else battle.pbDisplay(_INTL("{1}'s stat changes were removed by {2}'s {3}!", b.pbThis, battler.pbThis(true), battler.abilityName)) end end battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnSwitchIn.add(:DARKAURA, proc { |ability, battler, battle, switch_in| battle.pbShowAbilitySplash(battler) battle.pbDisplay(_INTL("{1} is radiating a dark aura!",battler.pbThis)) battle.pbHideAbilitySplash(battler) } ) Battle::AbilityEffects::OnSwitchIn.add(:DAUNTLESSSHIELD, proc { |ability, battler, battle, switch_in| battler.pbRaiseStatStageByAbility(:ATTACK, 1, battler) } ) Battle::AbilityEffects::OnSwitchIn.add(:DELTASTREAM, proc { |ability, battler, battle, switch_in| battle.pbStartWeatherAbility(:StrongWinds, battler, true) } ) Battle::AbilityEffects::OnSwitchIn.add(:DESOLATELAND, proc { |ability, battler, battle, switch_in| battle.pbStartWeatherAbility(:HarshSun, battler, true) } ) Battle::AbilityEffects::OnSwitchIn.add(:DOWNLOAD, proc { |ability, battler, battle, switch_in| oDef = oSpDef = 0 battle.allOtherSideBattlers(battler.index).each do |b| oDef += b.defense oSpDef += b.spdef end stat = (oDef