Initial commit

This commit is contained in:
Maruno17
2020-09-04 22:00:59 +01:00
commit ba94119d02
300 changed files with 227558 additions and 0 deletions

View File

@@ -0,0 +1,140 @@
class PokeBattle_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 :totalpp
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 = PBMoves.getName(@id) # Get the move's name
# Get data on the move
moveData = pbGetMoveData(@id)
@function = moveData[MOVE_FUNCTION_CODE]
@baseDamage = moveData[MOVE_BASE_DAMAGE]
@type = moveData[MOVE_TYPE]
@category = moveData[MOVE_CATEGORY]
@accuracy = moveData[MOVE_ACCURACY]
@pp = move.pp # Can be changed with Mimic/Transform
@addlEffect = moveData[MOVE_EFFECT_CHANCE]
@target = moveData[MOVE_TARGET]
@priority = moveData[MOVE_PRIORITY]
@flags = moveData[MOVE_FLAGS]
@calcType = -1
@powerBoost = false # For Aerilate, Pixilate, Refrigerate, Galvanize
@snatched = false
end
# This is the code actually used to generate a PokeBattle_Move object. The
# object generated is a subclass of this one which depends on the move's
# function code (found in the script section PokeBattle_MoveEffect).
def PokeBattle_Move.pbFromPBMove(battle,move)
move = PBMove.new(0) if !move
moveFunction = pbGetMoveData(move.id,MOVE_FUNCTION_CODE) || "000"
className = sprintf("PokeBattle_Move_%s",moveFunction)
if Object.const_defined?(className)
return Object.const_get(className).new(battle,move)
end
return PokeBattle_UnimplementedMove.new(battle,move)
end
#=============================================================================
# About the move
#=============================================================================
def pbTarget(user); return @target; end
def totalpp
return @totalpp if @totalpp && @totalpp>0 # Usually undefined
return @realMove.totalpp 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 MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType if @calcType>=0
thisType = @type if !thisType
return !PBTypes.isSpecialType?(thisType)
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 MOVE_CATEGORY_PER_MOVE
thisType ||= @calcType if @calcType>=0
thisType = @type if !thisType
return PBTypes.isSpecialType?(thisType)
end
def damagingMove?; return @category!=2; end
def statusMove?; return @category==2; 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 cannotRedirect?; return false; end # For Future Sight/Doom Desire
def worksWithNoTargets?; return false; end # For Explosion
def damageReducedByBurn?; return true; end # For Facade
def triggersHyperMode?; return false; end
def contactMove?; return @flags[/a/]; end
def canProtectAgainst?; return @flags[/b/]; end
def canMagicCoat?; return @flags[/c/]; end
def canSnatch?; return @flags[/d/]; end
def canMirrorMove?; return @flags[/e/]; end
def canKingsRock?; return @flags[/f/]; end
def thawsUser?; return @flags[/g/]; end
def highCriticalRate?; return @flags[/h/]; end
def bitingMove?; return @flags[/i/]; end
def punchingMove?; return @flags[/j/]; end
def soundMove?; return @flags[/k/]; end
def powderMove?; return @flags[/l/]; end
def pulseMove?; return @flags[/m/]; end
def bombMove?; return @flags[/n/]; end
def danceMove?; return @flags[/o/]; 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 NEWEST_BATTLE_MECHANICS
return true if soundMove?
return true if user && user.hasActiveAbility?(:INFILTRATOR)
end
return false
end
end

View File

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

View File

@@ -0,0 +1,491 @@
class PokeBattle_Move
#=============================================================================
# Move's type calculation
#=============================================================================
def pbBaseType(user)
ret = @type
return ret if !ret || ret<0
if user.abilityActive?
ret = BattleHandlers.triggerMoveBaseTypeModifierAbility(user.ability,user,self,ret)
end
return ret
end
def pbCalcType(user)
@powerBoost = false
ret = pbBaseType(user)
return ret if !ret || ret<0
if hasConst?(PBTypes,:ELECTRIC)
if @battle.field.effects[PBEffects::IonDeluge] && isConst?(ret,PBTypes,:NORMAL)
ret = getConst(PBTypes,:ELECTRIC)
@powerBoost = false
end
if user.effects[PBEffects::Electrify]
ret = getConst(PBTypes,:ELECTRIC)
@powerBoost = false
end
end
return ret
end
#=============================================================================
# Type effectiveness calculation
#=============================================================================
def pbCalcTypeModSingle(moveType,defType,user,target)
ret = PBTypes.getEffectiveness(moveType,defType)
# Ring Target
if target.hasActiveItem?(:RINGTARGET)
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if PBTypes.ineffective?(moveType,defType)
end
# Foresight
if user.hasActiveAbility?(:SCRAPPY) || target.effects[PBEffects::Foresight]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if isConst?(defType,PBTypes,:GHOST) &&
PBTypes.ineffective?(moveType,defType)
end
# Miracle Eye
if target.effects[PBEffects::MiracleEye]
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if isConst?(defType,PBTypes,:DARK) &&
PBTypes.ineffective?(moveType,defType)
end
# Delta Stream's weather
if @battle.pbWeather==PBWeather::StrongWinds
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if isConst?(defType,PBTypes,:FLYING) &&
PBTypes.superEffective?(moveType,defType)
end
# Grounded Flying-type Pokémon become susceptible to Ground moves
if !target.airborne?
ret = PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE if isConst?(defType,PBTypes,:FLYING) &&
isConst?(moveType,PBTypes,:GROUND)
end
return ret
end
def pbCalcTypeMod(moveType,user,target)
return PBTypeEffectiveness::NORMAL_EFFECTIVE if moveType<0
return PBTypeEffectiveness::NORMAL_EFFECTIVE if isConst?(moveType,PBTypes,:GROUND) &&
target.pbHasType?(:FLYING) && target.hasActiveItem?(:IRONBALL)
# Determine types
tTypes = target.pbTypes(true)
# Get effectivenesses
typeMods = [PBTypeEffectiveness::NORMAL_EFFECTIVE_ONE] * 3 # 3 types max
tTypes.each_with_index do |type,i|
typeMods[i] = pbCalcTypeModSingle(moveType,type,user,target)
end
# Multiply all effectivenesses together
ret = 1
typeMods.each { |m| ret *= m }
return ret
end
#=============================================================================
# Accuracy check
#=============================================================================
def pbBaseAccuracy(user,target); return @accuracy; end
# Accuracy calculations for one-hit KO moves and "always hit" 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_ACC] = baseAcc
modifiers[ACC_STAGE] = user.stages[PBStats::ACCURACY]
modifiers[EVA_STAGE] = target.stages[PBStats::EVASION]
modifiers[ACC_MULT] = 0x1000
modifiers[EVA_MULT] = 0x1000
pbCalcAccuracyModifiers(user,target,modifiers)
# Check if move can't miss
return true if modifiers[BASE_ACC]==0
# Calculation
accStage = [[modifiers[ACC_STAGE],-6].max,6].min + 6
evaStage = [[modifiers[EVA_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[ACC_MULT] / 0x1000).round
evasion = (evasion * modifiers[EVA_MULT] / 0x1000).round
evasion = 1 if evasion<1
# Calculation
return @battle.pbRandom(100) < modifiers[BASE_ACC] * accuracy / evasion
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.eachAlly 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 ACC_MULT or EVA_STAGE to specific values
if @battle.field.effects[PBEffects::Gravity]>0
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*5/3).round
end
if user.effects[PBEffects::MicleBerry]
user.effects[PBEffects::MicleBerry] = false
modifiers[ACC_MULT] = (modifiers[ACC_MULT]*1.2).round
end
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::Foresight] && modifiers[EVA_STAGE]>0
modifiers[EVA_STAGE] = 0 if target.effects[PBEffects::MiracleEye] && modifiers[EVA_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 = (NEWEST_BATTLE_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; return true
when -1; 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? && isConst?(@type,PBTypes,:SHADOW)
c = ratios.length-1 if c>=ratios.length
# Calculation
return @battle.pbRandom(ratios[c])==0
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[PBStats::SPATK]+6
end
return user.attack, user.stages[PBStats::ATTACK]+6
end
def pbGetDefenseStats(user,target)
if specialMove?
return target.spdef, target.stages[PBStats::SPDEF]+6
end
return target.defense, target.stages[PBStats::DEFENSE]+6
end
def pbCalcDamage(user,target,numTargets=1)
return if statusMove?
if target.damageState.disguise
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 # -1 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 = [0x1000,0x1000,0x1000,0x1000]
pbCalcDamageMultipliers(user,target,numTargets,type,baseDmg,multipliers)
# Main damage calculation
baseDmg = [(baseDmg * multipliers[BASE_DMG_MULT] / 0x1000).round,1].max
atk = [(atk * multipliers[ATK_MULT] / 0x1000).round,1].max
defense = [(defense * multipliers[DEF_MULT] / 0x1000).round,1].max
damage = (((2.0*user.level/5+2).floor*baseDmg*atk/defense).floor/50).floor+2
damage = [(damage * multipliers[FINAL_DMG_MULT] / 0x1000).round,1].max
target.damageState.calcDamage = damage
end
def pbCalcDamageMultipliers(user,target,numTargets,baseDmg,type,multipliers)
# Global abilities
if (@battle.pbCheckGlobalAbility(:DARKAURA) && isConst?(type,PBTypes,:DARK)) ||
(@battle.pbCheckGlobalAbility(:FAIRYAURA) && isConst?(type,PBTypes,:FAIRY))
if @battle.pbCheckGlobalAbility(:AURABREAK)
multipliers[BASE_DMG_MULT] *= 2/3.0
else
multipliers[BASE_DMG_MULT] *= 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.eachAlly 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.eachAlly 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_DMG_MULT] /= 4
end
# Other
if user.effects[PBEffects::MeFirst]
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
end
if user.effects[PBEffects::HelpingHand] && !self.is_a?(PokeBattle_Confusion)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
end
if user.effects[PBEffects::Charge]>0 && isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] *= 2
end
# Mud Sport
if isConst?(type,PBTypes,:ELECTRIC)
@battle.eachBattler do |b|
next if !b.effects[PBEffects::MudSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::MudSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
# Water Sport
if isConst?(type,PBTypes,:FIRE)
@battle.eachBattler do |b|
next if !b.effects[PBEffects::WaterSport]
multipliers[BASE_DMG_MULT] /= 3
break
end
if @battle.field.effects[PBEffects::WaterSportField]>0
multipliers[BASE_DMG_MULT] /= 3
end
end
# Terrain moves
if user.affectedByTerrain?
case @battle.field.terrain
when PBBattleTerrains::Electric
if isConst?(type,PBTypes,:ELECTRIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
end
when PBBattleTerrains::Grassy
if isConst?(type,PBTypes,:GRASS)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
end
when PBBattleTerrains::Psychic
if isConst?(type,PBTypes,:PSYCHIC)
multipliers[BASE_DMG_MULT] = (multipliers[BASE_DMG_MULT]*1.5).round
end
end
end
if @battle.field.terrain==PBBattleTerrains::Misty && target.affectedByTerrain? &&
isConst?(type,PBTypes,:DRAGON)
multipliers[BASE_DMG_MULT] /= 2
end
# Badge multipliers
if @battle.internalBattle
if user.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_ATTACK
multipliers[ATK_MULT] = (multipliers[ATK_MULT]*1.1).round
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPATK
multipliers[ATK_MULT] = (multipliers[ATK_MULT]*1.1).round
end
end
if target.pbOwnedByPlayer?
if physicalMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_DEFENSE
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round
elsif specialMove? && @battle.pbPlayer.numbadges>=NUM_BADGES_BOOST_SPDEF
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.1).round
end
end
end
# Multi-targeting attacks
if numTargets>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*0.75).round
end
# Weather
case @battle.pbWeather
when PBWeather::Sun, PBWeather::HarshSun
if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] /= 2
end
when PBWeather::Rain, PBWeather::HeavyRain
if isConst?(type,PBTypes,:FIRE)
multipliers[FINAL_DMG_MULT] /= 2
elsif isConst?(type,PBTypes,:WATER)
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
end
when PBWeather::Sandstorm
if target.pbHasType?(:ROCK) && specialMove? && @function!="122" # Psyshock
multipliers[DEF_MULT] = (multipliers[DEF_MULT]*1.5).round
end
end
# Critical hits
if target.damageState.critical
if NEWEST_BATTLE_MECHANICS
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
else
multipliers[FINAL_DMG_MULT] *= 2
end
end
# Random variance
if !self.is_a?(PokeBattle_Confusion)
random = 85+@battle.pbRandom(16)
multipliers[FINAL_DMG_MULT] *= random/100.0
end
# STAB
if type>=0 && user.pbHasType?(type)
if user.hasActiveAbility?(:ADAPTABILITY)
multipliers[FINAL_DMG_MULT] *= 2
else
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*1.5).round
end
end
# Type effectiveness
multipliers[FINAL_DMG_MULT] *= target.damageState.typeMod.to_f/PBTypeEffectiveness::NORMAL_EFFECTIVE
multipliers[FINAL_DMG_MULT] = multipliers[FINAL_DMG_MULT].round
# Burn
if user.status==PBStatuses::BURN && physicalMove? && damageReducedByBurn? &&
!user.hasActiveAbility?(:GUTS)
multipliers[FINAL_DMG_MULT] /= 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_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::Reflect]>0 && physicalMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
else
multipliers[FINAL_DMG_MULT] /= 2
end
elsif target.pbOwnSide.effects[PBEffects::LightScreen]>0 && specialMove?
if @battle.pbSideBattlerCount(target)>1
multipliers[FINAL_DMG_MULT] = (multipliers[FINAL_DMG_MULT]*2/3).round
else
multipliers[FINAL_DMG_MULT] /= 2
end
end
end
# Minimize
if target.effects[PBEffects::Minimize] && tramplesMinimize?(2)
multipliers[FINAL_DMG_MULT] *= 2
end
# Move-specific base damage modifiers
multipliers[BASE_DMG_MULT] = pbBaseDamageMultiplier(multipliers[BASE_DMG_MULT],user,target)
# Move-specific final damage modifiers
multipliers[FINAL_DMG_MULT] = pbModifyDamage(multipliers[FINAL_DMG_MULT],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 NEWEST_BATTLE_MECHANICS || @function!="0A4" # Secret Power
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,714 @@
#===============================================================================
# Superclass that handles moves using a non-existent function code.
# Damaging moves just do damage with no additional effect.
# Status moves always fail.
#===============================================================================
class PokeBattle_UnimplementedMove < PokeBattle_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 PokeBattle_Confusion < PokeBattle_Move
def initialize(battle,move)
@battle = battle
@realMove = move
@id = 0
@name = ""
@function = "000"
@baseDamage = 40
@type = -1
@category = 0
@accuracy = 100
@pp = -1
@target = 0
@priority = 0
@flags = ""
@addlEffect = 0
@calcType = -1
@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.
# For cases where the real move named Struggle is not defined.
#===============================================================================
class PokeBattle_Struggle < PokeBattle_Move
def initialize(battle,move)
@battle = battle
@realMove = nil # Not associated with a move
@id = (move) ? move.id : -1 # Doesn't work if 0
@name = (move) ? PBMoves.getName(@id) : _INTL("Struggle")
@function = "002"
@baseDamage = 50
@type = -1
@category = 0
@accuracy = 0
@pp = -1
@target = 0
@priority = 0
@flags = ""
@addlEffect = 0
@calcType = -1
@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 PokeBattle_SleepMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanSleep?(user,true,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 PokeBattle_PoisonMove < PokeBattle_Move
def initialize(battle,move)
super
@toxic = false
end
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanPoison?(user,true,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 PokeBattle_ParalysisMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanParalyze?(user,true,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 PokeBattle_BurnMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanBurn?(user,true,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 PokeBattle_FreezeMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanFreeze?(user,true,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 PokeBattle_FlinchMove < PokeBattle_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 PokeBattle_ConfuseMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanConfuse?(user,true,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 PokeBattle_StatUpMove < PokeBattle_Move
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 PokeBattle_MultiStatUpMove < PokeBattle_Move
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 PokeBattle_StatDownMove < PokeBattle_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 PokeBattle_TargetStatDownMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
return false if damagingMove?
return !target.pbCanLowerStatStage?(@statDown[0],user,self,true)
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 PokeBattle_TargetMultiStatDownMove < PokeBattle_Move
def pbFailsAgainstTarget?(user,target)
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
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
end
if canLower
target.pbCanLowerStatStage?(@statDown[0],user,self,true)
end
return true
end
return false
end
def pbEffectAgainstTarget(user,target)
return if damagingMove?
showAnim = 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)
showAnim = false
end
end
end
def pbAdditionalEffect(user,target)
return if target.damageState.substitute
showAnim = 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)
showAnim = false
end
end
end
end
#===============================================================================
# Fixed damage-inflicting move.
#===============================================================================
class PokeBattle_FixedDamageMove < PokeBattle_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 PokeBattle_TwoTurnMove < PokeBattle_Move
def chargingTurnMove?; return true; end
# user.effects[PBEffects::TwoTurnAttack] is set to the move's ID if this
# method returns true, or 0 if false.
# Non-zero means the charging turn. 0 means the attacking turn.
def pbIsChargingTurn?(user)
@powerHerb = false
@chargingTurn = false # Assume damaging turn by default
@damagingTurn = true
# 0 at start of charging turn, move's ID at start of damaging turn
if user.effects[PBEffects::TwoTurnAttack]==0
@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 !["0C9","0CA","0CB","0CC","0CD","0CE","14D"].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 PokeBattle_HealingMove < PokeBattle_Move
def healingMove?; return true; end
def pbHealAmount(user); return 1; 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 PokeBattle_RecoilMove < PokeBattle_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 PokeBattle_ProtectMove < PokeBattle_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 && NEWEST_BATTLE_MECHANICS) &&
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] *= (NEWEST_BATTLE_MECHANICS) ? 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 PokeBattle_WeatherMove < PokeBattle_Move
def initialize(battle,move)
super
@weatherType = PBWeather::None
end
def pbMoveFailed?(user,targets)
case @battle.field.weather
when PBWeather::HarshSun
@battle.pbDisplay(_INTL("The extremely harsh sunlight was not lessened at all!"))
return true
when PBWeather::HeavyRain
@battle.pbDisplay(_INTL("There is no relief from this heavy rain!"))
return true
when PBWeather::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 PokeBattle_PledgeMove < PokeBattle_Move
def pbOnStartUse(user,targets)
@pledgeSetup = false; @pledgeCombo = false; @pledgeOtherUser = nil
@comboEffect = nil; @overrideType = 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]; @overrideType = i[2]; @overrideAnim = i[3]
break
end
return if @pledgeCombo
# Check whether this is the setup of a combo move
user.eachAlly do |b|
next if @battle.choices[b.index][0]!=:UseMove || b.movedThisRound?
move = @battle.choices[b.index][2]
next if !move || move.id<=0
@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)
return @overrideType if @overrideType!=nil
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!=nil
return super
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