Files
infinitefusion-e18/Data/Scripts/012_Battle/003_Battle/002_PokeBattle_Battle.rb
2020-09-05 22:34:32 +01:00

782 lines
29 KiB
Ruby

# Results of battle:
# 0 - Undecided or aborted
# 1 - Player won
# 2 - Player lost
# 3 - Player or wild Pokémon ran from battle, or player forfeited the match
# 4 - Wild Pokémon was caught
# 5 - Draw
# Possible actions a battler can take in a round:
# :None
# :UseMove
# :SwitchOut
# :UseItem
# :Call
# :Run
# :Shift
# NOTE: If you want to have more than 3 Pokémon on a side at once, you will need
# to edit some code. Mainly this is to change/add coordinates for the
# sprites, describe the relationships between Pokémon and trainers, and to
# change messages. The methods that will need editing are as follows:
# class PokeBattle_Battle
# def setBattleMode
# def pbGetOwnerIndexFromBattlerIndex
# def pbGetOpposingIndicesInOrder
# def nearBattlers?
# def pbStartBattleSendOut
# def pbEORShiftDistantBattlers
# def pbCanShift?
# def pbEndOfRoundPhase
# class TargetMenuDisplay
# def initialize
# class PokemonDataBox
# def initializeDataBoxGraphic
# module PokeBattle_SceneConstants
# def self.pbBattlerPosition
# def self.pbTrainerPosition
# class PokemonTemp
# def recordBattleRule
# (There is no guarantee that this list is complete.)
class PokeBattle_Battle
attr_reader :scene # Scene object for this battle
attr_reader :peer
attr_reader :field # Effects common to the whole of a battle
attr_reader :sides # Effects common to each side of a battle
attr_reader :positions # Effects that apply to a battler position
attr_reader :battlers # Currently active Pokémon
attr_reader :sideSizes # Array of number of battlers per side
attr_accessor :backdrop # Filename fragment used for background graphics
attr_accessor :backdropBase # Filename fragment used for base graphics
attr_accessor :time # Time of day (0=day, 1=eve, 2=night)
attr_accessor :environment # Battle surroundings (for mechanics purposes)
attr_reader :turnCount
attr_accessor :decision # Decision: 0=undecided; 1=win; 2=loss; 3=escaped; 4=caught
attr_reader :player # Player trainer (or array of trainers)
attr_reader :opponent # Opponent trainer (or array of trainers)
attr_accessor :items # Items held by opponents
attr_accessor :endSpeeches
attr_accessor :endSpeechesWin
attr_accessor :party1starts # Array of start indexes for each player-side trainer's party
attr_accessor :party2starts # Array of start indexes for each opponent-side trainer's party
attr_accessor :internalBattle # Internal battle flag
attr_accessor :debug # Debug flag
attr_accessor :canRun # True if player can run from battle
attr_accessor :canLose # True if player won't black out if they lose
attr_accessor :switchStyle # Switch/Set "battle style" option
attr_accessor :showAnims # "Battle Effects" option
attr_accessor :controlPlayer # Whether player's Pokémon are AI controlled
attr_accessor :expGain # Whether Pokémon can gain Exp/EVs
attr_accessor :moneyGain # Whether the player can gain/lose money
attr_accessor :rules
attr_accessor :choices # Choices made by each Pokémon this round
attr_accessor :megaEvolution # Battle index of each trainer's Pokémon to Mega Evolve
attr_reader :initialItems
attr_reader :recycleItems
attr_reader :belch
attr_reader :battleBond
attr_reader :usedInBattle # Whether each Pokémon was used in battle (for Burmy)
attr_reader :successStates # Success states
attr_accessor :lastMoveUsed # Last move used
attr_accessor :lastMoveUser # Last move user
attr_reader :switching # True if during the switching phase of the round
attr_reader :futureSight # True if Future Sight is hitting
attr_reader :endOfRound # True during the end of round
attr_accessor :moldBreaker # True if Mold Breaker applies
attr_reader :struggle # The Struggle move
include PokeBattle_BattleCommon
def pbRandom(x); return rand(x); end
#=============================================================================
# Creating the battle class
#=============================================================================
def initialize(scene,p1,p2,player,opponent)
if p1.length==0
raise ArgumentError.new(_INTL("Party 1 has no Pokémon."))
elsif p2.length==0
raise ArgumentError.new(_INTL("Party 2 has no Pokémon."))
end
@scene = scene
@peer = PokeBattle_BattlePeer.create
@battleAI = PokeBattle_AI.new(self)
@field = PokeBattle_ActiveField.new # Whole field (gravity/rooms)
@sides = [PokeBattle_ActiveSide.new, # Player's side
PokeBattle_ActiveSide.new] # Foe's side
@positions = [] # Battler positions
@battlers = []
@sideSizes = [1,1] # Single battle, 1v1
@backdrop = ""
@backdropBase = nil
@time = 0
@environment = PBEnvironment::None # e.g. Tall grass, cave, still water
@turnCount = 0
@decision = 0
@caughtPokemon = []
player = [player] if !player.nil? && !player.is_a?(Array)
opponent = [opponent] if !opponent.nil? && !opponent.is_a?(Array)
@player = player # Array of PokeBattle_Trainer objects, or nil
@opponent = opponent # Array of PokeBattle_Trainer objects, or nil
@items = nil
@endSpeeches = []
@endSpeechesWin = []
@party1 = p1
@party2 = p2
@party1order = Array.new(@party1.length) { |i| i }
@party2order = Array.new(@party2.length) { |i| i }
@party1starts = [0]
@party2starts = [0]
@internalBattle = true
@debug = false
@canRun = true
@canLose = false
@switchStyle = true
@showAnims = true
@controlPlayer = false
@expGain = true
@moneyGain = true
@rules = {}
@priority = []
@priorityTrickRoom = false
@choices = []
@megaEvolution = [
[-1] * (@player ? @player.length : 1),
[-1] * (@opponent ? @opponent.length : 1)
]
@initialItems = [
Array.new(@party1.length) { |i| (@party1[i]) ? @party1[i].item : 0 },
Array.new(@party2.length) { |i| (@party2[i]) ? @party2[i].item : 0 }
]
@recycleItems = [Array.new(@party1.length,0),Array.new(@party2.length,0)]
@belch = [Array.new(@party1.length,false),Array.new(@party2.length,false)]
@battleBond = [Array.new(@party1.length,false),Array.new(@party2.length,false)]
@usedInBattle = [Array.new(@party1.length,false),Array.new(@party2.length,false)]
@successStates = []
@lastMoveUsed = -1
@lastMoveUser = -1
@switching = false
@futureSight = false
@endOfRound = false
@moldBreaker = false
@runCommand = 0
@nextPickupUse = 0
if hasConst?(PBMoves,:STRUGGLE)
@struggle = PokeBattle_Move.pbFromPBMove(self,PBMove.new(getConst(PBMoves,:STRUGGLE)))
else
@struggle = PokeBattle_Struggle.new(self,nil)
end
end
#=============================================================================
# Information about the type and size of the battle
#=============================================================================
def wildBattle?; return @opponent.nil?; end
def trainerBattle?; return !@opponent.nil?; end
# Sets the number of battler slots on each side of the field independently.
# For "1v2" names, the first number is for the player's side and the second
# number is for the opposing side.
def setBattleMode(mode)
@sideSizes =
case mode
when "triple", "3v3"; [3,3]
when "3v2"; [3,2]
when "3v1"; [3,1]
when "2v3"; [2,3]
when "double", "2v2"; [2,2]
when "2v1"; [2,1]
when "1v3"; [1,3]
when "1v2"; [1,2]
else; [1,1] # Single, 1v1 (default)
end
end
def singleBattle?
return pbSideSize(0)==1 && pbSideSize(1)==1
end
def pbSideSize(index)
return @sideSizes[index%2]
end
def maxBattlerIndex
return (pbSideSize(0)>pbSideSize(1)) ? (pbSideSize(0)-1)*2 : pbSideSize(1)*2-1
end
#=============================================================================
# Trainers and owner-related methods
#=============================================================================
def pbPlayer; return @player[0]; end
# Given a battler index, returns the index within @player/@opponent of the
# trainer that controls that battler index.
# NOTE: You shouldn't ever have more trainers on a side than there are battler
# positions on that side. This method doesn't account for if you do.
def pbGetOwnerIndexFromBattlerIndex(idxBattler)
trainer = (opposes?(idxBattler)) ? @opponent : @player
return 0 if !trainer
case trainer.length
when 2
n = pbSideSize(idxBattler%2)
return [0,0,1][idxBattler/2] if n==3
return idxBattler/2 # Same as [0,1][idxBattler/2], i.e. 2 battler slots
when 3; return idxBattler/2
end
return 0
end
def pbGetOwnerFromBattlerIndex(idxBattler)
idxTrainer = pbGetOwnerIndexFromBattlerIndex(idxBattler)
return (opposes?(idxBattler)) ? @opponent[idxTrainer] : @player[idxTrainer]
end
def pbGetOwnerIndexFromPartyIndex(idxBattler,idxParty)
ret = -1
pbPartyStarts(idxBattler).each_with_index do |start,i|
break if start>idxParty
ret = i
end
return ret
end
# Only used for the purpose of an error message when one trainer tries to
# switch another trainer's Pokémon.
def pbGetOwnerFromPartyIndex(idxBattler,idxParty)
idxTrainer = pbGetOwnerIndexFromPartyIndex(idxBattler,idxParty)
return (opposes?(idxBattler)) ? @opponent[idxTrainer] : @player[idxTrainer]
end
def pbGetOwnerName(idxBattler)
idxTrainer = pbGetOwnerIndexFromBattlerIndex(idxBattler)
return @opponent[idxTrainer].fullname if opposes?(idxBattler) # Opponent
return @player[idxTrainer].fullname if idxTrainer>0 # Ally trainer
return @player[idxTrainer].name # Player
end
def pbGetOwnerItems(idxBattler)
return [] if !@items || !opposes?(idxBattler)
return @items[pbGetOwnerIndexFromBattlerIndex(idxBattler)]
end
# Returns whether the battler in position idxBattler is owned by the same
# trainer that owns the Pokémon in party slot idxParty. This assumes that
# both the battler position and the party slot are from the same side.
def pbIsOwner?(idxBattler,idxParty)
idxTrainer1 = pbGetOwnerIndexFromBattlerIndex(idxBattler)
idxTrainer2 = pbGetOwnerIndexFromPartyIndex(idxBattler,idxParty)
return idxTrainer1==idxTrainer2
end
def pbOwnedByPlayer?(idxBattler)
return false if opposes?(idxBattler)
return pbGetOwnerIndexFromBattlerIndex(idxBattler)==0
end
# Returns the number of Pokémon positions controlled by the given trainerIndex
# on the given side of battle.
def pbNumPositions(side,idxTrainer)
ret = 0
for i in 0...pbSideSize(side)
t = pbGetOwnerIndexFromBattlerIndex(i*2+side)
next if t!=idxTrainer
ret += 1
end
return ret
end
#=============================================================================
# Get party information (counts all teams on the same side)
#=============================================================================
def pbParty(idxBattler)
return (opposes?(idxBattler)) ? @party2 : @party1
end
def pbOpposingParty(idxBattler)
return (opposes?(idxBattler)) ? @party1 : @party2
end
def pbPartyOrder(idxBattler)
return (opposes?(idxBattler)) ? @party2order : @party1order
end
def pbPartyStarts(idxBattler)
return (opposes?(idxBattler)) ? @party2starts : @party1starts
end
# Returns the player's team in its display order. Used when showing the party
# screen.
def pbPlayerDisplayParty(idxBattler=0)
partyOrders = pbPartyOrder(idxBattler)
idxStart, idxEnd = pbTeamIndexRangeFromBattlerIndex(idxBattler)
ret = []
eachInTeamFromBattlerIndex(idxBattler) { |pkmn,i| ret[partyOrders[i]-idxStart] = pkmn }
return ret
end
def pbAbleCount(idxBattler=0)
party = pbParty(idxBattler)
count = 0
party.each { |pkmn| count += 1 if pkmn && pkmn.able? }
return count
end
def pbAbleNonActiveCount(idxBattler=0)
party = pbParty(idxBattler)
inBattleIndices = []
eachSameSideBattler(idxBattler) { |b| inBattleIndices.push(b.pokemonIndex) }
count = 0
party.each_with_index do |pkmn,idxParty|
next if !pkmn || !pkmn.able?
next if inBattleIndices.include?(idxParty)
count += 1
end
return count
end
def pbAllFainted?(idxBattler=0)
return pbAbleCount(idxBattler)==0
end
# For the given side of the field (0=player's, 1=opponent's), returns an array
# containing the number of able Pokémon in each team.
def pbAbleTeamCounts(side)
party = pbParty(side)
partyStarts = pbPartyStarts(side)
ret = []
idxTeam = -1
nextStart = 0
party.each_with_index do |pkmn,i|
if i>=nextStart
idxTeam += 1
nextStart = (idxTeam<partyStarts.length-1) ? partyStarts[idxTeam+1] : party.length
end
next if !pkmn || !pkmn.able?
ret[idxTeam] = 0 if !ret[idxTeam]
ret[idxTeam] += 1
end
return ret
end
#=============================================================================
# Get team information (a team is only the Pokémon owned by a particular
# trainer)
#=============================================================================
def pbTeamIndexRangeFromBattlerIndex(idxBattler)
partyStarts = pbPartyStarts(idxBattler)
idxTrainer = pbGetOwnerIndexFromBattlerIndex(idxBattler)
idxPartyStart = partyStarts[idxTrainer]
idxPartyEnd = (idxTrainer<partyStarts.length-1) ? partyStarts[idxTrainer+1] : pbParty(idxBattler).length
return idxPartyStart, idxPartyEnd
end
def pbTeamLengthFromBattlerIndex(idxBattler)
idxPartyStart, idxPartyEnd = pbTeamIndexRangeFromBattlerIndex(idxBattler)
return idxPartyEnd-idxPartyStart
end
def eachInTeamFromBattlerIndex(idxBattler)
party = pbParty(idxBattler)
idxPartyStart, idxPartyEnd = pbTeamIndexRangeFromBattlerIndex(idxBattler)
party.each_with_index { |pkmn,i| yield pkmn,i if pkmn && i>=idxPartyStart && i<idxPartyEnd }
end
def eachInTeam(side,idxTrainer)
party = pbParty(side)
partyStarts = pbPartyStarts(side)
idxPartyStart = partyStarts[idxTrainer]
idxPartyEnd = (idxTrainer<partyStarts.length-1) ? partyStarts[idxTrainer+1] : party.length
party.each_with_index { |pkmn,i| yield pkmn,i if pkmn && i>=idxPartyStart && i<idxPartyEnd }
end
# Used for Illusion.
# NOTE: This cares about the temporary rearranged order of the team. That is,
# if you do some switching, the last Pokémon in the team could change
# and the Illusion could be a different Pokémon.
def pbLastInTeam(idxBattler)
party = pbParty(idxBattler)
partyOrders = pbPartyOrder(idxBattler)
idxPartyStart, idxPartyEnd = pbTeamIndexRangeFromBattlerIndex(idxBattler)
ret = -1
party.each_with_index do |pkmn,i|
next if i<idxPartyStart || i>=idxPartyEnd # Check the team only
next if !pkmn || !pkmn.able? # Can't copy a non-fainted Pokémon or egg
ret = i if partyOrders[i]>partyOrders[ret]
end
return ret
end
# Used to calculate money gained/lost after winning/losing a battle.
def pbMaxLevelInTeam(side,idxTrainer)
ret = 1
eachInTeam(side,idxTrainer) do |pkmn,i|
ret = pkmn.level if pkmn.level>ret
end
return ret
end
#=============================================================================
# Iterate through battlers
#=============================================================================
def eachBattler
@battlers.each { |b| yield b if b && !b.fainted? }
end
def eachSameSideBattler(idxBattler=0)
idxBattler = idxBattler.index if idxBattler.respond_to?("index")
@battlers.each { |b| yield b if b && !b.fainted? && !b.opposes?(idxBattler) }
end
def eachOtherSideBattler(idxBattler=0)
idxBattler = idxBattler.index if idxBattler.respond_to?("index")
@battlers.each { |b| yield b if b && !b.fainted? && b.opposes?(idxBattler) }
end
def pbSideBattlerCount(idxBattler=0)
ret = 0
eachSameSideBattler(idxBattler) { |b| ret += 1 }
return ret
end
def pbOpposingBattlerCount(idxBattler=0)
ret = 0
eachOtherSideBattler(idxBattler) { |b| ret += 1 }
return ret
end
# This method only counts the player's Pokémon, not a partner trainer's.
def pbPlayerBattlerCount
ret = 0
eachSameSideBattler { |b| ret += 1 if b.pbOwnedByPlayer? }
return ret
end
def pbCheckGlobalAbility(abil)
eachBattler { |b| return b if b.hasActiveAbility?(abil) }
return nil
end
def pbCheckOpposingAbility(abil,idxBattler=0,nearOnly=false)
eachOtherSideBattler(idxBattler) do |b|
next if nearOnly && !b.near?(idxBattler)
return b if b.hasActiveAbility?(abil)
end
return nil
end
# Given a battler index, and using battle side sizes, returns an array of
# battler indices from the opposing side that are in order of most "opposite".
# Used when choosing a target and pressing up/down to move the cursor to the
# opposite side, and also when deciding which target to select first for some
# moves.
def pbGetOpposingIndicesInOrder(idxBattler)
case pbSideSize(0)
when 1
case pbSideSize(1)
when 1 # 1v1 single
return [0] if opposes?(idxBattler)
return [1]
when 2 # 1v2
return [0] if opposes?(idxBattler)
return [3,1]
when 3 # 1v3
return [0] if opposes?(idxBattler)
return [3,5,1]
end
when 2
case pbSideSize(1)
when 1 # 2v1
return [0,2] if opposes?(idxBattler)
return [1]
when 2 # 2v2 double
return [[3,1],[2,0],[1,3],[0,2]][idxBattler]
when 3 # 2v3
return [[5,3,1],[2,0],[3,1,5]][idxBattler] if idxBattler<3
return [0,2]
end
when 3
case pbSideSize(1)
when 1 # 3v1
return [2,0,4] if opposes?(idxBattler)
return [1]
when 2 # 3v2
return [[3,1],[2,4,0],[3,1],[2,0,4],[1,3]][idxBattler]
when 3 # 3v3 triple
return [[5,3,1],[4,2,0],[3,5,1],[2,0,4],[1,3,5],[0,2,4]][idxBattler]
end
end
return [idxBattler]
end
#=============================================================================
# Comparing the positions of two battlers
#=============================================================================
def opposes?(idxBattler1,idxBattler2=0)
idxBattler1 = idxBattler1.index if idxBattler1.respond_to?("index")
idxBattler2 = idxBattler2.index if idxBattler2.respond_to?("index")
return (idxBattler1&1)!=(idxBattler2&1)
end
def nearBattlers?(idxBattler1,idxBattler2)
return false if idxBattler1==idxBattler2
return true if pbSideSize(0)<=2 && pbSideSize(1)<=2
# Get all pairs of battler positions that are not close to each other
pairsArray = [[0,4],[1,5]] # Covers 3v1 and 1v3
case pbSideSize(0)
when 3
case pbSideSize(1)
when 3 # 3v3 (triple)
pairsArray.push([0,1])
pairsArray.push([4,5])
when 2 # 3v2
pairsArray.push([0,1])
pairsArray.push([3,4])
end
when 2 # 2v3
pairsArray.push([0,1])
pairsArray.push([2,5])
end
# See if any pair matches the two battlers being assessed
pairsArray.each do |pair|
return false if pair.include?(idxBattler1) && pair.include?(idxBattler2)
end
return true
end
#=============================================================================
# Altering a party or rearranging battlers
#=============================================================================
def pbRemoveFromParty(idxBattler,idxParty)
party = pbParty(idxBattler)
# Erase the Pokémon from the party
party[idxParty] = nil
# Rearrange the display order of the team to place the erased Pokémon last
# in it (to avoid gaps)
partyOrders = pbPartyOrder(idxBattler)
partyStarts = pbPartyStarts(idxBattler)
idxTrainer = pbGetOwnerIndexFromPartyIndex(idxBattler,idxParty)
idxPartyStart = partyStarts[idxTrainer]
idxPartyEnd = (idxTrainer<partyStarts.length-1) ? partyStarts[idxTrainer+1] : party.length
origPartyPos = partyOrders[idxParty] # Position of erased Pokémon initially
partyOrders[idxParty] = idxPartyEnd # Put erased Pokémon last in the team
party.each_with_index do |pkmn,i|
next if i<idxPartyStart || i>=idxPartyEnd # Only check the team
next if partyOrders[i]<origPartyPos # Appeared before erased Pokémon
partyOrders[i] -= 1 # Appeared after erased Pokémon; bump it up by 1
end
end
def pbSwapBattlers(idxA,idxB)
return false if !@battlers[idxA] || !@battlers[idxB]
# Can't swap if battlers aren't owned by the same trainer
return false if opposes?(idxA,idxB)
return false if pbGetOwnerIndexFromBattlerIndex(idxA)!=pbGetOwnerIndexFromBattlerIndex(idxB)
@battlers[idxA], @battlers[idxB] = @battlers[idxB], @battlers[idxA]
@battlers[idxA].index, @battlers[idxB].index = @battlers[idxB].index, @battlers[idxA].index
@choices[idxA], @choices[idxB] = @choices[idxB], @choices[idxA]
@scene.pbSwapBattlerSprites(idxA,idxB)
# Swap the target of any battlers' effects that point at either of the
# swapped battlers, to ensure they still point at the correct target
# NOTE: LeechSeed is not swapped, because drained HP goes to whichever
# Pokémon is in the position that Leech Seed was used from.
# NOTE: PerishSongUser doesn't need to change, as it's only used to
# determine which side the Perish Song user was on, and a battler
# can't change sides.
effectsToSwap = [PBEffects::Attract,
PBEffects::BideTarget,
PBEffects::CounterTarget,
PBEffects::LockOnPos,
PBEffects::MeanLook,
PBEffects::MirrorCoatTarget,
PBEffects::SkyDrop,
PBEffects::TrappingUser]
eachBattler do |b|
for i in effectsToSwap
next if b.effects[i]!=idxA && b.effects[i]!=idxB
b.effects[i] = (b.effects[i]==idxA) ? idxB : idxA
end
end
return true
end
#=============================================================================
#
#=============================================================================
# Returns the battler representing the Pokémon at index idxParty in its party,
# on the same side as a battler with battler index of idxBattlerOther.
def pbFindBattler(idxParty,idxBattlerOther=0)
eachSameSideBattler(idxBattlerOther) { |b| return b if b.pokemonIndex==idxParty }
return nil
end
# Only used for Wish, as the Wishing Pokémon will no longer be in battle.
def pbThisEx(idxBattler,idxParty)
party = pbParty(idxBattler)
if opposes?(idxBattler)
return _INTL("The opposing {1}",party[idxParty].name) if trainerBattle?
return _INTL("The wild {1}",party[idxParty].name)
end
return _INTL("The ally {1}",party[idxParty].name) if !pbOwnedByPlayer?(idxBattler)
return party[idxParty].name
end
def pbSetSeen(battler)
return if !battler || !@internalBattle
pbPlayer.seen[battler.displaySpecies] = true
pbSeenForm(battler.displaySpecies,battler.displayGender,battler.displayForm)
end
def nextPickupUse
@nextPickupUse += 1
return @nextPickupUse
end
#=============================================================================
# Weather and terrain
#=============================================================================
def defaultWeather=(value)
@field.defaultWeather = value
@field.weather = value
@field.weatherDuration = -1
end
# Returns the effective weather (note that weather effects can be negated)
def pbWeather
eachBattler { |b| return PBWeather::None if b.hasActiveAbility?([:CLOUDNINE,:AIRLOCK]) }
return @field.weather
end
# Used for causing weather by a move or by an ability.
def pbStartWeather(user,newWeather,fixedDuration=false,showAnim=true)
return if @field.weather==newWeather
@field.weather = newWeather
duration = (fixedDuration) ? 5 : -1
if duration>0 && user && user.itemActive?
duration = BattleHandlers.triggerWeatherExtenderItem(user.item,
@field.weather,duration,user,self)
end
@field.weatherDuration = duration
pbCommonAnimation(PBWeather.animationName(@field.weather)) if showAnim
pbHideAbilitySplash(user) if user
case @field.weather
when PBWeather::Sun; pbDisplay(_INTL("The sunlight turned harsh!"))
when PBWeather::Rain; pbDisplay(_INTL("It started to rain!"))
when PBWeather::Sandstorm; pbDisplay(_INTL("A sandstorm brewed!"))
when PBWeather::Hail; pbDisplay(_INTL("It started to hail!"))
when PBWeather::HarshSun; pbDisplay(_INTL("The sunlight turned extremely harsh!"))
when PBWeather::HeavyRain; pbDisplay(_INTL("A heavy rain began to fall!"))
when PBWeather::StrongWinds; pbDisplay(_INTL("Mysterious strong winds are protecting Flying-type Pokémon!"))
when PBWeather::ShadowSky; pbDisplay(_INTL("A shadow sky appeared!"))
end
# Check for end of primordial weather, and weather-triggered form changes
eachBattler { |b| b.pbCheckFormOnWeatherChange }
pbEndPrimordialWeather
end
def pbEndPrimordialWeather
oldWeather = @field.weather
# End Primordial Sea, Desolate Land, Delta Stream
case @field.weather
when PBWeather::HarshSun
if !pbCheckGlobalAbility(:DESOLATELAND)
@field.weather = PBWeather::None
pbDisplay("The harsh sunlight faded!")
end
when PBWeather::HeavyRain
if !pbCheckGlobalAbility(:PRIMORDIALSEA)
@field.weather = PBWeather::None
pbDisplay("The heavy rain has lifted!")
end
when PBWeather::StrongWinds
if !pbCheckGlobalAbility(:DELTASTREAM)
@field.weather = PBWeather::None
pbDisplay("The mysterious air current has dissipated!")
end
end
# Check for form changes caused by the weather changing
if @field.weather!=oldWeather
eachBattler { |b| b.pbCheckFormOnWeatherChange }
end
end
def defaultTerrain=(value)
@field.defaultTerrain = value
@field.terrain = value
@field.terrainDuration = -1
end
def pbStartTerrain(user,newTerrain,fixedDuration=true)
return if @field.terrain==newTerrain
@field.terrain = newTerrain
duration = (fixedDuration) ? 5 : -1
if duration>0 && user && user.itemActive?
duration = BattleHandlers.triggerTerrainExtenderItem(user.item,
newTerrain,duration,user,self)
end
@field.terrainDuration = duration
pbCommonAnimation(PBBattleTerrains.animationName(@field.terrain))
pbHideAbilitySplash(user) if user
case @field.terrain
when PBBattleTerrains::Electric
pbDisplay(_INTL("An electric current runs across the battlefield!"))
when PBBattleTerrains::Grassy
pbDisplay(_INTL("Grass grew to cover the battlefield!"))
when PBBattleTerrains::Misty
pbDisplay(_INTL("Mist swirled about the battlefield!"))
when PBBattleTerrains::Psychic
pbDisplay(_INTL("The battlefield got weird!"))
end
# Check for terrain seeds that boost stats in a terrain
eachBattler { |b| b.pbItemTerrainStatBoostCheck }
end
#=============================================================================
# Messages and animations
#=============================================================================
def pbDisplay(msg,&block)
@scene.pbDisplayMessage(msg,&block)
end
def pbDisplayBrief(msg)
@scene.pbDisplayMessage(msg,true)
end
def pbDisplayPaused(msg,&block)
@scene.pbDisplayPausedMessage(msg,&block)
end
def pbDisplayConfirm(msg)
return @scene.pbDisplayConfirmMessage(msg)
end
def pbShowCommands(msg,commands,canCancel=true)
@scene.pbShowCommands(msg,commands,canCancel)
end
def pbAnimation(move,user,targets,hitNum=0)
@scene.pbAnimation(move,user,targets,hitNum) if @showAnims
end
def pbCommonAnimation(name,user=nil,targets=nil,hitNum=0)
@scene.pbCommonAnimation(name,user,targets,hitNum) if @showAnims
end
def pbShowAbilitySplash(battler,delay=false,logTrigger=true)
PBDebug.log("[Ability triggered] #{battler.pbThis}'s #{battler.abilityName}") if logTrigger
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@scene.pbShowAbilitySplash(battler)
if delay
Graphics.frame_rate.times { @scene.pbUpdate } # 1 second
end
end
def pbHideAbilitySplash(battler)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@scene.pbHideAbilitySplash(battler)
end
def pbReplaceAbilitySplash(battler)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@scene.pbReplaceAbilitySplash(battler)
end
end