From 1fb3ff540897ec748df870f313ea0273256d5e1a Mon Sep 17 00:00:00 2001 From: Maruno17 Date: Sun, 19 Sep 2021 19:03:17 +0100 Subject: [PATCH] Refactoring of code relating to switching, effect damage and effects that trigger after a move is used --- .../001_Battler/001_PokeBattle_Battler.rb | 4 +- .../001_Battler/002_Battler_Initialize.rb | 4 +- .../001_Battler/003_Battler_ChangeSelf.rb | 16 +- .../001_Battler/006_Battler_AbilityAndItem.rb | 84 ++------- .../001_Battler/007_Battler_UseMove.rb | 20 +- .../010_Battler_UseMove_TriggerEffects.rb | 78 ++++---- Data/Scripts/011_Battle/002_BattleHandlers.rb | 12 +- .../011_Battle/002_Move/002_Move_Usage.rb | 16 +- .../002_Move/005_MoveEffects_Misc.rb | 2 +- .../002_Move/006_MoveEffects_BattlerStats.rb | 2 +- .../002_Move/007_MoveEffects_BattlerOther.rb | 26 +-- .../008_MoveEffects_MoveAttributes.rb | 11 +- .../012_MoveEffects_ChangeMoveEffect.rb | 2 +- .../013_MoveEffects_SwitchingActing.rb | 49 ++--- .../003_Battle/003_Battle_StartAndEnd.rb | 2 +- .../003_Battle/006_Battle_Action_Switching.rb | 171 ++++++++++++------ .../003_Battle/009_Battle_Action_Other.rb | 6 +- .../003_Battle/011_Battle_Phase_Attack.rb | 2 +- .../003_Battle/012_Battle_Phase_EndOfRound.rb | 58 +++--- .../003_BattleHandlers_Abilities.rb | 38 ++-- .../011_Battle/004_BattleHandlers_Items.rb | 49 +++-- .../005_PokeBattle_BattleArena.rb | 9 +- .../011_Battle/007_PokeBattle_DamageState.rb | 20 +- Data/Scripts/011_Battle/Gen 8 abilities.rb | 7 +- 24 files changed, 345 insertions(+), 343 deletions(-) diff --git a/Data/Scripts/011_Battle/001_Battler/001_PokeBattle_Battler.rb b/Data/Scripts/011_Battle/001_Battler/001_PokeBattle_Battler.rb index 2af110ec6..83c8c91f7 100644 --- a/Data/Scripts/011_Battle/001_Battler/001_PokeBattle_Battler.rb +++ b/Data/Scripts/011_Battle/001_Battler/001_PokeBattle_Battler.rb @@ -38,13 +38,13 @@ class PokeBattle_Battler attr_accessor :lastRoundMoveFailed # For Stomping Tantrum attr_accessor :movesUsed attr_accessor :currentMove # ID of multi-turn move currently being used - attr_accessor :tookDamage # Boolean for whether self took damage this round + attr_accessor :droppedBelowHalfHP # Used for Emergency Exit/Wimp Out + attr_accessor :tookDamageThisRound # Boolean for whether self took damage this round attr_accessor :tookPhysicalHit attr_accessor :statsRaised # Boolean for whether self's stat(s) raised this round attr_accessor :statsLowered # Boolean for whether self's stat(s) lowered this round attr_accessor :canRestoreIceFace # Whether Hail started in the round attr_accessor :damageState - attr_accessor :initialHP # Set at the start of each move's usage #============================================================================= # Complex accessors diff --git a/Data/Scripts/011_Battle/001_Battler/002_Battler_Initialize.rb b/Data/Scripts/011_Battle/001_Battler/002_Battler_Initialize.rb index 486be11c6..bb58e6157 100644 --- a/Data/Scripts/011_Battle/001_Battler/002_Battler_Initialize.rb +++ b/Data/Scripts/011_Battle/001_Battler/002_Battler_Initialize.rb @@ -143,12 +143,12 @@ class PokeBattle_Battler @effects[PBEffects::Telekinesis] = 0 end @fainted = (@hp==0) - @initialHP = 0 @lastAttacker = [] @lastFoeAttacker = [] @lastHPLost = 0 @lastHPLostFromFoe = 0 - @tookDamage = false + @droppedBelowHalfHP = false + @tookDamageThisRound = false @tookPhysicalHit = false @statsRaised = false @statsLowered = false diff --git a/Data/Scripts/011_Battle/001_Battler/003_Battler_ChangeSelf.rb b/Data/Scripts/011_Battle/001_Battler/003_Battler_ChangeSelf.rb index 06226570e..f6afb670c 100644 --- a/Data/Scripts/011_Battle/001_Battler/003_Battler_ChangeSelf.rb +++ b/Data/Scripts/011_Battle/001_Battler/003_Battler_ChangeSelf.rb @@ -12,7 +12,10 @@ class PokeBattle_Battler raise _INTL("HP less than 0") if @hp<0 raise _INTL("HP greater than total HP") if @hp>@totalhp @battle.scene.pbHPChanged(self,oldHP,anim) if anyAnim && amt>0 - @tookDamage = true if amt>0 && registerDamage + if amt > 0 && registerDamage + @droppedBelowHalfHP = true if @hp < @totalhp / 2 && @hp + amt >= @totalhp / 2 + @tookDamageThisRound = true + end return amt end @@ -26,6 +29,7 @@ class PokeBattle_Battler raise _INTL("HP less than 0") if @hp<0 raise _INTL("HP greater than total HP") if @hp>@totalhp @battle.scene.pbHPChanged(self,oldHP,anim) if anyAnim && amt>0 + @droppedBelowHalfHP = false if @hp >= @totalhp / 2 return amt end @@ -46,6 +50,14 @@ class PokeBattle_Battler end end + def pbTakeEffectDamage(amt, show_anim = true) + hp_lost = pbReduceHP(amt, show_anim) + yield hp_lost if block_given? # Show message + pbItemHPHealCheck + pbAbilitiesOnDamageTaken + pbFaint if fainted? + end + def pbFaint(showMessage=true) if !fainted? PBDebug.log("!!!***Can't faint with HP greater than 0") @@ -310,7 +322,7 @@ class PokeBattle_Battler @effects[PBEffects::WeightChange] = target.effects[PBEffects::WeightChange] @battle.scene.pbRefreshOne(@index) @battle.pbDisplay(_INTL("{1} transformed into {2}!",pbThis,target.pbThis(true))) - pbOnAbilityChanged(oldAbil) + pbOnLosingAbility(oldAbil) end def pbHyperMode; end diff --git a/Data/Scripts/011_Battle/001_Battler/006_Battler_AbilityAndItem.rb b/Data/Scripts/011_Battle/001_Battler/006_Battler_AbilityAndItem.rb index 307f715e2..6e2f456c2 100644 --- a/Data/Scripts/011_Battle/001_Battler/006_Battler_AbilityAndItem.rb +++ b/Data/Scripts/011_Battle/001_Battler/006_Battler_AbilityAndItem.rb @@ -1,63 +1,4 @@ class PokeBattle_Battler - #============================================================================= - # Called when a Pokémon (self) is sent into battle or its ability changes. - #============================================================================= - def pbEffectsOnSwitchIn(switchIn=false) - # Healing Wish/Lunar Dance/entry hazards - @battle.pbOnActiveOne(self) if switchIn - # Primal Revert upon entering battle - @battle.pbPrimalReversion(@index) if !fainted? - # Ending primordial weather, checking Trace - pbContinualAbilityChecks(true) - # Abilities that trigger upon switching in - if (!fainted? && unstoppableAbility?) || abilityActive? - BattleHandlers.triggerAbilityOnSwitchIn(self.ability,self,@battle) - end - # Check for end of primordial weather - @battle.pbEndPrimordialWeather - # Items that trigger upon switching in (Air Balloon message) - if switchIn && itemActive? - BattleHandlers.triggerItemOnSwitchIn(self.item,self,@battle) - end - # Berry check, status-curing ability check - pbHeldItemTriggerCheck if switchIn - pbAbilityStatusCureCheck - end - - #============================================================================= - # Called when a Pokémon enters battle, and when Ally Switch is used. - #============================================================================= - def pbEffectsOnEnteringPosition - position = @battle.positions[@index] - # Healing Wish - if position.effects[PBEffects::HealingWish] - if canHeal? || self.status != :NONE - @battle.pbCommonAnimation("HealingWish", self) - @battle.pbDisplay(_INTL("The healing wish came true for {1}!", pbThis(true))) - pbRecoverHP(@totalhp) - pbCureStatus(false) - position.effects[PBEffects::HealingWish] = false - elsif Settings::MECHANICS_GENERATION < 8 - position.effects[PBEffects::HealingWish] = false - end - end - # Lunar Dance - if position.effects[PBEffects::LunarDance] - full_pp = true - eachMove { |m| full_pp = false if m.pp < m.total_pp } - if canHeal? || self.status != :NONE || !full_pp - @battle.pbCommonAnimation("LunarDance", self) - @battle.pbDisplay(_INTL("{1} became cloaked in mystical moonlight!", pbThis)) - pbRecoverHP(@totalhp) - pbCureStatus(false) - eachMove { |m| m.pp = m.total_pp } - position.effects[PBEffects::LunarDance] = false - elsif Settings::MECHANICS_GENERATION < 8 - position.effects[PBEffects::LunarDance] = false - end - end - end - #============================================================================= # Ability effects #============================================================================= @@ -86,13 +27,11 @@ class PokeBattle_Battler end end - # Used for Emergency Exit/Wimp Out. - def pbAbilitiesOnDamageTaken(oldHP,newHP=-1) + # Used for Emergency Exit/Wimp Out. Returns whether self has switched out. + def pbAbilitiesOnDamageTaken(move_user = nil) + return false if !@droppedBelowHalfHP return false if !abilityActive? - newHP = @hp if newHP<0 - return false if oldHP<@totalhp/2 || newHP>=@totalhp/2 # Didn't drop below half - ret = BattleHandlers.triggerAbilityOnHPDroppedBelowHalf(self.ability,self,@battle) - return ret # Whether self has switched out + return BattleHandlers.triggerAbilityOnHPDroppedBelowHalf(self.ability, self, move_user, @battle) end def pbAbilityOnTerrainChange(ability_changed = false) @@ -149,7 +88,7 @@ class PokeBattle_Battler #============================================================================= # Ability change #============================================================================= - def pbOnAbilityChanged(oldAbil) + def pbOnLosingAbility(oldAbil) if @effects[PBEffects::Illusion] && oldAbil == :ILLUSION @effects[PBEffects::Illusion] = nil if !@effects[PBEffects::Transform] @@ -160,10 +99,23 @@ class PokeBattle_Battler end @effects[PBEffects::GastroAcid] = false if unstoppableAbility? @effects[PBEffects::SlowStart] = 0 if self.ability != :SLOWSTART + # Check for end of primordial weather + @battle.pbEndPrimordialWeather # Revert form if Flower Gift/Forecast was lost pbCheckFormOnWeatherChange(true) # Abilities that trigger when the terrain changes pbAbilityOnTerrainChange(true) + end + + def pbTriggerAbilityOnGainingIt + # Ending primordial weather, checking Trace + pbContinualAbilityChecks(true) # Don't trigger Traced ability as it's triggered below + # Abilities that trigger upon switching in + if (!fainted? && unstoppableAbility?) || abilityActive? + BattleHandlers.triggerAbilityOnSwitchIn(self.ability, self, @battle) + end + # Status-curing ability check + pbAbilityStatusCureCheck # Check for end of primordial weather @battle.pbEndPrimordialWeather end diff --git a/Data/Scripts/011_Battle/001_Battler/007_Battler_UseMove.rb b/Data/Scripts/011_Battle/001_Battler/007_Battler_UseMove.rb index 3e5f6c9bc..14230ecd6 100644 --- a/Data/Scripts/011_Battle/001_Battler/007_Battler_UseMove.rb +++ b/Data/Scripts/011_Battle/001_Battler/007_Battler_UseMove.rb @@ -125,7 +125,6 @@ class PokeBattle_Battler def pbConfusionDamage(msg) @damageState.reset - @damageState.initialHP = @hp confusionMove = PokeBattle_Confusion.new(@battle,nil) confusionMove.calcType = confusionMove.pbCalcType(self) # nil @damageState.typeMod = confusionMove.pbCalcTypeMod(confusionMove.calcType,self,self) # 8 @@ -326,14 +325,10 @@ class PokeBattle_Battler @battle.pbDisplay(_INTL("When the flame touched the powder on the Pokémon, it exploded!")) user.lastMoveFailed = true if ![:Rain, :HeavyRain].include?(user.effectiveWeather) && user.takesIndirectDamage? - oldHP = user.hp - user.pbReduceHP((user.totalhp/4.0).round,false) - user.pbFaint if user.fainted? + user.pbTakeEffectDamage((user.totalhp / 4.0).round, false) { |hp_lost| + battle.pbDisplay(_INTL("{1} is hurt by its {2}!", battler.pbThis, battler.itemName)) + } @battle.pbGainExp # In case user is KO'd by this - user.pbItemHPHealCheck - if user.pbAbilitiesOnDamageTaken(oldHP) - user.pbEffectsOnSwitchIn(true) - end end pbCancelMoves pbEndTurn(choice) @@ -389,13 +384,11 @@ class PokeBattle_Battler user.lastMoveFailed = true else # We have targets, or move doesn't use targets # Reset whole damage state, perform various success checks (not accuracy) - user.initialHP = user.hp + @battle.eachBattler { |b| b.droppedBelowHalfHP = false } targets.each do |b| b.damageState.reset - b.damageState.initialHP = b.hp - if !pbSuccessCheckAgainstTarget(move, user, b, targets) - b.damageState.unaffected = true - end + next if pbSuccessCheckAgainstTarget(move, user, b, targets) + b.damageState.unaffected = true end # Magic Coat/Magic Bounce checks (for moves which don't target Pokémon) if targets.length==0 && move.statusMove? && move.canMagicCoat? @@ -503,6 +496,7 @@ class PokeBattle_Battler user.pbFaint if user.fainted? # External/general effects after all hits. Eject Button, Shell Bell, etc. pbEffectsAfterMove(user,targets,move,realNumHits) + @battle.eachBattler { |b| b.droppedBelowHalfHP = false } end # End effect of Mold Breaker @battle.moldBreaker = false diff --git a/Data/Scripts/011_Battle/001_Battler/010_Battler_UseMove_TriggerEffects.rb b/Data/Scripts/011_Battle/001_Battler/010_Battler_UseMove_TriggerEffects.rb index 71aee89db..f7b6c0c16 100644 --- a/Data/Scripts/011_Battle/001_Battler/010_Battler_UseMove_TriggerEffects.rb +++ b/Data/Scripts/011_Battle/001_Battler/010_Battler_UseMove_TriggerEffects.rb @@ -154,71 +154,65 @@ class PokeBattle_Battler b.pbConsumeItem end end - # Pokémon switching caused by Roar, Whirlwind, Circle Throw, Dragon Tail - switchedBattlers = [] - move.pbSwitchOutTargetsEffect(user,targets,numHits,switchedBattlers) + switched_battlers = [] # Indices of battlers that were switched out somehow + # Target switching caused by Roar, Whirlwind, Circle Throw, Dragon Tail + move.pbSwitchOutTargetEffect(user, targets, numHits, switched_battlers) # Target's item, user's item, target's ability (all negated by Sheer Force) - if move.addlEffect==0 || !user.hasActiveAbility?(:SHEERFORCE) - pbEffectsAfterMove2(user,targets,move,numHits,switchedBattlers) + if !(user.hasActiveAbility?(:SHEERFORCE) && move.addlEffect > 0) + pbEffectsAfterMove2(user, targets, move, numHits, switched_battlers) end - # Some move effects that need to happen here, i.e. U-turn/Volt Switch - # switching, Baton Pass switching, Parting Shot switching, Relic Song's form - # changing, Fling/Natural Gift consuming item. + # Some move effects that need to happen here, i.e. user switching caused by + # U-turn/Volt Switch/Baton Pass/Parting Shot, Relic Song's form changing, + # Fling/Natural Gift consuming item. if !switchedBattlers.include?(user.index) move.pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers) end + # User's ability/item that switches the user out (all negated by Sheer Force) + if !(user.hasActiveAbility?(:SHEERFORCE) && move.addlEffect > 0) + pbEffectsAfterMove3(user, targets, move, numHits, switched_battlers) + end if numHits>0 @battle.eachBattler { |b| b.pbItemEndOfMoveCheck } end end # Everything in this method is negated by Sheer Force. - def pbEffectsAfterMove2(user,targets,move,numHits,switchedBattlers) - hpNow = user.hp # Intentionally determined now, before Shell Bell - # Target's held item (Eject Button, Red Card) - switchByItem = [] + def pbEffectsAfterMove2(user, targets, move, numHits, switched_battlers) + # Target's held item (Eject Button, Red Card, Eject Pack) @battle.pbPriority(true).each do |b| next if !targets.any? { |targetB| targetB.index==b.index } - next if b.damageState.unaffected || b.damageState.calcDamage==0 || - switchedBattlers.include?(b.index) + next if b.damageState.unaffected || b.damageState.calcDamage == 0 next if !b.itemActive? - BattleHandlers.triggerTargetItemAfterMoveUse(b.item,b,user,move,switchByItem,@battle) + BattleHandlers.triggerTargetItemAfterMoveUse(b.item, b, user, move, switched_battlers, @battle) end - @battle.moldBreaker = false if switchByItem.include?(user.index) - @battle.pbPriority(true).each do |b| - b.pbEffectsOnSwitchIn(true) if switchByItem.include?(b.index) - end - switchByItem.each { |idxB| switchedBattlers.push(idxB) } - # User's held item (Life Orb, Shell Bell) - if !switchedBattlers.include?(user.index) && user.itemActive? + # User's held item (Life Orb, Shell Bell, Throat Spray, Eject Pack) + if !switched_battlers.include?(user.index) && user.itemActive? # Only if user hasn't switched out BattleHandlers.triggerUserItemAfterMoveUse(user.item,user,targets,move,numHits,@battle) end # Target's ability (Berserk, Color Change, Emergency Exit, Pickpocket, Wimp Out) - switchWimpOut = [] @battle.pbPriority(true).each do |b| - next if !targets.any? { |targetB| targetB.index==b.index } - next if b.damageState.unaffected || switchedBattlers.include?(b.index) - next if !b.abilityActive? - BattleHandlers.triggerTargetAbilityAfterMoveUse(b.ability,b,user,move,switchedBattlers,@battle) - if !switchedBattlers.include?(b.index) && move.damagingMove? - if b.pbAbilitiesOnDamageTaken(b.damageState.initialHP) # Emergency Exit, Wimp Out - switchWimpOut.push(b.index) + if targets.any? { |targetB| targetB.index==b.index } + next if b.damageState.unaffected || switched_battlers.include?(b.index) + next if !b.abilityActive? + BattleHandlers.triggerTargetAbilityAfterMoveUse(b.ability, b, user, move, switched_battlers, @battle) + end + # Emergency Exit, Wimp Out (including for Pokémon hurt by Flame Burst) + if switched_battlers.empty? && move.damagingMove? && b.index != user.index + if b.pbAbilitiesOnDamageTaken(user) + switched_battlers.push(b.index) end end end - @battle.moldBreaker = false if switchWimpOut.include?(user.index) - @battle.pbPriority(true).each do |b| - next if b.index==user.index - b.pbEffectsOnSwitchIn(true) if switchWimpOut.include?(b.index) - end - switchWimpOut.each { |idxB| switchedBattlers.push(idxB) } + end + + # Everything in this method is negated by Sheer Force. + def pbEffectsAfterMove3(user, targets, move, numHits, switched_battlers) + # TODO: User's Eject Pack. + # User's ability (Emergency Exit, Wimp Out) - if !switchedBattlers.include?(user.index) && move.damagingMove? - hpNow = user.hp if user.hp 0 + target.pbReduceHP(target.damageState.hpLost, false, true, false) end end @@ -360,12 +360,12 @@ class PokeBattle_Move 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 + target.lastHPLost = damage # For Focus Punch + target.tookDamageThisRound = 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 + target.lastHPLostFromFoe = damage # For Metal Burst + target.lastFoeAttacker.push(user.index) # For Metal Burst end end end diff --git a/Data/Scripts/011_Battle/002_Move/005_MoveEffects_Misc.rb b/Data/Scripts/011_Battle/002_Move/005_MoveEffects_Misc.rb index b2fd54c66..8d55b280f 100644 --- a/Data/Scripts/011_Battle/002_Move/005_MoveEffects_Misc.rb +++ b/Data/Scripts/011_Battle/002_Move/005_MoveEffects_Misc.rb @@ -684,7 +684,7 @@ class PokeBattle_Move_UserSwapsPositionsWithAlly < PokeBattle_Move if @battle.pbSwapBattlers(idxA,idxB) @battle.pbDisplay(_INTL("{1} and {2} switched places!", @battle.battlers[idxB].pbThis,@battle.battlers[idxA].pbThis(true))) - [idxA, idxB].each { |idx| @battle.battlers[idx].pbEffectsOnEnteringPosition } + [idxA, idxB].each { |idx| @battle.pbEffectsOnBattlerEnteringPosition(@battle.battlers[idx]) } end end end diff --git a/Data/Scripts/011_Battle/002_Move/006_MoveEffects_BattlerStats.rb b/Data/Scripts/011_Battle/002_Move/006_MoveEffects_BattlerStats.rb index 62291b5cd..52f3c3cde 100644 --- a/Data/Scripts/011_Battle/002_Move/006_MoveEffects_BattlerStats.rb +++ b/Data/Scripts/011_Battle/002_Move/006_MoveEffects_BattlerStats.rb @@ -59,7 +59,7 @@ class PokeBattle_Move_MaxUserAttackLoseHalfOfTotalHP < PokeBattle_Move def pbEffectGeneral(user) hpLoss = [user.totalhp/2,1].max - user.pbReduceHP(hpLoss,false) + user.pbReduceHP(hpLoss, false, false) if user.hasActiveAbility?(:CONTRARY) user.stages[:ATTACK] = -6 user.statsLowered = true diff --git a/Data/Scripts/011_Battle/002_Move/007_MoveEffects_BattlerOther.rb b/Data/Scripts/011_Battle/002_Move/007_MoveEffects_BattlerOther.rb index 5f7d66cc0..1ebce538a 100644 --- a/Data/Scripts/011_Battle/002_Move/007_MoveEffects_BattlerOther.rb +++ b/Data/Scripts/011_Battle/002_Move/007_MoveEffects_BattlerOther.rb @@ -891,7 +891,8 @@ class PokeBattle_Move_SetTargetAbilityToSimple < PokeBattle_Move @battle.pbReplaceAbilitySplash(target) @battle.pbDisplay(_INTL("{1} acquired {2}!",target.pbThis,target.abilityName)) @battle.pbHideAbilitySplash(target) - target.pbOnAbilityChanged(oldAbil) + target.pbOnLosingAbility(oldAbil) + target.pbTriggerAbilityOnGainingIt end end @@ -924,7 +925,8 @@ class PokeBattle_Move_SetTargetAbilityToInsomnia < PokeBattle_Move @battle.pbReplaceAbilitySplash(target) @battle.pbDisplay(_INTL("{1} acquired {2}!",target.pbThis,target.abilityName)) @battle.pbHideAbilitySplash(target) - target.pbOnAbilityChanged(oldAbil) + target.pbOnLosingAbility(oldAbil) + target.pbTriggerAbilityOnGainingIt end end @@ -963,8 +965,8 @@ class PokeBattle_Move_SetUserAbilityToTargetAbility < PokeBattle_Move @battle.pbDisplay(_INTL("{1} copied {2}'s {3}!", user.pbThis,target.pbThis(true),target.abilityName)) @battle.pbHideAbilitySplash(user) - user.pbOnAbilityChanged(oldAbil) - user.pbEffectsOnSwitchIn + user.pbOnLosingAbility(oldAbil) + user.pbTriggerAbilityOnGainingIt end end @@ -1002,8 +1004,8 @@ class PokeBattle_Move_SetTargetAbilityToUserAbility < PokeBattle_Move @battle.pbReplaceAbilitySplash(target) @battle.pbDisplay(_INTL("{1} acquired {2}!",target.pbThis,target.abilityName)) @battle.pbHideAbilitySplash(target) - target.pbOnAbilityChanged(oldAbil) - target.pbEffectsOnSwitchIn + target.pbOnLosingAbility(oldAbil) + target.pbTriggerAbilityOnGainingIt end end @@ -1069,10 +1071,10 @@ class PokeBattle_Move_UserTargetSwapAbilities < PokeBattle_Move @battle.pbHideAbilitySplash(user) @battle.pbHideAbilitySplash(target) end - user.pbOnAbilityChanged(oldUserAbil) - target.pbOnAbilityChanged(oldTargetAbil) - user.pbEffectsOnSwitchIn - target.pbEffectsOnSwitchIn + user.pbOnLosingAbility(oldUserAbil) + target.pbOnLosingAbility(oldTargetAbil) + user.pbTriggerAbilityOnGainingIt + target.pbTriggerAbilityOnGainingIt end end @@ -1094,7 +1096,7 @@ class PokeBattle_Move_NegateTargetAbility < PokeBattle_Move target.effects[PBEffects::GastroAcid] = true target.effects[PBEffects::Truant] = false @battle.pbDisplay(_INTL("{1}'s Ability was suppressed!",target.pbThis)) - target.pbOnAbilityChanged(target.ability) + target.pbOnLosingAbility(target.ability) end end @@ -1112,7 +1114,7 @@ class PokeBattle_Move_NegateTargetAbilityIfTargetActed < PokeBattle_Move target.effects[PBEffects::GastroAcid] = true target.effects[PBEffects::Truant] = false @battle.pbDisplay(_INTL("{1}'s Ability was suppressed!",target.pbThis)) - target.pbOnAbilityChanged(target.ability) + target.pbOnLosingAbility(target.ability) end end diff --git a/Data/Scripts/011_Battle/002_Move/008_MoveEffects_MoveAttributes.rb b/Data/Scripts/011_Battle/002_Move/008_MoveEffects_MoveAttributes.rb index b19c7fb1d..379e0573e 100644 --- a/Data/Scripts/011_Battle/002_Move/008_MoveEffects_MoveAttributes.rb +++ b/Data/Scripts/011_Battle/002_Move/008_MoveEffects_MoveAttributes.rb @@ -157,14 +157,7 @@ class PokeBattle_Move_DamageTargetAlly < PokeBattle_Move @battle.battlers[b[0]].pbThis(true))) end end - switchedAlly = [] - hitAlly.each do |b| - @battle.battlers[b[0]].pbItemHPHealCheck - if @battle.battlers[b[0]].pbAbilitiesOnDamageTaken(b[1]) - switchedAlly.push(@battle.battlers[b[0]]) - end - end - switchedAlly.each { |b| b.pbEffectsOnSwitchIn(true) } + hitAlly.each { |b| @battle.battlers[b[0]].pbItemHPHealCheck } end end @@ -602,7 +595,7 @@ end #=============================================================================== class PokeBattle_Move_DoublePowerIfTargetLostHPThisTurn < PokeBattle_Move def pbBaseDamage(baseDmg,user,target) - baseDmg *= 2 if target.tookDamage + baseDmg *= 2 if target.tookDamageThisRound return baseDmg end end diff --git a/Data/Scripts/011_Battle/002_Move/012_MoveEffects_ChangeMoveEffect.rb b/Data/Scripts/011_Battle/002_Move/012_MoveEffects_ChangeMoveEffect.rb index c1c512450..5a5a50466 100644 --- a/Data/Scripts/011_Battle/002_Move/012_MoveEffects_ChangeMoveEffect.rb +++ b/Data/Scripts/011_Battle/002_Move/012_MoveEffects_ChangeMoveEffect.rb @@ -189,7 +189,7 @@ class PokeBattle_Move_CurseTargetOrLowerUserSpd1RaiseUserAtkDef1 < PokeBattle_Mo # Ghost effect @battle.pbDisplay(_INTL("{1} cut its own HP and laid a curse on {2}!",user.pbThis,target.pbThis(true))) target.effects[PBEffects::Curse] = true - user.pbReduceHP(user.totalhp/2,false) + user.pbReduceHP(user.totalhp/2, false, false) user.pbItemHPHealCheck end diff --git a/Data/Scripts/011_Battle/002_Move/013_MoveEffects_SwitchingActing.rb b/Data/Scripts/011_Battle/002_Move/013_MoveEffects_SwitchingActing.rb index ea24df94e..6a98d84ea 100644 --- a/Data/Scripts/011_Battle/002_Move/013_MoveEffects_SwitchingActing.rb +++ b/Data/Scripts/011_Battle/002_Move/013_MoveEffects_SwitchingActing.rb @@ -45,8 +45,8 @@ class PokeBattle_Move_SwitchOutUserStatusMove < PokeBattle_Move @battle.pbRecallAndReplace(user.index,newPkmn) @battle.pbClearChoice(user.index) # Replacement Pokémon does nothing this round @battle.moldBreaker = false + @battle.pbOnBattlerEnteringBattle(user.index) switchedBattlers.push(user.index) - user.pbEffectsOnSwitchIn(true) end def pbEffectGeneral(user) @@ -79,8 +79,8 @@ class PokeBattle_Move_SwitchOutUserDamagingMove < PokeBattle_Move @battle.pbRecallAndReplace(user.index,newPkmn) @battle.pbClearChoice(user.index) # Replacement Pokémon does nothing this round @battle.moldBreaker = false + @battle.pbOnBattlerEnteringBattle(user.index) switchedBattlers.push(user.index) - user.pbEffectsOnSwitchIn(true) end end @@ -111,8 +111,8 @@ class PokeBattle_Move_LowerTargetAtkSpAtk1SwitchOutUser < PokeBattle_TargetMulti @battle.pbRecallAndReplace(switcher.index,newPkmn) @battle.pbClearChoice(switcher.index) # Replacement Pokémon does nothing this round @battle.moldBreaker = false if switcher.index==user.index + @battle.pbOnBattlerEnteringBattle(switcher.index) switchedBattlers.push(switcher.index) - switcher.pbEffectsOnSwitchIn(true) end end @@ -139,8 +139,8 @@ class PokeBattle_Move_SwitchOutUserPassOnEffects < PokeBattle_Move @battle.pbRecallAndReplace(user.index, newPkmn, false, true) @battle.pbClearChoice(user.index) # Replacement Pokémon does nothing this round @battle.moldBreaker = false + @battle.pbOnBattlerEnteringBattle(user.index) switchedBattlers.push(user.index) - user.pbEffectsOnSwitchIn(true) end end @@ -198,25 +198,21 @@ class PokeBattle_Move_SwitchOutTargetStatusMove < PokeBattle_Move @battle.decision = 3 if @battle.wildBattle? # Escaped from battle end - def pbSwitchOutTargetsEffect(user,targets,numHits,switchedBattlers) - return if @battle.wildBattle? - return if user.fainted? || numHits==0 - roarSwitched = [] + def pbSwitchOutTargetEffect(user, targets, numHits, switched_battlers) + return if @battle.wildBattle? || !switched_battlers.empty? + return if user.fainted? || numHits == 0 targets.each do |b| - next if b.fainted? || b.damageState.unaffected || switchedBattlers.include?(b.index) + next if b.fainted? || b.damageState.unaffected + next if b.effects[PBEffects::Ingrain] + next if b.hasActiveAbility?(:SUCTIONCUPS) && !@battle.moldBreaker newPkmn = @battle.pbGetReplacementPokemonIndex(b.index,true) # Random next if newPkmn<0 @battle.pbRecallAndReplace(b.index, newPkmn, true) @battle.pbDisplay(_INTL("{1} was dragged out!",b.pbThis)) @battle.pbClearChoice(b.index) # Replacement Pokémon does nothing this round - switchedBattlers.push(b.index) - roarSwitched.push(b.index) - end - if roarSwitched.length>0 - @battle.moldBreaker = false if roarSwitched.include?(user.index) - @battle.pbPriority(true).each do |b| - b.pbEffectsOnSwitchIn(true) if roarSwitched.include?(b.index) - end + @battle.pbOnBattlerEnteringBattle(b.index) + switched_battlers.push(b.index) + break end end end @@ -235,13 +231,11 @@ class PokeBattle_Move_SwitchOutTargetDamagingMove < PokeBattle_Move end end - def pbSwitchOutTargetsEffect(user,targets,numHits,switchedBattlers) - return if @battle.wildBattle? - return if user.fainted? || numHits==0 - roarSwitched = [] + def pbSwitchOutTargetEffect(user, targets, numHits, switched_battlers) + return if @battle.wildBattle? || !switched_battlers.empty? + return if user.fainted? || numHits == 0 targets.each do |b| next if b.fainted? || b.damageState.unaffected || b.damageState.substitute - next if switchedBattlers.include?(b.index) next if b.effects[PBEffects::Ingrain] next if b.hasActiveAbility?(:SUCTIONCUPS) && !@battle.moldBreaker newPkmn = @battle.pbGetReplacementPokemonIndex(b.index,true) # Random @@ -249,14 +243,9 @@ class PokeBattle_Move_SwitchOutTargetDamagingMove < PokeBattle_Move @battle.pbRecallAndReplace(b.index, newPkmn, true) @battle.pbDisplay(_INTL("{1} was dragged out!",b.pbThis)) @battle.pbClearChoice(b.index) # Replacement Pokémon does nothing this round - switchedBattlers.push(b.index) - roarSwitched.push(b.index) - end - if roarSwitched.length>0 - @battle.moldBreaker = false if roarSwitched.include?(user.index) - @battle.pbPriority(true).each do |b| - b.pbEffectsOnSwitchIn(true) if roarSwitched.include?(b.index) - end + @battle.pbOnBattlerEnteringBattle(b.index) + switched_battlers.push(b.index) + break end end end diff --git a/Data/Scripts/011_Battle/003_Battle/003_Battle_StartAndEnd.rb b/Data/Scripts/011_Battle/003_Battle/003_Battle_StartAndEnd.rb index 62482422c..ce2afa7cf 100644 --- a/Data/Scripts/011_Battle/003_Battle/003_Battle_StartAndEnd.rb +++ b/Data/Scripts/011_Battle/003_Battle/003_Battle_StartAndEnd.rb @@ -297,7 +297,7 @@ class PokeBattle_Battle pbDisplay(_INTL("The battlefield is weird!")) end # Abilities upon entering battle - pbOnActiveAll + pbOnAllBattlersEnteringBattle # Main battle loop pbBattleLoop end diff --git a/Data/Scripts/011_Battle/003_Battle/006_Battle_Action_Switching.rb b/Data/Scripts/011_Battle/003_Battle/006_Battle_Action_Switching.rb index 06cd4ba33..2db6f73e8 100644 --- a/Data/Scripts/011_Battle/003_Battle/006_Battle_Action_Switching.rb +++ b/Data/Scripts/011_Battle/003_Battle/006_Battle_Action_Switching.rb @@ -200,15 +200,12 @@ class PokeBattle_Battle end end break if switched.length==0 - pbPriority(true).each do |b| - b.pbEffectsOnSwitchIn(true) if switched.include?(b.index) - end + @battle.pbOnBattlerEnteringBattle(switched) end end def pbGetReplacementPokemonIndex(idxBattler,random=false) if random - return -1 if !pbCanSwitch?(idxBattler) # Can battler switch out? choices = [] # Find all Pokémon that can switch in eachInTeamFromBattlerIndex(idxBattler) do |_pkmn,i| choices.push(i) if pbCanSwitchLax?(idxBattler,i) @@ -304,91 +301,159 @@ class PokeBattle_Battle # Effects upon a Pokémon entering battle #============================================================================= # Called at the start of battle only. - def pbOnActiveAll - # Weather-inducing abilities, Trace, Imposter, etc. + def pbOnAllBattlersEnteringBattle pbCalculatePriority(true) - pbPriority(true).each { |b| b.pbEffectsOnSwitchIn(true) } + battler_indices = [] + eachBattler { |b| battler_indices.push(b.index) } + pbOnBattlerEnteringBattle(battler_indices) pbCalculatePriority # Check forms are correct eachBattler { |b| b.pbCheckForm } end - # Called when a Pokémon switches in (entry effects, entry hazards). - def pbOnActiveOne(battler) - return false if battler.fainted? - # Introduce Shadow Pokémon - if battler.opposes? && battler.shadowPokemon? - pbCommonAnimation("Shadow",battler) - pbDisplay(_INTL("Oh!\nA Shadow Pokémon!")) + # Called when one or more Pokémon switch in. Does a lot of things, including + # entry hazards, form changes and items/abilities that trigger upon switching + # in. + def pbOnBattlerEnteringBattle(*battler_indices) + battler_indices.flatten! + pbPriority(true).each do |b| + b.droppedBelowHalfHP = false end + # For each battler that entered battle, in speed order + pbPriority(true).each do |b| + next if !battler_indices.include?(b.index) || b.fainted? + pbRecordBattlerAsParticipated(b) + pbMessagesOnBattlerEnteringBattle(b) + # Position/field effects triggered by the battler appearing + pbEffectsOnBattlerEnteringPosition(b) # Healing Wish/Lunar Dance + pbEntryHazards(b) + # Battler faints if it is knocked out because of an entry hazard above + if b.fainted? + b.pbFaint + pbGainExp + pbJudge + next + end + b.pbCheckForm + # Primal Revert upon entering battle + pbPrimalReversion(b.index) + # Ending primordial weather, checking Trace + b.pbContinualAbilityChecks(true) + # Abilities that trigger upon switching in + if (!b.fainted? && b.unstoppableAbility?) || b.abilityActive? + BattleHandlers.triggerAbilityOnSwitchIn(b.ability, b, self) + end + pbEndPrimordialWeather # Checking this again just in case + # Items that trigger upon switching in (Air Balloon message) + if b.itemActive? + BattleHandlers.triggerItemOnSwitchIn(b.item, b, self) + end + # Berry check, status-curing ability check + b.pbHeldItemTriggerCheck + b.pbAbilityStatusCureCheck + end + # Check for triggering of Emergency Exit/Wimp Out/Eject Pack (only one will + # be triggered) + pbPriority(true).each do |b| + break if b.pbAbilitiesOnDamageTaken + end + pbPriority(true).each do |b| + b.droppedBelowHalfHP = false + end + end + + def pbRecordBattlerAsParticipated(battler) # Record money-doubling effect of Amulet Coin/Luck Incense if !battler.opposes? && [:AMULETCOIN, :LUCKINCENSE].include?(battler.item_id) @field.effects[PBEffects::AmuletCoin] = true end # Update battlers' participants (who will gain Exp/EVs when a battler faints) eachBattler { |b| b.pbUpdateParticipants } - # Healing Wish/Lunar Dance - battler.pbEffectsOnEnteringPosition - # Entry hazards + end + + def pbMessagesOnBattlerEnteringBattle(battler) + # Introduce Shadow Pokémon + if battler.shadowPokemon? + pbCommonAnimation("Shadow", battler) + pbDisplay(_INTL("Oh!\nA Shadow Pokémon!")) if battler.opposes? + end + end + + # Called when a Pokémon enters battle, and when Ally Switch is used. + def pbEffectsOnBattlerEnteringPosition(battler) + position = @positions[battler.index] + # Healing Wish + if position.effects[PBEffects::HealingWish] + if battler.canHeal? || battler.status != :NONE + pbCommonAnimation("HealingWish", battler) + pbDisplay(_INTL("The healing wish came true for {1}!", battler.pbThis(true))) + battler.pbRecoverHP(battler.totalhp) + battler.pbCureStatus(false) + position.effects[PBEffects::HealingWish] = false + elsif Settings::MECHANICS_GENERATION < 8 + position.effects[PBEffects::HealingWish] = false + end + end + # Lunar Dance + if position.effects[PBEffects::LunarDance] + full_pp = true + battler.eachMove { |m| full_pp = false if m.pp < m.total_pp } + if battler.canHeal? || battler.status != :NONE || !full_pp + pbCommonAnimation("LunarDance", battler) + pbDisplay(_INTL("{1} became cloaked in mystical moonlight!", battler.pbThis)) + battler.pbRecoverHP(battler.totalhp) + battler.pbCureStatus(false) + battler.eachMove { |m| m.pp = m.total_pp } + position.effects[PBEffects::LunarDance] = false + elsif Settings::MECHANICS_GENERATION < 8 + position.effects[PBEffects::LunarDance] = false + end + end + end + + def pbEntryHazards(battler) + battler_side = battler.pbOwnSide # Stealth Rock - if battler.pbOwnSide.effects[PBEffects::StealthRock] && battler.takesIndirectDamage? && + if battler_side.effects[PBEffects::StealthRock] && battler.takesIndirectDamage? && GameData::Type.exists?(:ROCK) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) bTypes = battler.pbTypes(true) eff = Effectiveness.calculate(:ROCK, bTypes[0], bTypes[1], bTypes[2]) if !Effectiveness.ineffective?(eff) eff = eff.to_f / Effectiveness::NORMAL_EFFECTIVE - oldHP = battler.hp - battler.pbReduceHP(battler.totalhp*eff/8,false) - pbDisplay(_INTL("Pointed stones dug into {1}!",battler.pbThis)) + battler.pbReduceHP(battler.totalhp * eff / 8, false) + pbDisplay(_INTL("Pointed stones dug into {1}!", battler.pbThis)) battler.pbItemHPHealCheck - if battler.pbAbilitiesOnDamageTaken(oldHP) # Switched out - return pbOnActiveOne(battler) # For replacement battler - end end end # Spikes - if battler.pbOwnSide.effects[PBEffects::Spikes]>0 && battler.takesIndirectDamage? && + if battler_side.effects[PBEffects::Spikes] > 0 && battler.takesIndirectDamage? && !battler.airborne? && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) - spikesDiv = [8,6,4][battler.pbOwnSide.effects[PBEffects::Spikes]-1] - oldHP = battler.hp - battler.pbReduceHP(battler.totalhp/spikesDiv,false) - pbDisplay(_INTL("{1} is hurt by the spikes!",battler.pbThis)) + spikesDiv = [8, 6, 4][battler_side.effects[PBEffects::Spikes] - 1] + battler.pbReduceHP(battler.totalhp / spikesDiv, false) + pbDisplay(_INTL("{1} is hurt by the spikes!", battler.pbThis)) battler.pbItemHPHealCheck - if battler.pbAbilitiesOnDamageTaken(oldHP) # Switched out - return pbOnActiveOne(battler) # For replacement battler - end end # Toxic Spikes - if battler.pbOwnSide.effects[PBEffects::ToxicSpikes]>0 && !battler.fainted? && - !battler.airborne? + if battler_side.effects[PBEffects::ToxicSpikes] > 0 && !battler.fainted? && !battler.airborne? if battler.pbHasType?(:POISON) - battler.pbOwnSide.effects[PBEffects::ToxicSpikes] = 0 - pbDisplay(_INTL("{1} absorbed the poison spikes!",battler.pbThis)) - elsif battler.pbCanPoison?(nil,false) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) - if battler.pbOwnSide.effects[PBEffects::ToxicSpikes]==2 - battler.pbPoison(nil,_INTL("{1} was badly poisoned by the poison spikes!",battler.pbThis),true) + battler_side.effects[PBEffects::ToxicSpikes] = 0 + pbDisplay(_INTL("{1} absorbed the poison spikes!", battler.pbThis)) + elsif battler.pbCanPoison?(nil, false) && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) + if battler_side.effects[PBEffects::ToxicSpikes] == 2 + battler.pbPoison(nil, _INTL("{1} was badly poisoned by the poison spikes!", battler.pbThis), true) else - battler.pbPoison(nil,_INTL("{1} was poisoned by the poison spikes!",battler.pbThis)) + battler.pbPoison(nil, _INTL("{1} was poisoned by the poison spikes!", battler.pbThis)) end end end # Sticky Web - if battler.pbOwnSide.effects[PBEffects::StickyWeb] && !battler.fainted? && - !battler.airborne? && !battler.hasActiveItem?(:HEAVYDUTYBOOTS) - pbDisplay(_INTL("{1} was caught in a sticky web!",battler.pbThis)) + if battler_side.effects[PBEffects::StickyWeb] && !battler.fainted? && !battler.airborne? && + !battler.hasActiveItem?(:HEAVYDUTYBOOTS) + pbDisplay(_INTL("{1} was caught in a sticky web!", battler.pbThis)) if battler.pbCanLowerStatStage?(:SPEED) - battler.pbLowerStatStage(:SPEED,1,nil) + battler.pbLowerStatStage(:SPEED, 1, nil) battler.pbItemStatRestoreCheck end end - # Battler faints if it is knocked out because of an entry hazard above - if battler.fainted? - battler.pbFaint - pbGainExp - pbJudge - return false - end - battler.pbCheckForm - return true end end diff --git a/Data/Scripts/011_Battle/003_Battle/009_Battle_Action_Other.rb b/Data/Scripts/011_Battle/003_Battle/009_Battle_Action_Other.rb index 13e00b374..b6d7fd636 100644 --- a/Data/Scripts/011_Battle/003_Battle/009_Battle_Action_Other.rb +++ b/Data/Scripts/011_Battle/003_Battle/009_Battle_Action_Other.rb @@ -127,6 +127,7 @@ class PokeBattle_Battle return if !battler || !battler.pokemon return if !battler.hasMega? || battler.mega? trainerName = pbGetOwnerName(idxBattler) + old_ability = battler.ability_id # Break Illusion if battler.hasActiveAbility?(:ILLUSION) BattleHandlers.triggerTargetAbilityOnHit(battler.ability,nil,battler,nil,self) @@ -157,7 +158,8 @@ class PokeBattle_Battle end pbCalculatePriority(false,[idxBattler]) if Settings::RECALCULATE_TURN_ORDER_AFTER_MEGA_EVOLUTION # Trigger ability - battler.pbEffectsOnSwitchIn + battler.pbOnLosingAbility(old_ability) + battler.pbTriggerAbilityOnGainingIt end #============================================================================= @@ -165,7 +167,7 @@ class PokeBattle_Battle #============================================================================= def pbPrimalReversion(idxBattler) battler = @battlers[idxBattler] - return if !battler || !battler.pokemon + return if !battler || !battler.pokemon || battler.fainted? return if !battler.hasPrimal? || battler.primal? if battler.isSpecies?(:KYOGRE) pbCommonAnimation("PrimalKyogre",battler) diff --git a/Data/Scripts/011_Battle/003_Battle/011_Battle_Phase_Attack.rb b/Data/Scripts/011_Battle/003_Battle/011_Battle_Phase_Attack.rb index 4632f399c..d9d4a1770 100644 --- a/Data/Scripts/011_Battle/003_Battle/011_Battle_Phase_Attack.rb +++ b/Data/Scripts/011_Battle/003_Battle/011_Battle_Phase_Attack.rb @@ -60,7 +60,7 @@ class PokeBattle_Battle return if @decision>0 # Switch Pokémon pbRecallAndReplace(b.index,idxNewPkmn) - b.pbEffectsOnSwitchIn(true) + pbOnBattlerEnteringBattle(b.index) end end diff --git a/Data/Scripts/011_Battle/003_Battle/012_Battle_Phase_EndOfRound.rb b/Data/Scripts/011_Battle/003_Battle/012_Battle_Phase_EndOfRound.rb index 47f4f66fc..29757a239 100644 --- a/Data/Scripts/011_Battle/003_Battle/012_Battle_Phase_EndOfRound.rb +++ b/Data/Scripts/011_Battle/003_Battle/012_Battle_Phase_EndOfRound.rb @@ -267,13 +267,10 @@ class PokeBattle_Battle priority.each do |b| next if b.opposes?(side) next if !b.takesIndirectDamage? || b.pbHasType?(:FIRE) - oldHP = b.hp @scene.pbDamageAnimation(b) - b.pbReduceHP(b.totalhp/8,false) - pbDisplay(_INTL("{1} is hurt by the sea of fire!",b.pbThis)) - b.pbItemHPHealCheck - b.pbAbilitiesOnDamageTaken(oldHP) - b.pbFaint if b.fainted? + b.pbTakeEffectDamage(b.totalhp / 8, false) { |hp_lost| + pbDisplay(_INTL("{1} is hurt by the sea of fire!", b.pbThis)) + } end end # Status-curing effects/abilities and HP-healing items @@ -314,16 +311,12 @@ class PokeBattle_Battle next if !b.takesIndirectDamage? recipient = @battlers[b.effects[PBEffects::LeechSeed]] next if !recipient || recipient.fainted? - oldHP = b.hp - oldHPRecipient = recipient.hp pbCommonAnimation("LeechSeed",recipient,b) - hpLoss = b.pbReduceHP(b.totalhp/8) - recipient.pbRecoverHPFromDrain(hpLoss,b, - _INTL("{1}'s health is sapped by Leech Seed!",b.pbThis)) - recipient.pbAbilitiesOnDamageTaken(oldHPRecipient) if recipient.hp= 7) ? b.totalhp/16 : b.totalhp/8 dmg = (dmg/2.0).round if b.hasActiveAbility?(:HEATPROOF) b.pbContinueStatus { b.pbReduceHP(dmg,false) } b.pbItemHPHealCheck - b.pbAbilitiesOnDamageTaken(oldHP) + b.pbAbilitiesOnDamageTaken b.pbFaint if b.fainted? end # Damage from sleep (Nightmare) priority.each do |b| b.effects[PBEffects::Nightmare] = false if !b.asleep? next if !b.effects[PBEffects::Nightmare] || !b.takesIndirectDamage? - oldHP = b.hp - b.pbReduceHP(b.totalhp/4) - pbDisplay(_INTL("{1} is locked in a nightmare!",b.pbThis)) - b.pbItemHPHealCheck - b.pbAbilitiesOnDamageTaken(oldHP) - b.pbFaint if b.fainted? + b.pbTakeEffectDamage(b.totalhp / 4) { |hp_lost| + pbDisplay(_INTL("{1} is locked in a nightmare!", b.pbThis)) + } end # Curse priority.each do |b| next if !b.effects[PBEffects::Curse] || !b.takesIndirectDamage? - oldHP = b.hp - b.pbReduceHP(b.totalhp/4) - pbDisplay(_INTL("{1} is afflicted by the curse!",b.pbThis)) - b.pbItemHPHealCheck - b.pbAbilitiesOnDamageTaken(oldHP) - b.pbFaint if b.fainted? + b.pbTakeEffectDamage(b.totalhp / 4) { |hp_lost| + pbDisplay(_INTL("{1} is afflicted by the curse!", b.pbThis)) + } end # Trapping attacks (Bind/Clamp/Fire Spin/Magma Storm/Sand Tomb/Whirlpool/Wrap) priority.each do |b| @@ -421,11 +406,9 @@ class PokeBattle_Battle hpLoss = (Settings::MECHANICS_GENERATION >= 6) ? b.totalhp/6 : b.totalhp/8 end @scene.pbDamageAnimation(b) - b.pbReduceHP(hpLoss,false) - pbDisplay(_INTL("{1} is hurt by {2}!",b.pbThis,moveName)) - b.pbItemHPHealCheck - # NOTE: No need to call pbAbilitiesOnDamageTaken as b can't switch out. - b.pbFaint if b.fainted? + b.pbTakeEffectDamage(hpLoss, false) { |hp_lost| + pbDisplay(_INTL("{1} is hurt by {2}!", b.pbThis, moveName)) + } end end end @@ -647,7 +630,8 @@ class PokeBattle_Battle b.effects[PBEffects::ThroatChop] -= 1 if b.effects[PBEffects::ThroatChop]>0 b.lastHPLost = 0 b.lastHPLostFromFoe = 0 - b.tookDamage = false + b.droppedBelowHalfHP = false + b.tookDamageThisRound = false b.tookPhysicalHit = false b.statsRaised = false b.statsLowered = false diff --git a/Data/Scripts/011_Battle/003_BattleHandlers_Abilities.rb b/Data/Scripts/011_Battle/003_BattleHandlers_Abilities.rb index db512f457..deb8aad16 100644 --- a/Data/Scripts/011_Battle/003_BattleHandlers_Abilities.rb +++ b/Data/Scripts/011_Battle/003_BattleHandlers_Abilities.rb @@ -71,7 +71,7 @@ BattleHandlers::WeightCalcAbility.add(:LIGHTMETAL, #=============================================================================== BattleHandlers::AbilityOnHPDroppedBelowHalf.add(:EMERGENCYEXIT, - proc { |ability,battler,battle| + proc { |ability, battler, move_user, battle| next false if battler.effects[PBEffects::SkyDrop]>=0 || battler.inTwoTurnAttack?("TwoTurnAttackInvulnerableInSkyTargetCannotAct") # Sky Drop # In wild battles @@ -105,6 +105,8 @@ BattleHandlers::AbilityOnHPDroppedBelowHalf.add(:EMERGENCYEXIT, 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 } ) @@ -1538,7 +1540,8 @@ BattleHandlers::TargetAbilityOnHit.add(:MUMMY, battle.pbHideAbilitySplash(user) if user.opposes?(target) end battle.pbHideAbilitySplash(target) if user.opposes?(target) - user.pbOnAbilityChanged(oldAbil) if oldAbil != nil + user.pbOnLosingAbility(oldAbil) + user.pbTriggerAbilityOnGainingIt } ) @@ -1714,16 +1717,16 @@ BattleHandlers::UserAbilityEndOfMove.add(:MOXIE, #=============================================================================== BattleHandlers::TargetAbilityAfterMoveUse.add(:BERSERK, - proc { |ability,target,user,move,switched,battle| + proc { |ability, target, user, move, switched_battlers, battle| next if !move.damagingMove? - next if target.damageState.initialHP=target.totalhp/2 + next if !target.droppedBelowHalfHP next if !target.pbCanRaiseStatStage?(:SPECIAL_ATTACK,target) target.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,target) } ) BattleHandlers::TargetAbilityAfterMoveUse.add(:COLORCHANGE, - proc { |ability,target,user,move,switched,battle| + 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) @@ -1737,13 +1740,13 @@ BattleHandlers::TargetAbilityAfterMoveUse.add(:COLORCHANGE, ) BattleHandlers::TargetAbilityAfterMoveUse.add(:PICKPOCKET, - proc { |ability,target,user,move,switched,battle| + 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 battle.wildBattle? && target.opposes? + next if switched_battlers.include?(user.index) # User was switched out next if !move.contactMove? - next if switched.include?(user.index) 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) @@ -1932,18 +1935,15 @@ BattleHandlers::EOREffectAbility.add(:BADDREAMS, next if !b.near?(battler) || !b.asleep? battle.pbShowAbilitySplash(battler) next if !b.takesIndirectDamage?(PokeBattle_SceneConstants::USE_ABILITY_SPLASH) - oldHP = b.hp - b.pbReduceHP(b.totalhp/8) - if PokeBattle_SceneConstants::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) - b.pbItemHPHealCheck - b.pbAbilitiesOnDamageTaken(oldHP) - b.pbFaint if b.fainted? + b.pbTakeEffectDamage(b.totalhp / 8) { |hp_lost| + if PokeBattle_SceneConstants::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 } ) diff --git a/Data/Scripts/011_Battle/004_BattleHandlers_Items.rb b/Data/Scripts/011_Battle/004_BattleHandlers_Items.rb index 9ae07c050..196e9d6b2 100644 --- a/Data/Scripts/011_Battle/004_BattleHandlers_Items.rb +++ b/Data/Scripts/011_Battle/004_BattleHandlers_Items.rb @@ -1281,7 +1281,8 @@ BattleHandlers::TargetItemOnHitPositiveBerry.add(:MARANGABERRY, #=============================================================================== BattleHandlers::TargetItemAfterMoveUse.add(:EJECTBUTTON, - proc { |item,battler,user,move,switched,battle| + proc { |item, battler, user, move, switched_battlers, battle| + next if !switched_battlers.empty? next if battle.pbAllFainted?(battler.idxOpposingSide) next if !battle.pbCanChooseNonActive?(battler.index) battle.pbCommonAnimation("UseItem",battler) @@ -1291,23 +1292,41 @@ BattleHandlers::TargetItemAfterMoveUse.add(:EJECTBUTTON, next if newPkmn<0 battle.pbRecallAndReplace(battler.index,newPkmn) battle.pbClearChoice(battler.index) # Replacement Pokémon does nothing this round - switched.push(battler.index) + switched_battlers.push(battler.index) + battle.moldBreaker = false if battler.index == user.index + battle.pbOnBattlerEnteringBattle(battler.index) } ) BattleHandlers::TargetItemAfterMoveUse.add(:REDCARD, - proc { |item,battler,user,move,switched,battle| - next if user.fainted? || switched.include?(user.index) + proc { |item, battler, user, move, switched_battlers, battle| + next if !switched_battlers.empty? || user.fainted? newPkmn = battle.pbGetReplacementPokemonIndex(user.index,true) # Random next if newPkmn<0 battle.pbCommonAnimation("UseItem",battler) battle.pbDisplay(_INTL("{1} held up its {2} against {3}!", battler.pbThis,battler.itemName,user.pbThis(true))) battler.pbConsumeItem + if user.hasActiveAbility?(:SUCTIONCUPS) && !battle.moldBreaker + battle.pbShowAbilitySplash(user) + if PokeBattle_SceneConstants::USE_ABILITY_SPLASH + battle.pbDisplay(_INTL("{1} anchors itself!", user.pbThis)) + else + battle.pbDisplay(_INTL("{1} anchors itself with {2}!", user.pbThis, user.abilityName)) + end + battle.pbHideAbilitySplash(user) + next + end + if user.effects[PBEffects::Ingrain] + battle.pbDisplay(_INTL("{1} anchored itself with its roots!", user.pbThis)) + next + end battle.pbRecallAndReplace(user.index, newPkmn, true) battle.pbDisplay(_INTL("{1} was dragged out!",user.pbThis)) battle.pbClearChoice(user.index) # Replacement Pokémon does nothing this round - switched.push(user.index) + switched_battlers.push(user.index) + battle.moldBreaker = false + battle.pbOnBattlerEnteringBattle(user.index) } ) @@ -1333,6 +1352,9 @@ BattleHandlers::UserItemAfterMoveUse.add(:LIFEORB, } ) +# NOTE: In the official games, Shell Bell does not prevent Emergency Exit/Wimp +# Out triggering even if Shell Bell heals the holder back to 50% HP or +# more. Essentials ignores this exception. BattleHandlers::UserItemAfterMoveUse.add(:SHELLBELL, proc { |item,user,targets,move,numHits,battle| next if !user.canHeal? @@ -1564,13 +1586,10 @@ BattleHandlers::EORHealingItem.add(:BLACKSLUDGE, battle.pbDisplay(_INTL("{1} restored a little HP using its {2}!", battler.pbThis,battler.itemName)) elsif battler.takesIndirectDamage? - oldHP = battler.hp battle.pbCommonAnimation("UseItem",battler) - battler.pbReduceHP(battler.totalhp/8) - battle.pbDisplay(_INTL("{1} is hurt by its {2}!",battler.pbThis,battler.itemName)) - battler.pbItemHPHealCheck - battler.pbAbilitiesOnDamageTaken(oldHP) - battler.pbFaint if battler.fainted? + battler.pbTakeEffectDamage(battler.totalhp / 8) { |hp_lost| + battle.pbDisplay(_INTL("{1} is hurt by its {2}!", battler.pbThis, battler.itemName)) + } end } ) @@ -1601,11 +1620,9 @@ BattleHandlers::EOREffectItem.add(:STICKYBARB, next if !battler.takesIndirectDamage? oldHP = battler.hp battle.scene.pbDamageAnimation(battler) - battler.pbReduceHP(battler.totalhp/8,false) - battle.pbDisplay(_INTL("{1} is hurt by its {2}!",battler.pbThis,battler.itemName)) - battler.pbItemHPHealCheck - battler.pbAbilitiesOnDamageTaken(oldHP) - battler.pbFaint if battler.fainted? + battler.pbTakeEffectDamage(battler.totalhp / 8, false) { |hp_lost| + battle.pbDisplay(_INTL("{1} is hurt by its {2}!", battler.pbThis, battler.itemName)) + } } ) diff --git a/Data/Scripts/011_Battle/006_Other battle types/005_PokeBattle_BattleArena.rb b/Data/Scripts/011_Battle/006_Other battle types/005_PokeBattle_BattleArena.rb index 30b11c98e..a1a19dcb3 100644 --- a/Data/Scripts/011_Battle/006_Other battle types/005_PokeBattle_BattleArena.rb +++ b/Data/Scripts/011_Battle/006_Other battle types/005_PokeBattle_BattleArena.rb @@ -70,12 +70,11 @@ class PokeBattle_BattleArena < PokeBattle_Battle newpoke = @partyindexes[side] pbMessagesOnReplace(side,newpoke) pbReplace(side,newpoke) - pbOnActiveOne(@battlers[side]) - @battlers[side].pbEffectsOnSwitchIn(true) + pbOnBattlerEnteringBattle(side) end end - def pbOnActiveAll + def pbOnAllBattlersEnteringBattle @battlersChanged = true for side in 0...2 @mind[side] = 0 @@ -86,12 +85,12 @@ class PokeBattle_BattleArena < PokeBattle_Battle return super end - def pbOnActiveOne(*arg) + def pbRecordBattlerAsActive(battler) @battlersChanged = true for side in 0...2 @mind[side] = 0 @skill[side] = 0 - @starthp[side] = battlers[side].hp + @starthp[side] = @battlers[side].hp end @count = 0 return super diff --git a/Data/Scripts/011_Battle/007_PokeBattle_DamageState.rb b/Data/Scripts/011_Battle/007_PokeBattle_DamageState.rb index 28afcb6da..9c59a7c8b 100644 --- a/Data/Scripts/011_Battle/007_PokeBattle_DamageState.rb +++ b/Data/Scripts/011_Battle/007_PokeBattle_DamageState.rb @@ -1,5 +1,4 @@ class PokeBattle_DamageState - attr_accessor :initialHP attr_accessor :typeMod # Type effectiveness attr_accessor :unaffected attr_accessor :protected @@ -25,16 +24,15 @@ class PokeBattle_DamageState def initialize; reset; end def reset - @initialHP = 0 - @typeMod = Effectiveness::INEFFECTIVE - @unaffected = false - @protected = false - @missed = false - @invulnerable = false - @magicCoat = false - @magicBounce = false - @totalHPLost = 0 - @fainted = false + @typeMod = Effectiveness::INEFFECTIVE + @unaffected = false + @protected = false + @missed = false + @invulnerable = false + @magicCoat = false + @magicBounce = false + @totalHPLost = 0 + @fainted = false resetPerHit end diff --git a/Data/Scripts/011_Battle/Gen 8 abilities.rb b/Data/Scripts/011_Battle/Gen 8 abilities.rb index eb9f90737..955bab63c 100644 --- a/Data/Scripts/011_Battle/Gen 8 abilities.rb +++ b/Data/Scripts/011_Battle/Gen 8 abilities.rb @@ -145,9 +145,10 @@ BattleHandlers::TargetAbilityOnHit.add(:WANDERINGSPIRIT, end end battle.pbHideAbilitySplash(target) if user.opposes?(target) - user.pbOnAbilityChanged(oldUserAbil) if oldUserAbil != nil - target.pbOnAbilityChanged(oldTargetAbil) if oldTargetAbil != nil - target.pbEffectsOnSwitchIn + user.pbOnLosingAbility(oldUserAbil) + target.pbOnLosingAbility(oldTargetAbil) + user.pbTriggerAbilityOnGainingIt + target.pbTriggerAbilityOnGainingIt } )