mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-06 06:01:46 +00:00
Initial commit
This commit is contained in:
140
Data/Scripts/011_Battle/002_Move/001_PokeBattle_Move.rb
Normal file
140
Data/Scripts/011_Battle/002_Move/001_PokeBattle_Move.rb
Normal 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
|
||||
350
Data/Scripts/011_Battle/002_Move/002_Move_Usage.rb
Normal file
350
Data/Scripts/011_Battle/002_Move/002_Move_Usage.rb
Normal 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
|
||||
491
Data/Scripts/011_Battle/002_Move/003_Move_Usage_Calculations.rb
Normal file
491
Data/Scripts/011_Battle/002_Move/003_Move_Usage_Calculations.rb
Normal 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
|
||||
714
Data/Scripts/011_Battle/002_Move/004_Move_Effects_Generic.rb
Normal file
714
Data/Scripts/011_Battle/002_Move/004_Move_Effects_Generic.rb
Normal 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
|
||||
2924
Data/Scripts/011_Battle/002_Move/005_Move_Effects_000-07F.rb
Normal file
2924
Data/Scripts/011_Battle/002_Move/005_Move_Effects_000-07F.rb
Normal file
File diff suppressed because it is too large
Load Diff
3746
Data/Scripts/011_Battle/002_Move/006_Move_Effects_080-0FF.rb
Normal file
3746
Data/Scripts/011_Battle/002_Move/006_Move_Effects_080-0FF.rb
Normal file
File diff suppressed because it is too large
Load Diff
2626
Data/Scripts/011_Battle/002_Move/007_Move_Effects_100-17F.rb
Normal file
2626
Data/Scripts/011_Battle/002_Move/007_Move_Effects_100-17F.rb
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user