Renamed all battle-related classes and modules

This commit is contained in:
Maruno17
2021-11-16 23:05:16 +00:00
parent 6dacd6a139
commit 1c4819e5f0
79 changed files with 1270 additions and 1310 deletions

View File

@@ -0,0 +1,147 @@
class Battle::Move
attr_reader :battle
attr_reader :realMove
attr_accessor :id
attr_reader :name
attr_reader :function
attr_reader :baseDamage
attr_reader :type
attr_reader :category
attr_reader :accuracy
attr_accessor :pp
attr_writer :total_pp
attr_reader :addlEffect
attr_reader :target
attr_reader :priority
attr_reader :flags
attr_accessor :calcType
attr_accessor :powerBoost
attr_accessor :snatched
def to_int; return @id; end
#=============================================================================
# Creating a move
#=============================================================================
def initialize(battle, move)
@battle = battle
@realMove = move
@id = move.id
@name = move.name # Get the move's name
# Get data on the move
@function = move.function_code
@baseDamage = move.base_damage
@type = move.type
@category = move.category
@accuracy = move.accuracy
@pp = move.pp # Can be changed with Mimic/Transform
@addlEffect = move.effect_chance
@target = move.target
@priority = move.priority
@flags = move.flags.clone
@calcType = nil
@powerBoost = false # For Aerilate, Pixilate, Refrigerate, Galvanize
@snatched = false
end
# This is the code actually used to generate a Battle::Move object. The
# object generated is a subclass of this one which depends on the move's
# function code.
def self.from_pokemon_move(battle, move)
validate move => Pokemon::Move
code = move.function_code || "None"
if code[/^\d/] # Begins with a digit
class_name = sprintf("Battle::Move::Effect%s", code)
else
class_name = sprintf("Battle::Move::%s", code)
end
if Object.const_defined?(class_name)
return Object.const_get(class_name).new(battle, move)
end
return Battle::Move::Unimplemented.new(battle, move)
end
#=============================================================================
# About the move
#=============================================================================
def pbTarget(_user); return GameData::Target.get(@target); end
def total_pp
return @total_pp if @total_pp && @total_pp>0 # Usually undefined
return @realMove.total_pp if @realMove
return 0
end
# NOTE: This method is only ever called while using a move (and also by the
# AI), so using @calcType here is acceptable.
def physicalMove?(thisType=nil)
return (@category==0) if Settings::MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType
thisType ||= @type
return true if !thisType
return GameData::Type.get(thisType).physical?
end
# NOTE: This method is only ever called while using a move (and also by the
# AI), so using @calcType here is acceptable.
def specialMove?(thisType=nil)
return (@category==1) if Settings::MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType
thisType ||= @type
return false if !thisType
return GameData::Type.get(thisType).special?
end
def damagingMove?; return @category!=2; end
def statusMove?; return @category==2; end
def pbPriority(user); return @priority; end
def usableWhenAsleep?; return false; end
def unusableInGravity?; return false; end
def healingMove?; return false; end
def recoilMove?; return false; end
def flinchingMove?; return false; end
def callsAnotherMove?; return false; end
# Whether the move can/will hit more than once in the same turn (including
# Beat Up which may instead hit just once). Not the same as pbNumHits>1.
def multiHitMove?; return false; end
def chargingTurnMove?; return false; end
def successCheckPerHit?; return false; end
def hitsFlyingTargets?; return false; end
def hitsDiggingTargets?; return false; end
def hitsDivingTargets?; return false; end
def ignoresReflect?; return false; end # For Brick Break
def targetsPosition?; return false; end # For Future Sight/Doom Desire
def cannotRedirect?; return false; end # For Snipe Shot
def worksWithNoTargets?; return false; end # For Explosion
def damageReducedByBurn?; return true; end # For Facade
def triggersHyperMode?; return false; end
def canSnatch?; return false; end
def canMagicCoat?; return false; end
def contactMove?; return @flags.any? { |f| f[/^Contact$/i] }; end
def canProtectAgainst?; return @flags.any? { |f| f[/^CanProtect$/i] }; end
def canMirrorMove?; return @flags.any? { |f| f[/^CanMirrorMove$/i] }; end
def thawsUser?; return @flags.any? { |f| f[/^ThawsUser$/i] }; end
def highCriticalRate?; return @flags.any? { |f| f[/^HighCriticalHitRate$/i] }; end
def bitingMove?; return @flags.any? { |f| f[/^Biting$/i] }; end
def punchingMove?; return @flags.any? { |f| f[/^Punching$/i] }; end
def soundMove?; return @flags.any? { |f| f[/^Sound$/i] }; end
def powderMove?; return @flags.any? { |f| f[/^Powder$/i] }; end
def pulseMove?; return @flags.any? { |f| f[/^Pulse$/i] }; end
def bombMove?; return @flags.any? { |f| f[/^Bomb$/i] }; end
def danceMove?; return @flags.any? { |f| f[/^Dance$/i] }; end
# Causes perfect accuracy (param=1) and double damage (param=2).
def tramplesMinimize?(_param=1); return false; end
def nonLethal?(_user,_target); return false; end # For False Swipe
def ignoresSubstitute?(user) # user is the Pokémon using this move
if Settings::MECHANICS_GENERATION >= 6
return true if soundMove?
return true if user && user.hasActiveAbility?(:INFILTRATOR)
end
return false
end
end

View File

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

View File

@@ -0,0 +1,504 @@
class Battle::Move
#=============================================================================
# Move's type calculation
#=============================================================================
def pbBaseType(user)
ret = @type
if ret && user.abilityActive?
ret = BattleHandlers.triggerMoveBaseTypeModifierAbility(user.ability,user,self,ret)
end
return ret
end
def pbCalcType(user)
@powerBoost = false
ret = pbBaseType(user)
if ret && GameData::Type.exists?(:ELECTRIC)
if @battle.field.effects[PBEffects::IonDeluge] && ret == :NORMAL
ret = :ELECTRIC
@powerBoost = false
end
if user.effects[PBEffects::Electrify]
ret = :ELECTRIC
@powerBoost = false
end
end
return ret
end
#=============================================================================
# Type effectiveness calculation
#=============================================================================
def pbCalcTypeModSingle(moveType,defType,user,target)
ret = Effectiveness.calculate_one(moveType, defType)
# Ring Target
if target.hasActiveItem?(:RINGTARGET)
ret = Effectiveness::NORMAL_EFFECTIVE_ONE if Effectiveness.ineffective_type?(moveType, defType)
end
# Foresight
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
ret = Effectiveness::NORMAL_EFFECTIVE_ONE if defType == :GHOST &&
Effectiveness.ineffective_type?(moveType, defType)
end
# Miracle Eye
if target.effects[PBEffects::MiracleEye]
ret = Effectiveness::NORMAL_EFFECTIVE_ONE if defType == :DARK &&
Effectiveness.ineffective_type?(moveType, defType)
end
# Delta Stream's weather
if target.effectiveWeather == :StrongWinds
ret = Effectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING &&
Effectiveness.super_effective_type?(moveType, defType)
end
# Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne?
ret = Effectiveness::NORMAL_EFFECTIVE_ONE if defType == :FLYING && moveType == :GROUND
end
return ret
end
def pbCalcTypeMod(moveType,user,target)
return Effectiveness::NORMAL_EFFECTIVE if !moveType
return Effectiveness::NORMAL_EFFECTIVE if moveType == :GROUND &&
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
# Determine types
tTypes = target.pbTypes(true)
# Get effectivenesses
typeMods = [Effectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
if moveType == :SHADOW
if target.shadowPokemon?
typeMods[0] = Effectiveness::NOT_VERY_EFFECTIVE_ONE
else
typeMods[0] = Effectiveness::SUPER_EFFECTIVE_ONE
end
else
tTypes.each_with_index do |type,i|
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
end
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
ret *= 2 if target.effects[PBEffects::TarShot] && moveType == :FIRE
return ret
end
#=============================================================================
# Accuracy check
#=============================================================================
def pbBaseAccuracy(user,target); return @accuracy; end
# Accuracy calculations for one-hit KO moves are handled elsewhere.
def pbAccuracyCheck(user,target)
# "Always hit" effects and "always hit" accuracy
return true if target.effects[PBEffects::Telekinesis]>0
return true if target.effects[PBEffects::Minimize] && tramplesMinimize?(1)
baseAcc = pbBaseAccuracy(user,target)
return true if baseAcc==0
# Calculate all multiplier effects
modifiers = {}
modifiers[:base_accuracy] = baseAcc
modifiers[:accuracy_stage] = user.stages[:ACCURACY]
modifiers[:evasion_stage] = target.stages[:EVASION]
modifiers[:accuracy_multiplier] = 1.0
modifiers[:evasion_multiplier] = 1.0
pbCalcAccuracyModifiers(user,target,modifiers)
# Check if move can't miss
return true if modifiers[:base_accuracy] == 0
# Calculation
accStage = [[modifiers[:accuracy_stage], -6].max, 6].min + 6
evaStage = [[modifiers[:evasion_stage], -6].max, 6].min + 6
stageMul = [3,3,3,3,3,3, 3, 4,5,6,7,8,9]
stageDiv = [9,8,7,6,5,4, 3, 3,3,3,3,3,3]
accuracy = 100.0 * stageMul[accStage] / stageDiv[accStage]
evasion = 100.0 * stageMul[evaStage] / stageDiv[evaStage]
accuracy = (accuracy * modifiers[:accuracy_multiplier]).round
evasion = (evasion * modifiers[:evasion_multiplier]).round
evasion = 1 if evasion < 1
threshold = modifiers[:base_accuracy] * accuracy / evasion
# Calculation
r = @battle.pbRandom(100)
if Settings::AFFECTION_EFFECTS && @battle.internalBattle &&
target.pbOwnedByPlayer? && target.affection_level == 5 && !target.mega?
return true if r < threshold - 10
target.damageState.affection_missed = true if r < threshold
return false
end
return r < threshold
end
def pbCalcAccuracyModifiers(user,target,modifiers)
# Ability effects that alter accuracy calculation
if user.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAbility(user.ability,
modifiers,user,target,self,@calcType)
end
user.allAllies.each do |b|
next if !b.abilityActive?
BattleHandlers.triggerAccuracyCalcUserAllyAbility(b.ability,
modifiers,user,target,self,@calcType)
end
if target.abilityActive? && !@battle.moldBreaker
BattleHandlers.triggerAccuracyCalcTargetAbility(target.ability,
modifiers,user,target,self,@calcType)
end
# Item effects that alter accuracy calculation
if user.itemActive?
BattleHandlers.triggerAccuracyCalcUserItem(user.item,
modifiers,user,target,self,@calcType)
end
if target.itemActive?
BattleHandlers.triggerAccuracyCalcTargetItem(target.item,
modifiers,user,target,self,@calcType)
end
# Other effects, inc. ones that set accuracy_multiplier or evasion_stage to
# specific values
if @battle.field.effects[PBEffects::Gravity] > 0
modifiers[:accuracy_multiplier] *= 5 / 3.0
end
if user.effects[PBEffects::MicleBerry]
user.effects[PBEffects::MicleBerry] = false
modifiers[:accuracy_multiplier] *= 1.2
end
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::Foresight] && modifiers[:evasion_stage] > 0
modifiers[:evasion_stage] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[:evasion_stage] > 0
end
#=============================================================================
# Critical hit check
#=============================================================================
# Return values:
# -1: Never a critical hit.
# 0: Calculate normally.
# 1: Always a critical hit.
def pbCritialOverride(user,target); return 0; end
# Returns whether the move will be a critical hit.
def pbIsCritical?(user,target)
return false if target.pbOwnSide.effects[PBEffects::LuckyChant]>0
# Set up the critical hit ratios
ratios = (Settings::NEW_CRITICAL_HIT_RATE_MECHANICS) ? [24,8,2,1] : [16,8,4,3,2]
c = 0
# Ability effects that alter critical hit rate
if c>=0 && user.abilityActive?
c = BattleHandlers.triggerCriticalCalcUserAbility(user.ability,user,target,c)
end
if c>=0 && target.abilityActive? && !@battle.moldBreaker
c = BattleHandlers.triggerCriticalCalcTargetAbility(target.ability,user,target,c)
end
# Item effects that alter critical hit rate
if c>=0 && user.itemActive?
c = BattleHandlers.triggerCriticalCalcUserItem(user.item,user,target,c)
end
if c>=0 && target.itemActive?
c = BattleHandlers.triggerCriticalCalcTargetItem(target.item,user,target,c)
end
return false if c<0
# Move-specific "always/never a critical hit" effects
case pbCritialOverride(user,target)
when 1 then return true
when -1 then return false
end
# Other effects
return true if c>50 # Merciless
return true if user.effects[PBEffects::LaserFocus]>0
c += 1 if highCriticalRate?
c += user.effects[PBEffects::FocusEnergy]
c += 1 if user.inHyperMode? && @type == :SHADOW
c = ratios.length-1 if c>=ratios.length
# Calculation
return true if ratios[c] == 1
r = @battle.pbRandom(ratios[c])
return true if r == 0
if r == 1 && Settings::AFFECTION_EFFECTS && @battle.internalBattle &&
user.pbOwnedByPlayer? && user.affection_level == 5 && !target.mega?
target.damageState.affection_critical = true
return true
end
return false
end
#=============================================================================
# Damage calculation
#=============================================================================
def pbBaseDamage(baseDmg,user,target); return baseDmg; end
def pbBaseDamageMultiplier(damageMult,user,target); return damageMult; end
def pbModifyDamage(damageMult,user,target); return damageMult; end
def pbGetAttackStats(user,target)
if specialMove?
return user.spatk, user.stages[:SPECIAL_ATTACK]+6
end
return user.attack, user.stages[:ATTACK]+6
end
def pbGetDefenseStats(user,target)
if specialMove?
return target.spdef, target.stages[:SPECIAL_DEFENSE]+6
end
return target.defense, target.stages[:DEFENSE]+6
end
def pbCalcDamage(user,target,numTargets=1)
return if statusMove?
if target.damageState.disguise || target.damageState.iceFace
target.damageState.calcDamage = 1
return
end
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
# Get the move's type
type = @calcType # nil is treated as physical
# Calculate whether this hit deals critical damage
target.damageState.critical = pbIsCritical?(user,target)
# Calcuate base power of move
baseDmg = pbBaseDamage(@baseDamage,user,target)
# Calculate user's attack stat
atk, atkStage = pbGetAttackStats(user,target)
if !target.hasActiveAbility?(:UNAWARE) || @battle.moldBreaker
atkStage = 6 if target.damageState.critical && atkStage<6
atk = (atk.to_f*stageMul[atkStage]/stageDiv[atkStage]).floor
end
# Calculate target's defense stat
defense, defStage = pbGetDefenseStats(user,target)
if !user.hasActiveAbility?(:UNAWARE)
defStage = 6 if target.damageState.critical && defStage>6
defense = (defense.to_f*stageMul[defStage]/stageDiv[defStage]).floor
end
# Calculate all multiplier effects
multipliers = {
:base_damage_multiplier => 1.0,
:attack_multiplier => 1.0,
:defense_multiplier => 1.0,
:final_damage_multiplier => 1.0
}
pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers)
# Main damage calculation
baseDmg = [(baseDmg * multipliers[:base_damage_multiplier]).round, 1].max
atk = [(atk * multipliers[:attack_multiplier]).round, 1].max
defense = [(defense * multipliers[:defense_multiplier]).round, 1].max
damage = (((2.0 * user.level / 5 + 2).floor * baseDmg * atk / defense).floor / 50).floor + 2
damage = [(damage * multipliers[:final_damage_multiplier]).round, 1].max
target.damageState.calcDamage = damage
end
def pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers)
# Global abilities
if (@battle.pbCheckGlobalAbility(:DARKAURA) && type == :DARK) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && type == :FAIRY)
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[:base_damage_multiplier] *= 2 / 3.0
else
multipliers[:base_damage_multiplier] *= 4 / 3.0
end
end
# Ability effects that alter damage
if user.abilityActive?
BattleHandlers.triggerDamageCalcUserAbility(user.ability,
user,target,self,multipliers,baseDmg,type)
end
if !@battle.moldBreaker
# NOTE: It's odd that the user's Mold Breaker prevents its partner's
# beneficial abilities (i.e. Flower Gift boosting Atk), but that's
# how it works.
user.allAllies.each do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcUserAllyAbility(b.ability,
user,target,self,multipliers,baseDmg,type)
end
if target.abilityActive?
BattleHandlers.triggerDamageCalcTargetAbility(target.ability,
user,target,self,multipliers,baseDmg,type) if !@battle.moldBreaker
BattleHandlers.triggerDamageCalcTargetAbilityNonIgnorable(target.ability,
user,target,self,multipliers,baseDmg,type)
end
target.allAllies.each do |b|
next if !b.abilityActive?
BattleHandlers.triggerDamageCalcTargetAllyAbility(b.ability,
user,target,self,multipliers,baseDmg,type)
end
end
# Item effects that alter damage
if user.itemActive?
BattleHandlers.triggerDamageCalcUserItem(user.item,
user,target,self,multipliers,baseDmg,type)
end
if target.itemActive?
BattleHandlers.triggerDamageCalcTargetItem(target.item,
user,target,self,multipliers,baseDmg,type)
end
# Parental Bond's second attack
if user.effects[PBEffects::ParentalBond]==1
multipliers[:base_damage_multiplier] /= (Settings::MECHANICS_GENERATION >= 7) ? 4 : 2
end
# Other
if user.effects[PBEffects::MeFirst]
multipliers[:base_damage_multiplier] *= 1.5
end
if user.effects[PBEffects::HelpingHand] && !self.is_a?(Battle::Move::Confusion)
multipliers[:base_damage_multiplier] *= 1.5
end
if user.effects[PBEffects::Charge]>0 && type == :ELECTRIC
multipliers[:base_damage_multiplier] *= 2
end
# Mud Sport
if type == :ELECTRIC
if @battle.allBattlers.any? { |b| b.effects[PBEffects::MudSport] }
multipliers[:base_damage_multiplier] /= 3
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[:base_damage_multiplier] /= 3
end
end
# Water Sport
if type == :FIRE
if @battle.allBattlers.any? { |b| b.effects[PBEffects::WaterSport] }
multipliers[:base_damage_multiplier] /= 3
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[:base_damage_multiplier] /= 3
end
end
# Terrain moves
terrain_multiplier = (Settings::MECHANICS_GENERATION >= 8) ? 1.3 : 1.5
case @battle.field.terrain
when :Electric
multipliers[:base_damage_multiplier] *= terrain_multiplier if type == :ELECTRIC && user.affectedByTerrain?
when :Grassy
multipliers[:base_damage_multiplier] *= terrain_multiplier if type == :GRASS && user.affectedByTerrain?
when :Psychic
multipliers[:base_damage_multiplier] *= terrain_multiplier if type == :PSYCHIC && user.affectedByTerrain?
when :Misty
multipliers[:base_damage_multiplier] /= 2 if type == :DRAGON && target.affectedByTerrain?
end
# Badge multipliers
if @battle.internalBattle
if user.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_ATTACK
multipliers[:attack_multiplier] *= 1.1
elsif specialMove? && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPATK
multipliers[:attack_multiplier] *= 1.1
end
end
if target.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_DEFENSE
multipliers[:defense_multiplier] *= 1.1
elsif specialMove? && @battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPDEF
multipliers[:defense_multiplier] *= 1.1
end
end
end
# Multi-targeting attacks
if numTargets>1
multipliers[:final_damage_multiplier] *= 0.75
end
# Weather
case user.effectiveWeather
when :Sun, :HarshSun
if type == :FIRE
multipliers[:final_damage_multiplier] *= 1.5
elsif type == :WATER
multipliers[:final_damage_multiplier] /= 2
end
when :Rain, :HeavyRain
if type == :FIRE
multipliers[:final_damage_multiplier] /= 2
elsif type == :WATER
multipliers[:final_damage_multiplier] *= 1.5
end
when :Sandstorm
if target.pbHasType?(:ROCK) && specialMove? && @function != "UseTargetDefenseInsteadOfTargetSpDef"
multipliers[:defense_multiplier] *= 1.5
end
end
# Critical hits
if target.damageState.critical
if Settings::NEW_CRITICAL_HIT_RATE_MECHANICS
multipliers[:final_damage_multiplier] *= 1.5
else
multipliers[:final_damage_multiplier] *= 2
end
end
# Random variance
if !self.is_a?(Battle::Move::Confusion)
random = 85+@battle.pbRandom(16)
multipliers[:final_damage_multiplier] *= random / 100.0
end
# STAB
if type && user.pbHasType?(type)
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[:final_damage_multiplier] *= 2
else
multipliers[:final_damage_multiplier] *= 1.5
end
end
# Type effectiveness
multipliers[:final_damage_multiplier] *= target.damageState.typeMod.to_f / Effectiveness::NORMAL_EFFECTIVE
# Burn
if user.status == :BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS)
multipliers[:final_damage_multiplier] /= 2
end
# Aurora Veil, Reflect, Light Screen
if !ignoresReflect? && !target.damageState.critical &&
!user.hasActiveAbility?(:INFILTRATOR)
if target.pbOwnSide.effects[PBEffects::AuroraVeil] > 0
if @battle.pbSideBattlerCount(target)>1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect] > 0 && physicalMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[:final_damage_multiplier] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen] > 0 && specialMove?
if @battle.pbSideBattlerCount(target) > 1
multipliers[:final_damage_multiplier] *= 2 / 3.0
else
multipliers[:final_damage_multiplier] /= 2
end
end
end
# Minimize
if target.effects[PBEffects::Minimize] && tramplesMinimize?(2)
multipliers[:final_damage_multiplier] *= 2
end
# Move-specific base damage modifiers
multipliers[:base_damage_multiplier] = pbBaseDamageMultiplier(multipliers[:base_damage_multiplier], user, target)
# Move-specific final damage modifiers
multipliers[:final_damage_multiplier] = pbModifyDamage(multipliers[:final_damage_multiplier], user, target)
end
#=============================================================================
# Additional effect chance
#=============================================================================
def pbAdditionalEffectChance(user,target,effectChance=0)
return 0 if target.hasActiveAbility?(:SHIELDDUST) && !@battle.moldBreaker
ret = (effectChance>0) ? effectChance : @addlEffect
if Settings::MECHANICS_GENERATION >= 6 || @function != "EffectDependsOnEnvironment"
ret *= 2 if user.hasActiveAbility?(:SERENEGRACE) ||
user.pbOwnSide.effects[PBEffects::Rainbow]>0
end
ret = 100 if $DEBUG && Input.press?(Input::CTRL)
return ret
end
# NOTE: Flinching caused by a move's effect is applied in that move's code,
# not here.
def pbFlinchChance(user,target)
return 0 if flinchingMove?
return 0 if target.hasActiveAbility?(:SHIELDDUST) && !@battle.moldBreaker
ret = 0
if user.hasActiveAbility?(:STENCH,true)
ret = 10
elsif user.hasActiveItem?([:KINGSROCK,:RAZORFANG],true)
ret = 10
end
ret *= 2 if user.hasActiveAbility?(:SERENEGRACE) ||
user.pbOwnSide.effects[PBEffects::Rainbow]>0
return ret
end
end

View File

@@ -0,0 +1,782 @@
# DO NOT USE ANY CLASS NAMES IN HERE AS FUNCTION CODES!
# These are base classes for other classes to build on; those other classes are
# named after function codes, so use those instead.
#===============================================================================
# Superclass that handles moves using a non-existent function code.
# Damaging moves just do damage with no additional effect.
# Status moves always fail.
#===============================================================================
class Battle::Move::Unimplemented < Battle::Move
def pbMoveFailed?(user,targets)
if statusMove?
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
end
#===============================================================================
# Pseudomove for confusion damage.
#===============================================================================
class Battle::Move::Confusion < Battle::Move
def initialize(battle,move)
@battle = battle
@realMove = move
@id = :CONFUSEDAMAGE
@name = ""
@function = "None"
@baseDamage = 40
@type = nil
@category = 0
@accuracy = 100
@pp = -1
@target = 0
@priority = 0
@flags = ""
@addlEffect = 0
@calcType = nil
@powerBoost = false
@snatched = false
end
def physicalMove?(thisType=nil); return true; end
def specialMove?(thisType=nil); return false; end
def pbCritialOverride(user,target); return -1; end
end
#===============================================================================
# Implements the move Struggle.
#===============================================================================
class Battle::Move::Struggle < Battle::Move
def initialize(battle,move)
@battle = battle
@realMove = nil # Not associated with a move
@id = (move) ? move.id : :STRUGGLE
@name = (move) ? move.name : _INTL("Struggle")
@function = "Struggle"
@baseDamage = 50
@type = nil
@category = 0
@accuracy = 0
@pp = -1
@target = 0
@priority = 0
@flags = ""
@addlEffect = 0
@calcType = nil
@powerBoost = false
@snatched = false
end
def physicalMove?(thisType=nil); return true; end
def specialMove?(thisType=nil); return false; end
def pbEffectAfterAllHits(user,target)
return if target.damageState.unaffected
user.pbReduceHP((user.totalhp/4.0).round,false)
@battle.pbDisplay(_INTL("{1} is damaged by recoil!",user.pbThis))
user.pbItemHPHealCheck
end
end
#===============================================================================
# Generic status problem-inflicting classes.
#===============================================================================
class Battle::Move::SleepMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanSleep?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbSleep
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbSleep if target.pbCanSleep?(user,false,self)
end
end
class Battle::Move::PoisonMove < Battle::Move
def canMagicCoat?; return true; end
def initialize(battle,move)
super
@toxic = false
end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanPoison?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbPoison(user,nil,@toxic)
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbPoison(user,nil,@toxic) if target.pbCanPoison?(user,false,self)
end
end
class Battle::Move::ParalysisMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanParalyze?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbParalyze(user)
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbParalyze(user) if target.pbCanParalyze?(user,false,self)
end
end
class Battle::Move::BurnMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanBurn?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbBurn(user)
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbBurn(user) if target.pbCanBurn?(user,false,self)
end
end
class Battle::Move::FreezeMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanFreeze?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbFreeze
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbFreeze if target.pbCanFreeze?(user,false,self)
end
end
#===============================================================================
# Other problem-causing classes.
#===============================================================================
class Battle::Move::FlinchMove < Battle::Move
def flinchingMove?; return true; end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbFlinch(user)
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbFlinch(user)
end
end
class Battle::Move::ConfuseMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanConfuse?(user, show_message, self)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbConfuse
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
return if !target.pbCanConfuse?(user,false,self)
target.pbConfuse
end
end
#===============================================================================
# Generic user's stat increase/decrease classes.
#===============================================================================
class Battle::Move::StatUpMove < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
return false if damagingMove?
return !user.pbCanRaiseStatStage?(@statUp[0],user,self,true)
end
def pbEffectGeneral(user)
return if damagingMove?
user.pbRaiseStatStage(@statUp[0],@statUp[1],user)
end
def pbAdditionalEffect(user,target)
if user.pbCanRaiseStatStage?(@statUp[0],user,self)
user.pbRaiseStatStage(@statUp[0],@statUp[1],user)
end
end
end
class Battle::Move::MultiStatUpMove < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
return false if damagingMove?
failed = true
for i in 0...@statUp.length/2
next if !user.pbCanRaiseStatStage?(@statUp[i*2],user,self)
failed = false
break
end
if failed
@battle.pbDisplay(_INTL("{1}'s stats won't go any higher!",user.pbThis))
return true
end
return false
end
def pbEffectGeneral(user)
return if damagingMove?
showAnim = true
for i in 0...@statUp.length/2
next if !user.pbCanRaiseStatStage?(@statUp[i*2],user,self)
if user.pbRaiseStatStage(@statUp[i*2],@statUp[i*2+1],user,showAnim)
showAnim = false
end
end
end
def pbAdditionalEffect(user,target)
showAnim = true
for i in 0...@statUp.length/2
next if !user.pbCanRaiseStatStage?(@statUp[i*2],user,self)
if user.pbRaiseStatStage(@statUp[i*2],@statUp[i*2+1],user,showAnim)
showAnim = false
end
end
end
end
class Battle::Move::StatDownMove < Battle::Move
def pbEffectWhenDealingDamage(user,target)
return if @battle.pbAllFainted?(target.idxOwnSide)
showAnim = true
for i in 0...@statDown.length/2
next if !user.pbCanLowerStatStage?(@statDown[i*2],user,self)
if user.pbLowerStatStage(@statDown[i*2],@statDown[i*2+1],user,showAnim)
showAnim = false
end
end
end
end
#===============================================================================
# Generic target's stat increase/decrease classes.
#===============================================================================
class Battle::Move::TargetStatDownMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
return !target.pbCanLowerStatStage?(@statDown[0], user, self, show_message)
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.pbLowerStatStage(@statDown[0],@statDown[1],user)
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
return if !target.pbCanLowerStatStage?(@statDown[0],user,self)
target.pbLowerStatStage(@statDown[0],@statDown[1],user)
end
end
class Battle::Move::TargetMultiStatDownMove < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
failed = true
for i in 0...@statDown.length/2
next if !target.pbCanLowerStatStage?(@statDown[i*2],user,self)
failed = false
break
end
if failed
# NOTE: It's a bit of a faff to make sure the appropriate failure message
# is shown here, I know.
canLower = false
if target.hasActiveAbility?(:CONTRARY) && !@battle.moldBreaker
for i in 0...@statDown.length/2
next if target.statStageAtMax?(@statDown[i*2])
canLower = true
break
end
@battle.pbDisplay(_INTL("{1}'s stats won't go any higher!",user.pbThis)) if !canLower && show_message
else
for i in 0...@statDown.length/2
next if target.statStageAtMin?(@statDown[i*2])
canLower = true
break
end
@battle.pbDisplay(_INTL("{1}'s stats won't go any lower!",user.pbThis)) if !canLower && show_message
end
if canLower
target.pbCanLowerStatStage?(@statDown[0], user, self, show_message)
end
return true
end
return false
end
def pbCheckForMirrorArmor(user, target)
if target.hasActiveAbility?(:MIRRORARMOR) && user.index != target.index
failed = true
for i in 0...@statDown.length / 2
next if target.statStageAtMin?(@statDown[i * 2])
next if !user.pbCanLowerStatStage?(@statDown[i * 2], target, self, false, false, true)
failed = false
break
end
if failed
@battle.pbShowAbilitySplash(target)
if !Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1}'s {2} activated!", target.pbThis, target.abilityName))
end
user.pbCanLowerStatStage?(@statDown[0], target, self, true, false, true) # Show fail message
@battle.pbHideAbilitySplash(target)
return false
end
end
return true
end
def pbLowerTargetMultipleStats(user, target)
return if !pbCheckForMirrorArmor(user, target)
showAnim = true
showMirrorArmorSplash = true
for i in 0...@statDown.length / 2
next if !target.pbCanLowerStatStage?(@statDown[i * 2], user, self)
if target.pbLowerStatStage(@statDown[i * 2], @statDown[i * 2 + 1], user,
showAnim, false, (showMirrorArmorSplash) ? 1 : 3)
showAnim = false
end
showMirrorArmorSplash = false
end
@battle.pbHideAbilitySplash(target) # To hide target's Mirror Armor splash
end
def pbEffectAgainstTarget(user,target)
pbLowerTargetMultipleStats(user, target) if !damagingMove?
end
def pbAdditionalEffect(user,target)
pbLowerTargetMultipleStats(user, target) if !target.damageState.substitute
end
end
#===============================================================================
# Fixed damage-inflicting move.
#===============================================================================
class Battle::Move::FixedDamageMove < Battle::Move
def pbFixedDamage(user,target); return 1; end
def pbCalcDamage(user,target,numTargets=1)
target.damageState.critical = false
target.damageState.calcDamage = pbFixedDamage(user,target)
target.damageState.calcDamage = 1 if target.damageState.calcDamage<1
end
end
#===============================================================================
# Two turn move.
#===============================================================================
class Battle::Move::TwoTurnMove < Battle::Move
attr_reader :chargingTurn
def chargingTurnMove?; return true; end
# user.effects[PBEffects::TwoTurnAttack] is set to the move's ID if this
# method returns true, or nil if false.
# Non-nil means the charging turn. nil means the attacking turn.
def pbIsChargingTurn?(user)
@powerHerb = false
@chargingTurn = false # Assume damaging turn by default
@damagingTurn = true
# nil at start of charging turn, move's ID at start of damaging turn
if !user.effects[PBEffects::TwoTurnAttack]
@powerHerb = user.hasActiveItem?(:POWERHERB)
@chargingTurn = true
@damagingTurn = @powerHerb
end
return !@damagingTurn # Deliberately not "return @chargingTurn"
end
def pbDamagingMove? # Stops damage being dealt in the first (charging) turn
return false if !@damagingTurn
return super
end
def pbAccuracyCheck(user,target)
return true if !@damagingTurn
return super
end
def pbInitialEffect(user,targets,hitNum)
pbChargingTurnMessage(user,targets) if @chargingTurn
if @chargingTurn && @damagingTurn # Move only takes one turn to use
pbShowAnimation(@id,user,targets,1) # Charging anim
targets.each { |b| pbChargingTurnEffect(user,b) }
if @powerHerb
# Moves that would make the user semi-invulnerable will hide the user
# after the charging animation, so the "UseItem" animation shouldn't show
# for it
if !["TwoTurnAttackInvulnerableInSky",
"TwoTurnAttackInvulnerableUnderground",
"TwoTurnAttackInvulnerableUnderwater",
"TwoTurnAttackInvulnerableInSkyParalyzeTarget",
"TwoTurnAttackInvulnerableRemoveProtections",
"TwoTurnAttackInvulnerableInSkyTargetCannotAct"].include?(@function)
@battle.pbCommonAnimation("UseItem",user)
end
@battle.pbDisplay(_INTL("{1} became fully charged due to its Power Herb!",user.pbThis))
user.pbConsumeItem
end
end
pbAttackingTurnMessage(user,targets) if @damagingTurn
end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} began charging up!",user.pbThis))
end
def pbAttackingTurnMessage(user,targets)
end
def pbChargingTurnEffect(user,target)
# Skull Bash/Sky Drop are the only two-turn moves with an effect here, and
# the latter just records the target is being Sky Dropped
end
def pbAttackingTurnEffect(user,target)
end
def pbEffectAgainstTarget(user,target)
if @damagingTurn
pbAttackingTurnEffect(user,target)
elsif @chargingTurn
pbChargingTurnEffect(user,target)
end
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
hitNum = 1 if @chargingTurn && !@damagingTurn # Charging anim
super
end
end
#===============================================================================
# Healing move.
#===============================================================================
class Battle::Move::HealingMove < Battle::Move
def healingMove?; return true; end
def pbHealAmount(user); return 1; end
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if user.hp==user.totalhp
@battle.pbDisplay(_INTL("{1}'s HP is full!",user.pbThis))
return true
end
return false
end
def pbEffectGeneral(user)
amt = pbHealAmount(user)
user.pbRecoverHP(amt)
@battle.pbDisplay(_INTL("{1}'s HP was restored.",user.pbThis))
end
end
#===============================================================================
# Recoil move.
#===============================================================================
class Battle::Move::RecoilMove < Battle::Move
def recoilMove?; return true; end
def pbRecoilDamage(user,target); return 1; end
def pbEffectAfterAllHits(user,target)
return if target.damageState.unaffected
return if !user.takesIndirectDamage?
return if user.hasActiveAbility?(:ROCKHEAD)
amt = pbRecoilDamage(user,target)
amt = 1 if amt<1
user.pbReduceHP(amt,false)
@battle.pbDisplay(_INTL("{1} is damaged by recoil!",user.pbThis))
user.pbItemHPHealCheck
end
end
#===============================================================================
# Protect move.
#===============================================================================
class Battle::Move::ProtectMove < Battle::Move
def initialize(battle,move)
super
@sidedEffect = false
end
def pbChangeUsageCounters(user,specialUsage)
oldVal = user.effects[PBEffects::ProtectRate]
super
user.effects[PBEffects::ProtectRate] = oldVal
end
def pbMoveFailed?(user,targets)
if @sidedEffect
if user.pbOwnSide.effects[@effect]
user.effects[PBEffects::ProtectRate] = 1
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
elsif user.effects[@effect]
user.effects[PBEffects::ProtectRate] = 1
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
if (!@sidedEffect || Settings::MECHANICS_GENERATION <= 5) &&
user.effects[PBEffects::ProtectRate]>1 &&
@battle.pbRandom(user.effects[PBEffects::ProtectRate])!=0
user.effects[PBEffects::ProtectRate] = 1
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
if pbMoveFailedLastInRound?(user)
user.effects[PBEffects::ProtectRate] = 1
return true
end
return false
end
def pbEffectGeneral(user)
if @sidedEffect
user.pbOwnSide.effects[@effect] = true
else
user.effects[@effect] = true
end
user.effects[PBEffects::ProtectRate] *= (Settings::MECHANICS_GENERATION >= 6) ? 3 : 2
pbProtectMessage(user)
end
def pbProtectMessage(user)
if @sidedEffect
@battle.pbDisplay(_INTL("{1} protected {2}!",@name,user.pbTeam(true)))
else
@battle.pbDisplay(_INTL("{1} protected itself!",user.pbThis))
end
end
end
#===============================================================================
# Weather-inducing move.
#===============================================================================
class Battle::Move::WeatherMove < Battle::Move
def initialize(battle,move)
super
@weatherType = :None
end
def pbMoveFailed?(user,targets)
case @battle.field.weather
when :HarshSun
@battle.pbDisplay(_INTL("The extremely harsh sunlight was not lessened at all!"))
return true
when :HeavyRain
@battle.pbDisplay(_INTL("There is no relief from this heavy rain!"))
return true
when :StrongWinds
@battle.pbDisplay(_INTL("The mysterious air current blows on regardless!"))
return true
when @weatherType
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbStartWeather(user,@weatherType,true,false)
end
end
#===============================================================================
# Pledge move.
#===============================================================================
class Battle::Move::PledgeMove < Battle::Move
def pbOnStartUse(user,targets)
@pledgeSetup = false
@pledgeCombo = false
@pledgeOtherUser = nil
@comboEffect = nil
@overrideAnim = nil
# Check whether this is the use of a combo move
@combos.each do |i|
next if i[0]!=user.effects[PBEffects::FirstPledge]
@battle.pbDisplay(_INTL("The two moves have become one! It's a combined move!"))
@pledgeCombo = true
@comboEffect = i[1]
@overrideAnim = i[3]
break
end
return if @pledgeCombo
# Check whether this is the setup of a combo move
user.allAllies.each do |b|
next if @battle.choices[b.index][0]!=:UseMove || b.movedThisRound?
move = @battle.choices[b.index][2]
next if !move
@combos.each do |i|
next if i[0]!=move.function
@pledgeSetup = true
@pledgeOtherUser = b
break
end
break if @pledgeSetup
end
end
def pbDamagingMove?
return false if @pledgeSetup
return super
end
def pbBaseType(user)
# This method is called before pbOnStartUse, so it has to calculate the type
# separately
@combos.each do |i|
next if i[0] != user.effects[PBEffects::FirstPledge]
next if !GameData::Type.exists?(i[2])
return i[2]
end
return super
end
def pbBaseDamage(baseDmg,user,target)
baseDmg *= 2 if @pledgeCombo
return baseDmg
end
def pbEffectGeneral(user)
user.effects[PBEffects::FirstPledge] = 0
return if !@pledgeSetup
@battle.pbDisplay(_INTL("{1} is waiting for {2}'s move...",
user.pbThis,@pledgeOtherUser.pbThis(true)))
@pledgeOtherUser.effects[PBEffects::FirstPledge] = @function
@pledgeOtherUser.effects[PBEffects::MoveNext] = true
user.lastMoveFailed = true # Treated as a failure for Stomping Tantrum
end
def pbEffectAfterAllHits(user,target)
return if !@pledgeCombo
msg = nil
animName = nil
case @comboEffect
when :SeaOfFire # Grass + Fire
if user.pbOpposingSide.effects[PBEffects::SeaOfFire]==0
user.pbOpposingSide.effects[PBEffects::SeaOfFire] = 4
msg = _INTL("A sea of fire enveloped {1}!",user.pbOpposingTeam(true))
animName = (user.opposes?) ? "SeaOfFire" : "SeaOfFireOpp"
end
when :Rainbow # Fire + Water
if user.pbOwnSide.effects[PBEffects::Rainbow]==0
user.pbOwnSide.effects[PBEffects::Rainbow] = 4
msg = _INTL("A rainbow appeared in the sky on {1}'s side!",user.pbTeam(true))
animName = (user.opposes?) ? "RainbowOpp" : "Rainbow"
end
when :Swamp # Water + Grass
if user.pbOpposingSide.effects[PBEffects::Swamp]==0
user.pbOpposingSide.effects[PBEffects::Swamp] = 4
msg = _INTL("A swamp enveloped {1}!",user.pbOpposingTeam(true))
animName = (user.opposes?) ? "Swamp" : "SwampOpp"
end
end
@battle.pbDisplay(msg) if msg
@battle.pbCommonAnimation(animName) if animName
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
return if @pledgeSetup # No animation for setting up
id = @overrideAnim if @overrideAnim
return super
end
end

View File

@@ -0,0 +1,691 @@
#===============================================================================
# No additional effect.
#===============================================================================
class Battle::Move::None < Battle::Move
end
#===============================================================================
# Does absolutely nothing. Shows a special message. (Celebrate)
#===============================================================================
class Battle::Move::DoesNothingCongratuations < Battle::Move
def pbEffectGeneral(user)
if user.wild?
@battle.pbDisplay(_INTL("Congratulations from {1}!",user.pbThis(true)))
else
@battle.pbDisplay(_INTL("Congratulations, {1}!",@battle.pbGetOwnerName(user.index)))
end
end
end
#===============================================================================
# Does absolutely nothing. (Hold Hands)
#===============================================================================
class Battle::Move::DoesNothingFailsIfNoAlly < Battle::Move
def ignoresSubstitute?(user); return true; end
def pbMoveFailed?(user,targets)
if user.allAllies.length == 0
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
end
#===============================================================================
# Does absolutely nothing. (Splash)
#===============================================================================
class Battle::Move::DoesNothingUnusableInGravity < Battle::Move
def unusableInGravity?; return true; end
def pbEffectGeneral(user)
@battle.pbDisplay(_INTL("But nothing happened!"))
end
end
#===============================================================================
# Scatters coins that the player picks up after winning the battle. (Pay Day)
# NOTE: In Gen 6+, if the user levels up after this move is used, the amount of
# money picked up depends on the user's new level rather than its level
# when it used the move. I think this is silly, so I haven't coded this
# effect.
#===============================================================================
class Battle::Move::AddMoneyGainedFromBattle < Battle::Move
def pbEffectGeneral(user)
if user.pbOwnedByPlayer?
@battle.field.effects[PBEffects::PayDay] += 5*user.level
end
@battle.pbDisplay(_INTL("Coins were scattered everywhere!"))
end
end
#===============================================================================
# Doubles the prize money the player gets after winning the battle. (Happy Hour)
#===============================================================================
class Battle::Move::DoubleMoneyGainedFromBattle < Battle::Move
def pbEffectGeneral(user)
@battle.field.effects[PBEffects::HappyHour] = true if !user.opposes?
@battle.pbDisplay(_INTL("Everyone is caught up in the happy atmosphere!"))
end
end
#===============================================================================
# Fails if this isn't the user's first turn. (First Impression)
#===============================================================================
class Battle::Move::FailsIfNotUserFirstTurn < Battle::Move
def pbMoveFailed?(user,targets)
if user.turnCount > 1
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
end
#===============================================================================
# Fails unless user has already used all other moves it knows. (Last Resort)
#===============================================================================
class Battle::Move::FailsIfUserHasUnusedMove < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
hasThisMove = false
hasOtherMoves = false
hasUnusedMoves = false
user.eachMove do |m|
hasThisMove = true if m.id==@id
hasOtherMoves = true if m.id!=@id
hasUnusedMoves = true if m.id!=@id && !user.movesUsed.include?(m.id)
end
if !hasThisMove || !hasOtherMoves || hasUnusedMoves
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
end
#===============================================================================
# Fails unless user has consumed a berry at some point. (Belch)
#===============================================================================
class Battle::Move::FailsIfUserNotConsumedBerry < Battle::Move
def pbCanChooseMove?(user,commandPhase,showMessages)
if !user.belched?
if showMessages
msg = _INTL("{1} hasn't eaten any held berry, so it can't possibly belch!",user.pbThis)
(commandPhase) ? @battle.pbDisplayPaused(msg) : @battle.pbDisplay(msg)
end
return false
end
return true
end
def pbMoveFailed?(user,targets)
if !user.belched?
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
end
#===============================================================================
# Fails if the target is not holding an item, or if the target is affected by
# Magic Room/Klutz. (Poltergeist)
#===============================================================================
class Battle::Move::FailsIfTargetHasNoItem < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
if !target.item || !target.itemActive?
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
@battle.pbDisplay(_INTL("{1} is about to be attacked by its {2}!", target.pbThis, target.itemName))
return false
end
end
#===============================================================================
# Only damages Pokémon that share a type with the user. (Synchronoise)
#===============================================================================
class Battle::Move::FailsUnlessTargetSharesTypeWithUser < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
userTypes = user.pbTypes(true)
targetTypes = target.pbTypes(true)
sharesType = false
userTypes.each do |t|
next if !targetTypes.include?(t)
sharesType = true
break
end
if !sharesType
@battle.pbDisplay(_INTL("{1} is unaffected!",target.pbThis)) if show_message
return true
end
return false
end
end
#===============================================================================
# Fails if user was hit by a damaging move this round. (Focus Punch)
#===============================================================================
class Battle::Move::FailsIfUserDamagedThisTurn < Battle::Move
def pbDisplayChargeMessage(user)
user.effects[PBEffects::FocusPunch] = true
@battle.pbCommonAnimation("FocusPunch",user)
@battle.pbDisplay(_INTL("{1} is tightening its focus!",user.pbThis))
end
def pbDisplayUseMessage(user)
super if !user.effects[PBEffects::FocusPunch] || user.lastHPLost==0
end
def pbMoveFailed?(user,targets)
if user.effects[PBEffects::FocusPunch] && user.lastHPLost>0
@battle.pbDisplay(_INTL("{1} lost its focus and couldn't move!",user.pbThis))
return true
end
return false
end
end
#===============================================================================
# Fails if the target didn't chose a damaging move to use this round, or has
# already moved. (Sucker Punch)
#===============================================================================
class Battle::Move::FailsIfTargetActed < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.choices[target.index][0]!=:UseMove
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
oppMove = @battle.choices[target.index][2]
if !oppMove ||
(oppMove.function!="UseMoveTargetIsAboutToUse" &&
(target.movedThisRound? || oppMove.statusMove?))
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
end
#===============================================================================
# If attack misses, user takes crash damage of 1/2 of max HP.
# (High Jump Kick, Jump Kick)
#===============================================================================
class Battle::Move::CrashDamageIfFailsUnusableInGravity < Battle::Move
def recoilMove?; return true; end
def unusableInGravity?; return true; end
def pbCrashDamage(user)
return if !user.takesIndirectDamage?
@battle.pbDisplay(_INTL("{1} kept going and crashed!",user.pbThis))
@battle.scene.pbDamageAnimation(user)
user.pbReduceHP(user.totalhp/2,false)
user.pbItemHPHealCheck
user.pbFaint if user.fainted?
end
end
#===============================================================================
# Starts sunny weather. (Sunny Day)
#===============================================================================
class Battle::Move::StartSunWeather < Battle::Move::WeatherMove
def initialize(battle,move)
super
@weatherType = :Sun
end
end
#===============================================================================
# Starts rainy weather. (Rain Dance)
#===============================================================================
class Battle::Move::StartRainWeather < Battle::Move::WeatherMove
def initialize(battle,move)
super
@weatherType = :Rain
end
end
#===============================================================================
# Starts sandstorm weather. (Sandstorm)
#===============================================================================
class Battle::Move::StartSandstormWeather < Battle::Move::WeatherMove
def initialize(battle,move)
super
@weatherType = :Sandstorm
end
end
#===============================================================================
# Starts hail weather. (Hail)
#===============================================================================
class Battle::Move::StartHailWeather < Battle::Move::WeatherMove
def initialize(battle,move)
super
@weatherType = :Hail
end
end
#===============================================================================
# For 5 rounds, creates an electric terrain which boosts Electric-type moves and
# prevents Pokémon from falling asleep. Affects non-airborne Pokémon only.
# (Electric Terrain)
#===============================================================================
class Battle::Move::StartElectricTerrain < Battle::Move
def pbMoveFailed?(user,targets)
if @battle.field.terrain == :Electric
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbStartTerrain(user, :Electric)
end
end
#===============================================================================
# For 5 rounds, creates a grassy terrain which boosts Grass-type moves and heals
# Pokémon at the end of each round. Affects non-airborne Pokémon only.
# (Grassy Terrain)
#===============================================================================
class Battle::Move::StartGrassyTerrain < Battle::Move
def pbMoveFailed?(user,targets)
if @battle.field.terrain == :Grassy
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbStartTerrain(user, :Grassy)
end
end
#===============================================================================
# For 5 rounds, creates a misty terrain which weakens Dragon-type moves and
# protects Pokémon from status problems. Affects non-airborne Pokémon only.
# (Misty Terrain)
#===============================================================================
class Battle::Move::StartMistyTerrain < Battle::Move
def pbMoveFailed?(user,targets)
if @battle.field.terrain == :Misty
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbStartTerrain(user, :Misty)
end
end
#===============================================================================
# For 5 rounds, creates a psychic terrain which boosts Psychic-type moves and
# prevents Pokémon from being hit by >0 priority moves. Affects non-airborne
# Pokémon only. (Psychic Terrain)
#===============================================================================
class Battle::Move::StartPsychicTerrain < Battle::Move
def pbMoveFailed?(user,targets)
if @battle.field.terrain == :Psychic
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbStartTerrain(user, :Psychic)
end
end
#===============================================================================
# Removes the current terrain. Fails if there is no terrain in effect.
# (Steel Roller)
#===============================================================================
class Battle::Move::RemoveTerrain < Battle::Move
def pbMoveFailed?(user, targets)
if @battle.field.terrain == :None
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
case @battle.field.terrain
when :Electric
@battle.pbDisplay(_INTL("The electricity disappeared from the battlefield."))
when :Grassy
@battle.pbDisplay(_INTL("The grass disappeared from the battlefield."))
when :Misty
@battle.pbDisplay(_INTL("The mist disappeared from the battlefield."))
when :Psychic
@battle.pbDisplay(_INTL("The weirdness disappeared from the battlefield."))
end
@battle.field.terrain = :None
end
end
#===============================================================================
# Entry hazard. Lays spikes on the opposing side (max. 3 layers). (Spikes)
#===============================================================================
class Battle::Move::AddSpikesToFoeSide < Battle::Move
def canMagicCoat?; return true; end
def pbMoveFailed?(user,targets)
if user.pbOpposingSide.effects[PBEffects::Spikes]>=3
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.pbOpposingSide.effects[PBEffects::Spikes] += 1
@battle.pbDisplay(_INTL("Spikes were scattered all around {1}'s feet!",
user.pbOpposingTeam(true)))
end
end
#===============================================================================
# Entry hazard. Lays poison spikes on the opposing side (max. 2 layers).
# (Toxic Spikes)
#===============================================================================
class Battle::Move::AddToxicSpikesToFoeSide < Battle::Move
def canMagicCoat?; return true; end
def pbMoveFailed?(user,targets)
if user.pbOpposingSide.effects[PBEffects::ToxicSpikes]>=2
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.pbOpposingSide.effects[PBEffects::ToxicSpikes] += 1
@battle.pbDisplay(_INTL("Poison spikes were scattered all around {1}'s feet!",
user.pbOpposingTeam(true)))
end
end
#===============================================================================
# Entry hazard. Lays stealth rocks on the opposing side. (Stealth Rock)
#===============================================================================
class Battle::Move::AddStealthRocksToFoeSide < Battle::Move
def canMagicCoat?; return true; end
def pbMoveFailed?(user,targets)
if user.pbOpposingSide.effects[PBEffects::StealthRock]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.pbOpposingSide.effects[PBEffects::StealthRock] = true
@battle.pbDisplay(_INTL("Pointed stones float in the air around {1}!",
user.pbOpposingTeam(true)))
end
end
#===============================================================================
# Entry hazard. Lays stealth rocks on the opposing side. (Sticky Web)
#===============================================================================
class Battle::Move::AddStickyWebToFoeSide < Battle::Move
def canMagicCoat?; return true; end
def pbMoveFailed?(user,targets)
if user.pbOpposingSide.effects[PBEffects::StickyWeb]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.pbOpposingSide.effects[PBEffects::StickyWeb] = true
@battle.pbDisplay(_INTL("A sticky web has been laid out beneath {1}'s feet!",
user.pbOpposingTeam(true)))
end
end
#===============================================================================
# All effects that apply to one side of the field are swapped to the opposite
# side. (Court Change)
#===============================================================================
class Battle::Move::SwapSideEffects < Battle::Move
def initialize(battle, move)
super
@number_effects = [
PBEffects::AuroraVeil,
PBEffects::LightScreen,
PBEffects::Mist,
PBEffects::Rainbow,
PBEffects::Reflect,
PBEffects::Safeguard,
PBEffects::SeaOfFire,
PBEffects::Spikes,
PBEffects::Swamp,
PBEffects::Tailwind,
PBEffects::ToxicSpikes
]
@boolean_effects = [
PBEffects::StealthRock,
PBEffects::StickyWeb
]
end
def pbMoveFailed?(user, targets)
has_effect = false
for side in 0...2
effects = @battle.sides[side].effects
@number_effects.each do |e|
next if effects[e] == 0
has_effect = true
break
end
break if has_effect
@boolean_effects.each do |e|
next if !effects[e]
has_effect = true
break
end
break if has_effect
end
if !has_effect
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
side0 = @battle.sides[0]
side1 = @battle.sides[1]
@number_effects.each do |e|
side0.effects[e], side1.effects[e] = side1.effects[e], side0.effects[e]
end
@boolean_effects.each do |e|
side0.effects[e], side1.effects[e] = side1.effects[e], side0.effects[e]
end
@battle.pbDisplay(_INTL("{1} swapped the battle effects affecting each side of the field!", user.pbThis))
end
end
#===============================================================================
# User turns 1/4 of max HP into a substitute. (Substitute)
#===============================================================================
class Battle::Move::UserMakeSubstitute < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if user.effects[PBEffects::Substitute]>0
@battle.pbDisplay(_INTL("{1} already has a substitute!",user.pbThis))
return true
end
@subLife = user.totalhp/4
@subLife = 1 if @subLife<1
if user.hp<=@subLife
@battle.pbDisplay(_INTL("But it does not have enough HP left to make a substitute!"))
return true
end
return false
end
def pbOnStartUse(user,targets)
user.pbReduceHP(@subLife,false,false)
user.pbItemHPHealCheck
end
def pbEffectGeneral(user)
user.effects[PBEffects::Trapping] = 0
user.effects[PBEffects::TrappingMove] = nil
user.effects[PBEffects::Substitute] = @subLife
@battle.pbDisplay(_INTL("{1} put in a substitute!",user.pbThis))
end
end
#===============================================================================
# Removes trapping moves, entry hazards and Leech Seed on user/user's side.
# Raises user's Speed by 1 stage (Gen 8+). (Rapid Spin)
#===============================================================================
class Battle::Move::RemoveUserBindingAndEntryHazards < Battle::Move::StatUpMove
def initialize(battle,move)
super
@statUp = [:SPEED, 1]
end
def pbEffectAfterAllHits(user,target)
return if user.fainted? || target.damageState.unaffected
if user.effects[PBEffects::Trapping]>0
trapMove = GameData::Move.get(user.effects[PBEffects::TrappingMove]).name
trapUser = @battle.battlers[user.effects[PBEffects::TrappingUser]]
@battle.pbDisplay(_INTL("{1} got free of {2}'s {3}!",user.pbThis,trapUser.pbThis(true),trapMove))
user.effects[PBEffects::Trapping] = 0
user.effects[PBEffects::TrappingMove] = nil
user.effects[PBEffects::TrappingUser] = -1
end
if user.effects[PBEffects::LeechSeed]>=0
user.effects[PBEffects::LeechSeed] = -1
@battle.pbDisplay(_INTL("{1} shed Leech Seed!",user.pbThis))
end
if user.pbOwnSide.effects[PBEffects::StealthRock]
user.pbOwnSide.effects[PBEffects::StealthRock] = false
@battle.pbDisplay(_INTL("{1} blew away stealth rocks!",user.pbThis))
end
if user.pbOwnSide.effects[PBEffects::Spikes]>0
user.pbOwnSide.effects[PBEffects::Spikes] = 0
@battle.pbDisplay(_INTL("{1} blew away spikes!",user.pbThis))
end
if user.pbOwnSide.effects[PBEffects::ToxicSpikes]>0
user.pbOwnSide.effects[PBEffects::ToxicSpikes] = 0
@battle.pbDisplay(_INTL("{1} blew away poison spikes!",user.pbThis))
end
if user.pbOwnSide.effects[PBEffects::StickyWeb]
user.pbOwnSide.effects[PBEffects::StickyWeb] = false
@battle.pbDisplay(_INTL("{1} blew away sticky webs!",user.pbThis))
end
end
def pbAdditionalEffect(user,target)
super if Settings::MECHANICS_GENERATION >= 8
end
end
#===============================================================================
# Attacks 2 rounds in the future. (Doom Desire, Future Sight)
#===============================================================================
class Battle::Move::AttackTwoTurnsLater < Battle::Move
def targetsPosition?; return true; end
def pbDamagingMove? # Stops damage being dealt in the setting-up turn
return false if !@battle.futureSight
return super
end
def pbAccuracyCheck(user,target)
return true if !@battle.futureSight
return super
end
def pbDisplayUseMessage(user)
super if !@battle.futureSight
end
def pbFailsAgainstTarget?(user, target, show_message)
if !@battle.futureSight &&
@battle.positions[target.index].effects[PBEffects::FutureSightCounter]>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
return if @battle.futureSight # Attack is hitting
effects = @battle.positions[target.index].effects
effects[PBEffects::FutureSightCounter] = 3
effects[PBEffects::FutureSightMove] = @id
effects[PBEffects::FutureSightUserIndex] = user.index
effects[PBEffects::FutureSightUserPartyIndex] = user.pokemonIndex
if @id == :DOOMDESIRE
@battle.pbDisplay(_INTL("{1} chose Doom Desire as its destiny!",user.pbThis))
else
@battle.pbDisplay(_INTL("{1} foresaw an attack!",user.pbThis))
end
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
hitNum = 1 if !@battle.futureSight # Charging anim
super
end
end
#===============================================================================
# User switches places with its ally. (Ally Switch)
#===============================================================================
class Battle::Move::UserSwapsPositionsWithAlly < Battle::Move
def pbMoveFailed?(user,targets)
numTargets = 0
@idxAlly = -1
idxUserOwner = @battle.pbGetOwnerIndexFromBattlerIndex(user.index)
user.allAllies.each do |b|
next if @battle.pbGetOwnerIndexFromBattlerIndex(b.index)!=idxUserOwner
next if !b.near?(user)
numTargets += 1
@idxAlly = b.index
end
if numTargets!=1
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
idxA = user.index
idxB = @idxAlly
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.pbEffectsOnBattlerEnteringPosition(@battle.battlers[idx]) }
end
end
end
#===============================================================================
# If a Pokémon makes contact with the user before it uses this move, the
# attacker is burned. (Beak Blast)
#===============================================================================
class Battle::Move::BurnAttackerBeforeUserActs < Battle::Move
def pbDisplayChargeMessage(user)
user.effects[PBEffects::BeakBlast] = true
@battle.pbCommonAnimation("BeakBlast",user)
@battle.pbDisplay(_INTL("{1} started heating up its beak!",user.pbThis))
end
end

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,621 @@
#===============================================================================
# Hits twice.
#===============================================================================
class Battle::Move::HitTwoTimes < Battle::Move
def multiHitMove?; return true; end
def pbNumHits(user,targets); return 2; end
end
#===============================================================================
# Hits twice. May poison the target on each hit. (Twineedle)
#===============================================================================
class Battle::Move::HitTwoTimesPoisonTarget < Battle::Move::PoisonMove
def multiHitMove?; return true; end
def pbNumHits(user,targets); return 2; end
end
#===============================================================================
# Hits twice. Causes the target to flinch. Does double damage and has perfect
# accuracy if the target is Minimized. (Double Iron Bash)
#===============================================================================
class Battle::Move::HitTwoTimesFlinchTarget < Battle::Move::FlinchMove
def multiHitMove?; return true; end
def pbNumHits(user,targets); return 2; end
def tramplesMinimize?(param=1); return Settings::MECHANICS_GENERATION <= 7; end
end
#===============================================================================
# Hits in 2 volleys. The second volley targets the original target's ally if it
# has one (that can be targeted), or the original target if not. A battler
# cannot be targeted if it is is immune to or protected from this move somehow,
# or if this move will miss it. (Dragon Darts)
# NOTE: This move sometimes shows a different failure message compared to the
# official games. This is because of the order in which failure checks are
# done (all checks for each target in turn, versus all targets for each
# check in turn). This is considered unimportant, and since correcting it
# would involve extensive code rewrites, it is being ignored.
#===============================================================================
class Battle::Move::HitTwoTimesTargetThenTargetAlly < Battle::Move
def pbNumHits(user, targets); return 1; end
def pbRepeatHit?; return true; end
def pbModifyTargets(targets, user)
return if targets.length != 1
choices = []
targets[0].allAllies.each { |b| user.pbAddTarget(choices, user, b, self) }
return if choices.length == 0
idxChoice = (choices.length > 1) ? @battle.pbRandom(choices.length) : 0
user.pbAddTarget(targets, user, choices[idxChoice], self, !pbTarget(user).can_choose_distant_target?)
end
def pbShowFailMessages?(targets)
if targets.length > 1
valid_targets = targets.select { |b| !b.fainted? && !b.damageState.unaffected }
return valid_targets.length <= 1
end
return super
end
def pbDesignateTargetsForHit(targets, hitNum)
valid_targets = []
targets.each { |b| valid_targets.push(b) if !b.damageState.unaffected }
return [valid_targets[1]] if valid_targets[1] && hitNum == 1
return [valid_targets[0]]
end
end
#===============================================================================
# Hits 3 times. Power is multiplied by the hit number. (Triple Kick)
# An accuracy check is performed for each hit.
#===============================================================================
class Battle::Move::HitThreeTimesPowersUpWithEachHit < Battle::Move
def multiHitMove?; return true; end
def pbNumHits(user,targets); return 3; end
def successCheckPerHit?
return @accCheckPerHit
end
def pbOnStartUse(user,targets)
@calcBaseDmg = 0
@accCheckPerHit = !user.hasActiveAbility?(:SKILLLINK)
end
def pbBaseDamage(baseDmg,user,target)
@calcBaseDmg += baseDmg
return @calcBaseDmg
end
end
#===============================================================================
# Hits 3 times in a row. If each hit could be a critical hit, it will definitely
# be a critical hit. (Surging Strikes)
#===============================================================================
class Battle::Move::HitThreeTimesAlwaysCriticalHit < Battle::Move
def multiHitMove?; return true; end
def pbNumHits(user, targets); return 3; end
def pbCritialOverride(user, target); return 1; end
end
#===============================================================================
# Hits 2-5 times.
#===============================================================================
class Battle::Move::HitTwoToFiveTimes < Battle::Move
def multiHitMove?; return true; end
def pbNumHits(user,targets)
hitChances = [
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3,
4, 4, 4,
5, 5, 5
]
r = @battle.pbRandom(hitChances.length)
r = hitChances.length-1 if user.hasActiveAbility?(:SKILLLINK)
return hitChances[r]
end
end
#===============================================================================
# Hits 2-5 times. If the user is Ash Greninja, powers up and hits 3 times.
# (Water Shuriken)
#===============================================================================
class Battle::Move::HitTwoToFiveTimesOrThreeForAshGreninja < Battle::Move::HitTwoToFiveTimes
def pbNumHits(user,targets)
return 3 if user.isSpecies?(:GRENINJA) && user.form == 2
return super
end
def pbBaseDamage(baseDmg,user,target)
return 20 if user.isSpecies?(:GRENINJA) && user.form == 2
return super
end
end
#===============================================================================
# Hits 2-5 times in a row. If the move does not fail, increases the user's Speed
# by 1 stage and decreases the user's Defense by 1 stage. (Scale Shot)
#===============================================================================
class Battle::Move::HitTwoToFiveTimesRaiseUserSpd1LowerUserDef1 < Battle::Move
def multiHitMove?; return true; end
def pbNumHits(user, targets)
hitChances = [
2, 2, 2, 2, 2, 2, 2,
3, 3, 3, 3, 3, 3, 3,
4, 4, 4,
5, 5, 5]
r = @battle.pbRandom(hitChances.length)
r = hitChances.length - 1 if user.hasActiveAbility?(:SKILLLINK)
return hitChances[r]
end
def pbEffectAfterAllHits(user, target)
return if target.damageState.unaffected
if user.pbCanLowerStatStage?(:DEFENSE, user, self)
user.pbLowerStatStage(:DEFENSE, 1, user)
end
if user.pbCanRaiseStatStage?(:SPEED, user, self)
user.pbRaiseStatStage(:SPEED, 1, user)
end
end
end
#===============================================================================
# Hits X times, where X is the number of non-user unfainted status-free Pokémon
# in the user's party (not including partner trainers). Fails if X is 0.
# Base power of each hit depends on the base Attack stat for the species of that
# hit's participant. (Beat Up)
#===============================================================================
class Battle::Move::HitOncePerUserTeamMember < Battle::Move
def multiHitMove?; return true; end
def pbMoveFailed?(user,targets)
@beatUpList = []
@battle.eachInTeamFromBattlerIndex(user.index) do |pkmn,i|
next if !pkmn.able? || pkmn.status != :NONE
@beatUpList.push(i)
end
if @beatUpList.length==0
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbNumHits(user,targets)
return @beatUpList.length
end
def pbBaseDamage(baseDmg,user,target)
i = @beatUpList.shift # First element in array, and removes it from array
atk = @battle.pbParty(user.index)[i].baseStats[:ATTACK]
return 5+(atk/10)
end
end
#===============================================================================
# Attacks first turn, skips second turn (if successful).
#===============================================================================
class Battle::Move::AttackAndSkipNextTurn < Battle::Move
def pbEffectGeneral(user)
user.effects[PBEffects::HyperBeam] = 2
user.currentMove = @id
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Razor Wind)
#===============================================================================
class Battle::Move::TwoTurnAttack < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} whipped up a whirlwind!",user.pbThis))
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Solar Beam, Solar Blade)
# Power halved in all weather except sunshine. In sunshine, takes 1 turn instead.
#===============================================================================
class Battle::Move::TwoTurnAttackOneTurnInSun < Battle::Move::TwoTurnMove
def pbIsChargingTurn?(user)
ret = super
if !user.effects[PBEffects::TwoTurnAttack]
if [:Sun, :HarshSun].include?(user.effectiveWeather)
@powerHerb = false
@chargingTurn = true
@damagingTurn = true
return false
end
end
return ret
end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} took in sunlight!",user.pbThis))
end
def pbBaseDamageMultiplier(damageMult,user,target)
damageMult /= 2 if ![:None, :Sun, :HarshSun].include?(user.effectiveWeather)
return damageMult
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Freeze Shock)
# May paralyze the target.
#===============================================================================
class Battle::Move::TwoTurnAttackParalyzeTarget < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} became cloaked in a freezing light!",user.pbThis))
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbParalyze(user) if target.pbCanParalyze?(user,false,self)
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Ice Burn)
# May burn the target.
#===============================================================================
class Battle::Move::TwoTurnAttackBurnTarget < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} became cloaked in freezing air!",user.pbThis))
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbBurn(user) if target.pbCanBurn?(user,false,self)
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Sky Attack)
# May make the target flinch.
#===============================================================================
class Battle::Move::TwoTurnAttackFlinchTarget < Battle::Move::TwoTurnMove
def flinchingMove?; return true; end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} became cloaked in a harsh light!",user.pbThis))
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbFlinch(user)
end
end
#===============================================================================
# Two turn attack. Skips first turn, and increases the user's Special Attack,
# Special Defense and Speed by 2 stages each in the second turn. (Geomancy)
#===============================================================================
class Battle::Move::TwoTurnAttackRaiseUserSpAtkSpDefSpd2 < Battle::Move::TwoTurnMove
def pbMoveFailed?(user,targets)
return false if user.effects[PBEffects::TwoTurnAttack] # Charging turn
if !user.pbCanRaiseStatStage?(:SPECIAL_ATTACK,user,self) &&
!user.pbCanRaiseStatStage?(:SPECIAL_DEFENSE,user,self) &&
!user.pbCanRaiseStatStage?(:SPEED,user,self)
@battle.pbDisplay(_INTL("{1}'s stats won't go any higher!",user.pbThis))
return true
end
return false
end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} is absorbing power!",user.pbThis))
end
def pbEffectGeneral(user)
return if !@damagingTurn
showAnim = true
[:SPECIAL_ATTACK,:SPECIAL_DEFENSE,:SPEED].each do |s|
next if !user.pbCanRaiseStatStage?(s,user,self)
if user.pbRaiseStatStage(s,2,user,showAnim)
showAnim = false
end
end
end
end
#===============================================================================
# Two turn attack. Ups user's Defense by 1 stage first turn, attacks second turn.
# (Skull Bash)
#===============================================================================
class Battle::Move::TwoTurnAttackChargeRaiseUserDefense1 < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} tucked in its head!",user.pbThis))
end
def pbChargingTurnEffect(user,target)
if user.pbCanRaiseStatStage?(:DEFENSE,user,self)
user.pbRaiseStatStage(:DEFENSE,1,user)
end
end
end
#===============================================================================
# Two-turn attack. On the first turn, increases the user's Special Attack by 1
# stage. On the second turn, does damage. (Meteor Beam)
#===============================================================================
class Battle::Move::TwoTurnAttackChargeRaiseUserSpAtk1 < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user, targets)
@battle.pbDisplay(_INTL("{1} is overflowing with space power!", user.pbThis))
end
def pbChargingTurnEffect(user, target)
if user.pbCanRaiseStatStage?(:SPECIAL_ATTACK, user, self)
user.pbRaiseStatStage(:SPECIAL_ATTACK, 1, user)
end
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Dig)
# (Handled in Battler's pbSuccessCheckPerHit): Is semi-invulnerable during use.
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableUnderground < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} burrowed its way under the ground!",user.pbThis))
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Dive)
# (Handled in Battler's pbSuccessCheckPerHit): Is semi-invulnerable during use.
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableUnderwater < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} hid underwater!",user.pbThis))
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Fly)
# (Handled in Battler's pbSuccessCheckPerHit): Is semi-invulnerable during use.
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableInSky < Battle::Move::TwoTurnMove
def unusableInGravity?; return true; end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} flew up high!",user.pbThis))
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Bounce)
# May paralyze the target.
# (Handled in Battler's pbSuccessCheckPerHit): Is semi-invulnerable during use.
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableInSkyParalyzeTarget < Battle::Move::TwoTurnMove
def unusableInGravity?; return true; end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} sprang up!",user.pbThis))
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
target.pbParalyze(user) if target.pbCanParalyze?(user,false,self)
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. (Sky Drop)
# (Handled in Battler's pbSuccessCheckPerHit): Is semi-invulnerable during use.
# Target is also semi-invulnerable during use, and can't take any action.
# Doesn't damage airborne Pokémon (but still makes them unable to move during).
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableInSkyTargetCannotAct < Battle::Move::TwoTurnMove
def unusableInGravity?; return true; end
def pbIsChargingTurn?(user)
# NOTE: Sky Drop doesn't benefit from Power Herb, probably because it works
# differently (i.e. immobilises the target during use too).
@powerHerb = false
@chargingTurn = (user.effects[PBEffects::TwoTurnAttack].nil?)
@damagingTurn = (!user.effects[PBEffects::TwoTurnAttack].nil?)
return !@damagingTurn
end
def pbFailsAgainstTarget?(user, target, show_message)
if !target.opposes?(user)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.effects[PBEffects::Substitute]>0 && !ignoresSubstitute?(user)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if Settings::MECHANICS_GENERATION >= 6 && target.pbWeight>=2000 # 200.0kg
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.semiInvulnerable? ||
(target.effects[PBEffects::SkyDrop]>=0 && @chargingTurn)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.effects[PBEffects::SkyDrop]!=user.index && @damagingTurn
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbCalcTypeMod(movetype,user,target)
return Effectiveness::INEFFECTIVE if target.pbHasType?(:FLYING)
return super
end
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} took {2} into the sky!",user.pbThis,targets[0].pbThis(true)))
end
def pbAttackingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} was freed from the Sky Drop!",targets[0].pbThis))
end
def pbChargingTurnEffect(user,target)
target.effects[PBEffects::SkyDrop] = user.index
end
def pbAttackingTurnEffect(user,target)
target.effects[PBEffects::SkyDrop] = -1
end
end
#===============================================================================
# Two turn attack. Skips first turn, attacks second turn. Is invulnerable during
# use. Ends target's protections upon hit. (Shadow Force, Phantom Force)
#===============================================================================
class Battle::Move::TwoTurnAttackInvulnerableRemoveProtections < Battle::Move::TwoTurnMove
def pbChargingTurnMessage(user,targets)
@battle.pbDisplay(_INTL("{1} vanished instantly!",user.pbThis))
end
def pbAttackingTurnEffect(user,target)
target.effects[PBEffects::BanefulBunker] = false
target.effects[PBEffects::KingsShield] = false
target.effects[PBEffects::Obstruct] = false
target.effects[PBEffects::Protect] = false
target.effects[PBEffects::SpikyShield] = false
target.pbOwnSide.effects[PBEffects::CraftyShield] = false
target.pbOwnSide.effects[PBEffects::MatBlock] = false
target.pbOwnSide.effects[PBEffects::QuickGuard] = false
target.pbOwnSide.effects[PBEffects::WideGuard] = false
end
end
#===============================================================================
# User must use this move for 2 more rounds. No battlers can sleep. (Uproar)
# NOTE: Bulbapedia claims that an uproar will wake up Pokémon even if they have
# Soundproof, and will not allow Pokémon to fall asleep even if they have
# Soundproof. I think this is an oversight, so I've let Soundproof Pokémon
# be unaffected by Uproar waking/non-sleeping effects.
#===============================================================================
class Battle::Move::MultiTurnAttackPreventSleeping < Battle::Move
def pbEffectGeneral(user)
return if user.effects[PBEffects::Uproar]>0
user.effects[PBEffects::Uproar] = 3
user.currentMove = @id
@battle.pbDisplay(_INTL("{1} caused an uproar!",user.pbThis))
@battle.pbPriority(true).each do |b|
next if b.fainted? || b.status != :SLEEP
next if b.hasActiveAbility?(:SOUNDPROOF)
b.pbCureStatus
end
end
end
#===============================================================================
# User must use this move for 1 or 2 more rounds. At end, user becomes confused.
# (Outrage, Petal Dange, Thrash)
#===============================================================================
class Battle::Move::MultiTurnAttackConfuseUserAtEnd < Battle::Move
def pbEffectAfterAllHits(user,target)
if !target.damageState.unaffected && user.effects[PBEffects::Outrage]==0
user.effects[PBEffects::Outrage] = 2+@battle.pbRandom(2)
user.currentMove = @id
end
if user.effects[PBEffects::Outrage]>0
user.effects[PBEffects::Outrage] -= 1
if user.effects[PBEffects::Outrage]==0 && user.pbCanConfuseSelf?(false)
user.pbConfuse(_INTL("{1} became confused due to fatigue!",user.pbThis))
end
end
end
end
#===============================================================================
# User must use this move for 4 more rounds. Power doubles each round.
# Power is also doubled if user has curled up. (Ice Ball, Rollout)
#===============================================================================
class Battle::Move::MultiTurnAttackPowersUpEachTurn < Battle::Move
def pbBaseDamage(baseDmg,user,target)
shift = (5 - user.effects[PBEffects::Rollout]) # 0-4, where 0 is most powerful
shift = 0 if user.effects[PBEffects::Rollout] == 0 # For first turn
shift += 1 if user.effects[PBEffects::DefenseCurl]
baseDmg *= 2**shift
return baseDmg
end
def pbEffectAfterAllHits(user,target)
if !target.damageState.unaffected && user.effects[PBEffects::Rollout] == 0
user.effects[PBEffects::Rollout] = 5
user.currentMove = @id
end
user.effects[PBEffects::Rollout] -= 1 if user.effects[PBEffects::Rollout] > 0
end
end
#===============================================================================
# User bides its time this round and next round. The round after, deals 2x the
# total direct damage it took while biding to the last battler that damaged it.
# (Bide)
#===============================================================================
class Battle::Move::MultiTurnAttackBideThenReturnDoubleDamage < Battle::Move::FixedDamageMove
def pbAddTarget(targets,user)
return if user.effects[PBEffects::Bide]!=1 # Not the attack turn
idxTarget = user.effects[PBEffects::BideTarget]
t = (idxTarget>=0) ? @battle.battlers[idxTarget] : nil
if !user.pbAddTarget(targets,user,t,self,false)
user.pbAddTargetRandomFoe(targets,user,self,false)
end
end
def pbMoveFailed?(user,targets)
return false if user.effects[PBEffects::Bide]!=1 # Not the attack turn
if user.effects[PBEffects::BideDamage]==0
@battle.pbDisplay(_INTL("But it failed!"))
user.effects[PBEffects::Bide] = 0 # No need to reset other Bide variables
return true
end
if targets.length==0
@battle.pbDisplay(_INTL("But there was no target..."))
user.effects[PBEffects::Bide] = 0 # No need to reset other Bide variables
return true
end
return false
end
def pbOnStartUse(user,targets)
@damagingTurn = (user.effects[PBEffects::Bide]==1) # If attack turn
end
def pbDisplayUseMessage(user)
if @damagingTurn # Attack turn
@battle.pbDisplayBrief(_INTL("{1} unleashed energy!",user.pbThis))
elsif user.effects[PBEffects::Bide]>1 # Charging turns
@battle.pbDisplayBrief(_INTL("{1} is storing energy!",user.pbThis))
else
super # Start using Bide
end
end
def pbDamagingMove? # Stops damage being dealt in the charging turns
return false if !@damagingTurn
return super
end
def pbFixedDamage(user,target)
return user.effects[PBEffects::BideDamage]*2
end
def pbEffectGeneral(user)
if user.effects[PBEffects::Bide]==0 # Starting using Bide
user.effects[PBEffects::Bide] = 3
user.effects[PBEffects::BideDamage] = 0
user.effects[PBEffects::BideTarget] = -1
user.currentMove = @id
end
user.effects[PBEffects::Bide] -= 1
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
hitNum = 1 if !@damagingTurn # Charging anim
super
end
end

View File

@@ -0,0 +1,686 @@
#===============================================================================
# Heals user to full HP. User falls asleep for 2 more rounds. (Rest)
#===============================================================================
class Battle::Move::HealUserFullyAndFallAsleep < Battle::Move::HealingMove
def pbMoveFailed?(user,targets)
if user.asleep?
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return true if !user.pbCanSleep?(user,true,self,true)
return true if super
return false
end
def pbHealAmount(user)
return user.totalhp-user.hp
end
def pbEffectGeneral(user)
user.pbSleepSelf(_INTL("{1} slept and became healthy!",user.pbThis),3)
super
end
end
#===============================================================================
# Heals user by 1/2 of its max HP.
#===============================================================================
class Battle::Move::HealUserHalfOfTotalHP < Battle::Move::HealingMove
def pbHealAmount(user)
return (user.totalhp/2.0).round
end
end
#===============================================================================
# Heals user by an amount depending on the weather. (Moonlight, Morning Sun,
# Synthesis)
#===============================================================================
class Battle::Move::HealUserDependingOnWeather < Battle::Move::HealingMove
def pbOnStartUse(user,targets)
case user.effectiveWeather
when :Sun, :HarshSun
@healAmount = (user.totalhp*2/3.0).round
when :None, :StrongWinds
@healAmount = (user.totalhp/2.0).round
else
@healAmount = (user.totalhp/4.0).round
end
end
def pbHealAmount(user)
return @healAmount
end
end
#===============================================================================
# Heals user by 1/2 of its max HP, or 2/3 of its max HP in a sandstorm. (Shore Up)
#===============================================================================
class Battle::Move::HealUserDependingOnSandstorm < Battle::Move::HealingMove
def pbHealAmount(user)
return (user.totalhp * 2 / 3.0).round if user.effectiveWeather == :Sandstorm
return (user.totalhp / 2.0).round
end
end
#===============================================================================
# Heals user by 1/2 of its max HP. (Roost)
# User roosts, and its Flying type is ignored for attacks used against it.
#===============================================================================
class Battle::Move::HealUserHalfOfTotalHPLoseFlyingTypeThisTurn < Battle::Move::HealingMove
def pbHealAmount(user)
return (user.totalhp/2.0).round
end
def pbEffectGeneral(user)
super
user.effects[PBEffects::Roost] = true
end
end
#===============================================================================
# Cures the target's permanent status problems. Heals user by 1/2 of its max HP.
# (Purify)
#===============================================================================
class Battle::Move::CureTargetStatusHealUserHalfOfTotalHP < Battle::Move::HealingMove
def canSnatch?; return false; end # Because it affects a target
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.status == :NONE
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbHealAmount(user)
return (user.totalhp/2.0).round
end
def pbEffectAgainstTarget(user,target)
target.pbCureStatus
super
end
end
#===============================================================================
# Decreases the target's Attack by 1 stage. Heals user by an amount equal to the
# target's Attack stat (after applying stat stages, before this move decreases
# it). (Strength Sap)
#===============================================================================
class Battle::Move::HealUserByTargetAttackLowerTargetAttack1 < Battle::Move
def healingMove?; return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
# NOTE: The official games appear to just check whether the target's Attack
# stat stage is -6 and fail if so, but I've added the "fail if target
# has Contrary and is at +6" check too for symmetry. This move still
# works even if the stat stage cannot be changed due to an ability or
# other effect.
if !@battle.moldBreaker && target.hasActiveAbility?(:CONTRARY) &&
target.statStageAtMax?(:ATTACK)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
elsif target.statStageAtMin?(:ATTACK)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
# Calculate target's effective attack value
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
atk = target.attack
atkStage = target.stages[:ATTACK]+6
healAmt = (atk.to_f*stageMul[atkStage]/stageDiv[atkStage]).floor
# Reduce target's Attack stat
if target.pbCanLowerStatStage?(:ATTACK,user,self)
target.pbLowerStatStage(:ATTACK,1,user)
end
# Heal user
if target.hasActiveAbility?(:LIQUIDOOZE)
@battle.pbShowAbilitySplash(target)
user.pbReduceHP(healAmt)
@battle.pbDisplay(_INTL("{1} sucked up the liquid ooze!",user.pbThis))
@battle.pbHideAbilitySplash(target)
user.pbItemHPHealCheck
elsif user.canHeal?
healAmt = (healAmt*1.3).floor if user.hasActiveItem?(:BIGROOT)
user.pbRecoverHP(healAmt)
@battle.pbDisplay(_INTL("{1}'s HP was restored.",user.pbThis))
end
end
end
#===============================================================================
# User gains half the HP it inflicts as damage.
#===============================================================================
class Battle::Move::HealUserByHalfOfDamageDone < Battle::Move
def healingMove?; return Settings::MECHANICS_GENERATION >= 6; end
def pbEffectAgainstTarget(user,target)
return if target.damageState.hpLost<=0
hpGain = (target.damageState.hpLost/2.0).round
user.pbRecoverHPFromDrain(hpGain,target)
end
end
#===============================================================================
# User gains half the HP it inflicts as damage. Fails if target is not asleep.
# (Dream Eater)
#===============================================================================
class Battle::Move::HealUserByHalfOfDamageDoneIfTargetAsleep < Battle::Move
def healingMove?; return Settings::MECHANICS_GENERATION >= 6; end
def pbFailsAgainstTarget?(user, target, show_message)
if !target.asleep?
@battle.pbDisplay(_INTL("{1} wasn't affected!", target.pbThis)) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
return if target.damageState.hpLost<=0
hpGain = (target.damageState.hpLost/2.0).round
user.pbRecoverHPFromDrain(hpGain,target)
end
end
#===============================================================================
# User gains 3/4 the HP it inflicts as damage. (Draining Kiss, Oblivion Wing)
#===============================================================================
class Battle::Move::HealUserByThreeQuartersOfDamageDone < Battle::Move
def healingMove?; return Settings::MECHANICS_GENERATION >= 6; end
def pbEffectAgainstTarget(user,target)
return if target.damageState.hpLost<=0
hpGain = (target.damageState.hpLost*0.75).round
user.pbRecoverHPFromDrain(hpGain,target)
end
end
#===============================================================================
# The user and its allies gain 25% of their total HP. (Life Dew)
#===============================================================================
class Battle::Move::HealUserAndAlliesQuarterOfTotalHP < Battle::Move
def healingMove?; return true; end
def pbMoveFailed?(user, targets)
if @battle.allSameSideBattlers(user).none? { |b| b.canHeal? }
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbFailsAgainstTarget?(user, target, show_message)
return !target.canHeal?
end
def pbEffectAgainstTarget(user, target)
target.pbRecoverHP(target.totalhp / 4)
@battle.pbDisplay(_INTL("{1}'s HP was restored.", target.pbThis))
end
end
#===============================================================================
# The user and its allies gain 25% of their total HP and are cured of their
# permanent status problems. (Jungle Healing)
#===============================================================================
class Battle::Move::HealUserAndAlliesQuarterOfTotalHPCureStatus < Battle::Move
def healingMove?; return true; end
def pbMoveFailed?(user, targets)
if @battle.allSameSideBattlers(user).none? { |b| b.canHeal? || b.status != :NONE }
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbFailsAgainstTarget?(user, target, show_message)
return target.status == :NONE && !target.canHeal?
end
def pbEffectAgainstTarget(user, target)
if target.canHeal?
target.pbRecoverHP(target.totalhp / 4)
@battle.pbDisplay(_INTL("{1}'s HP was restored.", target.pbThis))
end
if target.status != :NONE
old_status = target.status
target.pbCureStatus(false)
case old_status
when :SLEEP
@battle.pbDisplay(_INTL("{1} was woken from sleep.", target.pbThis))
when :POISON
@battle.pbDisplay(_INTL("{1} was cured of its poisoning.", target.pbThis))
when :BURN
@battle.pbDisplay(_INTL("{1}'s burn was healed.", target.pbThis))
when :PARALYSIS
@battle.pbDisplay(_INTL("{1} was cured of paralysis.", target.pbThis))
when :FROZEN
@battle.pbDisplay(_INTL("{1} was thawed out.", target.pbThis))
end
end
end
end
#===============================================================================
# Heals target by 1/2 of its max HP. (Heal Pulse)
#===============================================================================
class Battle::Move::HealTargetHalfOfTotalHP < Battle::Move
def healingMove?; return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.hp==target.totalhp
@battle.pbDisplay(_INTL("{1}'s HP is full!", target.pbThis)) if show_message
return true
elsif !target.canHeal?
@battle.pbDisplay(_INTL("{1} is unaffected!", target.pbThis)) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
hpGain = (target.totalhp/2.0).round
if pulseMove? && user.hasActiveAbility?(:MEGALAUNCHER)
hpGain = (target.totalhp*3/4.0).round
end
target.pbRecoverHP(hpGain)
@battle.pbDisplay(_INTL("{1}'s HP was restored.",target.pbThis))
end
end
#===============================================================================
# Heals target by 1/2 of its max HP, or 2/3 of its max HP in Grassy Terrain.
# (Floral Healing)
#===============================================================================
class Battle::Move::HealTargetDependingOnGrassyTerrain < Battle::Move
def healingMove?; return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.hp==target.totalhp
@battle.pbDisplay(_INTL("{1}'s HP is full!", target.pbThis)) if show_message
return true
elsif !target.canHeal?
@battle.pbDisplay(_INTL("{1} is unaffected!", target.pbThis)) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
hpGain = (target.totalhp/2.0).round
hpGain = (target.totalhp*2/3.0).round if @battle.field.terrain == :Grassy
target.pbRecoverHP(hpGain)
@battle.pbDisplay(_INTL("{1}'s HP was restored.",target.pbThis))
end
end
#===============================================================================
# Battler in user's position is healed by 1/2 of its max HP, at the end of the
# next round. (Wish)
#===============================================================================
class Battle::Move::HealUserPositionNextTurn < Battle::Move
def healingMove?; return true; end
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if @battle.positions[user.index].effects[PBEffects::Wish]>0
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.positions[user.index].effects[PBEffects::Wish] = 2
@battle.positions[user.index].effects[PBEffects::WishAmount] = (user.totalhp/2.0).round
@battle.positions[user.index].effects[PBEffects::WishMaker] = user.pokemonIndex
end
end
#===============================================================================
# Rings the user. Ringed Pokémon gain 1/16 of max HP at the end of each round.
# (Aqua Ring)
#===============================================================================
class Battle::Move::StartHealUserEachTurn < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if user.effects[PBEffects::AquaRing]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.effects[PBEffects::AquaRing] = true
@battle.pbDisplay(_INTL("{1} surrounded itself with a veil of water!",user.pbThis))
end
end
#===============================================================================
# Ingrains the user. Ingrained Pokémon gain 1/16 of max HP at the end of each
# round, and cannot flee or switch out. (Ingrain)
#===============================================================================
class Battle::Move::StartHealUserEachTurnTrapUserInBattle < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if user.effects[PBEffects::Ingrain]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.effects[PBEffects::Ingrain] = true
@battle.pbDisplay(_INTL("{1} planted its roots!",user.pbThis))
end
end
#===============================================================================
# Target will lose 1/4 of max HP at end of each round, while asleep. (Nightmare)
#===============================================================================
class Battle::Move::StartDamageTargetEachTurnIfTargetAsleep < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
if !target.asleep? || target.effects[PBEffects::Nightmare]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Nightmare] = true
@battle.pbDisplay(_INTL("{1} began having a nightmare!",target.pbThis))
end
end
#===============================================================================
# Seeds the target. Seeded Pokémon lose 1/8 of max HP at the end of each round,
# and the Pokémon in the user's position gains the same amount. (Leech Seed)
#===============================================================================
class Battle::Move::StartLeechSeedTarget < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::LeechSeed]>=0
@battle.pbDisplay(_INTL("{1} evaded the attack!", target.pbThis)) if show_message
return true
end
if target.pbHasType?(:GRASS)
@battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) if show_message
return true
end
return false
end
def pbMissMessage(user,target)
@battle.pbDisplay(_INTL("{1} evaded the attack!",target.pbThis))
return true
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::LeechSeed] = user.index
@battle.pbDisplay(_INTL("{1} was seeded!",target.pbThis))
end
end
#===============================================================================
# The user takes damage equal to 1/2 of its total HP, even if the target is
# unaffected (this is not recoil damage). (Steel Beam)
#===============================================================================
class Battle::Move::UserLosesHalfOfTotalHP < Battle::Move
def pbEffectAfterAllHits(user, target)
return if !user.takesIndirectDamage?
amt = (user.totalhp / 2.0).ceil
amt = 1 if amt < 1
user.pbReduceHP(amt, false)
@battle.pbDisplay(_INTL("{1} is damaged by recoil!", user.pbThis))
user.pbItemHPHealCheck
end
end
#===============================================================================
# Damages user by 1/2 of its max HP, even if this move misses. (Mind Blown)
#===============================================================================
class Battle::Move::UserLosesHalfOfTotalHPExplosive < Battle::Move
def worksWithNoTargets?; return true; end
def pbMoveFailed?(user,targets)
if !@battle.moldBreaker
bearer = @battle.pbCheckGlobalAbility(:DAMP)
if bearer!=nil
@battle.pbShowAbilitySplash(bearer)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} cannot use {2}!",user.pbThis,@name))
else
@battle.pbDisplay(_INTL("{1} cannot use {2} because of {3}'s {4}!",
user.pbThis,@name,bearer.pbThis(true),bearer.abilityName))
end
@battle.pbHideAbilitySplash(bearer)
return true
end
end
return false
end
def pbSelfKO(user)
return if !user.takesIndirectDamage?
user.pbReduceHP((user.totalhp/2.0).round,false)
user.pbItemHPHealCheck
end
end
#===============================================================================
# User faints, even if the move does nothing else. (Explosion, Self-Destruct)
#===============================================================================
class Battle::Move::UserFaintsExplosive < Battle::Move
def worksWithNoTargets?; return true; end
def pbNumHits(user,targets); return 1; end
def pbMoveFailed?(user,targets)
if !@battle.moldBreaker
bearer = @battle.pbCheckGlobalAbility(:DAMP)
if bearer!=nil
@battle.pbShowAbilitySplash(bearer)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} cannot use {2}!",user.pbThis,@name))
else
@battle.pbDisplay(_INTL("{1} cannot use {2} because of {3}'s {4}!",
user.pbThis,@name,bearer.pbThis(true),bearer.abilityName))
end
@battle.pbHideAbilitySplash(bearer)
return true
end
end
return false
end
def pbSelfKO(user)
return if user.fainted?
user.pbReduceHP(user.hp,false)
user.pbItemHPHealCheck
end
end
#===============================================================================
# User faints. If Misty Terrain applies, base power is multiplied by 1.5.
# (Misty Explosion)
#===============================================================================
class Battle::Move::UserFaintsPowersUpInMistyTerrainExplosive < Battle::Move::UserFaintsExplosive
def pbBaseDamage(baseDmg, user, target)
baseDmg = baseDmg * 3 / 2 if @battle.field.terrain == :Misty
return baseDmg
end
end
#===============================================================================
# Inflicts fixed damage equal to user's current HP. (Final Gambit)
# User faints (if successful).
#===============================================================================
class Battle::Move::UserFaintsFixedDamageUserHP < Battle::Move::FixedDamageMove
def pbNumHits(user,targets); return 1; end
def pbOnStartUse(user,targets)
@finalGambitDamage = user.hp
end
def pbFixedDamage(user,target)
return @finalGambitDamage
end
def pbSelfKO(user)
return if user.fainted?
user.pbReduceHP(user.hp,false)
user.pbItemHPHealCheck
end
end
#===============================================================================
# Decreases the target's Attack and Special Attack by 2 stages each. (Memento)
# User faints (if successful).
#===============================================================================
class Battle::Move::UserFaintsLowerTargetAtkSpAtk2 < Battle::Move::TargetMultiStatDownMove
def canMagicCoat?; return false; end
def initialize(battle,move)
super
@statDown = [:ATTACK,2,:SPECIAL_ATTACK,2]
end
# NOTE: The user faints even if the target's stats cannot be changed, so this
# method must always return false to allow the move's usage to continue.
def pbFailsAgainstTarget?(user, target, show_message)
return false
end
def pbSelfKO(user)
return if user.fainted?
user.pbReduceHP(user.hp,false)
user.pbItemHPHealCheck
end
end
#===============================================================================
# User faints. The Pokémon that replaces the user is fully healed (HP and
# status). Fails if user won't be replaced. (Healing Wish)
#===============================================================================
class Battle::Move::UserFaintsHealAndCureReplacement < Battle::Move
def healingMove?; return true; end
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if !@battle.pbCanChooseNonActive?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbSelfKO(user)
return if user.fainted?
user.pbReduceHP(user.hp,false)
user.pbItemHPHealCheck
@battle.positions[user.index].effects[PBEffects::HealingWish] = true
end
end
#===============================================================================
# User faints. The Pokémon that replaces the user is fully healed (HP, PP and
# status). Fails if user won't be replaced. (Lunar Dance)
#===============================================================================
class Battle::Move::UserFaintsHealAndCureReplacementRestorePP < Battle::Move
def healingMove?; return true; end
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if !@battle.pbCanChooseNonActive?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbSelfKO(user)
return if user.fainted?
user.pbReduceHP(user.hp,false)
user.pbItemHPHealCheck
@battle.positions[user.index].effects[PBEffects::LunarDance] = true
end
end
#===============================================================================
# All current battlers will perish after 3 more rounds. (Perish Song)
#===============================================================================
class Battle::Move::StartPerishCountsForAllBattlers < Battle::Move
def pbMoveFailed?(user,targets)
failed = true
targets.each do |b|
next if b.effects[PBEffects::PerishSong]>0 # Heard it before
failed = false
break
end
if failed
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbFailsAgainstTarget?(user, target, show_message)
return target.effects[PBEffects::PerishSong]>0 # Heard it before
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::PerishSong] = 4
target.effects[PBEffects::PerishSongUser] = user.index
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
super
@battle.pbDisplay(_INTL("All Pokémon that hear the song will faint in three turns!"))
end
end
#===============================================================================
# If user is KO'd before it next moves, the battler that caused it also faints.
# (Destiny Bond)
#===============================================================================
class Battle::Move::AttackerFaintsIfUserFaints < Battle::Move
def pbMoveFailed?(user,targets)
if Settings::MECHANICS_GENERATION >= 7 && user.effects[PBEffects::DestinyBondPrevious]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.effects[PBEffects::DestinyBond] = true
@battle.pbDisplay(_INTL("{1} is hoping to take its attacker down with it!",user.pbThis))
end
end
#===============================================================================
# If user is KO'd before it next moves, the attack that caused it loses all PP.
# (Grudge)
#===============================================================================
class Battle::Move::SetAttackerMovePPTo0IfUserFaints < Battle::Move
def pbEffectGeneral(user)
user.effects[PBEffects::Grudge] = true
@battle.pbDisplay(_INTL("{1} wants its target to bear a grudge!",user.pbThis))
end
end

View File

@@ -0,0 +1,600 @@
#===============================================================================
# User steals the target's item, if the user has none itself. (Covet, Thief)
# Items stolen from wild Pokémon are kept after the battle.
#===============================================================================
class Battle::Move::UserTakesTargetItem < Battle::Move
def pbEffectAfterAllHits(user,target)
return if user.wild? # Wild Pokémon can't thieve
return if user.fainted?
return if target.damageState.unaffected || target.damageState.substitute
return if !target.item || user.item
return if target.unlosableItem?(target.item)
return if user.unlosableItem?(target.item)
return if target.hasActiveAbility?(:STICKYHOLD) && !@battle.moldBreaker
itemName = target.itemName
user.item = target.item
# Permanently steal the item from wild Pokémon
if target.wild? && !user.initialItem && target.item == target.initialItem
user.setInitialItem(target.item)
target.pbRemoveItem
else
target.pbRemoveItem(false)
end
@battle.pbDisplay(_INTL("{1} stole {2}'s {3}!",user.pbThis,target.pbThis(true),itemName))
user.pbHeldItemTriggerCheck
end
end
#===============================================================================
# User gives its item to the target. The item remains given after wild battles.
# (Bestow)
#===============================================================================
class Battle::Move::TargetTakesUserItem < Battle::Move
def ignoresSubstitute?(user)
return true if Settings::MECHANICS_GENERATION >= 6
return super
end
def pbMoveFailed?(user,targets)
if !user.item || user.unlosableItem?(user.item)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbFailsAgainstTarget?(user, target, show_message)
if target.item || target.unlosableItem?(user.item)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
itemName = user.itemName
target.item = user.item
# Permanently steal the item from wild Pokémon
if user.wild? && !target.initialItem && user.item == user.initialItem
target.setInitialItem(user.item)
user.pbRemoveItem
else
user.pbRemoveItem(false)
end
@battle.pbDisplay(_INTL("{1} received {2} from {3}!",target.pbThis,itemName,user.pbThis(true)))
target.pbHeldItemTriggerCheck
end
end
#===============================================================================
# User and target swap items. They remain swapped after wild battles.
# (Switcheroo, Trick)
#===============================================================================
class Battle::Move::UserTargetSwapItems < Battle::Move
def pbMoveFailed?(user,targets)
if user.wild?
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbFailsAgainstTarget?(user, target, show_message)
if !user.item && !target.item
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.unlosableItem?(target.item) ||
target.unlosableItem?(user.item) ||
user.unlosableItem?(user.item) ||
user.unlosableItem?(target.item)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.hasActiveAbility?(:STICKYHOLD) && !@battle.moldBreaker
if show_message
@battle.pbShowAbilitySplash(target)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("But it failed to affect {1}!", target.pbThis(true)))
else
@battle.pbDisplay(_INTL("But it failed to affect {1} because of its {2}!",
target.pbThis(true), target.abilityName))
end
@battle.pbHideAbilitySplash(target)
end
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
oldUserItem = user.item
oldUserItemName = user.itemName
oldTargetItem = target.item
oldTargetItemName = target.itemName
user.item = oldTargetItem
user.effects[PBEffects::ChoiceBand] = nil if !user.hasActiveAbility?(:GORILLATACTICS)
user.effects[PBEffects::Unburden] = (!user.item && oldUserItem) if user.hasActiveAbility?(:UNBURDEN)
target.item = oldUserItem
target.effects[PBEffects::ChoiceBand] = nil if !target.hasActiveAbility?(:GORILLATACTICS)
target.effects[PBEffects::Unburden] = (!target.item && oldTargetItem) if target.hasActiveAbility?(:UNBURDEN)
# Permanently steal the item from wild Pokémon
if target.wild? && !user.initialItem && oldTargetItem == target.initialItem
user.setInitialItem(oldTargetItem)
end
@battle.pbDisplay(_INTL("{1} switched items with its opponent!",user.pbThis))
@battle.pbDisplay(_INTL("{1} obtained {2}.",user.pbThis,oldTargetItemName)) if oldTargetItem
@battle.pbDisplay(_INTL("{1} obtained {2}.",target.pbThis,oldUserItemName)) if oldUserItem
user.pbHeldItemTriggerCheck
target.pbHeldItemTriggerCheck
end
end
#===============================================================================
# User recovers the last item it held and consumed. (Recycle)
#===============================================================================
class Battle::Move::RestoreUserConsumedItem < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if !user.recycleItem
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
item = user.recycleItem
user.item = item
user.setInitialItem(item) if @battle.wildBattle? && !user.initialItem
user.setRecycleItem(nil)
user.effects[PBEffects::PickupItem] = nil
user.effects[PBEffects::PickupUse] = 0
itemName = GameData::Item.get(item).name
if itemName.starts_with_vowel?
@battle.pbDisplay(_INTL("{1} found an {2}!",user.pbThis,itemName))
else
@battle.pbDisplay(_INTL("{1} found a {2}!",user.pbThis,itemName))
end
user.pbHeldItemTriggerCheck
end
end
#===============================================================================
# Target drops its item. It regains the item at the end of the battle. (Knock Off)
# If target has a losable item, damage is multiplied by 1.5.
#===============================================================================
class Battle::Move::RemoveTargetItem < Battle::Move
def pbBaseDamage(baseDmg,user,target)
if Settings::MECHANICS_GENERATION >= 6 &&
target.item && !target.unlosableItem?(target.item)
# NOTE: Damage is still boosted even if target has Sticky Hold or a
# substitute.
baseDmg = (baseDmg*1.5).round
end
return baseDmg
end
def pbEffectAfterAllHits(user,target)
return if user.wild? # Wild Pokémon can't knock off
return if user.fainted?
return if target.damageState.unaffected || target.damageState.substitute
return if !target.item || target.unlosableItem?(target.item)
return if target.hasActiveAbility?(:STICKYHOLD) && !@battle.moldBreaker
itemName = target.itemName
target.pbRemoveItem(false)
@battle.pbDisplay(_INTL("{1} dropped its {2}!",target.pbThis,itemName))
end
end
#===============================================================================
# Target's berry/Gem is destroyed. (Incinerate)
#===============================================================================
class Battle::Move::DestroyTargetBerryOrGem < Battle::Move
def pbEffectWhenDealingDamage(user,target)
return if target.damageState.substitute || target.damageState.berryWeakened
return if !target.item || (!target.item.is_berry? &&
!(Settings::MECHANICS_GENERATION >= 6 && target.item.is_gem?))
target.pbRemoveItem
@battle.pbDisplay(_INTL("{1}'s {2} was incinerated!",target.pbThis,target.itemName))
end
end
#===============================================================================
# Negates the effect and usability of the target's held item for the rest of the
# battle (even if it is switched out). Fails if the target doesn't have a held
# item, the item is unlosable, the target has Sticky Hold, or the target is
# behind a substitute. (Corrosive Gas)
#===============================================================================
class Battle::Move::CorrodeTargetItem < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if !target.item || target.unlosableItem?(target.item) ||
target.effects[PBEffects::Substitute] > 0
@battle.pbDisplay(_INTL("{1} is unaffected!", target.pbThis)) if show_message
return true
end
if target.hasActiveAbility?(:STICKYHOLD) && !@battle.moldBreaker
if show_message
@battle.pbShowAbilitySplash(target)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} is unaffected!", target.pbThis))
else
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!",
target.pbThis(true), target.abilityName))
end
@battle.pbHideAbilitySplash(target)
end
return true
end
if @battle.corrosiveGas[target.index % 2][target.pokemonIndex]
@battle.pbDisplay(_INTL("{1} is unaffected!", target.pbThis)) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user, target)
@battle.corrosiveGas[target.index % 2][target.pokemonIndex] = true
@battle.pbDisplay(_INTL("{1} corroded {2}'s {3}!",
user.pbThis, target.pbThis(true), target.itemName))
end
end
#===============================================================================
# For 5 rounds, the target cannnot use its held item, its held item has no
# effect, and no items can be used on it. (Embargo)
#===============================================================================
class Battle::Move::StartTargetCannotUseItem < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::Embargo]>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Embargo] = 5
@battle.pbDisplay(_INTL("{1} can't use items anymore!",target.pbThis))
end
end
#===============================================================================
# For 5 rounds, all held items cannot be used in any way and have no effect.
# Held items can still change hands, but can't be thrown. (Magic Room)
#===============================================================================
class Battle::Move::StartNegateHeldItems < Battle::Move
def pbEffectGeneral(user)
if @battle.field.effects[PBEffects::MagicRoom]>0
@battle.field.effects[PBEffects::MagicRoom] = 0
@battle.pbDisplay(_INTL("The area returned to normal!"))
else
@battle.field.effects[PBEffects::MagicRoom] = 5
@battle.pbDisplay(_INTL("It created a bizarre area in which Pokémon's held items lose their effects!"))
end
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
return if @battle.field.effects[PBEffects::MagicRoom]>0 # No animation
super
end
end
#===============================================================================
# The user consumes its held berry and gains its effect. Also, increases the
# user's Defense by 2 stages. The berry can be consumed even if Unnerve/Magic
# Room apply. Fails if the user is not holding a berry. This move cannot be
# chosen to be used if the user is not holding a berry. (Stuff Cheeks)
#===============================================================================
class Battle::Move::UserConsumeBerryRaiseDefense2 < Battle::Move::StatUpMove
def initialize(battle, move)
super
@statUp = [:DEFENSE, 2]
end
def pbCanChooseMove?(user, commandPhase, showMessages)
item = user.item
if !item || !item.is_berry? || !user.itemActive?
if showMessages
msg = _INTL("{1} can't use that move because it doesn't have a Berry!", user.pbThis)
(commandPhase) ? @battle.pbDisplayPaused(msg) : @battle.pbDisplay(msg)
end
return false
end
return true
end
def pbMoveFailed?(user, targets)
# NOTE: Unnerve does not stop a Pokémon using this move.
item = user.item
if !item || !item.is_berry? || !user.itemActive?
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return super
end
def pbEffectGeneral(user)
super
@battle.pbDisplay(_INTL("{1} ate its {2}!", user.pbThis, user.itemName))
item = user.item
user.pbConsumeItem(true, false) # Don't trigger Symbiosis yet
user.pbHeldItemTriggerCheck(item, false)
end
end
#===============================================================================
# All Pokémon (except semi-invulnerable ones) consume their held berries and
# gain their effects. Berries can be consumed even if Unnerve/Magic Room apply.
# Fails if no Pokémon have a held berry. If this move would trigger an ability
# that negates the move, e.g. Lightning Rod, the bearer of that ability will
# have their ability triggered regardless of whether they are holding a berry,
# and they will not consume their berry. (Teatime)
# TODO: This isn't quite right for the messages shown when a berry is consumed.
#===============================================================================
class Battle::Move::AllBattlersConsumeBerry < Battle::Move
def pbMoveFailed?(user, targets)
failed = true
targets.each do |b|
next if !b.item || !b.item.is_berry?
next if b.semiInvulnerable?
failed = false
break
end
if failed
@battle.pbDisplay(_INTL("But nothing happened!"))
return true
end
return false
end
def pbOnStartUse(user, targets)
@battle.pbDisplay(_INTL("It's teatime! Everyone dug in to their Berries!"))
end
def pbFailsAgainstTarget?(user, target, show_message)
return true if !target.item || !target.item.is_berry? || target.semiInvulnerable?
return false
end
def pbEffectAgainstTarget(user, target)
@battle.pbCommonAnimation("EatBerry", target)
item = target.item
target.pbConsumeItem(true, false) # Don't trigger Symbiosis yet
target.pbHeldItemTriggerCheck(item, false)
end
end
#===============================================================================
# User consumes target's berry and gains its effect. (Bug Bite, Pluck)
#===============================================================================
class Battle::Move::UserConsumeTargetBerry < Battle::Move
def pbEffectAfterAllHits(user,target)
return if user.fainted? || target.fainted?
return if target.damageState.unaffected || target.damageState.substitute
return if !target.item || !target.item.is_berry?
return if target.hasActiveAbility?(:STICKYHOLD) && !@battle.moldBreaker
item = target.item
itemName = target.itemName
target.pbRemoveItem
@battle.pbDisplay(_INTL("{1} stole and ate its target's {2}!",user.pbThis,itemName))
user.pbHeldItemTriggerCheck(item,false)
end
end
#===============================================================================
# User flings its item at the target. Power/effect depend on the item. (Fling)
#===============================================================================
class Battle::Move::ThrowUserItemAtTarget < Battle::Move
def initialize(battle,move)
super
# 80 => all Mega Stones
# 10 => all Berries
@flingPowers = {
130 => [:IRONBALL
],
100 => [:HARDSTONE,:RAREBONE,
# Fossils
:ARMORFOSSIL,:CLAWFOSSIL,:COVERFOSSIL,:DOMEFOSSIL,:HELIXFOSSIL,
:JAWFOSSIL,:OLDAMBER,:PLUMEFOSSIL,:ROOTFOSSIL,:SAILFOSSIL,
:SKULLFOSSIL
],
90 => [:DEEPSEATOOTH,:GRIPCLAW,:THICKCLUB,
# Plates
:DRACOPLATE,:DREADPLATE,:EARTHPLATE,:FISTPLATE,:FLAMEPLATE,
:ICICLEPLATE,:INSECTPLATE,:IRONPLATE,:MEADOWPLATE,:MINDPLATE,
:PIXIEPLATE,:SKYPLATE,:SPLASHPLATE,:SPOOKYPLATE,:STONEPLATE,
:TOXICPLATE,:ZAPPLATE
],
80 => [:ASSAULTVEST,:CHIPPEDPOT,:CRACKEDPOT,:DAWNSTONE,:DUSKSTONE,
:ELECTIRIZER,:HEAVYDUTYBOOTS,:MAGMARIZER,:ODDKEYSTONE,:OVALSTONE,
:PROTECTOR,:QUICKCLAW,:RAZORCLAW,:SACHET,:SAFETYGOGGLES,
:SHINYSTONE,:STICKYBARB,:WEAKNESSPOLICY,:WHIPPEDDREAM
],
70 => [:DRAGONFANG,:POISONBARB,
# EV-training items (Macho Brace is 60)
:POWERANKLET,:POWERBAND,:POWERBELT,:POWERBRACER,:POWERLENS,
:POWERWEIGHT,
# Drives
:BURNDRIVE,:CHILLDRIVE,:DOUSEDRIVE,:SHOCKDRIVE
],
60 => [:ADAMANTORB,:DAMPROCK,:GRISEOUSORB,:HEATROCK,:LEEK,:LUSTROUSORB,
:MACHOBRACE,:ROCKYHELMET,:STICK,:TERRAINEXTENDER
],
50 => [:DUBIOUSDISC,:SHARPBEAK,
# Memories
:BUGMEMORY,:DARKMEMORY,:DRAGONMEMORY,:ELECTRICMEMORY,:FAIRYMEMORY,
:FIGHTINGMEMORY,:FIREMEMORY,:FLYINGMEMORY,:GHOSTMEMORY,
:GRASSMEMORY,:GROUNDMEMORY,:ICEMEMORY,:POISONMEMORY,
:PSYCHICMEMORY,:ROCKMEMORY,:STEELMEMORY,:WATERMEMORY
],
40 => [:EVIOLITE,:ICYROCK,:LUCKYPUNCH
],
30 => [:ABSORBBULB,:ADRENALINEORB,:AMULETCOIN,:BINDINGBAND,:BLACKBELT,
:BLACKGLASSES,:BLACKSLUDGE,:BOTTLECAP,:CELLBATTERY,:CHARCOAL,
:CLEANSETAG,:DEEPSEASCALE,:DRAGONSCALE,:EJECTBUTTON,:ESCAPEROPE,
:EXPSHARE,:FLAMEORB,:FLOATSTONE,:FLUFFYTAIL,:GOLDBOTTLECAP,
:HEARTSCALE,:HONEY,:KINGSROCK,:LIFEORB,:LIGHTBALL,:LIGHTCLAY,
:LUCKYEGG,:LUMINOUSMOSS,:MAGNET,:METALCOAT,:METRONOME,
:MIRACLESEED,:MYSTICWATER,:NEVERMELTICE,:PASSORB,:POKEDOLL,
:POKETOY,:PRISMSCALE,:PROTECTIVEPADS,:RAZORFANG,:SACREDASH,
:SCOPELENS,:SHELLBELL,:SHOALSALT,:SHOALSHELL,:SMOKEBALL,:SNOWBALL,
:SOULDEW,:SPELLTAG,:TOXICORB,:TWISTEDSPOON,:UPGRADE,
# Healing items
:ANTIDOTE,:AWAKENING,:BERRYJUICE,:BIGMALASADA,:BLUEFLUTE,
:BURNHEAL,:CASTELIACONE,:ELIXIR,:ENERGYPOWDER,:ENERGYROOT,:ETHER,
:FRESHWATER,:FULLHEAL,:FULLRESTORE,:HEALPOWDER,:HYPERPOTION,
:ICEHEAL,:LAVACOOKIE,:LEMONADE,:LUMIOSEGALETTE,:MAXELIXIR,
:MAXETHER,:MAXHONEY,:MAXPOTION,:MAXREVIVE,:MOOMOOMILK,:OLDGATEAU,
:PARALYZEHEAL,:PARLYZHEAL,:PEWTERCRUNCHIES,:POTION,:RAGECANDYBAR,
:REDFLUTE,:REVIVALHERB,:REVIVE,:SHALOURSABLE,:SODAPOP,
:SUPERPOTION,:SWEETHEART,:YELLOWFLUTE,
# Battle items
:XACCURACY,:XACCURACY2,:XACCURACY3,:XACCURACY6,
:XATTACK,:XATTACK2,:XATTACK3,:XATTACK6,
:XDEFEND,:XDEFEND2,:XDEFEND3,:XDEFEND6,
:XDEFENSE,:XDEFENSE2,:XDEFENSE3,:XDEFENSE6,
:XSPATK,:XSPATK2,:XSPATK3,:XSPATK6,
:XSPECIAL,:XSPECIAL2,:XSPECIAL3,:XSPECIAL6,
:XSPDEF,:XSPDEF2,:XSPDEF3,:XSPDEF6,
:XSPEED,:XSPEED2,:XSPEED3,:XSPEED6,
:DIREHIT,:DIREHIT2,:DIREHIT3,
:ABILITYURGE,:GUARDSPEC,:ITEMDROP,:ITEMURGE,:RESETURGE,
:MAXMUSHROOMS,
# Vitamins
:CALCIUM,:CARBOS,:HPUP,:IRON,:PPUP,:PPMAX,:PROTEIN,:ZINC,
:RARECANDY,
# Most evolution stones (see also 80)
:EVERSTONE,:FIRESTONE,:ICESTONE,:LEAFSTONE,:MOONSTONE,:SUNSTONE,
:THUNDERSTONE,:WATERSTONE,:SWEETAPPLE,:TARTAPPLE, :GALARICACUFF,
:GALARICAWREATH,
# Repels
:MAXREPEL,:REPEL,:SUPERREPEL,
# Mulches
:AMAZEMULCH,:BOOSTMULCH,:DAMPMULCH,:GOOEYMULCH,:GROWTHMULCH,
:RICHMULCH,:STABLEMULCH,:SURPRISEMULCH,
# Shards
:BLUESHARD,:GREENSHARD,:REDSHARD,:YELLOWSHARD,
# Valuables
:BALMMUSHROOM,:BIGMUSHROOM,:BIGNUGGET,:BIGPEARL,:COMETSHARD,
:NUGGET,:PEARL,:PEARLSTRING,:RELICBAND,:RELICCOPPER,:RELICCROWN,
:RELICGOLD,:RELICSILVER,:RELICSTATUE,:RELICVASE,:STARDUST,
:STARPIECE,:STRANGESOUVENIR,:TINYMUSHROOM,
# Exp Candies
:EXPCANDYXS, :EXPCANDYS, :EXPCANDYM, :EXPCANDYL, :EXPCANDYXL
],
20 => [# Feathers
:CLEVERFEATHER,:GENIUSFEATHER,:HEALTHFEATHER,:MUSCLEFEATHER,
:PRETTYFEATHER,:RESISTFEATHER,:SWIFTFEATHER,
:CLEVERWING,:GENIUSWING,:HEALTHWING,:MUSCLEWING,:PRETTYWING,
:RESISTWING,:SWIFTWING
],
10 => [:AIRBALLOON,:BIGROOT,:BRIGHTPOWDER,:CHOICEBAND,:CHOICESCARF,
:CHOICESPECS,:DESTINYKNOT,:DISCOUNTCOUPON,:EXPERTBELT,:FOCUSBAND,
:FOCUSSASH,:LAGGINGTAIL,:LEFTOVERS,:MENTALHERB,:METALPOWDER,
:MUSCLEBAND,:POWERHERB,:QUICKPOWDER,:REAPERCLOTH,:REDCARD,
:RINGTARGET,:SHEDSHELL,:SILKSCARF,:SILVERPOWDER,:SMOOTHROCK,
:SOFTSAND,:SOOTHEBELL,:WHITEHERB,:WIDELENS,:WISEGLASSES,:ZOOMLENS,
# Terrain seeds
:ELECTRICSEED,:GRASSYSEED,:MISTYSEED,:PSYCHICSEED,
# Nectar
:PINKNECTAR,:PURPLENECTAR,:REDNECTAR,:YELLOWNECTAR,
# Incenses
:FULLINCENSE,:LAXINCENSE,:LUCKINCENSE,:ODDINCENSE,:PUREINCENSE,
:ROCKINCENSE,:ROSEINCENSE,:SEAINCENSE,:WAVEINCENSE,
# Scarves
:BLUESCARF,:GREENSCARF,:PINKSCARF,:REDSCARF,:YELLOWSCARF,
# Mints
:LONELYMINT, :ADAMANTMINT, :NAUGHTYMINT, :BRAVEMINT, :BOLDMINT,
:IMPISHMINT, :LAXMINT, :RELAXEDMINT, :MODESTMINT, :MILDMINT,
:RASHMINT, :QUIETMINT, :CALMMINT, :GENTLEMINT, :CAREFULMINT,
:SASSYMINT, :TIMIDMINT, :HASTYMINT, :JOLLYMINT, :NAIVEMINT,
:SERIOUSMINT,
# Sweets
:STRAWBERRYSWEET, :LOVESWEET, :BERRYSWEET, :CLOVERSWEET,
:FLOWERSWEET, :STARSWEET, :RIBBONSWEET
]
}
end
def pbCheckFlingSuccess(user)
@willFail = false
@willFail = true if !user.item || !user.itemActive? || user.unlosableItem?(user.item)
return if @willFail
@willFail = true if user.item.is_berry? && !user.canConsumeBerry?
return if @willFail
return if user.item.is_mega_stone? || user.item.is_TR?
flingableItem = false
@flingPowers.each do |_power, items|
next if !items.include?(user.item_id)
flingableItem = true
break
end
@willFail = true if !flingableItem
end
def pbMoveFailed?(user,targets)
if @willFail
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbDisplayUseMessage(user)
super
pbCheckFlingSuccess(user)
if !@willFail
@battle.pbDisplay(_INTL("{1} flung its {2}!",user.pbThis,user.itemName))
end
end
def pbNumHits(user,targets); return 1; end
def pbBaseDamage(baseDmg,user,target)
return 0 if !user.item
return 10 if user.item.is_berry?
return 80 if user.item.is_mega_stone?
if user.item.is_TR?
ret = GameData::Move.get(user.item.move).base_damage
ret = 10 if ret < 10
return ret
end
@flingPowers.each do |power,items|
return power if items.include?(user.item_id)
end
return 10
end
def pbEffectAgainstTarget(user,target)
return if target.damageState.substitute
return if target.hasActiveAbility?(:SHIELDDUST) && !@battle.moldBreaker
case user.item_id
when :POISONBARB
target.pbPoison(user) if target.pbCanPoison?(user,false,self)
when :TOXICORB
target.pbPoison(user,nil,true) if target.pbCanPoison?(user,false,self)
when :FLAMEORB
target.pbBurn(user) if target.pbCanBurn?(user,false,self)
when :LIGHTBALL
target.pbParalyze(user) if target.pbCanParalyze?(user,false,self)
when :KINGSROCK, :RAZORFANG
target.pbFlinch(user)
else
target.pbHeldItemTriggerCheck(user.item,true)
end
end
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
# NOTE: The item is consumed even if this move was Protected against or it
# missed. The item is not consumed if the target was switched out by
# an effect like a target's Red Card.
# NOTE: There is no item consumption animation.
user.pbConsumeItem(true,true,false) if user.item
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,925 @@
#===============================================================================
# User flees from battle. (Teleport (Gen 7-))
#===============================================================================
class Battle::Move::FleeFromBattle < Battle::Move
def pbMoveFailed?(user,targets)
if !@battle.pbCanRun?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.pbDisplay(_INTL("{1} fled from battle!",user.pbThis))
@battle.decision = 3 # Escaped
end
end
#===============================================================================
# User switches out. If user is a wild Pokémon, ends the battle instead.
# (Teleport (Gen 8+))
#===============================================================================
class Battle::Move::SwitchOutUserStatusMove < Battle::Move
def pbMoveFailed?(user,targets)
if user.wild?
if !@battle.pbCanRun?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
elsif !@battle.pbCanChooseNonActive?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
return if user.wild?
@battle.pbDisplay(_INTL("{1} went back to {2}!",user.pbThis,
@battle.pbGetOwnerName(user.index)))
@battle.pbPursuit(user.index)
return if user.fainted?
newPkmn = @battle.pbGetReplacementPokemonIndex(user.index) # Owner chooses
return if newPkmn<0
@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)
end
def pbEffectGeneral(user)
if user.wild?
@battle.pbDisplay(_INTL("{1} fled from battle!",user.pbThis))
@battle.decision = 3 # Escaped
end
end
end
#===============================================================================
# After inflicting damage, user switches out. Ignores trapping moves.
# (U-turn, Volt Switch)
#===============================================================================
class Battle::Move::SwitchOutUserDamagingMove < Battle::Move
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
return if user.fainted? || numHits==0 || @battle.pbAllFainted?(user.idxOpposingSide)
targetSwitched = true
targets.each do |b|
targetSwitched = false if !switchedBattlers.include?(b.index)
end
return if targetSwitched
return if !@battle.pbCanChooseNonActive?(user.index)
@battle.pbDisplay(_INTL("{1} went back to {2}!",user.pbThis,
@battle.pbGetOwnerName(user.index)))
@battle.pbPursuit(user.index)
return if user.fainted?
newPkmn = @battle.pbGetReplacementPokemonIndex(user.index) # Owner chooses
return if newPkmn<0
@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)
end
end
#===============================================================================
# Decreases the target's Attack and Special Attack by 1 stage each. Then, user
# switches out. Ignores trapping moves. (Parting Shot)
#===============================================================================
class Battle::Move::LowerTargetAtkSpAtk1SwitchOutUser < Battle::Move::TargetMultiStatDownMove
def initialize(battle,move)
super
@statDown = [:ATTACK,1,:SPECIAL_ATTACK,1]
end
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
switcher = user
targets.each do |b|
next if switchedBattlers.include?(b.index)
switcher = b if b.effects[PBEffects::MagicCoat] || b.effects[PBEffects::MagicBounce]
end
return if switcher.fainted? || numHits==0
return if !@battle.pbCanChooseNonActive?(switcher.index)
@battle.pbDisplay(_INTL("{1} went back to {2}!",switcher.pbThis,
@battle.pbGetOwnerName(switcher.index)))
@battle.pbPursuit(switcher.index)
return if switcher.fainted?
newPkmn = @battle.pbGetReplacementPokemonIndex(switcher.index) # Owner chooses
return if newPkmn<0
@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)
end
end
#===============================================================================
# User switches out. Various effects affecting the user are passed to the
# replacement. (Baton Pass)
#===============================================================================
class Battle::Move::SwitchOutUserPassOnEffects < Battle::Move
def pbMoveFailed?(user,targets)
if !@battle.pbCanChooseNonActive?(user.index)
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEndOfMoveUsageEffect(user,targets,numHits,switchedBattlers)
return if user.fainted? || numHits==0
return if !@battle.pbCanChooseNonActive?(user.index)
@battle.pbPursuit(user.index)
return if user.fainted?
newPkmn = @battle.pbGetReplacementPokemonIndex(user.index) # Owner chooses
return if newPkmn<0
@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)
end
end
#===============================================================================
# In wild battles, makes target flee. Fails if target is a higher level than the
# user.
# In trainer battles, target switches out.
# For status moves. (Roar, Whirlwind)
#===============================================================================
class Battle::Move::SwitchOutTargetStatusMove < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.hasActiveAbility?(:SUCTIONCUPS) && !@battle.moldBreaker
if show_message
@battle.pbShowAbilitySplash(target)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} anchors itself!", target.pbThis))
else
@battle.pbDisplay(_INTL("{1} anchors itself with {2}!", target.pbThis, target.abilityName))
end
@battle.pbHideAbilitySplash(target)
end
return true
end
if target.effects[PBEffects::Ingrain]
@battle.pbDisplay(_INTL("{1} anchored itself with its roots!", target.pbThis)) if show_message
return true
end
if !@battle.canRun
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if @battle.wildBattle? && target.level>user.level
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if @battle.trainerBattle?
canSwitch = false
@battle.eachInTeamFromBattlerIndex(target.index) do |_pkmn,i|
next if !@battle.pbCanSwitchLax?(target.index,i)
canSwitch = true
break
end
if !canSwitch
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
end
return false
end
def pbEffectGeneral(user)
@battle.decision = 3 if @battle.wildBattle? # Escaped from battle
end
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
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
@battle.pbOnBattlerEnteringBattle(b.index)
switched_battlers.push(b.index)
break
end
end
end
#===============================================================================
# In wild battles, makes target flee. Fails if target is a higher level than the
# user.
# In trainer battles, target switches out.
# For damaging moves. (Circle Throw, Dragon Tail)
#===============================================================================
class Battle::Move::SwitchOutTargetDamagingMove < Battle::Move
def pbEffectAgainstTarget(user,target)
if @battle.wildBattle? && target.level<=user.level && @battle.canRun &&
(target.effects[PBEffects::Substitute]==0 || ignoresSubstitute?(user))
@battle.decision = 3
end
end
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 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
@battle.pbOnBattlerEnteringBattle(b.index)
switched_battlers.push(b.index)
break
end
end
end
#===============================================================================
# Trapping move. Traps for 5 or 6 rounds. Trapped Pokémon lose 1/16 of max HP
# at end of each round.
#===============================================================================
class Battle::Move::BindTarget < Battle::Move
def pbEffectAgainstTarget(user,target)
return if target.fainted? || target.damageState.substitute
return if target.effects[PBEffects::Trapping]>0
# Set trapping effect duration and info
if user.hasActiveItem?(:GRIPCLAW)
target.effects[PBEffects::Trapping] = (Settings::MECHANICS_GENERATION >= 5) ? 8 : 6
else
target.effects[PBEffects::Trapping] = 5+@battle.pbRandom(2)
end
target.effects[PBEffects::TrappingMove] = @id
target.effects[PBEffects::TrappingUser] = user.index
# Message
msg = _INTL("{1} was trapped in the vortex!",target.pbThis)
case @id
when :BIND
msg = _INTL("{1} was squeezed by {2}!",target.pbThis,user.pbThis(true))
when :CLAMP
msg = _INTL("{1} clamped {2}!",user.pbThis,target.pbThis(true))
when :FIRESPIN
msg = _INTL("{1} was trapped in the fiery vortex!",target.pbThis)
when :INFESTATION
msg = _INTL("{1} has been afflicted with an infestation by {2}!",target.pbThis,user.pbThis(true))
when :MAGMASTORM
msg = _INTL("{1} became trapped by Magma Storm!",target.pbThis)
when :SANDTOMB
msg = _INTL("{1} became trapped by Sand Tomb!",target.pbThis)
when :WHIRLPOOL
msg = _INTL("{1} became trapped in the vortex!",target.pbThis)
when :WRAP
msg = _INTL("{1} was wrapped by {2}!",target.pbThis,user.pbThis(true))
end
@battle.pbDisplay(msg)
end
end
#===============================================================================
# Trapping move. Traps for 5 or 6 rounds. Trapped Pokémon lose 1/16 of max HP
# at end of each round. (Whirlpool)
# Power is doubled if target is using Dive. Hits some semi-invulnerable targets.
#===============================================================================
class Battle::Move::BindTargetDoublePowerIfTargetUnderwater < Battle::Move::BindTarget
def hitsDivingTargets?; return true; end
def pbModifyDamage(damageMult,user,target)
damageMult *= 2 if target.inTwoTurnAttack?("TwoTurnAttackInvulnerableUnderwater")
return damageMult
end
end
#===============================================================================
# Target can no longer switch out or flee, as long as the user remains active.
# (Anchor Shot, Block, Mean Look, Spider Web, Spirit Shackle, Thousand Waves)
#===============================================================================
class Battle::Move::TrapTargetInBattle < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
if target.effects[PBEffects::MeanLook]>=0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if Settings::MORE_TYPE_EFFECTS && target.pbHasType?(:GHOST)
@battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
target.effects[PBEffects::MeanLook] = user.index
@battle.pbDisplay(_INTL("{1} can no longer escape!",target.pbThis))
end
def pbAdditionalEffect(user,target)
return if target.fainted? || target.damageState.substitute
return if target.effects[PBEffects::MeanLook]>=0
return if Settings::MORE_TYPE_EFFECTS && target.pbHasType?(:GHOST)
target.effects[PBEffects::MeanLook] = user.index
@battle.pbDisplay(_INTL("{1} can no longer escape!",target.pbThis))
end
end
#===============================================================================
# The target can no longer switch out or flee, while the user remains in battle.
# At the end of each round, the target's Defense and Special Defense are lowered
# by 1 stage each. (Octolock)
#===============================================================================
class Battle::Move::TrapTargetInBattleLowerTargetDefSpDef1EachTurn < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
return false if damagingMove?
if target.effects[PBEffects::Octolock] >= 0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if Settings::MORE_TYPE_EFFECTS && target.pbHasType?(:GHOST)
@battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true))) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user, target)
target.effects[PBEffects::Octolock] = user.index
@battle.pbDisplay(_INTL("{1} can no longer escape because of {2}!", target.pbThis, @name))
end
end
#===============================================================================
# Prevents the user and the target from switching out or fleeing. This effect
# isn't applied if either Pokémon is already prevented from switching out or
# fleeing. (Jaw Lock)
#===============================================================================
class Battle::Move::TrapUserAndTargetInBattle < Battle::Move
def pbAdditionalEffect(user, target)
return if user.fainted? || target.fainted? || target.damageState.substitute
return if Settings::MORE_TYPE_EFFECTS && target.pbHasType?(:GHOST)
return if user.trappedInBattle? || target.trappedInBattle?
target.effects[PBEffects::JawLock] = user.index
@battle.pbDisplay(_INTL("Neither Pokémon can run away!"))
end
end
#===============================================================================
# No Pokémon can switch out or flee until the end of the next round, as long as
# the user remains active. (Fairy Lock)
#===============================================================================
class Battle::Move::TrapAllBattlersInBattleForOneTurn < Battle::Move
def pbMoveFailed?(user,targets)
if @battle.field.effects[PBEffects::FairyLock]>0
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
@battle.field.effects[PBEffects::FairyLock] = 2
@battle.pbDisplay(_INTL("No one will be able to run away during the next turn!"))
end
end
#===============================================================================
# Interrupts a foe switching out or using U-turn/Volt Switch/Parting Shot. Power
# is doubled in that case. (Pursuit)
# (Handled in Battle's pbAttackPhase): Makes this attack happen before switching.
#===============================================================================
class Battle::Move::PursueSwitchingFoe < Battle::Move
def pbAccuracyCheck(user,target)
return true if @battle.switching
return super
end
def pbBaseDamage(baseDmg,user,target)
baseDmg *= 2 if @battle.switching
return baseDmg
end
end
#===============================================================================
# Fails if user has not been hit by an opponent's physical move this round.
# (Shell Trap)
#===============================================================================
class Battle::Move::UsedAfterUserTakesPhysicalDamage < Battle::Move
def pbDisplayChargeMessage(user)
user.effects[PBEffects::ShellTrap] = true
@battle.pbCommonAnimation("ShellTrap",user)
@battle.pbDisplay(_INTL("{1} set a shell trap!",user.pbThis))
end
def pbDisplayUseMessage(user)
super if user.tookPhysicalHit
end
def pbMoveFailed?(user,targets)
if !user.effects[PBEffects::ShellTrap]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
if !user.tookPhysicalHit
@battle.pbDisplay(_INTL("{1}'s shell trap didn't work!",user.pbThis))
return true
end
return false
end
end
#===============================================================================
# Power is doubled if a user's ally has already used this move this round. (Round)
# If an ally is about to use the same move, make it go next, ignoring priority.
#===============================================================================
class Battle::Move::UsedAfterAllyRoundWithDoublePower < Battle::Move
def pbBaseDamage(baseDmg,user,target)
baseDmg *= 2 if user.pbOwnSide.effects[PBEffects::Round]
return baseDmg
end
def pbEffectGeneral(user)
user.pbOwnSide.effects[PBEffects::Round] = true
user.allAllies.each do |b|
next if @battle.choices[b.index][0]!=:UseMove || b.movedThisRound?
next if @battle.choices[b.index][2].function!=@function
b.effects[PBEffects::MoveNext] = true
b.effects[PBEffects::Quash] = 0
break
end
end
end
#===============================================================================
# Target moves immediately after the user, ignoring priority/speed. (After You)
#===============================================================================
class Battle::Move::TargetActsNext < Battle::Move
def ignoresSubstitute?(user); return true; end
def pbFailsAgainstTarget?(user, target, show_message)
# Target has already moved this round
return true if pbMoveFailedTargetAlreadyMoved?(target, show_message)
# Target was going to move next anyway (somehow)
if target.effects[PBEffects::MoveNext]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
# Target didn't choose to use a move this round
oppMove = @battle.choices[target.index][2]
if !oppMove
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::MoveNext] = true
target.effects[PBEffects::Quash] = 0
@battle.pbDisplay(_INTL("{1} took the kind offer!",target.pbThis))
end
end
#===============================================================================
# Target moves last this round, ignoring priority/speed. (Quash)
#===============================================================================
class Battle::Move::TargetActsLast < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
return true if pbMoveFailedTargetAlreadyMoved?(target, show_message)
# Target isn't going to use a move
oppMove = @battle.choices[target.index][2]
if !oppMove
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
# Target is already maximally Quashed and will move last anyway
highestQuash = 0
@battle.allBattlers.each do |b|
next if b.effects[PBEffects::Quash]<=highestQuash
highestQuash = b.effects[PBEffects::Quash]
end
if highestQuash>0 && target.effects[PBEffects::Quash]==highestQuash
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
# Target was already going to move last
if highestQuash==0 && @battle.pbPriority.last.index==target.index
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
highestQuash = 0
@battle.allBattlers.each do |b|
next if b.effects[PBEffects::Quash]<=highestQuash
highestQuash = b.effects[PBEffects::Quash]
end
target.effects[PBEffects::Quash] = highestQuash+1
target.effects[PBEffects::MoveNext] = false
@battle.pbDisplay(_INTL("{1}'s move was postponed!",target.pbThis))
end
end
#===============================================================================
# The target uses its most recent move again. (Instruct)
#===============================================================================
class Battle::Move::TargetUsesItsLastUsedMoveAgain < Battle::Move
def ignoresSubstitute?(user); return true; end
def initialize(battle,move)
super
@moveBlacklist = [
"MultiTurnAttackBideThenReturnDoubleDamage", # Bide
"ProtectUserFromDamagingMovesKingsShield", # King's Shield
"TargetUsesItsLastUsedMoveAgain", # Instruct (this move)
# Struggle
"Struggle", # Struggle
# Moves that affect the moveset
"ReplaceMoveThisBattleWithTargetLastMoveUsed", # Mimic
"ReplaceMoveWithTargetLastMoveUsed", # Sketch
"TransformUserIntoTarget", # Transform
# Moves that call other moves
"UseLastMoveUsedByTarget", # Mirror Move
"UseLastMoveUsed", # Copycat
"UseMoveTargetIsAboutToUse", # Me First
"UseMoveDependingOnEnvironment", # Nature Power
"UseRandomUserMoveIfAsleep", # Sleep Talk
"UseRandomMoveFromUserParty", # Assist
"UseRandomMove", # Metronome
# Moves that require a recharge turn
"AttackAndSkipNextTurn", # Hyper Beam
# Two-turn attacks
"TwoTurnAttack", # Razor Wind
"TwoTurnAttackOneTurnInSun", # Solar Beam, Solar Blade
"TwoTurnAttackParalyzeTarget", # Freeze Shock
"TwoTurnAttackBurnTarget", # Ice Burn
"TwoTurnAttackFlinchTarget", # Sky Attack
"TwoTurnAttackChargeRaiseUserDefense1", # Skull Bash
"TwoTurnAttackInvulnerableInSky", # Fly
"TwoTurnAttackInvulnerableUnderground", # Dig
"TwoTurnAttackInvulnerableUnderwater", # Dive
"TwoTurnAttackInvulnerableInSkyParalyzeTarget", # Bounce
"TwoTurnAttackInvulnerableRemoveProtections", # Shadow Force, Phantom Force
"TwoTurnAttackInvulnerableInSkyTargetCannotAct", # Sky Drop
"AllBattlersLoseHalfHPUserSkipsNextTurn", # Shadow Half
"TwoTurnAttackRaiseUserSpAtkSpDefSpd2", # Geomancy
# Moves that start focussing at the start of the round
"FailsIfUserDamagedThisTurn", # Focus Punch
"UsedAfterUserTakesPhysicalDamage", # Shell Trap
"BurnAttackerBeforeUserActs" # Beak Blast
]
end
def pbFailsAgainstTarget?(user, target, show_message)
if !target.lastRegularMoveUsed || !target.pbHasMove?(target.lastRegularMoveUsed)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.usingMultiTurnAttack?
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
targetMove = @battle.choices[target.index][2]
if targetMove && (targetMove.function=="FailsIfUserDamagedThisTurn" || # Focus Punch
targetMove.function=="UsedAfterUserTakesPhysicalDamage" || # Shell Trap
targetMove.function=="BurnAttackerBeforeUserActs") # Beak Blast
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if @moveBlacklist.include?(GameData::Move.get(target.lastRegularMoveUsed).function_code)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
idxMove = -1
target.eachMoveWithIndex do |m,i|
idxMove = i if m.id==target.lastRegularMoveUsed
end
if target.moves[idxMove].pp==0 && target.moves[idxMove].total_pp>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Instruct] = true
end
end
#===============================================================================
# For 5 rounds, for each priority bracket, slow Pokémon move before fast ones.
# (Trick Room)
#===============================================================================
class Battle::Move::StartSlowerBattlersActFirst < Battle::Move
def pbEffectGeneral(user)
if @battle.field.effects[PBEffects::TrickRoom]>0
@battle.field.effects[PBEffects::TrickRoom] = 0
@battle.pbDisplay(_INTL("{1} reverted the dimensions!",user.pbThis))
else
@battle.field.effects[PBEffects::TrickRoom] = 5
@battle.pbDisplay(_INTL("{1} twisted the dimensions!",user.pbThis))
end
end
def pbShowAnimation(id,user,targets,hitNum=0,showAnimation=true)
return if @battle.field.effects[PBEffects::TrickRoom]>0 # No animation
super
end
end
#===============================================================================
# If Grassy Terrain applies, priority is increased by 1. (Grassy Glide)
#===============================================================================
class Battle::Move::HigherPriorityInGrassyTerrain < Battle::Move
def pbPriority(user)
ret = super
ret += 1 if @battle.field.terrain == :Grass && user.affectedByTerrain?
return ret
end
end
#===============================================================================
# Decreases the PP of the last attack used by the target by 3 (or as much as
# possible). (Eerie Spell)
#===============================================================================
class Battle::Move::LowerPPOfTargetLastMoveBy3 < Battle::Move
def pbFailsAgainstTarget?(user, target, show_message)
last_move = target.pbGetMoveWithID(target.lastRegularMoveUsed)
if !last_move || last_move.pp == 0 || last_move.total_pp <= 0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user, target)
last_move = target.pbGetMoveWithID(target.lastRegularMoveUsed)
reduction = [3, last_move.pp].min
target.pbSetPP(last_move, last_move.pp - reduction)
@battle.pbDisplay(_INTL("It reduced the PP of {1}'s {2} by {3}!",
target.pbThis(true), last_move.name, reduction))
end
end
#===============================================================================
# Target's last move used loses 4 PP. (Spite)
#===============================================================================
class Battle::Move::LowerPPOfTargetLastMoveBy4 < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
last_move = target.pbGetMoveWithID(target.lastRegularMoveUsed)
if !last_move || last_move.pp == 0 || last_move.total_pp <= 0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user, target)
last_move = target.pbGetMoveWithID(target.lastRegularMoveUsed)
reduction = [4, last_move.pp].min
target.pbSetPP(last_move, last_move.pp - reduction)
@battle.pbDisplay(_INTL("It reduced the PP of {1}'s {2} by {3}!",
target.pbThis(true), last_move.name, reduction))
end
end
#===============================================================================
# For 5 rounds, disables the last move the target used. (Disable)
#===============================================================================
class Battle::Move::DisableTargetLastMoveUsed < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::Disable]>0 || !target.lastRegularMoveUsed
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return true if pbMoveFailedAromaVeil?(user, target, show_message)
canDisable = false
target.eachMove do |m|
next if m.id!=target.lastRegularMoveUsed
next if m.pp==0 && m.total_pp>0
canDisable = true
break
end
if !canDisable
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Disable] = 5
target.effects[PBEffects::DisableMove] = target.lastRegularMoveUsed
@battle.pbDisplay(_INTL("{1}'s {2} was disabled!",target.pbThis,
GameData::Move.get(target.lastRegularMoveUsed).name))
target.pbItemStatusCureCheck
end
end
#===============================================================================
# The target can no longer use the same move twice in a row. (Torment)
#===============================================================================
class Battle::Move::DisableTargetUsingSameMoveConsecutively < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::Torment]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return true if pbMoveFailedAromaVeil?(user, target, show_message)
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Torment] = true
@battle.pbDisplay(_INTL("{1} was subjected to torment!",target.pbThis))
target.pbItemStatusCureCheck
end
end
#===============================================================================
# For 4 rounds, the target must use the same move each round. (Encore)
#===============================================================================
class Battle::Move::DisableTargetUsingDifferentMove < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def initialize(battle,move)
super
@moveBlacklist = [
"DisableTargetUsingDifferentMove", # Encore
# Struggle
"Struggle", # Struggle
# Moves that affect the moveset
"ReplaceMoveThisBattleWithTargetLastMoveUsed", # Mimic
"ReplaceMoveWithTargetLastMoveUsed", # Sketch
"TransformUserIntoTarget", # Transform
# Moves that call other moves (see also below)
"UseLastMoveUsedByTarget" # Mirror Move
]
if Settings::MECHANICS_GENERATION >= 7
@moveBlacklist += [
# Moves that call other moves
# "UseLastMoveUsedByTarget", # Mirror Move # See above
"UseLastMoveUsed", # Copycat
"UseMoveTargetIsAboutToUse", # Me First
"UseMoveDependingOnEnvironment", # Nature Power
"UseRandomUserMoveIfAsleep", # Sleep Talk
"UseRandomMoveFromUserParty", # Assist
"UseRandomMove" # Metronome
]
end
end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::Encore]>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if !target.lastRegularMoveUsed ||
@moveBlacklist.include?(GameData::Move.get(target.lastRegularMoveUsed).function_code)
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
if target.effects[PBEffects::ShellTrap]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return true if pbMoveFailedAromaVeil?(user, target, show_message)
canEncore = false
target.eachMove do |m|
next if m.id!=target.lastRegularMoveUsed
next if m.pp==0 && m.total_pp>0
canEncore = true
break
end
if !canEncore
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Encore] = 4
target.effects[PBEffects::EncoreMove] = target.lastRegularMoveUsed
@battle.pbDisplay(_INTL("{1} received an encore!",target.pbThis))
target.pbItemStatusCureCheck
end
end
#===============================================================================
# For 4 rounds, disables the target's non-damaging moves. (Taunt)
#===============================================================================
class Battle::Move::DisableTargetStatusMoves < Battle::Move
def ignoresSubstitute?(user); return true; end
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::Taunt]>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return true if pbMoveFailedAromaVeil?(user, target, show_message)
if Settings::MECHANICS_GENERATION >= 6 && target.hasActiveAbility?(:OBLIVIOUS) &&
!@battle.moldBreaker
if show_message
@battle.pbShowAbilitySplash(target)
if Battle::Scene::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("But it failed!"))
else
@battle.pbDisplay(_INTL("But it failed because of {1}'s {2}!",
target.pbThis(true), target.abilityName))
end
@battle.pbHideAbilitySplash(target)
end
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::Taunt] = 4
@battle.pbDisplay(_INTL("{1} fell for the taunt!",target.pbThis))
target.pbItemStatusCureCheck
end
end
#===============================================================================
# For 5 rounds, disables the target's healing moves. (Heal Block)
#===============================================================================
class Battle::Move::DisableTargetHealingMoves < Battle::Move
def canMagicCoat?; return true; end
def pbFailsAgainstTarget?(user, target, show_message)
if target.effects[PBEffects::HealBlock]>0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return true if pbMoveFailedAromaVeil?(user, target, show_message)
return false
end
def pbEffectAgainstTarget(user,target)
target.effects[PBEffects::HealBlock] = 5
@battle.pbDisplay(_INTL("{1} was prevented from healing!",target.pbThis))
target.pbItemStatusCureCheck
end
end
#===============================================================================
# Target cannot use sound-based moves for 2 more rounds. (Throat Chop)
#===============================================================================
class Battle::Move::DisableTargetSoundMoves < Battle::Move
def pbAdditionalEffect(user,target)
return if target.fainted? || target.damageState.substitute
@battle.pbDisplay(_INTL("The effects of {1} prevent {2} from using certain moves!",
@name,target.pbThis(true))) if target.effects[PBEffects::ThroatChop]==0
target.effects[PBEffects::ThroatChop] = 3
end
end
#===============================================================================
# Disables all target's moves that the user also knows. (Imprison)
#===============================================================================
class Battle::Move::DisableTargetMovesKnownByUser < Battle::Move
def canSnatch?; return true; end
def pbMoveFailed?(user,targets)
if user.effects[PBEffects::Imprison]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return false
end
def pbEffectGeneral(user)
user.effects[PBEffects::Imprison] = true
@battle.pbDisplay(_INTL("{1} sealed any moves its target shares with it!",user.pbThis))
end
end