mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-08 21:54:58 +00:00
351 lines
11 KiB
Ruby
351 lines
11 KiB
Ruby
# Battle scene (the visuals of the battle)
|
|
class PokeBattle_Scene
|
|
attr_accessor :abortable # For non-interactive battles, can quit immediately
|
|
attr_reader :viewport
|
|
attr_reader :sprites
|
|
|
|
BLANK = 0
|
|
MESSAGE_BOX = 1
|
|
COMMAND_BOX = 2
|
|
FIGHT_BOX = 3
|
|
TARGET_BOX = 4
|
|
|
|
MESSAGE_PAUSE_TIME = (Graphics.frame_rate*0.25).floor # 1 second
|
|
|
|
#=============================================================================
|
|
# Updating and refreshing
|
|
#=============================================================================
|
|
def pbUpdate(cw=nil)
|
|
pbGraphicsUpdate
|
|
pbInputUpdate
|
|
pbFrameUpdate(cw)
|
|
end
|
|
|
|
def pbGraphicsUpdate
|
|
# Update lineup animations
|
|
if @animations.length>0
|
|
shouldCompact = false
|
|
@animations.each_with_index do |a,i|
|
|
a.update
|
|
if a.animDone?
|
|
a.dispose
|
|
@animations[i] = nil
|
|
shouldCompact = true
|
|
end
|
|
end
|
|
@animations.compact! if shouldCompact
|
|
end
|
|
# Update other graphics
|
|
@sprites["battle_bg"].update if @sprites["battle_bg"].respond_to?("update")
|
|
Graphics.update
|
|
@frameCounter += 1
|
|
@frameCounter = @frameCounter%(Graphics.frame_rate*12/20)
|
|
end
|
|
|
|
def pbInputUpdate
|
|
Input.update
|
|
if Input.trigger?(Input::BACK) && @abortable && !@aborted
|
|
@aborted = true
|
|
@battle.pbAbort
|
|
end
|
|
end
|
|
|
|
def pbFrameUpdate(cw=nil)
|
|
cw.update if cw
|
|
@battle.battlers.each_with_index do |b,i|
|
|
next if !b
|
|
@sprites["dataBox_#{i}"].update(@frameCounter) if @sprites["dataBox_#{i}"]
|
|
@sprites["pokemon_#{i}"].update(@frameCounter) if @sprites["pokemon_#{i}"]
|
|
@sprites["shadow_#{i}"].update(@frameCounter) if @sprites["shadow_#{i}"]
|
|
end
|
|
end
|
|
|
|
def pbRefresh
|
|
@battle.battlers.each_with_index do |b,i|
|
|
next if !b
|
|
@sprites["dataBox_#{i}"].refresh if @sprites["dataBox_#{i}"]
|
|
end
|
|
end
|
|
|
|
def pbRefreshOne(idxBattler)
|
|
@sprites["dataBox_#{idxBattler}"].refresh if @sprites["dataBox_#{idxBattler}"]
|
|
end
|
|
|
|
#=============================================================================
|
|
# Party lineup
|
|
#=============================================================================
|
|
# Returns whether the party line-ups are currently coming on-screen
|
|
def inPartyAnimation?
|
|
return @animations.length>0
|
|
end
|
|
|
|
#=============================================================================
|
|
# Window displays
|
|
#=============================================================================
|
|
def pbShowWindow(windowType)
|
|
# NOTE: If you are not using fancy graphics for the command/fight menus, you
|
|
# will need to make "messageBox" also visible if the windowtype if
|
|
# COMMAND_BOX/FIGHT_BOX respectively.
|
|
@sprites["messageBox"].visible = (windowType==MESSAGE_BOX)
|
|
@sprites["messageWindow"].visible = (windowType==MESSAGE_BOX)
|
|
@sprites["commandWindow"].visible = (windowType==COMMAND_BOX)
|
|
@sprites["fightWindow"].visible = (windowType==FIGHT_BOX)
|
|
@sprites["targetWindow"].visible = (windowType==TARGET_BOX)
|
|
end
|
|
|
|
# This is for the end of brief messages, which have been lingering on-screen
|
|
# while other things happened. This is only called when another message wants
|
|
# to be shown, and makes the brief message linger for one more second first.
|
|
# Some animations skip this extra second by setting @briefMessage to false
|
|
# despite not having any other messages to show.
|
|
def pbWaitMessage
|
|
return if !@briefMessage
|
|
pbShowWindow(MESSAGE_BOX)
|
|
cw = @sprites["messageWindow"]
|
|
MESSAGE_PAUSE_TIME.times do
|
|
pbUpdate(cw)
|
|
end
|
|
cw.text = ""
|
|
cw.visible = false
|
|
@briefMessage = false
|
|
end
|
|
|
|
# NOTE: A regular message is displayed for 1 second after it fully appears (or
|
|
# less if Back/Use is pressed). Disappears automatically after that time.
|
|
def pbDisplayMessage(msg,brief=false)
|
|
pbWaitMessage
|
|
pbShowWindow(MESSAGE_BOX)
|
|
cw = @sprites["messageWindow"]
|
|
cw.setText(msg)
|
|
PBDebug.log(msg)
|
|
yielded = false
|
|
i = 0
|
|
loop do
|
|
pbUpdate(cw)
|
|
if !cw.busy?
|
|
if !yielded
|
|
yield if block_given? # For playing SE as soon as the message is all shown
|
|
yielded = true
|
|
end
|
|
if brief
|
|
# NOTE: A brief message lingers on-screen while other things happen. A
|
|
# regular message has to end before the game can continue.
|
|
@briefMessage = true
|
|
break
|
|
end
|
|
if i>=MESSAGE_PAUSE_TIME # Autoclose after 1 second
|
|
cw.text = ""
|
|
cw.visible = false
|
|
break
|
|
end
|
|
i += 1
|
|
end
|
|
if Input.trigger?(Input::BACK) || Input.trigger?(Input::USE) || @abortable
|
|
if cw.busy?
|
|
pbPlayDecisionSE if cw.pausing? && !@abortable
|
|
cw.skipAhead
|
|
elsif !@abortable
|
|
cw.text = ""
|
|
cw.visible = false
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
alias pbDisplay pbDisplayMessage
|
|
|
|
# NOTE: A paused message has the arrow in the bottom corner indicating there
|
|
# is another message immediately afterward. It is displayed for 3
|
|
# seconds after it fully appears (or less if B/C is pressed) and
|
|
# disappears automatically after that time, except at the end of battle.
|
|
def pbDisplayPausedMessage(msg)
|
|
pbWaitMessage
|
|
pbShowWindow(MESSAGE_BOX)
|
|
cw = @sprites["messageWindow"]
|
|
cw.text = _INTL("{1}\1",msg)
|
|
PBDebug.log(msg)
|
|
yielded = false
|
|
i = 0
|
|
loop do
|
|
pbUpdate(cw)
|
|
if !cw.busy?
|
|
if !yielded
|
|
yield if block_given? # For playing SE as soon as the message is all shown
|
|
yielded = true
|
|
end
|
|
if !@battleEnd
|
|
if i>=MESSAGE_PAUSE_TIME*3 # Autoclose after 3 seconds
|
|
cw.text = ""
|
|
cw.visible = false
|
|
break
|
|
end
|
|
i += 1
|
|
end
|
|
end
|
|
if Input.trigger?(Input::BACK) || Input.trigger?(Input::USE) || @abortable
|
|
if cw.busy?
|
|
pbPlayDecisionSE if cw.pausing? && !@abortable
|
|
cw.skipAhead
|
|
elsif !@abortable
|
|
cw.text = ""
|
|
pbPlayDecisionSE
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
def pbDisplayConfirmMessage(msg)
|
|
return pbShowCommands(msg,[_INTL("Yes"),_INTL("No")],1)==0
|
|
end
|
|
|
|
def pbShowCommands(msg,commands,defaultValue)
|
|
pbWaitMessage
|
|
pbShowWindow(MESSAGE_BOX)
|
|
dw = @sprites["messageWindow"]
|
|
dw.text = msg
|
|
cw = Window_CommandPokemon.new(commands)
|
|
cw.x = Graphics.width-cw.width
|
|
cw.y = Graphics.height-cw.height-dw.height
|
|
cw.z = dw.z+1
|
|
cw.index = 0
|
|
cw.viewport = @viewport
|
|
PBDebug.log(msg)
|
|
loop do
|
|
cw.visible = (!dw.busy?)
|
|
pbUpdate(cw)
|
|
dw.update
|
|
if Input.trigger?(Input::BACK) && defaultValue>=0
|
|
if dw.busy?
|
|
pbPlayDecisionSE if dw.pausing?
|
|
dw.resume
|
|
else
|
|
cw.dispose
|
|
dw.text = ""
|
|
return defaultValue
|
|
end
|
|
elsif Input.trigger?(Input::USE)
|
|
if dw.busy?
|
|
pbPlayDecisionSE if dw.pausing?
|
|
dw.resume
|
|
else
|
|
cw.dispose
|
|
dw.text = ""
|
|
return cw.index
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
#=============================================================================
|
|
# Sprites
|
|
#=============================================================================
|
|
def pbAddSprite(id,x,y,filename,viewport)
|
|
sprite = IconSprite.new(x,y,viewport)
|
|
if filename
|
|
sprite.setBitmap(filename) rescue nil
|
|
end
|
|
@sprites[id] = sprite
|
|
return sprite
|
|
end
|
|
|
|
def pbAddPlane(id,filename,viewport)
|
|
sprite = AnimatedPlane.new(viewport)
|
|
if filename
|
|
sprite.setBitmap(filename)
|
|
end
|
|
@sprites[id] = sprite
|
|
return sprite
|
|
end
|
|
|
|
def pbDisposeSprites
|
|
pbDisposeSpriteHash(@sprites)
|
|
end
|
|
|
|
# Used by Ally Switch.
|
|
def pbSwapBattlerSprites(idxA,idxB)
|
|
@sprites["pokemon_#{idxA}"], @sprites["pokemon_#{idxB}"] = @sprites["pokemon_#{idxB}"], @sprites["pokemon_#{idxA}"]
|
|
@sprites["shadow_#{idxA}"], @sprites["shadow_#{idxB}"] = @sprites["shadow_#{idxB}"], @sprites["shadow_#{idxA}"]
|
|
@lastCmd[idxA], @lastCmd[idxB] = @lastCmd[idxB], @lastCmd[idxA]
|
|
@lastMove[idxA], @lastMove[idxB] = @lastMove[idxB], @lastMove[idxA]
|
|
[idxA,idxB].each do |i|
|
|
@sprites["pokemon_#{i}"].index = i
|
|
@sprites["pokemon_#{i}"].pbSetPosition
|
|
@sprites["shadow_#{i}"].index = i
|
|
@sprites["shadow_#{i}"].pbSetPosition
|
|
@sprites["dataBox_#{i}"].battler = @battle.battlers[i]
|
|
end
|
|
pbRefresh
|
|
end
|
|
|
|
#=============================================================================
|
|
# Phases
|
|
#=============================================================================
|
|
def pbBeginCommandPhase
|
|
@sprites["messageWindow"].text = ""
|
|
end
|
|
|
|
def pbBeginAttackPhase
|
|
pbSelectBattler(-1)
|
|
pbShowWindow(MESSAGE_BOX)
|
|
end
|
|
|
|
def pbBeginEndOfRoundPhase
|
|
end
|
|
|
|
def pbEndBattle(_result)
|
|
@abortable = false
|
|
pbShowWindow(BLANK)
|
|
# Fade out all sprites
|
|
pbBGMFade(1.0)
|
|
pbFadeOutAndHide(@sprites)
|
|
pbDisposeSprites
|
|
end
|
|
|
|
#=============================================================================
|
|
#
|
|
#=============================================================================
|
|
def pbSelectBattler(idxBattler,selectMode=1)
|
|
numWindows = @battle.sideSizes.max*2
|
|
for i in 0...numWindows
|
|
sel = (idxBattler.is_a?(Array)) ? !idxBattler[i].nil? : i==idxBattler
|
|
selVal = (sel) ? selectMode : 0
|
|
@sprites["dataBox_#{i}"].selected = selVal if @sprites["dataBox_#{i}"]
|
|
@sprites["pokemon_#{i}"].selected = selVal if @sprites["pokemon_#{i}"]
|
|
end
|
|
end
|
|
|
|
def pbChangePokemon(idxBattler,pkmn)
|
|
idxBattler = idxBattler.index if idxBattler.respond_to?("index")
|
|
pkmnSprite = @sprites["pokemon_#{idxBattler}"]
|
|
shadowSprite = @sprites["shadow_#{idxBattler}"]
|
|
back = !@battle.opposes?(idxBattler)
|
|
shadowSprite.setPokemonBitmap(pkmn)
|
|
pkmnSprite.setPokemonBitmap(pkmn,back)
|
|
pkmnSprite.mirror=true if back
|
|
# Set visibility of battler's shadow
|
|
shadowSprite.visible = true#pkmn.species_data.shows_shadow? if shadowSprite #&& !back
|
|
end
|
|
|
|
def pbResetMoveIndex(idxBattler)
|
|
@lastMove[idxBattler] = 0
|
|
end
|
|
|
|
#=============================================================================
|
|
#
|
|
#=============================================================================
|
|
# This method is called when the player wins a wild Pokémon battle.
|
|
# This method can change the battle's music for example.
|
|
def pbWildBattleSuccess
|
|
@battleEnd = true
|
|
pbBGMPlay(pbGetWildVictoryME)
|
|
end
|
|
|
|
# This method is called when the player wins a trainer battle.
|
|
# This method can change the battle's music for example.
|
|
def pbTrainerBattleSuccess
|
|
@battleEnd = true
|
|
pbBGMPlay(pbGetTrainerVictoryME(@battle.opponent))
|
|
end
|
|
end
|