mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 21:24:59 +00:00
782 lines
35 KiB
Ruby
782 lines
35 KiB
Ruby
class Battle
|
|
#=============================================================================
|
|
# End Of Round end weather check and weather effects
|
|
#=============================================================================
|
|
def pbEOREndWeather(priority)
|
|
# NOTE: Primordial weather doesn't need to be checked here, because if it
|
|
# could wear off here, it will have worn off already.
|
|
# Count down weather duration
|
|
@field.weatherDuration -= 1 if @field.weatherDuration > 0
|
|
# Weather wears off
|
|
if @field.weatherDuration == 0
|
|
case @field.weather
|
|
when :Sun then pbDisplay(_INTL("The sunlight faded."))
|
|
when :Rain then pbDisplay(_INTL("The rain stopped."))
|
|
when :Sandstorm then pbDisplay(_INTL("The sandstorm subsided."))
|
|
when :Hail then pbDisplay(_INTL("The hail stopped."))
|
|
when :ShadowSky then pbDisplay(_INTL("The shadow sky faded."))
|
|
end
|
|
@field.weather = :None
|
|
# Check for form changes caused by the weather changing
|
|
allBattlers.each { |battler| battler.pbCheckFormOnWeatherChange }
|
|
# Start up the default weather
|
|
pbStartWeather(nil, @field.defaultWeather) if @field.defaultWeather != :None
|
|
return if @field.weather == :None
|
|
end
|
|
# Weather continues
|
|
weather_data = GameData::BattleWeather.try_get(@field.weather)
|
|
pbCommonAnimation(weather_data.animation) if weather_data
|
|
case @field.weather
|
|
when :Sun then pbDisplay(_INTL("The sunlight is strong."))
|
|
when :Rain then pbDisplay(_INTL("Rain continues to fall."))
|
|
when :Sandstorm then pbDisplay(_INTL("The sandstorm is raging."))
|
|
when :Hail then pbDisplay(_INTL("The hail is crashing down."))
|
|
when :HarshSun then pbDisplay(_INTL("The sunlight is extremely harsh."))
|
|
when :HeavyRain then pbDisplay(_INTL("It is raining heavily."))
|
|
when :StrongWinds then pbDisplay(_INTL("The wind is strong."))
|
|
when :ShadowSky then pbDisplay(_INTL("The shadow sky continues."))
|
|
end
|
|
# Effects due to weather
|
|
priority.each do |battler|
|
|
# Weather-related abilities
|
|
if battler.abilityActive?
|
|
Battle::AbilityEffects.triggerEndOfRoundWeather(battler.ability, battler.effectiveWeather, battler, self)
|
|
battler.pbFaint if battler.fainted?
|
|
end
|
|
# Weather damage
|
|
pbEORWeatherDamage(battler)
|
|
end
|
|
end
|
|
|
|
def pbEORWeatherDamage(battler)
|
|
return if battler.fainted?
|
|
amt = -1
|
|
case battler.effectiveWeather
|
|
when :Sandstorm
|
|
return if !battler.takesSandstormDamage?
|
|
pbDisplay(_INTL("{1} is buffeted by the sandstorm!", battler.pbThis))
|
|
amt = battler.totalhp / 16
|
|
when :Hail
|
|
return if !battler.takesHailDamage?
|
|
pbDisplay(_INTL("{1} is buffeted by the hail!", battler.pbThis))
|
|
amt = battler.totalhp / 16
|
|
when :ShadowSky
|
|
return if !battler.takesShadowSkyDamage?
|
|
pbDisplay(_INTL("{1} is hurt by the shadow sky!", battler.pbThis))
|
|
amt = battler.totalhp / 16
|
|
end
|
|
return if amt < 0
|
|
@scene.pbDamageAnimation(battler)
|
|
battler.pbReduceHP(amt, false)
|
|
battler.pbItemHPHealCheck
|
|
battler.pbFaint if battler.fainted?
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round use delayed moves (Future Sight, Doom Desire)
|
|
#=============================================================================
|
|
def pbEORUseFutureSight(position, position_index)
|
|
return if !position || position.effects[PBEffects::FutureSightCounter] == 0
|
|
position.effects[PBEffects::FutureSightCounter] -= 1
|
|
return if position.effects[PBEffects::FutureSightCounter] > 0
|
|
return if !@battlers[position_index] || @battlers[position_index].fainted? # No target
|
|
moveUser = nil
|
|
allBattlers.each do |battler|
|
|
next if battler.opposes?(position.effects[PBEffects::FutureSightUserIndex])
|
|
next if battler.pokemonIndex != position.effects[PBEffects::FutureSightUserPartyIndex]
|
|
moveUser = battler
|
|
break
|
|
end
|
|
return if moveUser && moveUser.index == position_index # Target is the user
|
|
if !moveUser # User isn't in battle, get it from the party
|
|
party = pbParty(position.effects[PBEffects::FutureSightUserIndex])
|
|
pkmn = party[position.effects[PBEffects::FutureSightUserPartyIndex]]
|
|
if pkmn&.able?
|
|
moveUser = Battler.new(self, position.effects[PBEffects::FutureSightUserIndex])
|
|
moveUser.pbInitDummyPokemon(pkmn, position.effects[PBEffects::FutureSightUserPartyIndex])
|
|
end
|
|
end
|
|
return if !moveUser # User is fainted
|
|
move = position.effects[PBEffects::FutureSightMove]
|
|
pbDisplay(_INTL("{1} took the {2} attack!", @battlers[position_index].pbThis,
|
|
GameData::Move.get(move).name))
|
|
# NOTE: Future Sight failing against the target here doesn't count towards
|
|
# Stomping Tantrum.
|
|
userLastMoveFailed = moveUser.lastMoveFailed
|
|
@futureSight = true
|
|
moveUser.pbUseMoveSimple(move, position_index)
|
|
@futureSight = false
|
|
moveUser.lastMoveFailed = userLastMoveFailed
|
|
@battlers[position_index].pbFaint if @battlers[position_index].fainted?
|
|
position.effects[PBEffects::FutureSightCounter] = 0
|
|
position.effects[PBEffects::FutureSightMove] = nil
|
|
position.effects[PBEffects::FutureSightUserIndex] = -1
|
|
position.effects[PBEffects::FutureSightUserPartyIndex] = -1
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round healing from Wish
|
|
#=============================================================================
|
|
def pbEORWishHealing
|
|
@positions.each_with_index do |pos, idxPos|
|
|
next if !pos || pos.effects[PBEffects::Wish] == 0
|
|
pos.effects[PBEffects::Wish] -= 1
|
|
next if pos.effects[PBEffects::Wish] > 0
|
|
next if !@battlers[idxPos] || !@battlers[idxPos].canHeal?
|
|
wishMaker = pbThisEx(idxPos, pos.effects[PBEffects::WishMaker])
|
|
@battlers[idxPos].pbRecoverHP(pos.effects[PBEffects::WishAmount])
|
|
pbDisplay(_INTL("{1}'s wish came true!", wishMaker))
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round Sea of Fire damage (Fire Pledge + Grass Pledge combination)
|
|
#=============================================================================
|
|
def pbEORSeaOfFireDamage(priority)
|
|
2.times do |side|
|
|
next if sides[side].effects[PBEffects::SeaOfFire] == 0
|
|
sides[side].effects[PBEffects::SeaOfFire] -= 1
|
|
next if sides[side].effects[PBEffects::SeaOfFire] == 0
|
|
pbCommonAnimation("SeaOfFire") if side == 0
|
|
pbCommonAnimation("SeaOfFireOpp") if side == 1
|
|
priority.each do |battler|
|
|
next if battler.opposes?(side)
|
|
next if !battler.takesIndirectDamage? || battler.pbHasType?(:FIRE)
|
|
@scene.pbDamageAnimation(battler)
|
|
battler.pbTakeEffectDamage(battler.totalhp / 8, false) do |hp_lost|
|
|
pbDisplay(_INTL("{1} is hurt by the sea of fire!", battler.pbThis))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round healing from Grassy Terrain
|
|
#=============================================================================
|
|
def pbEORTerrainHealing(battler)
|
|
return if battler.fainted?
|
|
# Grassy Terrain (healing)
|
|
if @field.terrain == :Grassy && battler.affectedByTerrain? && battler.canHeal?
|
|
PBDebug.log("[Lingering effect] Grassy Terrain heals #{battler.pbThis(true)}")
|
|
battler.pbRecoverHP(battler.totalhp / 16)
|
|
pbDisplay(_INTL("{1}'s HP was restored.", battler.pbThis))
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round various healing effects
|
|
#=============================================================================
|
|
def pbEORHealingEffects(priority)
|
|
# Aqua Ring
|
|
priority.each do |battler|
|
|
next if !battler.effects[PBEffects::AquaRing]
|
|
next if !battler.canHeal?
|
|
hpGain = battler.totalhp / 16
|
|
hpGain = (hpGain * 1.3).floor if battler.hasActiveItem?(:BIGROOT)
|
|
battler.pbRecoverHP(hpGain)
|
|
pbDisplay(_INTL("Aqua Ring restored {1}'s HP!", battler.pbThis(true)))
|
|
end
|
|
# Ingrain
|
|
priority.each do |battler|
|
|
next if !battler.effects[PBEffects::Ingrain]
|
|
next if !battler.canHeal?
|
|
hpGain = battler.totalhp / 16
|
|
hpGain = (hpGain * 1.3).floor if battler.hasActiveItem?(:BIGROOT)
|
|
battler.pbRecoverHP(hpGain)
|
|
pbDisplay(_INTL("{1} absorbed nutrients with its roots!", battler.pbThis))
|
|
end
|
|
# Leech Seed
|
|
priority.each do |battler|
|
|
next if battler.effects[PBEffects::LeechSeed] < 0
|
|
next if !battler.takesIndirectDamage?
|
|
recipient = @battlers[battler.effects[PBEffects::LeechSeed]]
|
|
next if !recipient || recipient.fainted?
|
|
pbCommonAnimation("LeechSeed", recipient, battler)
|
|
battler.pbTakeEffectDamage(battler.totalhp / 8) do |hp_lost|
|
|
recipient.pbRecoverHPFromDrain(hp_lost, battler,
|
|
_INTL("{1}'s health is sapped by Leech Seed!", battler.pbThis))
|
|
recipient.pbAbilitiesOnDamageTaken
|
|
end
|
|
recipient.pbFaint if recipient.fainted?
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round deal damage from status problems
|
|
#=============================================================================
|
|
def pbEORStatusProblemDamage(priority)
|
|
# Damage from poisoning
|
|
priority.each do |battler|
|
|
next if battler.fainted?
|
|
next if battler.status != :POISON
|
|
if battler.statusCount > 0
|
|
battler.effects[PBEffects::Toxic] += 1
|
|
battler.effects[PBEffects::Toxic] = 16 if battler.effects[PBEffects::Toxic] > 16
|
|
end
|
|
if battler.hasActiveAbility?(:POISONHEAL)
|
|
if battler.canHeal?
|
|
anim_name = GameData::Status.get(:POISON).animation
|
|
pbCommonAnimation(anim_name, battler) if anim_name
|
|
pbShowAbilitySplash(battler)
|
|
battler.pbRecoverHP(battler.totalhp / 8)
|
|
if Scene::USE_ABILITY_SPLASH
|
|
pbDisplay(_INTL("{1}'s HP was restored.", battler.pbThis))
|
|
else
|
|
pbDisplay(_INTL("{1}'s {2} restored its HP.", battler.pbThis, battler.abilityName))
|
|
end
|
|
pbHideAbilitySplash(battler)
|
|
end
|
|
elsif battler.takesIndirectDamage?
|
|
battler.droppedBelowHalfHP = false
|
|
dmg = battler.totalhp / 8
|
|
dmg = battler.totalhp * battler.effects[PBEffects::Toxic] / 16 if battler.statusCount > 0
|
|
battler.pbContinueStatus { battler.pbReduceHP(dmg, false) }
|
|
battler.pbItemHPHealCheck
|
|
battler.pbAbilitiesOnDamageTaken
|
|
battler.pbFaint if battler.fainted?
|
|
battler.droppedBelowHalfHP = false
|
|
end
|
|
end
|
|
# Damage from burn
|
|
priority.each do |battler|
|
|
next if battler.status != :BURN || !battler.takesIndirectDamage?
|
|
battler.droppedBelowHalfHP = false
|
|
dmg = (Settings::MECHANICS_GENERATION >= 7) ? battler.totalhp / 16 : battler.totalhp / 8
|
|
dmg = (dmg / 2.0).round if battler.hasActiveAbility?(:HEATPROOF)
|
|
battler.pbContinueStatus { battler.pbReduceHP(dmg, false) }
|
|
battler.pbItemHPHealCheck
|
|
battler.pbAbilitiesOnDamageTaken
|
|
battler.pbFaint if battler.fainted?
|
|
battler.droppedBelowHalfHP = false
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round deal damage from effects (except by trapping)
|
|
#=============================================================================
|
|
def pbEOREffectDamage(priority)
|
|
# Damage from sleep (Nightmare)
|
|
priority.each do |battler|
|
|
battler.effects[PBEffects::Nightmare] = false if !battler.asleep?
|
|
next if !battler.effects[PBEffects::Nightmare] || !battler.takesIndirectDamage?
|
|
battler.pbTakeEffectDamage(battler.totalhp / 4) do |hp_lost|
|
|
pbDisplay(_INTL("{1} is locked in a nightmare!", battler.pbThis))
|
|
end
|
|
end
|
|
# Curse
|
|
priority.each do |battler|
|
|
next if !battler.effects[PBEffects::Curse] || !battler.takesIndirectDamage?
|
|
battler.pbTakeEffectDamage(battler.totalhp / 4) do |hp_lost|
|
|
pbDisplay(_INTL("{1} is afflicted by the curse!", battler.pbThis))
|
|
end
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round deal damage to trapped battlers
|
|
#=============================================================================
|
|
TRAPPING_MOVE_COMMON_ANIMATIONS = {
|
|
:BIND => "Bind",
|
|
:CLAMP => "Clamp",
|
|
:FIRESPIN => "FireSpin",
|
|
:MAGMASTORM => "MagmaStorm",
|
|
:SANDTOMB => "SandTomb",
|
|
:WRAP => "Wrap",
|
|
:INFESTATION => "Infestation"
|
|
}
|
|
|
|
def pbEORTrappingDamage(battler)
|
|
return if battler.fainted? || battler.effects[PBEffects::Trapping] == 0
|
|
battler.effects[PBEffects::Trapping] -= 1
|
|
move_name = GameData::Move.get(battler.effects[PBEffects::TrappingMove]).name
|
|
if battler.effects[PBEffects::Trapping] == 0
|
|
pbDisplay(_INTL("{1} was freed from {2}!", battler.pbThis, move_name))
|
|
return
|
|
end
|
|
anim = TRAPPING_MOVE_COMMON_ANIMATIONS[battler.effects[PBEffects::TrappingMove]] || "Wrap"
|
|
pbCommonAnimation(anim, battler)
|
|
return if !battler.takesIndirectDamage?
|
|
hpLoss = (Settings::MECHANICS_GENERATION >= 6) ? battler.totalhp / 8 : battler.totalhp / 16
|
|
if @battlers[battler.effects[PBEffects::TrappingUser]].hasActiveItem?(:BINDINGBAND)
|
|
hpLoss = (Settings::MECHANICS_GENERATION >= 6) ? battler.totalhp / 6 : battler.totalhp / 8
|
|
end
|
|
@scene.pbDamageAnimation(battler)
|
|
battler.pbTakeEffectDamage(hpLoss, false) do |hp_lost|
|
|
pbDisplay(_INTL("{1} is hurt by {2}!", battler.pbThis, move_name))
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round end effects that apply to a battler
|
|
#=============================================================================
|
|
def pbEORCountDownBattlerEffect(priority, effect)
|
|
priority.each do |battler|
|
|
next if battler.fainted? || battler.effects[effect] == 0
|
|
battler.effects[effect] -= 1
|
|
yield battler if block_given? && battler.effects[effect] == 0
|
|
end
|
|
end
|
|
|
|
def pbEOREndBattlerEffects(priority)
|
|
# Taunt
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::Taunt) do |battler|
|
|
pbDisplay(_INTL("{1}'s taunt wore off!", battler.pbThis))
|
|
end
|
|
# Encore
|
|
priority.each do |battler|
|
|
next if battler.fainted? || battler.effects[PBEffects::Encore] == 0
|
|
idxEncoreMove = battler.pbEncoredMoveIndex
|
|
if idxEncoreMove >= 0
|
|
battler.effects[PBEffects::Encore] -= 1
|
|
if battler.effects[PBEffects::Encore] == 0 || battler.moves[idxEncoreMove].pp == 0
|
|
battler.effects[PBEffects::Encore] = 0
|
|
pbDisplay(_INTL("{1}'s encore ended!", battler.pbThis))
|
|
end
|
|
else
|
|
PBDebug.log("[End of effect] #{battler.pbThis}'s encore ended (encored move no longer known)")
|
|
battler.effects[PBEffects::Encore] = 0
|
|
battler.effects[PBEffects::EncoreMove] = nil
|
|
end
|
|
end
|
|
# Disable/Cursed Body
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::Disable) do |battler|
|
|
battler.effects[PBEffects::DisableMove] = nil
|
|
pbDisplay(_INTL("{1} is no longer disabled!", battler.pbThis))
|
|
end
|
|
# Magnet Rise
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::MagnetRise) do |battler|
|
|
pbDisplay(_INTL("{1}'s electromagnetism wore off!", battler.pbThis))
|
|
end
|
|
# Telekinesis
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::Telekinesis) do |battler|
|
|
pbDisplay(_INTL("{1} was freed from the telekinesis!", battler.pbThis))
|
|
end
|
|
# Heal Block
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::HealBlock) do |battler|
|
|
pbDisplay(_INTL("{1}'s Heal Block wore off!", battler.pbThis))
|
|
end
|
|
# Embargo
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::Embargo) do |battler|
|
|
pbDisplay(_INTL("{1} can use items again!", battler.pbThis))
|
|
battler.pbItemTerrainStatBoostCheck
|
|
end
|
|
# Yawn
|
|
pbEORCountDownBattlerEffect(priority, PBEffects::Yawn) do |battler|
|
|
if battler.pbCanSleepYawn?
|
|
PBDebug.log("[Lingering effect] #{battler.pbThis} fell asleep because of Yawn")
|
|
battler.pbSleep
|
|
end
|
|
end
|
|
# Perish Song
|
|
perishSongUsers = []
|
|
priority.each do |battler|
|
|
next if battler.fainted? || battler.effects[PBEffects::PerishSong] == 0
|
|
battler.effects[PBEffects::PerishSong] -= 1
|
|
pbDisplay(_INTL("{1}'s perish count fell to {2}!", battler.pbThis, battler.effects[PBEffects::PerishSong]))
|
|
if battler.effects[PBEffects::PerishSong] == 0
|
|
perishSongUsers.push(battler.effects[PBEffects::PerishSongUser])
|
|
battler.pbReduceHP(battler.hp)
|
|
end
|
|
battler.pbItemHPHealCheck
|
|
battler.pbFaint if battler.fainted?
|
|
end
|
|
# Judge if all remaining Pokemon fainted by a Perish Song triggered by a single side
|
|
if perishSongUsers.length > 0 &&
|
|
((perishSongUsers.find_all { |idxBattler| opposes?(idxBattler) }.length == perishSongUsers.length) ||
|
|
(perishSongUsers.find_all { |idxBattler| !opposes?(idxBattler) }.length == perishSongUsers.length))
|
|
pbJudgeCheckpoint(@battlers[perishSongUsers[0]])
|
|
end
|
|
return if @decision > 0
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round end effects that apply to one side of the field
|
|
#=============================================================================
|
|
def pbEORCountDownSideEffect(side, effect, msg)
|
|
return if @sides[side].effects[effect] <= 0
|
|
@sides[side].effects[effect] -= 1
|
|
pbDisplay(msg) if @sides[side].effects[effect] == 0
|
|
end
|
|
|
|
def pbEOREndSideEffects(side, priority)
|
|
# Reflect
|
|
pbEORCountDownSideEffect(side, PBEffects::Reflect,
|
|
_INTL("{1}'s Reflect wore off!", @battlers[side].pbTeam))
|
|
# Light Screen
|
|
pbEORCountDownSideEffect(side, PBEffects::LightScreen,
|
|
_INTL("{1}'s Light Screen wore off!", @battlers[side].pbTeam))
|
|
# Safeguard
|
|
pbEORCountDownSideEffect(side, PBEffects::Safeguard,
|
|
_INTL("{1} is no longer protected by Safeguard!", @battlers[side].pbTeam))
|
|
# Mist
|
|
pbEORCountDownSideEffect(side, PBEffects::Mist,
|
|
_INTL("{1} is no longer protected by mist!", @battlers[side].pbTeam))
|
|
# Tailwind
|
|
pbEORCountDownSideEffect(side, PBEffects::Tailwind,
|
|
_INTL("{1}'s Tailwind petered out!", @battlers[side].pbTeam))
|
|
# Lucky Chant
|
|
pbEORCountDownSideEffect(side, PBEffects::LuckyChant,
|
|
_INTL("{1}'s Lucky Chant wore off!", @battlers[side].pbTeam))
|
|
# Pledge Rainbow
|
|
pbEORCountDownSideEffect(side, PBEffects::Rainbow,
|
|
_INTL("The rainbow on {1}'s side disappeared!", @battlers[side].pbTeam(true)))
|
|
# Pledge Sea of Fire
|
|
pbEORCountDownSideEffect(side, PBEffects::SeaOfFire,
|
|
_INTL("The sea of fire around {1} disappeared!", @battlers[side].pbTeam(true)))
|
|
# Pledge Swamp
|
|
pbEORCountDownSideEffect(side, PBEffects::Swamp,
|
|
_INTL("The swamp around {1} disappeared!", @battlers[side].pbTeam(true)))
|
|
# Aurora Veil
|
|
pbEORCountDownSideEffect(side, PBEffects::AuroraVeil,
|
|
_INTL("{1}'s Aurora Veil wore off!", @battlers[side].pbTeam))
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round end effects that apply to the whole field
|
|
#=============================================================================
|
|
def pbEORCountDownFieldEffect(effect, msg)
|
|
return if @field.effects[effect] <= 0
|
|
@field.effects[effect] -= 1
|
|
return if @field.effects[effect] > 0
|
|
pbDisplay(msg)
|
|
if effect == PBEffects::MagicRoom
|
|
pbPriority(true).each { |battler| battler.pbItemTerrainStatBoostCheck }
|
|
end
|
|
end
|
|
|
|
def pbEOREndFieldEffects(priority)
|
|
# Trick Room
|
|
pbEORCountDownFieldEffect(PBEffects::TrickRoom,
|
|
_INTL("The twisted dimensions returned to normal!"))
|
|
# Gravity
|
|
pbEORCountDownFieldEffect(PBEffects::Gravity,
|
|
_INTL("Gravity returned to normal!"))
|
|
# Water Sport
|
|
pbEORCountDownFieldEffect(PBEffects::WaterSportField,
|
|
_INTL("The effects of Water Sport have faded."))
|
|
# Mud Sport
|
|
pbEORCountDownFieldEffect(PBEffects::MudSportField,
|
|
_INTL("The effects of Mud Sport have faded."))
|
|
# Wonder Room
|
|
pbEORCountDownFieldEffect(PBEffects::WonderRoom,
|
|
_INTL("Wonder Room wore off, and Defense and Sp. Def stats returned to normal!"))
|
|
# Magic Room
|
|
pbEORCountDownFieldEffect(PBEffects::MagicRoom,
|
|
_INTL("Magic Room wore off, and held items' effects returned to normal!"))
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round end terrain check
|
|
#=============================================================================
|
|
def pbEOREndTerrain
|
|
# Count down terrain duration
|
|
@field.terrainDuration -= 1 if @field.terrainDuration > 0
|
|
# Terrain wears off
|
|
if @field.terrain != :None && @field.terrainDuration == 0
|
|
case @field.terrain
|
|
when :Electric
|
|
pbDisplay(_INTL("The electric current disappeared from the battlefield!"))
|
|
when :Grassy
|
|
pbDisplay(_INTL("The grass disappeared from the battlefield!"))
|
|
when :Misty
|
|
pbDisplay(_INTL("The mist disappeared from the battlefield!"))
|
|
when :Psychic
|
|
pbDisplay(_INTL("The weirdness disappeared from the battlefield!"))
|
|
end
|
|
@field.terrain = :None
|
|
allBattlers.each { |battler| battler.pbAbilityOnTerrainChange }
|
|
# Start up the default terrain
|
|
if @field.defaultTerrain != :None
|
|
pbStartTerrain(nil, @field.defaultTerrain, false)
|
|
allBattlers.each { |battler| battler.pbAbilityOnTerrainChange }
|
|
allBattlers.each { |battler| battler.pbItemTerrainStatBoostCheck }
|
|
end
|
|
return if @field.terrain == :None
|
|
end
|
|
# Terrain continues
|
|
terrain_data = GameData::BattleTerrain.try_get(@field.terrain)
|
|
pbCommonAnimation(terrain_data.animation) if terrain_data
|
|
case @field.terrain
|
|
when :Electric then pbDisplay(_INTL("An electric current is running across the battlefield."))
|
|
when :Grassy then pbDisplay(_INTL("Grass is covering the battlefield."))
|
|
when :Misty then pbDisplay(_INTL("Mist is swirling about the battlefield."))
|
|
when :Psychic then pbDisplay(_INTL("The battlefield is weird."))
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round end self-inflicted effects on battler
|
|
#=============================================================================
|
|
def pbEOREndBattlerSelfEffects(battler)
|
|
return if battler.fainted?
|
|
# Hyper Mode (Shadow Pokémon)
|
|
if battler.inHyperMode?
|
|
if pbRandom(100) < 10
|
|
battler.pokemon.hyper_mode = false
|
|
pbDisplay(_INTL("{1} came to its senses!", battler.pbThis))
|
|
else
|
|
pbDisplay(_INTL("{1} is in Hyper Mode!", battler.pbThis))
|
|
end
|
|
end
|
|
# Uproar
|
|
if battler.effects[PBEffects::Uproar] > 0
|
|
battler.effects[PBEffects::Uproar] -= 1
|
|
if battler.effects[PBEffects::Uproar] == 0
|
|
pbDisplay(_INTL("{1} calmed down.", battler.pbThis))
|
|
else
|
|
pbDisplay(_INTL("{1} is making an uproar!", battler.pbThis))
|
|
end
|
|
end
|
|
# Slow Start's end message
|
|
if battler.effects[PBEffects::SlowStart] > 0
|
|
battler.effects[PBEffects::SlowStart] -= 1
|
|
if battler.effects[PBEffects::SlowStart] == 0
|
|
pbDisplay(_INTL("{1} finally got its act together!", battler.pbThis))
|
|
end
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# End Of Round shift distant battlers to middle positions
|
|
#=============================================================================
|
|
def pbEORShiftDistantBattlers
|
|
# Move battlers around if none are near to each other
|
|
# NOTE: This code assumes each side has a maximum of 3 battlers on it, and
|
|
# is not generalised to larger side sizes.
|
|
if !singleBattle?
|
|
swaps = [] # Each element is an array of two battler indices to swap
|
|
2.times do |side|
|
|
next if pbSideSize(side) == 1 # Only battlers on sides of size 2+ need to move
|
|
# Check if any battler on this side is near any battler on the other side
|
|
anyNear = false
|
|
allSameSideBattlers(side).each do |battler|
|
|
anyNear = allOtherSideBattlers(battler).any? { |other| nearBattlers?(other.index, battler.index) }
|
|
break if anyNear
|
|
end
|
|
break if anyNear
|
|
# No battlers on this side are near any battlers on the other side; try
|
|
# to move them
|
|
# NOTE: If we get to here (assuming both sides are of size 3 or less),
|
|
# there is definitely only 1 able battler on this side, so we
|
|
# don't need to worry about multiple battlers trying to move into
|
|
# the same position. If you add support for a side of size 4+,
|
|
# this code will need revising to account for that, as well as to
|
|
# add more complex code to ensure battlers will end up near each
|
|
# other.
|
|
allSameSideBattlers(side).each do |battler|
|
|
# Get the position to move to
|
|
pos = -1
|
|
case pbSideSize(side)
|
|
when 2 then pos = [2, 3, 0, 1][battler.index] # The unoccupied position
|
|
when 3 then pos = (side == 0) ? 2 : 3 # The centre position
|
|
end
|
|
next if pos < 0
|
|
# Can't move if the same trainer doesn't control both positions
|
|
idxOwner = pbGetOwnerIndexFromBattlerIndex(battler.index)
|
|
next if pbGetOwnerIndexFromBattlerIndex(pos) != idxOwner
|
|
swaps.push([battler.index, pos])
|
|
end
|
|
end
|
|
# Move battlers around
|
|
swaps.each do |pair|
|
|
next if pbSideSize(pair[0]) == 2 && swaps.length > 1
|
|
next if !pbSwapBattlers(pair[0], pair[1])
|
|
case pbSideSize(pair[1])
|
|
when 2
|
|
pbDisplay(_INTL("{1} moved across!", @battlers[pair[1]].pbThis))
|
|
when 3
|
|
pbDisplay(_INTL("{1} moved to the center!", @battlers[pair[1]].pbThis))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# Main End Of Round phase method
|
|
#=============================================================================
|
|
def pbEndOfRoundPhase
|
|
PBDebug.log("")
|
|
PBDebug.log("[End of round #{@turnCount + 1}]")
|
|
@endOfRound = true
|
|
@scene.pbBeginEndOfRoundPhase
|
|
pbCalculatePriority # recalculate speeds
|
|
priority = pbPriority(true) # in order of fastest -> slowest speeds only
|
|
# Weather
|
|
pbEOREndWeather(priority)
|
|
# Future Sight/Doom Desire
|
|
@positions.each_with_index { |pos, idxPos| pbEORUseFutureSight(pos, idxPos) }
|
|
# Wish
|
|
pbEORWishHealing
|
|
# Sea of Fire damage (Fire Pledge + Grass Pledge combination)
|
|
pbEORSeaOfFireDamage(priority)
|
|
# Status-curing effects/abilities and HP-healing items
|
|
priority.each do |battler|
|
|
pbEORTerrainHealing(battler)
|
|
# Healer, Hydration, Shed Skin
|
|
if battler.abilityActive?
|
|
Battle::AbilityEffects.triggerEndOfRoundHealing(battler.ability, battler, self)
|
|
end
|
|
# Black Sludge, Leftovers
|
|
if battler.itemActive?
|
|
Battle::ItemEffects.triggerEndOfRoundHealing(battler.item, battler, self)
|
|
end
|
|
end
|
|
# Self-curing of status due to affection
|
|
if Settings::AFFECTION_EFFECTS && @internalBattle
|
|
priority.each do |battler|
|
|
next if battler.fainted? || battler.status == :NONE
|
|
next if !battler.pbOwnedByPlayer? || battler.affection_level < 4 || battler.mega?
|
|
next if pbRandom(100) < 80
|
|
old_status = battler.status
|
|
battler.pbCureStatus(false)
|
|
case old_status
|
|
when :SLEEP
|
|
pbDisplay(_INTL("{1} shook itself awake so you wouldn't worry!", battler.pbThis))
|
|
when :POISON
|
|
pbDisplay(_INTL("{1} managed to expel the poison so you wouldn't worry!", battler.pbThis))
|
|
when :BURN
|
|
pbDisplay(_INTL("{1} healed its burn with its sheer determination so you wouldn't worry!", battler.pbThis))
|
|
when :PARALYSIS
|
|
pbDisplay(_INTL("{1} gathered all its energy to break through its paralysis so you wouldn't worry!", battler.pbThis))
|
|
when :FROZEN
|
|
pbDisplay(_INTL("{1} melted the ice with its fiery determination so you wouldn't worry!", battler.pbThis))
|
|
end
|
|
end
|
|
end
|
|
# Healing from Aqua Ring, Ingrain, Leech Seed
|
|
pbEORHealingEffects(priority)
|
|
# Damage from Hyper Mode (Shadow Pokémon)
|
|
priority.each do |battler|
|
|
next if !battler.inHyperMode? || @choices[battler.index][0] != :UseMove
|
|
hpLoss = battler.totalhp / 24
|
|
@scene.pbDamageAnimation(battler)
|
|
battler.pbReduceHP(hpLoss, false)
|
|
pbDisplay(_INTL("The Hyper Mode attack hurts {1}!", battler.pbThis(true)))
|
|
battler.pbFaint if battler.fainted?
|
|
end
|
|
# Damage from poison/burn
|
|
pbEORStatusProblemDamage(priority)
|
|
# Damage from Nightmare and Curse
|
|
pbEOREffectDamage(priority)
|
|
# Trapping attacks (Bind/Clamp/Fire Spin/Magma Storm/Sand Tomb/Whirlpool/Wrap)
|
|
priority.each { |battler| pbEORTrappingDamage(battler) }
|
|
# Octolock
|
|
priority.each do |battler|
|
|
next if battler.fainted? || battler.effects[PBEffects::Octolock] < 0
|
|
pbCommonAnimation("Octolock", battler)
|
|
battler.pbLowerStatStage(:DEFENSE, 1, nil) if battler.pbCanLowerStatStage?(:DEFENSE)
|
|
battler.pbLowerStatStage(:SPECIAL_DEFENSE, 1, nil) if battler.pbCanLowerStatStage?(:SPECIAL_DEFENSE)
|
|
battler.pbItemOnStatDropped
|
|
end
|
|
# Effects that apply to a battler that wear off after a number of rounds
|
|
pbEOREndBattlerEffects(priority)
|
|
# Check for end of battle (i.e. because of Perish Song)
|
|
if @decision > 0
|
|
pbGainExp
|
|
return
|
|
end
|
|
# Effects that apply to a side that wear off after a number of rounds
|
|
2.times { |side| pbEOREndSideEffects(side, priority) }
|
|
# Effects that apply to the whole field that wear off after a number of rounds
|
|
pbEOREndFieldEffects(priority)
|
|
# End of terrains
|
|
pbEOREndTerrain
|
|
priority.each do |battler|
|
|
# Self-inflicted effects that wear off after a number of rounds
|
|
pbEOREndBattlerSelfEffects(battler)
|
|
# Bad Dreams, Moody, Speed Boost
|
|
if battler.abilityActive?
|
|
Battle::AbilityEffects.triggerEndOfRoundEffect(battler.ability, battler, self)
|
|
end
|
|
# Flame Orb, Sticky Barb, Toxic Orb
|
|
if battler.itemActive?
|
|
Battle::ItemEffects.triggerEndOfRoundEffect(battler.item, battler, self)
|
|
end
|
|
# Harvest, Pickup, Ball Fetch
|
|
if battler.abilityActive?
|
|
Battle::AbilityEffects.triggerEndOfRoundGainItem(battler.ability, battler, self)
|
|
end
|
|
end
|
|
pbGainExp
|
|
return if @decision > 0
|
|
# Form checks
|
|
priority.each { |battler| battler.pbCheckForm(true) }
|
|
# Switch Pokémon in if possible
|
|
pbEORSwitch
|
|
return if @decision > 0
|
|
# In battles with at least one side of size 3+, move battlers around if none
|
|
# are near to any foes
|
|
pbEORShiftDistantBattlers
|
|
# Try to make Trace work, check for end of primordial weather
|
|
priority.each { |battler| battler.pbContinualAbilityChecks }
|
|
# Reset/count down battler-specific effects (no messages)
|
|
allBattlers.each do |battler|
|
|
battler.effects[PBEffects::BanefulBunker] = false
|
|
battler.effects[PBEffects::Charge] -= 1 if battler.effects[PBEffects::Charge] > 0
|
|
battler.effects[PBEffects::Counter] = -1
|
|
battler.effects[PBEffects::CounterTarget] = -1
|
|
battler.effects[PBEffects::Electrify] = false
|
|
battler.effects[PBEffects::Endure] = false
|
|
battler.effects[PBEffects::FirstPledge] = nil
|
|
battler.effects[PBEffects::Flinch] = false
|
|
battler.effects[PBEffects::FocusPunch] = false
|
|
battler.effects[PBEffects::FollowMe] = 0
|
|
battler.effects[PBEffects::HelpingHand] = false
|
|
battler.effects[PBEffects::HyperBeam] -= 1 if battler.effects[PBEffects::HyperBeam] > 0
|
|
battler.effects[PBEffects::KingsShield] = false
|
|
battler.effects[PBEffects::LaserFocus] -= 1 if battler.effects[PBEffects::LaserFocus] > 0
|
|
if battler.effects[PBEffects::LockOn] > 0 # Also Mind Reader
|
|
battler.effects[PBEffects::LockOn] -= 1
|
|
battler.effects[PBEffects::LockOnPos] = -1 if battler.effects[PBEffects::LockOn] == 0
|
|
end
|
|
battler.effects[PBEffects::MagicBounce] = false
|
|
battler.effects[PBEffects::MagicCoat] = false
|
|
battler.effects[PBEffects::MirrorCoat] = -1
|
|
battler.effects[PBEffects::MirrorCoatTarget] = -1
|
|
battler.effects[PBEffects::Obstruct] = false
|
|
battler.effects[PBEffects::Powder] = false
|
|
battler.effects[PBEffects::Prankster] = false
|
|
battler.effects[PBEffects::PriorityAbility] = false
|
|
battler.effects[PBEffects::PriorityItem] = false
|
|
battler.effects[PBEffects::Protect] = false
|
|
battler.effects[PBEffects::RagePowder] = false
|
|
battler.effects[PBEffects::Roost] = false
|
|
battler.effects[PBEffects::Snatch] = 0
|
|
battler.effects[PBEffects::SpikyShield] = false
|
|
battler.effects[PBEffects::Spotlight] = 0
|
|
battler.effects[PBEffects::ThroatChop] -= 1 if battler.effects[PBEffects::ThroatChop] > 0
|
|
battler.lastHPLost = 0
|
|
battler.lastHPLostFromFoe = 0
|
|
battler.droppedBelowHalfHP = false
|
|
battler.statsDropped = false
|
|
battler.tookMoveDamageThisRound = false
|
|
battler.tookDamageThisRound = false
|
|
battler.tookPhysicalHit = false
|
|
battler.statsRaisedThisRound = false
|
|
battler.statsLoweredThisRound = false
|
|
battler.canRestoreIceFace = false
|
|
battler.lastRoundMoveFailed = battler.lastMoveFailed
|
|
battler.lastAttacker.clear
|
|
battler.lastFoeAttacker.clear
|
|
end
|
|
# Reset/count down side-specific effects (no messages)
|
|
2.times do |side|
|
|
@sides[side].effects[PBEffects::CraftyShield] = false
|
|
if !@sides[side].effects[PBEffects::EchoedVoiceUsed]
|
|
@sides[side].effects[PBEffects::EchoedVoiceCounter] = 0
|
|
end
|
|
@sides[side].effects[PBEffects::EchoedVoiceUsed] = false
|
|
@sides[side].effects[PBEffects::MatBlock] = false
|
|
@sides[side].effects[PBEffects::QuickGuard] = false
|
|
@sides[side].effects[PBEffects::Round] = false
|
|
@sides[side].effects[PBEffects::WideGuard] = false
|
|
end
|
|
# Reset/count down field-specific effects (no messages)
|
|
@field.effects[PBEffects::IonDeluge] = false
|
|
@field.effects[PBEffects::FairyLock] -= 1 if @field.effects[PBEffects::FairyLock] > 0
|
|
@field.effects[PBEffects::FusionBolt] = false
|
|
@field.effects[PBEffects::FusionFlare] = false
|
|
@endOfRound = false
|
|
end
|
|
end
|