class Battle::Battler #============================================================================= # Get move's user #============================================================================= def pbFindUser(_choice, _move) return self end def pbChangeUser(choice, move, user) # Snatch move.snatched = false if move.statusMove? && move.canSnatch? newUser = nil strength = 100 @battle.allBattlers.each do |b| next if b.effects[PBEffects::Snatch] == 0 || b.effects[PBEffects::Snatch] >= strength next if b.effects[PBEffects::SkyDrop] >= 0 newUser = b strength = b.effects[PBEffects::Snatch] end if newUser user = newUser user.effects[PBEffects::Snatch] = 0 move.snatched = true @battle.moldBreaker = user.hasMoldBreaker? choice[3] = -1 # Clear pre-chosen target end end return user end #============================================================================= # Get move's default target(s) #============================================================================= def pbFindTargets(choice, move, user) preTarget = choice[3] # A target that was already chosen targets = [] # Get list of targets case move.pbTarget(user).id # Curse can change its target type when :NearAlly targetBattler = (preTarget >= 0) ? @battle.battlers[preTarget] : nil if !pbAddTarget(targets, user, targetBattler, move) pbAddTargetRandomAlly(targets, user, move) end when :UserOrNearAlly targetBattler = (preTarget >= 0) ? @battle.battlers[preTarget] : nil if !pbAddTarget(targets, user, targetBattler, move, true, true) pbAddTarget(targets, user, user, move, true, true) end when :AllAllies @battle.allSameSideBattlers(user.index).each do |b| pbAddTarget(targets, user, b, move, false, true) if b.index != user.index end when :UserAndAllies pbAddTarget(targets, user, user, move, true, true) @battle.allSameSideBattlers(user.index).each { |b| pbAddTarget(targets, user, b, move, false, true) } when :NearFoe, :NearOther targetBattler = (preTarget >= 0) ? @battle.battlers[preTarget] : nil if !pbAddTarget(targets, user, targetBattler, move) if preTarget >= 0 && !user.opposes?(preTarget) pbAddTargetRandomAlly(targets, user, move) else pbAddTargetRandomFoe(targets, user, move) end end when :RandomNearFoe pbAddTargetRandomFoe(targets, user, move) when :AllNearFoes @battle.allOtherSideBattlers(user.index).each { |b| pbAddTarget(targets, user, b, move) } when :Foe, :Other targetBattler = (preTarget >= 0) ? @battle.battlers[preTarget] : nil if !pbAddTarget(targets, user, targetBattler, move, false) if preTarget >= 0 && !user.opposes?(preTarget) pbAddTargetRandomAlly(targets, user, move, false) else pbAddTargetRandomFoe(targets, user, move, false) end end when :AllFoes @battle.allOtherSideBattlers(user.index).each { |b| pbAddTarget(targets, user, b, move, false) } when :AllNearOthers @battle.allBattlers.each { |b| pbAddTarget(targets, user, b, move) } when :AllBattlers @battle.allBattlers.each { |b| pbAddTarget(targets, user, b, move, false, true) } else # Used by Counter/Mirror Coat/Metal Burst/Bide move.pbAddTarget(targets, user) # Move-specific pbAddTarget, not the def below end return targets end #============================================================================= # Redirect attack to another target #============================================================================= def pbChangeTargets(move, user, targets) target_data = move.pbTarget(user) return targets if @battle.switching # For Pursuit interrupting a switch return targets if move.cannotRedirect? || move.targetsPosition? return targets if !target_data.can_target_one_foe? || targets.length != 1 move.pbModifyTargets(targets, user) # For Dragon Darts return targets if user.hasActiveAbility?([:PROPELLERTAIL, :STALWART]) priority = @battle.pbPriority(true) nearOnly = !target_data.can_choose_distant_target? # Spotlight (takes priority over Follow Me/Rage Powder/Lightning Rod/Storm Drain) newTarget = nil strength = 100 # Lower strength takes priority priority.each do |b| next if b.fainted? || b.effects[PBEffects::SkyDrop] >= 0 next if b.effects[PBEffects::Spotlight] == 0 || b.effects[PBEffects::Spotlight] >= strength next if !b.opposes?(user) next if nearOnly && !b.near?(user) newTarget = b strength = b.effects[PBEffects::Spotlight] end if newTarget PBDebug.log("[Move target changed] #{newTarget.pbThis}'s Spotlight made it the target") targets = [] pbAddTarget(targets, user, newTarget, move, nearOnly) return targets end # Follow Me/Rage Powder (takes priority over Lightning Rod/Storm Drain) newTarget = nil strength = 100 # Lower strength takes priority priority.each do |b| next if b.fainted? || b.effects[PBEffects::SkyDrop] >= 0 next if b.effects[PBEffects::RagePowder] && !user.affectedByPowder? next if b.effects[PBEffects::FollowMe] == 0 || b.effects[PBEffects::FollowMe] >= strength next if !b.opposes?(user) next if nearOnly && !b.near?(user) newTarget = b strength = b.effects[PBEffects::FollowMe] end if newTarget PBDebug.log("[Move target changed] #{newTarget.pbThis}'s Follow Me/Rage Powder made it the target") targets = [] pbAddTarget(targets, user, newTarget, move, nearOnly) return targets end # Lightning Rod targets = pbChangeTargetByAbility(:LIGHTNINGROD, :ELECTRIC, move, user, targets, priority, nearOnly) # Storm Drain targets = pbChangeTargetByAbility(:STORMDRAIN, :WATER, move, user, targets, priority, nearOnly) return targets end def pbChangeTargetByAbility(drawingAbility, drawnType, move, user, targets, priority, nearOnly) return targets if move.calcType != drawnType return targets if targets[0].hasActiveAbility?(drawingAbility) priority.each do |b| next if b.index == user.index || b.index == targets[0].index next if !b.hasActiveAbility?(drawingAbility) next if nearOnly && !b.near?(user) @battle.pbShowAbilitySplash(b) targets.clear pbAddTarget(targets, user, b, move, nearOnly) if Battle::Scene::USE_ABILITY_SPLASH @battle.pbDisplay(_INTL("{1} took the attack!", b.pbThis)) else @battle.pbDisplay(_INTL("{1} took the attack with its {2}!", b.pbThis, b.abilityName)) end @battle.pbHideAbilitySplash(b) break end return targets end #============================================================================= # Register target #============================================================================= def pbAddTarget(targets, user, target, move, nearOnly = true, allowUser = false) return false if !target || (target.fainted? && !move.targetsPosition?) return false if !allowUser && target == user return false if nearOnly && !user.near?(target) && target != user targets.each { |b| return true if b.index == target.index } # Already added targets.push(target) return true end def pbAddTargetRandomAlly(targets, user, move, nearOnly = true) choices = [] user.allAllies.each do |b| next if nearOnly && !user.near?(b) pbAddTarget(choices, user, b, move, nearOnly) end if choices.length > 0 pbAddTarget(targets, user, choices[@battle.pbRandom(choices.length)], move, nearOnly) end end def pbAddTargetRandomFoe(targets, user, move, nearOnly = true) choices = [] user.allOpposing.each do |b| next if nearOnly && !user.near?(b) pbAddTarget(choices, user, b, move, nearOnly) end if choices.length > 0 pbAddTarget(targets, user, choices[@battle.pbRandom(choices.length)], move, nearOnly) end end end