Update 6.8

This commit is contained in:
chardub
2026-07-10 15:42:06 -04:00
parent 5b85e72cb2
commit 6a6f126a18
7871 changed files with 493194 additions and 224826 deletions
@@ -42,6 +42,7 @@ class PokeBattle_Battler
attr_accessor :tookPhysicalHit
attr_accessor :damageState
attr_accessor :initialHP # Set at the start of each move's usage
attr_accessor :original_ability
#=============================================================================
# Complex accessors
@@ -771,6 +772,21 @@ class PokeBattle_Battler
@battle.pbDisplay(_INTL("{1} changed to the Meteor Form!", pbThis))
end
end
if @pokemon.species == :TRIPLE_CELESTIAL_M
if new_hp <= (@totalhp / 2)
changeBattlerForm(:TRIPLE_CELESTIAL_M, :TRIPLE_CELESTIAL_C,nil, :SHELLSMASH)
@battle.pbDisplay(_INTL("{1} changed to the Core Form!", pbThis))
end
end
if @pokemon.species == :TRIPLE_CELESTIAL_C
if new_hp > (@totalhp / 2)
changeBattlerForm(:TRIPLE_CELESTIAL_C, :TRIPLE_CELESTIAL_M,nil, :SHELLSMASH)
@battle.pbDisplay(_INTL("{1} changed to the Meteor Form!", pbThis))
end
end
end
end
@@ -798,4 +814,6 @@ class PokeBattle_Battler
@battle.scene.pbAnimation(moveID, self,self)
@battle.scene.pbRefreshOne(@index)
end
end
@@ -22,7 +22,6 @@ class PokeBattle_Battler
@hp = @totalhp = 0
@type1 = @type2 = nil
@ability_id = nil
@ability2_id = nil
@item_id = nil
@gender = 0
@attack = @defense = @spatk = @spdef = @speed = 0
@@ -82,7 +81,7 @@ class PokeBattle_Battler
@type1 = pkmn.type1
@type2 = pkmn.type2
@ability_id = pkmn.ability_id
@ability2_id = pkmn.ability2_id
@original_ability = @ability_id
@item_id = pkmn.item_id
@gender = pkmn.gender
@attack = pkmn.attack
@@ -54,6 +54,7 @@ class PokeBattle_Battler
return if @fainted # Has already fainted properly
@battle.pbDisplayBrief(_INTL("{1} fainted!",pbThis)) if showMessage
updateSpirits()
$Trainer.stats&.incr_nb_pokemon_defeated if opposes?
PBDebug.log("[Pokémon fainted] #{pbThis} (#{@index})") if !showMessage
@battle.scene.pbFaintBattler(self)
pbInitEffects(false)
@@ -283,7 +284,6 @@ class PokeBattle_Battler
@effects[PBEffects::TransformSpecies] = target.species
pbChangeTypes(target)
self.ability = target.ability
self.ability2 = target.ability2 if target.ability2
@attack = target.attack
@defense = target.defense
@spatk = target.spatk
@@ -60,9 +60,11 @@ class PokeBattle_Battler
if abilityActive?
BattleHandlers.triggerAbilityOnStatGain(self.ability,self,stat,user)
end
checkStatRaiseBattleChallenge(stat,increment) if user.pbOwnedByPlayer?
return true
end
def pbRaiseStatStageByCause(stat,increment,user,cause,showAnim=true,ignoreContrary=false)
# Contrary
if hasActiveAbility?(:CONTRARY) && !ignoreContrary && !@battle.moldBreaker
@@ -120,6 +120,7 @@ class PokeBattle_Battler
@effects[PBEffects::GemConsumed] = nil
@effects[PBEffects::ShellTrap] = false
@battle.eachBattler { |b| b.pbContinualAbilityChecks } # Trace, end primordial weathers
checkChallengesAfterTurn
end
def pbConfusionDamage(msg)
@@ -723,6 +724,10 @@ class PokeBattle_Battler
targets.each do |b|
next if b.damageState.unaffected
move.pbInflictHPDamage(b)
unless onPlayerSide?
@battle.damage_received += b.damageState.hpLost
end
end
# Animate the hit flashing and HP bar changes
move.pbAnimateHitAndHPLost(user, targets)
@@ -806,4 +811,8 @@ class PokeBattle_Battler
user.pbFaint if user.fainted?
return true
end
def onPlayerSide?
return (@index % 2) == 0
end
end
@@ -222,7 +222,11 @@ class PokeBattle_Battler
end
end
end
# Obedience check
if @battle.caughtOffGuard && @battle.turnCount == 0 && !@battle.pbOwnedByPlayer?(@index)
@battle.pbDisplay(_INTL("{1} was caught off guard and couldn't move!",pbThis))
return false
end
# Obedience check
return false if !pbObedienceCheck?(choice)
# Truant
if hasActiveAbility?(:TRUANT)
@@ -98,7 +98,6 @@ class PokeBattle_Battler
# User's ability
if user.abilityActive?
BattleHandlers.triggerUserAbilityEndOfMove(user.ability,user,targets,move,@battle)
BattleHandlers.triggerUserAbilityEndOfMove(user.ability2,user,targets,move,@battle) if user.ability2
end
# Greninja - Battle Bond
if !user.fainted? && !user.effects[PBEffects::Transform] &&
@@ -168,7 +167,6 @@ class PokeBattle_Battler
next if b.damageState.unaffected || switchedBattlers.include?(b.index)
next if !b.abilityActive?
BattleHandlers.triggerTargetAbilityAfterMoveUse(b.ability,b,user,move,switchedBattlers,@battle)
BattleHandlers.triggerTargetAbilityAfterMoveUse(b.ability2,b,user,move,switchedBattlers,@battle) if b.ability2
if !switchedBattlers.include?(b.index) && move.damagingMove?
if b.pbAbilitiesOnDamageTaken(b.damageState.initialHP) # Emergency Exit, Wimp Out
switchWimpOut.push(b.index)
@@ -251,12 +251,24 @@ class PokeBattle_Move
#=============================================================================
def pbEffectivenessMessage(user,target,numTargets=1)
return if target.damageState.disguise
if Effectiveness.super_effective?(target.damageState.typeMod)
if Effectiveness.extremely_effective?(target.damageState.typeMod)
if numTargets>1
@battle.pbDisplay(_INTL("It's extremely effective on {1}!",target.pbThis(true)))
else
@battle.pbDisplay(_INTL("It's extremely effective!"))
end
elsif Effectiveness.super_effective?(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 Effectiveness.mostly_ineffective?(target.damageState.typeMod)
if numTargets>1
@battle.pbDisplay(_INTL("It's mostly ineffective on {1}...",target.pbThis(true)))
else
@battle.pbDisplay(_INTL("It's mostly ineffective..."))
end
elsif Effectiveness.not_very_effective?(target.damageState.typeMod)
if numTargets>1
@battle.pbDisplay(_INTL("It's not very effective on {1}...",target.pbThis(true)))
@@ -5,9 +5,11 @@ module PokeBattle_BattleCommon
def pbStorePokemon(pkmn)
# Nickname the Pokémon (unless it's a Shadow Pokémon)
if !pkmn.shadowPokemon?
if pbDisplayConfirm(_INTL("Would you like to give a nickname to {1}?", pkmn.name))
nickname = @scene.pbNameEntry(_INTL("{1}'s nickname?", pkmn.speciesName), pkmn)
pkmn.name = nickname
if $PokemonSystem.prompt_nicknames
if pbDisplayConfirm(_INTL("Would you like to give a nickname to {1}?", pkmn.name))
nickname = @scene.pbNameEntry(_INTL("{1}'s nickname?", pkmn.speciesName), pkmn)
pkmn.name = nickname
end
end
end
# Store the Pokémon
@@ -64,7 +66,7 @@ module PokeBattle_BattleCommon
if $Trainer.has_pokedex
pbDisplayPaused(_INTL("{1}'s data was added to the Pokédex.", pkmn.name))
pbPlayer.pokedex.register_last_seen(pkmn)
@scene.pbShowPokedex(pkmn.species)
@scene.pbShowPokedex(pkmn)
end
end
# Record a Shadow Pokémon's species as having been caught
@@ -194,6 +196,8 @@ module PokeBattle_BattleCommon
pkmn.owner = Pokemon::Owner.new_from_trainer(pbPlayer)
end
BallHandlers.onCatch(ball, self, pkmn)
checkCatchChallenge(ball, self, pkmn)
pkmn.poke_ball = ball
pkmn.makeUnmega if pkmn.mega?
pkmn.makeUnprimal
@@ -226,7 +230,9 @@ module PokeBattle_BattleCommon
catch_rate /= 10
end
if @scene&.battle&.caughtOffGuard
catch_rate = [catch_rate * 1.5, 255].min
end
# First half of the shakes calculation
a = battler.totalhp
@@ -247,15 +253,15 @@ module PokeBattle_BattleCommon
#Increased chances of catching if is on last ball
isOnLastBall = !$PokemonBag.pbHasItem?(ball)
echoln isOnLastBall
# Critical capture check
if isOnLastBall
c = x * 6 / 12
if c > 0 && pbRandom(256) < c
if c > 0 && pbRandom(256) < c || pkmn.shiny?
@criticalCapture = true
return 4
end
end
# Calculate the number of shakes
numShakes = 0
for i in 0...4
@@ -67,6 +67,7 @@ class PokeBattle_Battle
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 :caughtOffGuard
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
@@ -83,6 +84,13 @@ class PokeBattle_Battle
attr_reader :endOfRound # True during the end of round
attr_accessor :moldBreaker # True if Mold Breaker applies
attr_reader :struggle # The Struggle move
attr_accessor :wind_side
#statistics
attr_accessor :balls_thrown
attr_accessor :damage_received
attr_accessor :favored_moves
include PokeBattle_BattleCommon
@@ -137,6 +145,7 @@ class PokeBattle_Battle
@controlPlayer = false
@expGain = true
@moneyGain = true
@caughtOffGuard = false
@rules = {}
@priority = []
@priorityTrickRoom = false
@@ -167,6 +176,10 @@ class PokeBattle_Battle
else
@struggle = PokeBattle_Struggle.new(self, nil)
end
@favored_moves = [] #Some trainers can be set to prioritize certain moves (ex: move tutor battles)
@balls_thrown =0
@damage_received = 0
end
#=============================================================================
@@ -205,6 +218,8 @@ class PokeBattle_Battle
end
end
def singleBattle?
return pbSideSize(0)==1 && pbSideSize(1)==1
end
@@ -414,7 +429,7 @@ class PokeBattle_Battle
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
next if !pkmn #|| !pkmn.able? # Can't copy a non-fainted Pokémon or egg
ret = i if ret < 0 || partyOrders[i] > partyOrders[ret]
end
return ret
@@ -694,12 +709,12 @@ class PokeBattle_Battle
when :HarshSun
if !pbCheckGlobalAbility(:DESOLATELAND)
@field.weather = :None
pbDisplay("The harsh sunlight faded!")
pbDisplay(_INTL("The harsh sunlight faded!"))
end
when :HeavyRain
if !pbCheckGlobalAbility(:PRIMORDIALSEA)
@field.weather = :None
pbDisplay("The heavy rain has lifted!")
pbDisplay(_INTL("The heavy rain has lifted!"))
end
# when :StrongWinds
# if !pbCheckGlobalAbility(:DELTASTREAM)
@@ -16,139 +16,130 @@ class PokeBattle_Battle
#=============================================================================
def pbEnsureParticipants
# Prevent battles larger than 2v2 if both sides have multiple trainers
# NOTE: This is necessary to ensure that battlers can never become unable to
# hit each other due to being too far away. In such situations,
# battlers will move to the centre position at the end of a round, but
# because they cannot move into a position owned by a different
# trainer, it's possible that battlers will be unable to move close
# enough to hit each other if there are multiple trainers on each
# side.
if trainerBattle? && (@sideSizes[0]>2 || @sideSizes[1]>2) &&
@player.length>1 && @opponent.length>1
if trainerBattle? && (@sideSizes[0] > 2 || @sideSizes[1] > 2) &&
@player.length > 1 && @opponent.length > 1
raise _INTL("Can't have battles larger than 2v2 where both sides have multiple trainers")
end
# Find out how many Pokémon each trainer has
side1counts = pbAbleTeamCounts(0)
side2counts = pbAbleTeamCounts(1)
# Change the size of the battle depending on how many wild Pokémon there are
if wildBattle? && side2counts[0]!=@sideSizes[1]
if @sideSizes[0]==@sideSizes[1]
# Even number of battlers per side, change both equally
@sideSizes = [side2counts[0],side2counts[0]]
# Adjust for wild multi battles
if wildBattle? && side2counts[0] != @sideSizes[1]
if @sideSizes[0] == @sideSizes[1]
@sideSizes = [side2counts[0], side2counts[0]]
else
# Uneven number of battlers per side, just change wild side's size
@sideSizes[1] = side2counts[0]
end
end
# Check if battle is possible, including changing the number of battlers per
# side if necessary
# Main loop to ensure battle is possible
loop do
needsChanging = false
for side in 0...2 # Each side in turn
next if side==1 && wildBattle? # Wild side's size already checked above
sideCounts = (side==0) ? side1counts : side2counts
bottleneck = [nil, nil] # track which side is the problem
# Check each side (player=0, opponent=1)
for side in 0...2
next if side == 1 && wildBattle?
sideCounts = (side == 0) ? side1counts : side2counts
requireds = []
# Find out how many Pokémon each trainer on side needs to have
# Count required battler slots per trainer
for i in 0...@sideSizes[side]
idxTrainer = pbGetOwnerIndexFromBattlerIndex(i*2+side)
requireds[idxTrainer] = 0 if requireds[idxTrainer].nil?
idxTrainer = pbGetOwnerIndexFromBattlerIndex(i * 2 + side)
requireds[idxTrainer] ||= 0
requireds[idxTrainer] += 1
end
# Compare the have values with the need values
# if requireds.length>sideCounts.length
# raise "Error: def pbGetOwnerIndexFromBattlerIndex gives invalid owner index ({1} for battle type {2}v{3}, trainers {4}v{5}",
# requireds.length-1,@sideSizes[0],@sideSizes[1],side1counts.length,side2counts.length)
# end
sideCounts.each_with_index do |_count,i|
if !requireds[i] || requireds[i]==0
raise _INTL("Player-side trainer {1} has no battler position for their Pokémon to go (trying {2}v{3} battle)",
i+1,@sideSizes[0],@sideSizes[1]) if side==0
raise _INTL("Opposing trainer {1} has no battler position for their Pokémon to go (trying {2}v{3} battle)",
i+1,@sideSizes[0],@sideSizes[1]) if side==1
# Compare required vs actual Pokémon
sideCounts.each_with_index do |_count, i|
if !requireds[i] || requireds[i] == 0
needsChanging = true
bottleneck[side] = true
break
end
next if requireds[i]<=sideCounts[i] # Trainer has enough Pokémon to fill their positions
if requireds[i]==1
raise _INTL("Player-side trainer {1} has no able Pokémon",i+1) if side==0
raise _INTL("Opposing trainer {1} has no able Pokémon",i+1) if side==1
if requireds[i] > sideCounts[i]
needsChanging = true
bottleneck[side] = true
break
end
# Not enough Pokémon, try lowering the number of battler positions
needsChanging = true
break
end
break if needsChanging
end
break if !needsChanging
# Reduce one or both side's sizes by 1 and try again
if wildBattle?
PBDebug.log("#{@sideSizes[0]}v#{@sideSizes[1]} battle isn't possible " +
"(#{side1counts} player-side teams versus #{side2counts[0]} wild Pokémon)")
newSize = @sideSizes[0]-1
break unless needsChanging
# SAFE SHRINK — shrink whichever side is the bottleneck
# If opponent side is the problem, shrink it first, then match player to it
# If player side is the problem (or both), shrink player side
PBDebug.log("#{@sideSizes[0]}v#{@sideSizes[1]} battle isn't possible; shrinking…")
if bottleneck[0] && !bottleneck[1]
# Only player side is the bottleneck — shrink it
@sideSizes[0] -= 1
# Never touch opponent side size
elsif bottleneck[1] && !bottleneck[0]
# Only opponent side is the bottleneck — shrink it
@sideSizes[1] -= 1
# Sync player down if it now exceeds opponent (can't have player outnumber opponent slots)
@sideSizes[0] = @sideSizes[1] if @sideSizes[0] > @sideSizes[1]
else
PBDebug.log("#{@sideSizes[0]}v#{@sideSizes[1]} battle isn't possible " +
"(#{side1counts} player-side teams versus #{side2counts} opposing teams)")
newSize = @sideSizes.max-1
end
if newSize==0
raise _INTL("Couldn't lower either side's size any further, battle isn't possible")
end
for side in 0...2
next if side==1 && wildBattle? # Wild Pokémon's side size is fixed
next if @sideSizes[side]==1 || newSize>@sideSizes[side]
@sideSizes[side] = newSize
# Both sides are bottlenecks — shrink whichever is larger, or player if equal
if @sideSizes[1] > @sideSizes[0]
@sideSizes[1] -= 1
else
@sideSizes[0] -= 1
end
end
PBDebug.log("Trying #{@sideSizes[0]}v#{@sideSizes[1]} battle instead")
if @sideSizes[0] <= 0 || @sideSizes[1] <= 0
raise _INTL("Couldn't reduce battle size any further, battle isn't possible")
end
end
end
#=============================================================================
# Set up all battlers
#=============================================================================
def pbCreateBattler(idxBattler,pkmn,idxParty)
def pbCreateBattler(idxBattler, pkmn, idxParty)
if !@battlers[idxBattler].nil?
raise _INTL("Battler index {1} already exists",idxBattler)
raise _INTL("Battler index {1} already exists", idxBattler)
end
@battlers[idxBattler] = PokeBattle_Battler.new(self,idxBattler)
@battlers[idxBattler] = PokeBattle_Battler.new(self, idxBattler)
@positions[idxBattler] = PokeBattle_ActivePosition.new
pbClearChoice(idxBattler)
@successStates[idxBattler] = PokeBattle_SuccessState.new
@battlers[idxBattler].pbInitialize(pkmn,idxParty)
@battlers[idxBattler].pbInitialize(pkmn, idxParty)
end
def pbSetUpSides
ret = [[],[]]
ret = [[], []]
for side in 0...2
# Set up wild Pokémon
if side==1 && wildBattle?
pbParty(1).each_with_index do |pkmn,idxPkmn|
pbCreateBattler(2*idxPkmn+side,pkmn,idxPkmn)
if side == 1 && wildBattle?
pbParty(1).each_with_index do |pkmn, idxPkmn|
pbCreateBattler(2 * idxPkmn + side, pkmn, idxPkmn)
# Changes the Pokémon's form upon entering battle (if it should)
@peer.pbOnEnteringBattle(self,pkmn,true)
pbSetSeen(@battlers[2*idxPkmn+side])
@peer.pbOnEnteringBattle(self, pkmn, true)
pbSetSeen(@battlers[2 * idxPkmn + side])
@usedInBattle[side][idxPkmn] = true
end
next
end
# Set up player's Pokémon and trainers' Pokémon
trainer = (side==0) ? @player : @opponent
trainer = (side == 0) ? @player : @opponent
requireds = []
# Find out how many Pokémon each trainer on side needs to have
for i in 0...@sideSizes[side]
idxTrainer = pbGetOwnerIndexFromBattlerIndex(i*2+side)
idxTrainer = pbGetOwnerIndexFromBattlerIndex(i * 2 + side)
requireds[idxTrainer] = 0 if requireds[idxTrainer].nil?
requireds[idxTrainer] += 1
end
# For each trainer in turn, find the needed number of Pokémon for them to
# send out, and initialize them
battlerNumber = 0
trainer.each_with_index do |_t,idxTrainer|
trainer.each_with_index do |_t, idxTrainer|
ret[side][idxTrainer] = []
eachInTeam(side,idxTrainer) do |pkmn,idxPkmn|
eachInTeam(side, idxTrainer) do |pkmn, idxPkmn|
next if !pkmn.able?
idxBattler = 2*battlerNumber+side
pbCreateBattler(idxBattler,pkmn,idxPkmn)
idxBattler = 2 * battlerNumber + side
pbCreateBattler(idxBattler, pkmn, idxPkmn)
ret[side][idxTrainer].push(idxBattler)
battlerNumber += 1
break if ret[side][idxTrainer].length>=requireds[idxTrainer]
break if ret[side][idxTrainer].length >= requireds[idxTrainer]
end
end
end
@@ -164,80 +155,85 @@ class PokeBattle_Battle
foeParty = pbParty(1)
case foeParty.length
when 1
pbDisplayPaused(_INTL("Oh! A wild {1} appeared!",foeParty[0].name))
if @caughtOffGuard
pbDisplayPaused(_INTL("The wild {1} was caught off guard!", foeParty[0].name))
else
pbDisplayPaused(_INTL("Oh! A wild {1} appeared!", foeParty[0].name))
end
when 2
pbDisplayPaused(_INTL("Oh! A wild {1} and {2} appeared!",foeParty[0].name,
foeParty[1].name))
pbDisplayPaused(_INTL("Oh! A wild {1} and {2} appeared!", foeParty[0].name,
foeParty[1].name))
when 3
pbDisplayPaused(_INTL("Oh! A wild {1}, {2} and {3} appeared!",foeParty[0].name,
foeParty[1].name,foeParty[2].name))
pbDisplayPaused(_INTL("Oh! A wild {1}, {2} and {3} appeared!", foeParty[0].name,
foeParty[1].name, foeParty[2].name))
end
else # Trainer battle
else
# Trainer battle
case @opponent.length
when 1
pbDisplayPaused(_INTL("You are challenged by {1}!",@opponent[0].full_name))
pbDisplayPaused(_INTL("You are challenged by {1}!", @opponent[0].full_name))
when 2
pbDisplayPaused(_INTL("You are challenged by {1} and {2}!",@opponent[0].full_name,
@opponent[1].full_name))
pbDisplayPaused(_INTL("You are challenged by {1} and {2}!", @opponent[0].full_name,
@opponent[1].full_name))
when 3
pbDisplayPaused(_INTL("You are challenged by {1}, {2} and {3}!",
@opponent[0].full_name,@opponent[1].full_name,@opponent[2].full_name))
@opponent[0].full_name, @opponent[1].full_name, @opponent[2].full_name))
end
end
# Send out Pokémon (opposing trainers first)
for side in [1,0]
next if side==1 && wildBattle?
for side in [1, 0]
next if side == 1 && wildBattle?
msg = ""
toSendOut = []
trainers = (side==0) ? @player : @opponent
trainers = (side == 0) ? @player : @opponent
# Opposing trainers and partner trainers's messages about sending out Pokémon
trainers.each_with_index do |t,i|
next if side==0 && i==0 # The player's message is shown last
msg += "\r\n" if msg.length>0
trainers.each_with_index do |t, i|
next if side == 0 && i == 0 # The player's message is shown last
msg += "\r\n" if msg.length > 0
sent = sendOuts[side][i]
case sent.length
when 1
msg += _INTL("{1} sent out {2}!",t.full_name,@battlers[sent[0]].name)
msg += _INTL("{1} sent out {2}!", t.full_name, @battlers[sent[0]].name)
when 2
msg += _INTL("{1} sent out {2} and {3}!",t.full_name,
@battlers[sent[0]].name,@battlers[sent[1]].name)
msg += _INTL("{1} sent out {2} and {3}!", t.full_name,
@battlers[sent[0]].name, @battlers[sent[1]].name)
when 3
if $game_switches[SWITCH_TRIPLE_BOSS_BATTLE]
if $game_switches[SWITCH_SILVERBOSS_BATTLE]
msg += _INTL("A wild Paldiatina appeared!",t.full_name)
msg += _INTL("A wild Paldiatina appeared!", t.full_name)
else
msg += _INTL("{1} sent out Zapmolcuno!",t.full_name)
msg += _INTL("{1} sent out Zapmolcuno!", t.full_name)
end
else
msg += _INTL("{1} sent out {2}, {3} and {4}!",t.full_name,
@battlers[sent[0]].name,@battlers[sent[1]].name,@battlers[sent[2]].name)
msg += _INTL("{1} sent out {2}, {3} and {4}!", t.full_name,
@battlers[sent[0]].name, @battlers[sent[1]].name, @battlers[sent[2]].name)
end
end
toSendOut.concat(sent)
end
# The player's message about sending out Pokémon
if side==0
msg += "\r\n" if msg.length>0
if side == 0
msg += "\r\n" if msg.length > 0
sent = sendOuts[side][0]
case sent.length
when 1
msg += _INTL("Go! {1}!",@battlers[sent[0]].name)
msg += _INTL("Go! {1}!", @battlers[sent[0]].name)
when 2
msg += _INTL("Go! {1} and {2}!",@battlers[sent[0]].name,@battlers[sent[1]].name)
msg += _INTL("Go! {1} and {2}!", @battlers[sent[0]].name, @battlers[sent[1]].name)
when 3
msg += _INTL("Go! {1}, {2} and {3}!",@battlers[sent[0]].name,
@battlers[sent[1]].name,@battlers[sent[2]].name)
msg += _INTL("Go! {1}, {2} and {3}!", @battlers[sent[0]].name,
@battlers[sent[1]].name, @battlers[sent[2]].name)
end
toSendOut.concat(sent)
end
pbDisplayBrief(msg) if msg.length>0
pbDisplayBrief(msg) if msg.length > 0
# The actual sending out of Pokémon
animSendOuts = []
toSendOut.each do |idxBattler|
animSendOuts.push([idxBattler,@battlers[idxBattler].pokemon])
animSendOuts.push([idxBattler, @battlers[idxBattler].pokemon])
end
pbSendOut(animSendOuts,true)
pbSendOut(animSendOuts, true)
end
end
@@ -248,11 +244,11 @@ class PokeBattle_Battle
PBDebug.log("")
PBDebug.log("******************************************")
logMsg = "[Started battle] "
if @sideSizes[0]==1 && @sideSizes[1]==1
if @sideSizes[0] == 1 && @sideSizes[1] == 1
logMsg += "Single "
elsif @sideSizes[0]==2 && @sideSizes[1]==2
elsif @sideSizes[0] == 2 && @sideSizes[1] == 2
logMsg += "Double "
elsif @sideSizes[0]==3 && @sideSizes[1]==3
elsif @sideSizes[0] == 3 && @sideSizes[1] == 3
logMsg += "Triple "
else
logMsg += "#{@sideSizes[0]}v#{@sideSizes[1]} "
@@ -264,6 +260,7 @@ class PokeBattle_Battle
logMsg += "#{@opponent.length} trainer(s))" if trainerBattle?
PBDebug.log(logMsg)
pbEnsureParticipants
echoln "Final sideSizes: #{@sideSizes[0]}v#{@sideSizes[1]}"
begin
pbStartBattleCore
rescue BattleAbortedException
@@ -283,18 +280,18 @@ class PokeBattle_Battle
# Weather announcement
weather_data = GameData::BattleWeather.try_get(@field.weather)
echoln "Current weather: #{@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("It is raining."))
when :Sandstorm then pbDisplay(_INTL("A sandstorm is raging."))
when :Hail then pbDisplay(_INTL("Hail is falling."))
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 sky is shadowy."))
when :Sun then pbDisplay(_INTL("The sunlight is strong."))
when :Rain then pbDisplay(_INTL("It is raining."))
when :Sandstorm then pbDisplay(_INTL("A sandstorm is raging."))
when :Hail then pbDisplay(_INTL("Hail is falling."))
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 sky is shadowy."))
end
pbApplyBattleStartWeatherEffects
# Terrain announcement
terrain_data = GameData::BattleTerrain.try_get(@field.terrain)
pbCommonAnimation(terrain_data.animation) if terrain_data
@@ -314,15 +311,30 @@ class PokeBattle_Battle
pbBattleLoop
end
def pbApplyBattleStartWeatherEffects
if @field.weather == :StrongWinds
wind_side = [0,1].sample
echoln @wind_side
wind_side = @wind_side.to_i if @wind_side
@sides[wind_side].effects[PBEffects::Tailwind] = 4
if wind_side == 0
pbDisplay(_INTL("The wind is blowing from your side."))
else
pbDisplay(_INTL("The wind is blowing from the opponent's side."))
end
end
end
#=============================================================================
# Main battle loop
#=============================================================================
def pbBattleLoop
@turnCount = 0
loop do # Now begin the battle loop
loop do
# Now begin the battle loop
PBDebug.log("")
PBDebug.log("***Round #{@turnCount+1}***")
if @debug && @turnCount>=100
PBDebug.log("***Round #{@turnCount + 1}***")
if @debug && @turnCount >= 100
@decision = pbDecisionOnTime
PBDebug.log("")
PBDebug.log("***Undecided after 100 rounds, aborting***")
@@ -332,48 +344,72 @@ class PokeBattle_Battle
PBDebug.log("")
# Command phase
PBDebug.logonerr { pbCommandPhase }
break if @decision>0
break if @decision > 0
# Attack phase
PBDebug.logonerr { pbAttackPhase }
break if @decision>0
break if @decision > 0
# End of round phase
PBDebug.logonerr { pbEndOfRoundPhase }
break if @decision>0
break if @decision > 0
@turnCount += 1
end
pbEndOfBattle
end
def calculateMoneyGain
return unless trainerBattle?
tMoney = 0
@opponent.each_with_index do |t, i|
tMoney += pbMaxLevelInTeam(1, i) * t.base_money
end
tMoney *= 2 if @field.effects[PBEffects::AmuletCoin]
tMoney *= 2 if @field.effects[PBEffects::HappyHour]
return tMoney
end
#=============================================================================
# End of battle
#=============================================================================
def pbGainMoney
return if $game_switches[SWITCH_IS_REMATCH] #is rematch
def pbGainCosmeticsMoney
return 0 unless Settings::HOENN
return 0 unless trainerBattle?
cosmetics_money = (calculateMoneyGain / 2).floor
$Trainer.cosmetics_money = 0 unless $Trainer.cosmetics_money
pbPlayer.cosmetics_money += cosmetics_money
if !@moneyGain && cosmetics_money > 0 # message displayed in pbGainMoney if player wins money
pbDisplayPaused(_INTL("You got some {1} for winning!", COSMETIC_CURRENCY_NAME))
end
return cosmetics_money
end
def pbGainMoney(cosmetics_money = 0)
return if $game_switches[SWITCH_IS_REMATCH] # is rematch
return if !@internalBattle || !@moneyGain
# Money rewarded from opposing trainers
if trainerBattle?
tMoney = 0
@opponent.each_with_index do |t,i|
tMoney += pbMaxLevelInTeam(1, i) * t.base_money
end
tMoney *= 2 if @field.effects[PBEffects::AmuletCoin]
tMoney *= 2 if @field.effects[PBEffects::HappyHour]
tMoney = calculateMoneyGain
oldMoney = pbPlayer.money
pbPlayer.money += tMoney
moneyGained = pbPlayer.money-oldMoney
if moneyGained>0
pbDisplayPaused(_INTL("You got ${1} for winning!",moneyGained.to_s_formatted))
moneyGained = pbPlayer.money - oldMoney
if moneyGained > 0
if cosmetics_money > 0
pbDisplayPaused(_INTL("You got ${1} and some {2} for winning!", moneyGained.to_s_formatted, COSMETIC_CURRENCY_NAME))
else
pbDisplayPaused(_INTL("You got ${1} for winning!", moneyGained.to_s_formatted))
end
end
end
# Pick up money scattered by Pay Day
if @field.effects[PBEffects::PayDay]>0
if @field.effects[PBEffects::PayDay] > 0
@field.effects[PBEffects::PayDay] *= 2 if @field.effects[PBEffects::AmuletCoin]
@field.effects[PBEffects::PayDay] *= 2 if @field.effects[PBEffects::HappyHour]
oldMoney = pbPlayer.money
pbPlayer.money += @field.effects[PBEffects::PayDay]
moneyGained = pbPlayer.money-oldMoney
if moneyGained>0
pbDisplayPaused(_INTL("You picked up ${1}!",moneyGained.to_s_formatted))
moneyGained = pbPlayer.money - oldMoney
if moneyGained > 0
pbDisplayPaused(_INTL("You picked up ${1}!", moneyGained.to_s_formatted))
end
end
end
@@ -381,28 +417,28 @@ class PokeBattle_Battle
def pbLoseMoney
return if !@internalBattle || !@moneyGain
return if $game_switches[Settings::NO_MONEY_LOSS]
maxLevel = pbMaxLevelInTeam(0,0) # Player's Pokémon only, not partner's
multiplier = [8,16,24,36,48,64,80,100,120]
maxLevel = pbMaxLevelInTeam(0, 0) # Player's Pokémon only, not partner's
multiplier = [8, 16, 24, 36, 48, 64, 80, 100, 120]
idxMultiplier = [pbPlayer.badge_count, multiplier.length - 1].min
tMoney = maxLevel*multiplier[idxMultiplier]
tMoney = pbPlayer.money if tMoney>pbPlayer.money
tMoney = maxLevel * multiplier[idxMultiplier]
tMoney = pbPlayer.money if tMoney > pbPlayer.money
oldMoney = pbPlayer.money
pbPlayer.money -= tMoney
moneyLost = oldMoney-pbPlayer.money
if moneyLost>0
moneyLost = oldMoney - pbPlayer.money
if moneyLost > 0
if trainerBattle?
pbDisplayPaused(_INTL("You gave ${1} to the winner...",moneyLost.to_s_formatted))
pbDisplayPaused(_INTL("You gave ${1} to the winner...", moneyLost.to_s_formatted))
else
pbDisplayPaused(_INTL("You panicked and dropped ${1}...",moneyLost.to_s_formatted))
pbDisplayPaused(_INTL("You panicked and dropped ${1}...", moneyLost.to_s_formatted))
end
end
end
def pbEndOfBattle
oldDecision = @decision
@decision = 4 if @decision==1 && wildBattle? && @caughtPokemon.length>0
@decision = 4 if @decision == 1 && wildBattle? && @caughtPokemon.length > 0
case oldDecision
##### WIN #####
##### WIN #####
when 1
PBDebug.log("")
PBDebug.log("***Player won***")
@@ -410,109 +446,112 @@ class PokeBattle_Battle
@scene.pbTrainerBattleSuccess
case @opponent.length
when 1
pbDisplayPaused(_INTL("You defeated {1}!",@opponent[0].full_name))
pbDisplayPaused(_INTL("You defeated {1}!", @opponent[0].full_name))
when 2
pbDisplayPaused(_INTL("You defeated {1} and {2}!",@opponent[0].full_name,
@opponent[1].full_name))
pbDisplayPaused(_INTL("You defeated {1} and {2}!", @opponent[0].full_name,
@opponent[1].full_name))
when 3
pbDisplayPaused(_INTL("You defeated {1}, {2} and {3}!",@opponent[0].full_name,
@opponent[1].full_name,@opponent[2].full_name))
pbDisplayPaused(_INTL("You defeated {1}, {2} and {3}!", @opponent[0].full_name,
@opponent[1].full_name, @opponent[2].full_name))
end
@opponent.each_with_index do |_t,i|
@opponent.each_with_index do |_t, i|
@scene.pbShowOpponent(i)
msg = (@endSpeeches[i] && @endSpeeches[i] !="") ? @endSpeeches[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/,pbPlayer.name))
msg = (@endSpeeches[i] && @endSpeeches[i] != "") ? @endSpeeches[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/, pbPlayer.name))
end
end
# Gain money from winning a trainer battle, and from Pay Day
pbGainMoney if @decision!=4
cosmetics_money = pbGainCosmeticsMoney
pbGainMoney(cosmetics_money) if @decision != 4
# Hide remaining trainer
@scene.pbShowOpponent(@opponent.length) if trainerBattle? && @caughtPokemon.length>0
@scene.pbShowOpponent(@opponent.length) if trainerBattle? && @caughtPokemon.length > 0
if $game_switches[AUTOSAVE_WIN_SWITCH]
Kernel.tryAutosave()
end
##### LOSE, DRAW #####
##### LOSE, DRAW #####
when 2, 5
PBDebug.log("")
PBDebug.log("***Player lost***") if @decision==2
PBDebug.log("***Player drew with opponent***") if @decision==5
if @decision == 2
$Trainer.stats&.incr_nb_battles_lost
PBDebug.log("***Player lost***")
end
PBDebug.log("***Player drew with opponent***") if @decision == 5
if @internalBattle
pbDisplayPaused(_INTL("You have no more Pokémon that can fight!"))
if trainerBattle?
case @opponent.length
when 1
pbDisplayPaused(_INTL("You lost against {1}!",@opponent[0].full_name))
pbDisplayPaused(_INTL("You lost against {1}!", @opponent[0].full_name))
when 2
pbDisplayPaused(_INTL("You lost against {1} and {2}!",
@opponent[0].full_name,@opponent[1].full_name))
@opponent[0].full_name, @opponent[1].full_name))
when 3
pbDisplayPaused(_INTL("You lost against {1}, {2} and {3}!",
@opponent[0].full_name,@opponent[1].full_name,@opponent[2].full_name))
@opponent[0].full_name, @opponent[1].full_name, @opponent[2].full_name))
end
end
# Lose money from losing a battle
pbLoseMoney
pbDisplayPaused(_INTL("You blacked out!")) if !@canLose
elsif @decision==2
elsif @decision == 2
if @opponent
@opponent.each_with_index do |_t,i|
@opponent.each_with_index do |_t, i|
@scene.pbShowOpponent(i)
msg = (@endSpeechesWin[i] && @endSpeechesWin[i]!="") ? @endSpeechesWin[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/,pbPlayer.name))
msg = (@endSpeechesWin[i] && @endSpeechesWin[i] != "") ? @endSpeechesWin[i] : "..."
pbDisplayPaused(msg.gsub(/\\[Pp][Nn]/, pbPlayer.name))
end
end
end
##### CAUGHT WILD POKÉMON #####
##### CAUGHT WILD POKÉMON #####
when 4
@scene.pbWildBattleSuccess if !Settings::GAIN_EXP_FOR_CAPTURE
end
# Register captured Pokémon in the Pokédex, and store them
#pbRecordAndStoreCaughtPokemon
# pbRecordAndStoreCaughtPokemon
isRematch = $game_switches[SWITCH_IS_REMATCH]
begin
if isRematch
if @opponent.is_a?(Array)
for trainer in @opponent
rematchId = getRematchId(trainer.name,trainer.trainer_type)
if isRematch
if @opponent.is_a?(Array)
for trainer in @opponent
rematchId = getRematchId(trainer.name, trainer.trainer_type)
incrNbRematches(rematchId)
end
else
rematchId = getRematchId(@opponent.name, @opponent.trainer_type)
incrNbRematches(rematchId)
end
else
rematchId = getRematchId(@opponent.name,@opponent.trainer_type)
incrNbRematches(rematchId)
end
end
rescue
$game_switches[SWITCH_IS_REMATCH]=false
$game_switches[SWITCH_IS_REMATCH] = false
end
# Collect Pay Day money in a wild battle that ended in a capture
pbGainMoney if @decision==4
pbGainMoney if @decision == 4
# Pass on Pokérus within the party
if @internalBattle
infected = []
$Trainer.party.each_with_index do |pkmn,i|
infected.push(i) if pkmn.pokerusStage==1
$Trainer.party.each_with_index do |pkmn, i|
infected.push(i) if pkmn.pokerusStage == 1
end
infected.each do |idxParty|
strain = $Trainer.party[idxParty].pokerusStrain
if idxParty>0 && $Trainer.party[idxParty-1].pokerusStage==0
$Trainer.party[idxParty-1].givePokerus(strain) if rand(3)==0 # 33%
if idxParty > 0 && $Trainer.party[idxParty - 1].pokerusStage == 0
$Trainer.party[idxParty - 1].givePokerus(strain) if rand(3) == 0 # 33%
end
if idxParty<$Trainer.party.length-1 && $Trainer.party[idxParty+1].pokerusStage==0
$Trainer.party[idxParty+1].givePokerus(strain) if rand(3)==0 # 33%
if idxParty < $Trainer.party.length - 1 && $Trainer.party[idxParty + 1].pokerusStage == 0
$Trainer.party[idxParty + 1].givePokerus(strain) if rand(3) == 0 # 33%
end
end
end
pbParty(0).each_with_index do |pkmn,i|
pbParty(0).each_with_index do |pkmn, i|
next if !pkmn
@peer.pbOnLeavingBattle(self,pkmn,@usedInBattle[0][i],true) # Reset form
@peer.pbOnLeavingBattle(self, pkmn, @usedInBattle[0][i], true) # Reset form
pkmn.item = @initialItems[0][i]
pkmn.spriteform_head=nil
pkmn.spriteform_body=nil
pkmn.spriteform_head = nil
pkmn.spriteform_body = nil
end
pbRecordAndStoreCaughtPokemon
@@ -520,62 +559,70 @@ class PokeBattle_Battle
@scene.pbEndBattle(@decision)
@battlers.each do |b|
next if !b
pbCancelChoice(b.index) # Restore unused items to Bag
BattleHandlers.triggerAbilityOnSwitchOut(b.ability,b,true) if b.abilityActive?
pbCancelChoice(b.index) # Restore unused items to Bag
BattleHandlers.triggerAbilityOnSwitchOut(b.ability, b, true) if b.abilityActive?
end
return @decision
end
#=============================================================================
# Judging
#=============================================================================
def pbJudgeCheckpoint(user,move=nil); end
def pbJudgeCheckpoint(user, move = nil)
;
end
def pbDecisionOnTime
counts = [0,0]
hpTotals = [0,0]
counts = [0, 0]
hpTotals = [0, 0]
for side in 0...2
pbParty(side).each do |pkmn|
next if !pkmn || !pkmn.able?
counts[side] += 1
counts[side] += 1
hpTotals[side] += pkmn.hp
end
end
return 1 if counts[0]>counts[1] # Win (player has more able Pokémon)
return 2 if counts[0]<counts[1] # Loss (foe has more able Pokémon)
return 1 if hpTotals[0]>hpTotals[1] # Win (player has more HP in total)
return 2 if hpTotals[0]<hpTotals[1] # Loss (foe has more HP in total)
return 5 # Draw
return 1 if counts[0] > counts[1] # Win (player has more able Pokémon)
return 2 if counts[0] < counts[1] # Loss (foe has more able Pokémon)
return 1 if hpTotals[0] > hpTotals[1] # Win (player has more HP in total)
return 2 if hpTotals[0] < hpTotals[1] # Loss (foe has more HP in total)
return 5 # Draw
end
# Unused
def pbDecisionOnTime2
counts = [0,0]
hpTotals = [0,0]
counts = [0, 0]
hpTotals = [0, 0]
for side in 0...2
pbParty(side).each do |pkmn|
next if !pkmn || !pkmn.able?
counts[side] += 1
hpTotals[side] += 100*pkmn.hp/pkmn.totalhp
counts[side] += 1
hpTotals[side] += 100 * pkmn.hp / pkmn.totalhp
end
hpTotals[side] /= counts[side] if counts[side]>1
hpTotals[side] /= counts[side] if counts[side] > 1
end
return 1 if counts[0]>counts[1] # Win (player has more able Pokémon)
return 2 if counts[0]<counts[1] # Loss (foe has more able Pokémon)
return 1 if hpTotals[0]>hpTotals[1] # Win (player has a bigger average HP %)
return 2 if hpTotals[0]<hpTotals[1] # Loss (foe has a bigger average HP %)
return 5 # Draw
return 1 if counts[0] > counts[1] # Win (player has more able Pokémon)
return 2 if counts[0] < counts[1] # Loss (foe has more able Pokémon)
return 1 if hpTotals[0] > hpTotals[1] # Win (player has a bigger average HP %)
return 2 if hpTotals[0] < hpTotals[1] # Loss (foe has a bigger average HP %)
return 5 # Draw
end
def pbDecisionOnDraw; return 5; end # Draw
def pbDecisionOnDraw
return 5;
end
# Draw
def pbJudge
fainted1 = pbAllFainted?(0)
fainted2 = pbAllFainted?(1)
if fainted1 && fainted2; @decision = pbDecisionOnDraw # Draw
elsif fainted1; @decision = 2 # Loss
elsif fainted2; @decision = 1 # Win
if fainted1 && fainted2;
@decision = pbDecisionOnDraw # Draw
elsif fainted1;
@decision = 2 # Loss
elsif fainted2;
@decision = 1 # Win
end
end
end
@@ -8,7 +8,7 @@ class PokeBattle_Battle
return if !@internalBattle || !@expGain
# Go through each battler in turn to find the Pokémon that participated in
# battle against it, and award those Pokémon Exp/EVs
expAll = (GameData::Item.exists?(:EXPALL) && $PokemonBag.pbHasItem?(:EXPALL)) || $game_switches[SWITCH_GAME_DIFFICULTY_EASY]
expAll = (GameData::Item.exists?(:EXPALL) && $PokemonBag.pbHasItem?(:EXPALL)) || ( $game_switches[SWITCH_GAME_DIFFICULTY_EASY] && Settings::KANTO)
p1 = pbParty(0)
@battlers.each do |b|
next unless b && b.opposes? # Can only gain Exp from fainted foes
@@ -154,6 +154,14 @@ class PokeBattle_Battle
end
exp = i if i >= 0
# Make sure Exp doesn't exceed the maximum
if pokemonExceedsLevelCap(pkmn)
if $PokemonSystem.level_caps==1 #Level caps enabled
exp = 0
else
exp = (exp *= 0.6).floor #Pokémon still gain less exp when over level cap, even if level caps option is disabled
end
end
exp = 0 if $PokemonSystem.level_caps==1 && pokemonExceedsLevelCap(pkmn)
@@ -206,8 +214,9 @@ class PokeBattle_Battle
else
pkmn.exp_gained_since_fused += expGained
end
end
pkmn.exp_gained_with_player =0 if pkmn.exp_gained_with_player == nil
pkmn.exp_gained_with_player += expGained
@scene.pbEXPBar(battler, levelMinExp, levelMaxExp, tempExp1, tempExp2) if !dontAnimate
@@ -239,9 +248,6 @@ class PokeBattle_Battle
@scene.pbLevelUp(pkmn, battler, oldTotalHP, oldAttack, oldDefense,
oldSpAtk, oldSpDef, oldSpeed)
end
echoln "256"
# Learn all moves learned at this level
moveList = pkmn.getMoveList
moveList.each { |m| pbLearnMove(idxParty, m[1]) if m[0] == curLevel }
@@ -55,6 +55,8 @@ class PokeBattle_Battle
break
end
items.compact!
$PokemonTemp.battle_npc_used_items = [] unless $PokemonTemp.battle_npc_used_items
$PokemonTemp.battle_npc_used_items << item
end
end
@@ -497,14 +497,14 @@ BattleHandlers::StatLossImmunityAllyAbility.add(:FLOWERVEIL,
BattleHandlers::AbilityOnStatLoss.add(:COMPETITIVE,
proc { |ability,battler,stat,user|
next if user && !user.opposes?(battler)
battler.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,2,battler,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,2,battler,GameData::Ability.get(ability).name)
}
)
BattleHandlers::AbilityOnStatLoss.add(:DEFIANT,
proc { |ability,battler,stat,user|
next if user && !user.opposes?(battler)
battler.pbRaiseStatStageByAbility(:ATTACK,2,battler,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(:ATTACK,2,battler,GameData::Ability.get(ability).name)
}
)
@@ -555,7 +555,7 @@ BattleHandlers::PriorityBracketChangeAbility.add(:STALL,
BattleHandlers::AbilityOnFlinch.add(:STEADFAST,
proc { |ability,battler,battle|
battler.pbRaiseStatStageByAbility(:SPEED,1,battler,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(:SPEED,1,battler,GameData::Ability.get(ability).name)
}
)
@@ -1441,7 +1441,7 @@ BattleHandlers::TargetAbilityOnHit.add(:FLAMEBODY,
BattleHandlers::TargetAbilityOnHit.add(:GOOEY,
proc { |ability,user,target,move,battle|
next if !move.pbContactMove?(user)
user.pbLowerStatStageByAbility(:SPEED,1,target,true,true,GameData::Ability.get(ability).real_name)
user.pbLowerStatStageByAbility(:SPEED,1,target,true,true,GameData::Ability.get(ability).name)
}
)
@@ -1500,7 +1500,7 @@ BattleHandlers::TargetAbilityOnHit.copy(:IRONBARBS,:ROUGHSKIN)
BattleHandlers::TargetAbilityOnHit.add(:JUSTIFIED,
proc { |ability,user,target,move,battle|
next if move.calcType != :DARK
target.pbRaiseStatStageByAbility(:ATTACK,1,target,GameData::Ability.get(ability).real_name)
target.pbRaiseStatStageByAbility(:ATTACK,1,target,GameData::Ability.get(ability).name)
}
)
@@ -1549,13 +1549,13 @@ BattleHandlers::TargetAbilityOnHit.add(:POISONPOINT,
BattleHandlers::TargetAbilityOnHit.add(:RATTLED,
proc { |ability,user,target,move,battle|
next if ![:BUG, :DARK, :GHOST].include?(move.calcType)
target.pbRaiseStatStageByAbility(:SPEED,1,target,GameData::Ability.get(ability).real_name)
target.pbRaiseStatStageByAbility(:SPEED,1,target,GameData::Ability.get(ability).name)
}
)
BattleHandlers::TargetAbilityOnHit.add(:STAMINA,
proc { |ability,user,target,move,battle|
target.pbRaiseStatStageByAbility(:DEFENSE,1,target,GameData::Ability.get(ability).real_name)
target.pbRaiseStatStageByAbility(:DEFENSE,1,target,GameData::Ability.get(ability).name)
}
)
@@ -1580,7 +1580,7 @@ BattleHandlers::TargetAbilityOnHit.add(:STATIC,
BattleHandlers::TargetAbilityOnHit.add(:WATERCOMPACTION,
proc { |ability,user,target,move,battle|
next if move.calcType != :WATER
target.pbRaiseStatStageByAbility(:DEFENSE,2,target,GameData::Ability.get(ability).real_name)
target.pbRaiseStatStageByAbility(:DEFENSE,2,target,GameData::Ability.get(ability).name)
}
)
@@ -1590,9 +1590,9 @@ BattleHandlers::TargetAbilityOnHit.add(:WEAKARMOR,
next if !target.pbCanLowerStatStage?(:DEFENSE, target) &&
!target.pbCanRaiseStatStage?(:SPEED, target)
battle.pbShowAbilitySplash(target)
target.pbLowerStatStageByAbility(:DEFENSE, 1, target, false,GameData::Ability.get(ability).real_name)
target.pbLowerStatStageByAbility(:DEFENSE, 1, target, false,GameData::Ability.get(ability).name)
target.pbRaiseStatStageByAbility(:SPEED,
(Settings::MECHANICS_GENERATION >= 7) ? 2 : 1, target, false,GameData::Ability.get(ability).real_name)
(Settings::MECHANICS_GENERATION >= 7) ? 2 : 1, target, false,GameData::Ability.get(ability).name)
battle.pbHideAbilitySplash(target)
}
)
@@ -1639,7 +1639,7 @@ BattleHandlers::UserAbilityEndOfMove.add(:BEASTBOOST,
GameData::Stat.each_main_battle do |s|
next if userStats[s.id] < highestStatValue
if user.pbCanRaiseStatStage?(s.id, user)
user.pbRaiseStatStageByAbility(s.id, numFainted, user,GameData::Ability.get(ability).real_name)
user.pbRaiseStatStageByAbility(s.id, numFainted, user,GameData::Ability.get(ability).name)
end
break
end
@@ -1668,7 +1668,7 @@ BattleHandlers::UserAbilityEndOfMove.add(:MAGICIAN,
user.item = b.item
b.item = nil
b.effects[PBEffects::Unburden] = true
if battle.wildBattle? && !user.initialItem && b.initialItem==user.item
if battle.wildBattle? && !user.initialItem && user.item == b.initialItem
user.setInitialItem(user.item)
b.setInitialItem(nil)
end
@@ -1692,7 +1692,7 @@ BattleHandlers::UserAbilityEndOfMove.add(:MOXIE,
numFainted = 0
targets.each { |b| numFainted += 1 if b.damageState.fainted }
next if numFainted==0 || !user.pbCanRaiseStatStage?(:ATTACK,user)
user.pbRaiseStatStageByAbility(:ATTACK,numFainted,user,GameData::Ability.get(ability).real_name)
user.pbRaiseStatStageByAbility(:ATTACK,numFainted,user,GameData::Ability.get(ability).name)
}
)
@@ -1705,7 +1705,7 @@ BattleHandlers::TargetAbilityAfterMoveUse.add(:BERSERK,
next if !move.damagingMove?
next if target.damageState.initialHP<target.totalhp/2 || target.hp>=target.totalhp/2
next if !target.pbCanRaiseStatStage?(:SPECIAL_ATTACK,target)
target.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,target,GameData::Ability.get(ability).real_name)
target.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,target,GameData::Ability.get(ability).name)
}
)
@@ -1947,12 +1947,12 @@ BattleHandlers::EOREffectAbility.add(:MOODY,
battle.pbShowAbilitySplash(battler)
if randomUp.length>0
r = battle.pbRandom(randomUp.length)
battler.pbRaiseStatStageByAbility(randomUp[r],2,battler,false,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(randomUp[r],2,battler,false,GameData::Ability.get(ability).name)
randomDown.delete(randomUp[r])
end
if randomDown.length>0
r = battle.pbRandom(randomDown.length)
battler.pbLowerStatStageByAbility(randomDown[r],1,battler,false,GameData::Ability.get(ability).real_name)
battler.pbLowerStatStageByAbility(randomDown[r],1,battler,false,GameData::Ability.get(ability).name)
end
battle.pbHideAbilitySplash(battler)
battler.pbItemStatRestoreCheck if randomDown.length>0
@@ -1964,7 +1964,7 @@ BattleHandlers::EOREffectAbility.add(:SPEEDBOOST,
# A Pokémon's turnCount is 0 if it became active after the beginning of a
# round
if battler.turnCount>0 && battler.pbCanRaiseStatStage?(:SPEED,battler)
ability_name = GameData::Ability.get(ability).real_name
ability_name = GameData::Ability.get(ability).name
battler.pbRaiseStatStageByAbility(:SPEED,1,battler,true,ability_name)
end
}
@@ -2142,7 +2142,7 @@ BattleHandlers::AbilityOnSwitchIn.add(:DOWNLOAD,
oSpDef += b.spdef
end
stat = (oDef<oSpDef) ? :ATTACK : :SPECIAL_ATTACK
battler.pbRaiseStatStageByAbility(stat,1,battler,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(stat,1,battler,GameData::Ability.get(ability).name)
}
)
@@ -2411,7 +2411,7 @@ BattleHandlers::AbilityChangeOnBattlerFainting.copy(:POWEROFALCHEMY,:RECEIVER)
BattleHandlers::AbilityOnBattlerFainting.add(:SOULHEART,
proc { |ability,battler,fainted,battle|
battler.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,battler,GameData::Ability.get(ability).real_name)
battler.pbRaiseStatStageByAbility(:SPECIAL_ATTACK,1,battler,GameData::Ability.get(ability).name)
}
)
@@ -10,8 +10,8 @@
module PBTrainerAI
# Minimum skill level to be in each AI category.
def self.minimumSkill; return 1; end
def self.mediumSkill; return 32; end
def self.highSkill; return 48; end
def self.mediumSkill; return 16; end
def self.highSkill; return 32; end
def self.bestSkill; return 100; end
end
@@ -139,6 +139,8 @@ class PokeBattle_AI
next if !@battle.pbMoveCanTarget?(user.index, b.index, target_data)
next if target_data.targets_foe && !user.opposes?(b)
score = pbGetMoveScore(move, user, b, skill)
#echoln "Move: #{move.id} Score: #{score}"
scoresAndTargets.push([score, b.index]) if score > 0
end
if scoresAndTargets.length > 0
@@ -156,6 +158,9 @@ class PokeBattle_AI
skill = PBTrainerAI.minimumSkill if skill < PBTrainerAI.minimumSkill
score = 100
score = pbGetMoveScoreFunctionCode(score, move, user, target, skill)
#echoln "Move #{move.id} : score"
# A score of 0 here means it absolutely should not be used
return 0 if score <= 0
if skill >= PBTrainerAI.mediumSkill
File diff suppressed because it is too large Load Diff
@@ -850,6 +850,13 @@ BattleHandlers::DamageCalcTargetItem.add(:COLBURBERRY,
}
)
BattleHandlers::DamageCalcTargetItem.add(:ROSELIBERRY,
proc { |item,user,target,move,mults,baseDmg,type|
pbBattleTypeWeakingBerry(:FAIRY,type,target,mults)
}
)
BattleHandlers::DamageCalcTargetItem.add(:DEEPSEASCALE,
proc { |item,user,target,move,mults,baseDmg,type|
if target.isSpecies?(:CLAMPERL) && move.specialMove?
@@ -147,7 +147,10 @@ BallHandlers::ModifyCatchRate.add(:TIMERBALL,proc { |ball,catchRate,battle,battl
BallHandlers::ModifyCatchRate.add(:DUSKBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3 : 3.5
catchRate *= multiplier if battle.time==2
if GameData::MapMetadata.exists?($game_map.map_id)
battle_environment = GameData::MapMetadata.get($game_map.map_id).battle_environment
end
catchRate *= multiplier if (battle.time==2 || battle_environment && battle_environment == :Cave)
next catchRate
})
@@ -8,7 +8,7 @@ class BattleIntroAnimation < PokeBattle_Animation
end
def createProcesses
appearTime = 20 # This is in 1/20 seconds
appearTime = 10 # This is in 1/20 seconds
# Background
if @sprites["battle_bg2"]
makeSlideSprite("battle_bg",0.5,appearTime)
@@ -42,7 +42,7 @@ class BattleIntroAnimation < PokeBattle_Animation
blackScreen.moveOpacity(0,8,0)
# Fading blackness over command bar
blackBar = addNewSprite(@sprites["cmdBar_bg"].x,@sprites["cmdBar_bg"].y,
"Graphics/Battle animations/black_bar")
"Graphics/Battle animations/black_bar")
blackBar.setZ(0,998)
blackBar.moveOpacity(appearTime*3/4,appearTime/4,0)
end
@@ -235,13 +235,9 @@ class AbilitySplashAppearAnimation < PokeBattle_Animation
end
def createProcesses
if @secondAbility
return if !@sprites["ability2Bar_#{@side}"]
bar = addSprite(@sprites["ability2Bar_#{@side}"])
else
return if !@sprites["abilityBar_#{@side}"]
bar = addSprite(@sprites["abilityBar_#{@side}"])
end
return if !@sprites["abilityBar_#{@side}"]
bar = addSprite(@sprites["abilityBar_#{@side}"])
bar.setVisible(0,true)
dir = (@side==0) ? 1 : -1
@@ -277,18 +273,21 @@ end
# Used at the end of battle.
#===============================================================================
class TrainerAppearAnimation < PokeBattle_Animation
TRAINER_SPRITE_MOVE_DURATION = 8 #16
FADEIN_DURATION = 8 #12
FADEIN_DELAY = 0
def initialize(sprites,viewport,idxTrainer)
@idxTrainer = idxTrainer
super(sprites,viewport)
end
def createProcesses
delay = 0
delay = FADEIN_DELAY
# Make old trainer sprite move off-screen first if necessary
if @idxTrainer>0 && @sprites["trainer_#{@idxTrainer}"].visible
oldTrainer = addSprite(@sprites["trainer_#{@idxTrainer}"],PictureOrigin::Bottom)
oldTrainer.moveDelta(delay,8,Graphics.width/4,0)
oldTrainer.setVisible(delay+8,false)
oldTrainer.moveDelta(delay,TRAINER_SPRITE_MOVE_DURATION,Graphics.width/4,0)
oldTrainer.setVisible(delay+FADEIN_DURATION,false)
delay = oldTrainer.totalDuration
end
# Make new trainer sprite move on-screen
@@ -298,7 +297,7 @@ class TrainerAppearAnimation < PokeBattle_Animation
newTrainer = addSprite(@sprites["trainer_#{@idxTrainer+1}"],PictureOrigin::Bottom)
newTrainer.setVisible(delay,true)
newTrainer.setXY(delay,trainerX,trainerY)
newTrainer.moveDelta(delay,8,-Graphics.width/4,0)
newTrainer.moveDelta(delay,TRAINER_SPRITE_MOVE_DURATION,-Graphics.width/4,0)
end
end
end
@@ -311,6 +310,9 @@ end
# Doesn't show the ball thrown or the Pokémon.
#===============================================================================
class PlayerFadeAnimation < PokeBattle_Animation
TRAINER_SPRITE_MOVE_DURATION = 8 #16
FADEOUT_DURATION = 6 #12
FADEOUT_DELAY = 2
def initialize(sprites,viewport,fullAnim=false)
@fullAnim = fullAnim # True at start of battle, false when switching
super(sprites,viewport)
@@ -326,7 +328,7 @@ class PlayerFadeAnimation < PokeBattle_Animation
i += 1
next if !pl.visible || pl.x<0
trainer = addSprite(pl,PictureOrigin::Bottom)
trainer.moveDelta(0,16,-Graphics.width/2,0)
trainer.moveDelta(0,TRAINER_SPRITE_MOVE_DURATION,-Graphics.width/2,0)
# Animate trainer sprite(s) if they have multiple frames
if pl.bitmap && !pl.bitmap.disposed? && pl.bitmap.width>=pl.bitmap.height*2
size = pl.src_rect.width # Width per frame
@@ -335,24 +337,24 @@ class PlayerFadeAnimation < PokeBattle_Animation
trainer.setSrc(7,size*3,0)
trainer.setSrc(9,size*4,0)
end
trainer.setVisible(16,false)
trainer.setVisible(TRAINER_SPRITE_MOVE_DURATION,false)
end
# Move and fade party bar/balls
delay = 3
delay = FADEOUT_DELAY
if @sprites["partyBar_0"] && @sprites["partyBar_0"].visible
partyBar = addSprite(@sprites["partyBar_0"])
partyBar.moveDelta(delay,16,-Graphics.width/4,0) if @fullAnim
partyBar.moveOpacity(delay,12,0)
partyBar.setVisible(delay+12,false)
partyBar.setOpacity(delay+12,255)
partyBar.moveDelta(delay,TRAINER_SPRITE_MOVE_DURATION,-Graphics.width/4,0) if @fullAnim
partyBar.moveOpacity(delay,FADEOUT_DURATION,0)
partyBar.setVisible(delay+FADEOUT_DURATION,false)
partyBar.setOpacity(delay+FADEOUT_DURATION,255)
end
for i in 0...PokeBattle_SceneConstants::NUM_BALLS
next if !@sprites["partyBall_0_#{i}"] || !@sprites["partyBall_0_#{i}"].visible
partyBall = addSprite(@sprites["partyBall_0_#{i}"])
partyBall.moveDelta(delay+2*i,16,-Graphics.width,0) if @fullAnim
partyBall.moveOpacity(delay,12,0)
partyBall.setVisible(delay+12,false)
partyBall.setOpacity(delay+12,255)
partyBall.moveDelta(delay+2*i,TRAINER_SPRITE_MOVE_DURATION,-Graphics.width,0) if @fullAnim
partyBall.moveOpacity(delay,FADEOUT_DURATION,0)
partyBall.setVisible(delay+FADEOUT_DURATION,false)
partyBall.setOpacity(delay+FADEOUT_DURATION,255)
end
end
end
@@ -364,6 +366,9 @@ end
# Doesn't show the ball thrown or the Pokémon.
#===============================================================================
class TrainerFadeAnimation < PokeBattle_Animation
TRAINER_SPRITE_MOVE_DURATION = 16 #16
FADEOUT_DURATION = 12 #12
FADEOUT_DELAY = 3
def initialize(sprites,viewport,fullAnim=false)
@fullAnim = fullAnim # True at start of battle, false when switching
super(sprites,viewport)
@@ -379,11 +384,11 @@ class TrainerFadeAnimation < PokeBattle_Animation
i += 1
next if !trSprite.visible || trSprite.x>Graphics.width
trainer = addSprite(trSprite,PictureOrigin::Bottom)
trainer.moveDelta(0,16,Graphics.width/2,0)
trainer.setVisible(16,false)
trainer.moveDelta(0,TRAINER_SPRITE_MOVE_DURATION,Graphics.width/2,0)
trainer.setVisible(TRAINER_SPRITE_MOVE_DURATION,false)
end
# Move and fade party bar/balls
delay = 3
delay = FADEOUT_DELAY
if @sprites["partyBar_1"] && @sprites["partyBar_1"].visible
partyBar = addSprite(@sprites["partyBar_1"])
partyBar.moveDelta(delay,16,Graphics.width/4,0) if @fullAnim
@@ -394,10 +399,10 @@ class TrainerFadeAnimation < PokeBattle_Animation
for i in 0...PokeBattle_SceneConstants::NUM_BALLS
next if !@sprites["partyBall_1_#{i}"] || !@sprites["partyBall_1_#{i}"].visible
partyBall = addSprite(@sprites["partyBall_1_#{i}"])
partyBall.moveDelta(delay+2*i,16,Graphics.width,0) if @fullAnim
partyBall.moveOpacity(delay,12,0)
partyBall.setVisible(delay+12,false)
partyBall.setOpacity(delay+12,255)
partyBall.moveDelta(delay+2*i,TRAINER_SPRITE_MOVE_DURATION,Graphics.width,0) if @fullAnim
partyBall.moveOpacity(delay,FADEOUT_DURATION,0)
partyBall.setVisible(delay+FADEOUT_DURATION,false)
partyBall.setOpacity(delay+FADEOUT_DURATION,255)
end
end
end
@@ -455,7 +460,7 @@ class PokeballPlayerSendOutAnimation < PokeBattle_Animation
delay = ball.totalDuration # 0 or 7
# Poké Ball trajectory animation
createBallTrajectory(ball,delay,12,
ballStartX,ballStartY,ballMidX,ballMidY,battlerStartX,battlerStartY-18)
ballStartX,ballStartY,ballMidX,ballMidY,battlerStartX,battlerStartY-18)
ball.setZ(9,batSprite.z-1)
delay = ball.totalDuration+4
delay += 10*@idxOrder # Stagger appearances if multiple Pokémon are sent out at once
@@ -659,7 +664,7 @@ class BattlerFaintAnimation < PokeBattle_Animation
# Get approx duration depending on sprite's position/size. Min 20 frames.
battlerTop = batSprite.y-batSprite.height
cropY = PokeBattle_SceneConstants.pbBattlerPosition(@idxBattler,
@battle.pbSideSize(@idxBattler))[1]
@battle.pbSideSize(@idxBattler))[1]
cropY += 8
duration = (cropY-battlerTop)/8
duration = 5#10 if duration<10 # Min 0.5 seconds
@@ -733,7 +738,7 @@ class PokeballThrowCaptureAnimation < PokeBattle_Animation
# Poké Ball arc animation
ball.setSE(delay,"Battle throw")
createBallTrajectory(ball,delay,16,
ballStartX,ballStartY,ballMidX,ballMidY,ballEndX,ballEndY)
ballStartX,ballStartY,ballMidX,ballMidY,ballEndX,ballEndY)
ball.setZ(9,batSprite.z+1)
ball.setSE(delay+16,"Battle ball hit")
# Poké Ball opens up
@@ -866,7 +871,7 @@ class PokeballThrowDeflectAnimation < PokeBattle_Animation
# Poké Ball arc animation
ball.setSE(0,"Battle throw")
createBallTrajectory(ball,0,16,
ballStartX,ballStartY,ballMidX,ballMidY,ballEndX,ballEndY)
ballStartX,ballStartY,ballMidX,ballMidY,ballEndX,ballEndY)
# Poké Ball knocked back
delay = ball.totalDuration
ball.setSE(delay,"Battle ball drop")
@@ -2,13 +2,13 @@
# Data box for regular battles
#===============================================================================
class PokemonDataBox < SpriteWrapper
attr_reader :battler
attr_reader :battler
attr_accessor :selected
attr_reader :animatingHP
attr_reader :animatingExp
attr_reader :animatingHP
attr_reader :animatingExp
# Time in seconds to fully fill the Exp bar (from empty).
EXP_BAR_FILL_TIME = 1.75
EXP_BAR_FILL_TIME = 1.75
# Maximum time in seconds to make a change to the HP bar.
HP_BAR_CHANGE_TIME = 1.0
STATUS_ICON_HEIGHT = 16
@@ -18,75 +18,71 @@ class PokemonDataBox < SpriteWrapper
# MALE_SHADOW_COLOR = NAME_SHADOW_COLOR
# FEMALE_BASE_COLOR = Color.new(248,88,40)
# FEMALE_SHADOW_COLOR = NAME_SHADOW_COLOR
NAME_BASE_COLOR = Color.new(255,255,255)
NAME_SHADOW_COLOR = Color.new(32,32,32)
MALE_BASE_COLOR = Color.new(48,96,216)
MALE_SHADOW_COLOR = NAME_SHADOW_COLOR
FEMALE_BASE_COLOR = Color.new(248,88,40)
FEMALE_SHADOW_COLOR = NAME_SHADOW_COLOR
NAME_BASE_COLOR = Color.new(255, 255, 255)
NAME_SHADOW_COLOR = Color.new(32, 32, 32)
MALE_BASE_COLOR = Color.new(48, 96, 216)
MALE_SHADOW_COLOR = NAME_SHADOW_COLOR
FEMALE_BASE_COLOR = Color.new(248, 88, 40)
FEMALE_SHADOW_COLOR = NAME_SHADOW_COLOR
def initialize(battler,sideSize,viewport=nil)
def initialize(battler, sideSize, viewport = nil)
super(viewport)
@battler = battler
@sprites = {}
@spriteX = 0
@spriteY = 0
@spriteBaseX = 0
@selected = 0
@frame = 0
@showHP = false # Specifically, show the HP numbers
@animatingHP = false
@showExp = false # Specifically, show the Exp bar
@battler = battler
@sprites = {}
@spriteX = 0
@spriteY = 0
@spriteBaseX = 0
@selected = 0
@frame = 0
@showHP = false # Specifically, show the HP numbers
@animatingHP = false
@showExp = false # Specifically, show the Exp bar
@animatingExp = false
@expFlash = 0
@expFlash = 0
initializeDataBoxGraphic(sideSize)
initializeOtherGraphics(viewport)
refresh
end
def initializeDataBoxGraphic(sideSize)
onPlayerSide = ((@battler.index%2)==0)
onPlayerSide = ((@battler.index % 2) == 0)
# Get the data box graphic and set whether the HP numbers/Exp bar are shown
if sideSize==1 # One Pokémon on side, use the regular dara box BG
if sideSize == 1 # One Pokémon on side, use the regular dara box BG
bgFilename = ["Graphics/Pictures/Battle/databox_normal",
"Graphics/Pictures/Battle/databox_normal_foe"][@battler.index%2]
"Graphics/Pictures/Battle/databox_normal_foe"][@battler.index % 2]
if onPlayerSide
@showHP = true
@showHP = true
@showExp = true
end
else # Multiple Pokémon on side, use the thin dara box BG
else
# Multiple Pokémon on side, use the thin dara box BG
bgFilename = ["Graphics/Pictures/Battle/databox_thin",
"Graphics/Pictures/Battle/databox_thin_foe"][@battler.index%2]
"Graphics/Pictures/Battle/databox_thin_foe"][@battler.index % 2]
end
@databoxBitmap = AnimatedBitmap.new(bgFilename)
@databoxBitmap = AnimatedBitmap.new(bgFilename)
# Determine the co-ordinates of the data box and the left edge padding width
if onPlayerSide
@spriteX = Graphics.width - 244
@spriteY = Graphics.height - 176#192
@spriteY = Graphics.height - 176 # 192
@spriteBaseX = 34
else
@spriteX = 8 #-16
@spriteY = 0##36
@spriteBaseX = 8 #16
@spriteY = 0 ##36
@spriteBaseX = 8 # 16
end
case sideSize
when 2
@spriteX += [-12, 12, 0, 0][@battler.index]
@spriteX += [-12, 12, 0, 0][@battler.index]
#@spriteY += [-38, -6, 16, 48][@battler.index] #standard
#@spriteY += [-32, -6, 16, 42][@battler.index] #smaller gap
@spriteY += [-18, -6, 16, 28][@battler.index] #overlap
@spriteY += [-18, -6, 16, 28][@battler.index] # overlap
#@spriteY += [-20, -34, 34, 20][@battler.index]
when 3
@spriteX += [-12, 12, -6, 6, 0, 0][@battler.index]
@spriteX += [-12, 12, -6, 6, 0, 0][@battler.index]
#@spriteY += [-74, -8, -28, 38, 16, 84][@battler.index] #standard
@spriteY += [-54, -8, -18, 26, 16, 58][@battler.index] #overlap
@spriteY += [-54, -8, -18, 26, 16, 58][@battler.index] # overlap
end
end
@@ -94,26 +90,26 @@ class PokemonDataBox < SpriteWrapper
def initializeOtherGraphics(viewport)
# Create other bitmaps
@numbersBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/icon_numbers")
@hpBarBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/overlay_hp")
@expBarBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/overlay_exp")
@hpBarBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/overlay_hp")
@expBarBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/overlay_exp")
# Create sprite to draw HP numbers on
@hpNumbers = BitmapSprite.new(124,16,viewport)
@hpNumbers = BitmapSprite.new(124, 16, viewport)
pbSetSmallFont(@hpNumbers.bitmap)
@sprites["hpNumbers"] = @hpNumbers
# Create sprite wrapper that displays HP bar
@hpBar = SpriteWrapper.new(viewport)
@hpBar.bitmap = @hpBarBitmap.bitmap
@hpBar.src_rect.height = @hpBarBitmap.height/3
@hpBar.src_rect.height = @hpBarBitmap.height / 3
@sprites["hpBar"] = @hpBar
# Create sprite wrapper that displays Exp bar
@expBar = SpriteWrapper.new(viewport)
@expBar.bitmap = @expBarBitmap.bitmap
@sprites["expBar"] = @expBar
# Create sprite wrapper that displays everything except the above
@contents = BitmapWrapper.new(@databoxBitmap.width+14,@databoxBitmap.height)
self.bitmap = @contents
@contents = BitmapWrapper.new(@databoxBitmap.width + 14, @databoxBitmap.height)
self.bitmap = @contents
self.visible = false
self.z = 150+((@battler.index)/2)*5
self.z = 150 + ((@battler.index) / 2) * 5
pbSetSystemFont(self.bitmap)
end
@@ -129,23 +125,23 @@ class PokemonDataBox < SpriteWrapper
def x=(value)
super
@hpBar.x = value+@spriteBaseX+12#102
@expBar.x = value+@spriteBaseX+24
@hpNumbers.x = value+@spriteBaseX+80
@hpBar.x = value + @spriteBaseX + 12 # 102
@expBar.x = value + @spriteBaseX + 24
@hpNumbers.x = value + @spriteBaseX + 80
end
def y=(value)
super
@hpBar.y = value+40
@expBar.y = value+64
@hpNumbers.y = value+52
@hpBar.y = value + 40
@expBar.y = value + 64
@hpNumbers.y = value + 52
end
def z=(value)
super
@hpBar.z = value+1
@expBar.z = value+1
@hpNumbers.z = value+2
@hpBar.z = value + 1
@expBar.z = value + 1
@hpNumbers.z = value + 2
end
def opacity=(value)
@@ -180,42 +176,42 @@ class PokemonDataBox < SpriteWrapper
end
def exp_fraction
return (@animatingExp) ? @currentExp.to_f/@rangeExp : @battler.pokemon.exp_fraction
return (@animatingExp) ? @currentExp.to_f / @rangeExp : @battler.pokemon.exp_fraction
end
def animateHP(oldHP,newHP,rangeHP)
@currentHP = oldHP
@endHP = newHP
@rangeHP = rangeHP
def animateHP(oldHP, newHP, rangeHP)
@currentHP = oldHP
@endHP = newHP
@rangeHP = rangeHP
# NOTE: A change in HP takes the same amount of time to animate, no matter
# how big a change it is.
@hpIncPerFrame = (newHP-oldHP).abs/(HP_BAR_CHANGE_TIME*Graphics.frame_rate)
@hpIncPerFrame = (newHP - oldHP).abs / (HP_BAR_CHANGE_TIME * Graphics.frame_rate)
# minInc is the smallest amount that HP is allowed to change per frame.
# This avoids a tiny change in HP still taking HP_BAR_CHANGE_TIME seconds.
minInc = (rangeHP*4)/(@hpBarBitmap.width*HP_BAR_CHANGE_TIME*Graphics.frame_rate)
@hpIncPerFrame = minInc if @hpIncPerFrame<minInc
@animatingHP = true
minInc = (rangeHP * 4) / (@hpBarBitmap.width * HP_BAR_CHANGE_TIME * Graphics.frame_rate)
@hpIncPerFrame = minInc if @hpIncPerFrame < minInc
@animatingHP = true
end
def animateExp(oldExp,newExp,rangeExp)
@currentExp = oldExp
@endExp = newExp
@rangeExp = rangeExp
def animateExp(oldExp, newExp, rangeExp)
@currentExp = oldExp
@endExp = newExp
@rangeExp = rangeExp
# NOTE: Filling the Exp bar from empty to full takes EXP_BAR_FILL_TIME
# seconds no matter what. Filling half of it takes half as long, etc.
@expIncPerFrame = rangeExp/(EXP_BAR_FILL_TIME*Graphics.frame_rate)
@animatingExp = true
@expIncPerFrame = rangeExp / (EXP_BAR_FILL_TIME * Graphics.frame_rate)
@animatingExp = true
pbSEPlay("Pkmn exp gain") if @showExp
end
def pbDrawNumber(number,btmp,startX,startY,align=0)
def pbDrawNumber(number, btmp, startX, startY, align = 0)
# -1 means draw the / character
n = (number == -1) ? [10] : number.to_i.digits.reverse
charWidth = @numbersBitmap.width/11
charWidth = @numbersBitmap.width / 11
charHeight = @numbersBitmap.height
startX -= charWidth*n.length if align==1
startX -= charWidth * n.length if align == 1
n.each do |i|
btmp.blt(startX,startY,@numbersBitmap.bitmap,Rect.new(i*charWidth,0,charWidth,charHeight))
btmp.blt(startX, startY, @numbersBitmap.bitmap, Rect.new(i * charWidth, 0, charWidth, charHeight))
startX += charWidth
end
end
@@ -226,61 +222,61 @@ class PokemonDataBox < SpriteWrapper
textPos = []
imagePos = []
# Draw background panel
self.bitmap.blt(0,0,@databoxBitmap.bitmap,Rect.new(0,0,@databoxBitmap.width,@databoxBitmap.height))
self.bitmap.blt(0, 0, @databoxBitmap.bitmap, Rect.new(0, 0, @databoxBitmap.width, @databoxBitmap.height))
# Draw Pokémon's name
nameWidth = self.bitmap.text_size(@battler.name).width
nameOffset = 0
nameOffset = nameWidth-116 if nameWidth>116
textPos.push([@battler.name,@spriteBaseX+8-nameOffset,0,false,NAME_BASE_COLOR,NAME_SHADOW_COLOR])
nameOffset = nameWidth - 116 if nameWidth > 116
textPos.push([@battler.name, @spriteBaseX + 8 - nameOffset, 0, false, NAME_BASE_COLOR, NAME_SHADOW_COLOR])
# Draw Pokémon's gender symbol
case @battler.displayGender
when 0 # Male
textPos.push(["",@spriteBaseX+126,0,false,MALE_BASE_COLOR,MALE_SHADOW_COLOR])
when 1 # Female
textPos.push(["",@spriteBaseX+126,0,false,FEMALE_BASE_COLOR,FEMALE_SHADOW_COLOR])
when 0 # Male
textPos.push(["", @spriteBaseX + 126, 0, false, MALE_BASE_COLOR, MALE_SHADOW_COLOR])
when 1 # Female
textPos.push(["", @spriteBaseX + 126, 0, false, FEMALE_BASE_COLOR, FEMALE_SHADOW_COLOR])
end
pbDrawTextPositions(self.bitmap,textPos)
pbDrawTextPositions(self.bitmap, textPos)
# Draw Pokémon's level
imagePos.push(["Graphics/Pictures/Battle/overlay_lv",@spriteBaseX+140,16]) if !$game_switches[SWITCH_NO_LEVELS_MODE]
pbDrawNumber(@battler.level,self.bitmap,@spriteBaseX+162,16) if !$game_switches[SWITCH_NO_LEVELS_MODE]
imagePos.push(["Graphics/Pictures/Battle/overlay_lv", @spriteBaseX + 140, 16]) if !$game_switches[SWITCH_NO_LEVELS_MODE]
pbDrawNumber(@battler.level, self.bitmap, @spriteBaseX + 162, 16) if !$game_switches[SWITCH_NO_LEVELS_MODE]
# Draw shiny icon
if @battler.shiny?
shinyX = (@battler.opposes?(0)) ? -8 : -6 # Foe's/player's
shinyX = (@battler.opposes?(0)) ? -8 : -6 # Foe's/player's
pokeRadarShiny= !@battler.pokemon.debugShiny? && !@battler.pokemon.naturalShiny?
addShinyStarsToGraphicsArray(imagePos,@spriteBaseX+shinyX,15, @battler.pokemon.bodyShiny?,@battler.pokemon.headShiny?,@battler.pokemon.debugShiny?, pokeRadarShiny)
# pokeRadarShiny= !@battler.pokemon.debugShiny? && !@battler.pokemon.naturalShiny?
addShinyStarsToGraphicsArray(imagePos, @spriteBaseX + shinyX, 15, @battler.pokemon.bodyShiny?, @battler.pokemon.headShiny?, @battler.pokemon.debugShiny?, @battler.pokemon.radarShiny?)
end
# Draw Mega Evolution/Primal Reversion icon
if @battler.mega?
imagePos.push(["Graphics/Pictures/Battle/icon_mega",@spriteBaseX+8,34])
imagePos.push(["Graphics/Pictures/Battle/icon_mega", @spriteBaseX + 8, 34])
elsif @battler.primal?
primalX = (@battler.opposes?) ? 208 : -28 # Foe's/player's
primalX = (@battler.opposes?) ? 208 : -28 # Foe's/player's
if @battler.isSpecies?(:KYOGRE)
imagePos.push(["Graphics/Pictures/Battle/icon_primal_Kyogre",@spriteBaseX+primalX,4])
imagePos.push(["Graphics/Pictures/Battle/icon_primal_Kyogre", @spriteBaseX + primalX, 4])
elsif @battler.isSpecies?(:GROUDON)
imagePos.push(["Graphics/Pictures/Battle/icon_primal_Groudon",@spriteBaseX+primalX,4])
imagePos.push(["Graphics/Pictures/Battle/icon_primal_Groudon", @spriteBaseX + primalX, 4])
end
end
# Draw owned icon (foe Pokémon only)
if @battler.owned? && @battler.opposes?(0)
imagePos.push(["Graphics/Pictures/Battle/icon_own",@spriteBaseX-8,42])
imagePos.push(["Graphics/Pictures/Battle/icon_own", @spriteBaseX - 8, 42])
end
# Draw status icon
if @battler.status != :NONE
s = GameData::Status.get(@battler.status).id_number
if s == :POISON && @battler.statusCount > 0 # Badly poisoned
if s == :POISON && @battler.statusCount > 0 # Badly poisoned
s = GameData::Status::DATA.keys.length / 2
end
imagePos.push(["Graphics/Pictures/Battle/icon_statuses",@spriteBaseX+24,56,
0,(s-1)*STATUS_ICON_HEIGHT,-1,STATUS_ICON_HEIGHT])
imagePos.push(["Graphics/Pictures/Battle/icon_statuses", @spriteBaseX + 24, 56,
0, (s - 1) * STATUS_ICON_HEIGHT, -1, STATUS_ICON_HEIGHT])
end
#Draw type icons (foe Pokémon only)
# Draw type icons (foe Pokémon only)
if @battler.opposes?(0) && $PokemonSystem.type_icons
drawEnemyTypeIcons(imagePos)
end
pbDrawImagePositions(self.bitmap,imagePos)
pbDrawImagePositions(self.bitmap, imagePos)
refreshHP
refreshExp
end
@@ -289,33 +285,30 @@ class PokemonDataBox < SpriteWrapper
return if @battler.is_a?(PokeBattle_FakeBattler)
type1_number = GameData::Type.get(@battler.type1).id_number
type2_number = GameData::Type.get(@battler.type2).id_number
echoln type1_number
vertical_margin = 2
iconHeight=19
iconHeight = 19
type_icons_x_position = @spriteBaseX + 210
type1_icon_y_position = 16
type2_icon_y_position = type1_icon_y_position+vertical_margin+iconHeight
type2_icon_y_position = type1_icon_y_position + vertical_margin + iconHeight
type1_y_offset = type1_number*iconHeight
type2_y_offset = type2_number*iconHeight
x_offset=0
type1_y_offset = type1_number * iconHeight
type2_y_offset = type2_number * iconHeight
x_offset = 0
types_icon_path = "Graphics/Pictures/Battle/typesSmall"
if type1_number == type2_number
imagePos.push([types_icon_path,type_icons_x_position,type1_icon_y_position,
x_offset,type1_y_offset,-1,iconHeight])
imagePos.push([types_icon_path, type_icons_x_position, type1_icon_y_position,
x_offset, type1_y_offset, -1, iconHeight])
else
imagePos.push([types_icon_path,type_icons_x_position,
imagePos.push([types_icon_path, type_icons_x_position,
type1_icon_y_position,
x_offset,
type1_y_offset,-1,iconHeight]
type1_y_offset, -1, iconHeight]
)
imagePos.push([types_icon_path,type_icons_x_position,type2_icon_y_position,
imagePos.push([types_icon_path, type_icons_x_position, type2_icon_y_position,
x_offset,
type2_y_offset,-1,iconHeight])
type2_y_offset, -1, iconHeight])
end
end
@@ -324,24 +317,24 @@ class PokemonDataBox < SpriteWrapper
return if !@battler.pokemon
# Show HP numbers
if @showHP
pbDrawNumber(self.hp,@hpNumbers.bitmap,54,2,1)
pbDrawNumber(-1,@hpNumbers.bitmap,54,2) # / char
pbDrawNumber(@battler.totalhp,@hpNumbers.bitmap,70,2)
pbDrawNumber(self.hp, @hpNumbers.bitmap, 54, 2, 1)
pbDrawNumber(-1, @hpNumbers.bitmap, 54, 2) # / char
pbDrawNumber(@battler.totalhp, @hpNumbers.bitmap, 70, 2)
end
# Resize HP bar
w = 0
if self.hp>0
w = @hpBarBitmap.width.to_f*self.hp/@battler.totalhp
w = 1 if w<1
if self.hp > 0
w = @hpBarBitmap.width.to_f * self.hp / @battler.totalhp
w = 1 if w < 1
# NOTE: The line below snaps the bar's width to the nearest 2 pixels, to
# fit in with the rest of the graphics which are doubled in size.
w = ((w/2.0).round)*2
w = ((w / 2.0).round) * 2
end
@hpBar.src_rect.width = w
hpColor = 0 # Green bar
hpColor = 1 if self.hp<=@battler.totalhp/2 # Yellow bar
hpColor = 2 if self.hp<=@battler.totalhp/4 # Red bar
@hpBar.src_rect.y = hpColor*@hpBarBitmap.height/3
hpColor = 0 # Green bar
hpColor = 1 if self.hp <= @battler.totalhp / 2 # Yellow bar
hpColor = 2 if self.hp <= @battler.totalhp / 4 # Red bar
@hpBar.src_rect.y = hpColor * @hpBarBitmap.height / 3
end
def refreshExp
@@ -350,54 +343,54 @@ class PokemonDataBox < SpriteWrapper
w = exp_fraction * @expBarBitmap.width
# NOTE: The line below snaps the bar's width to the nearest 2 pixels, to
# fit in with the rest of the graphics which are doubled in size.
w = ((w/2).round)*2
w = ((w / 2).round) * 2
@expBar.src_rect.width = w
end
def updateHPAnimation
return if !@animatingHP
if @currentHP<@endHP # Gaining HP
if @currentHP < @endHP # Gaining HP
@currentHP += @hpIncPerFrame
@currentHP = @endHP if @currentHP>=@endHP
elsif @currentHP>@endHP # Losing HP
@currentHP = @endHP if @currentHP >= @endHP
elsif @currentHP > @endHP # Losing HP
@currentHP -= @hpIncPerFrame
@currentHP = @endHP if @currentHP<=@endHP
@currentHP = @endHP if @currentHP <= @endHP
end
# Refresh the HP bar/numbers
refreshHP
@animatingHP = false if @currentHP==@endHP
@animatingHP = false if @currentHP == @endHP
end
def updateExpAnimation
return if !@animatingExp
if !@showExp # Not showing the Exp bar, no need to waste time animating it
if !@showExp # Not showing the Exp bar, no need to waste time animating it
@currentExp = @endExp
@animatingExp = false
return
end
if @currentExp<@endExp # Gaining Exp
if @currentExp < @endExp # Gaining Exp
@currentExp += @expIncPerFrame
@currentExp = @endExp if @currentExp>=@endExp
elsif @currentExp>@endExp # Losing Exp
@currentExp = @endExp if @currentExp >= @endExp
elsif @currentExp > @endExp # Losing Exp
@currentExp -= @expIncPerFrame
@currentExp = @endExp if @currentExp<=@endExp
@currentExp = @endExp if @currentExp <= @endExp
end
# Refresh the Exp bar
refreshExp
return if @currentExp!=@endExp # Exp bar still has more to animate
return if @currentExp != @endExp # Exp bar still has more to animate
# Exp bar is completely filled, level up with a flash and sound effect
if @currentExp>=@rangeExp
if @expFlash==0
if @currentExp >= @rangeExp
if @expFlash == 0
pbSEStop
@expFlash = Graphics.frame_rate/5
@expFlash = Graphics.frame_rate / 5
pbSEPlay("Pkmn exp full")
self.flash(Color.new(64,200,248,192),@expFlash)
self.flash(Color.new(64, 200, 248, 192), @expFlash)
for i in @sprites
i[1].flash(Color.new(64,200,248,192),@expFlash) if !i[1].disposed?
i[1].flash(Color.new(64, 200, 248, 192), @expFlash) if !i[1].disposed?
end
else
@expFlash -= 1
@animatingExp = false if @expFlash==0
@animatingExp = false if @expFlash == 0
end
else
pbSEStop
@@ -406,21 +399,21 @@ class PokemonDataBox < SpriteWrapper
end
end
QUARTER_ANIM_PERIOD = Graphics.frame_rate*3/20
QUARTER_ANIM_PERIOD = Graphics.frame_rate * 3 / 20
def updatePositions(frameCounter)
self.x = @spriteX
self.y = @spriteY
# Data box bobbing while Pokémon is selected
if @selected==1 || @selected==2 # Choosing commands/targeted or damaged
case (frameCounter/QUARTER_ANIM_PERIOD).floor
when 1 then self.y = @spriteY-2
when 3 then self.y = @spriteY+2
if @selected == 1 || @selected == 2 # Choosing commands/targeted or damaged
case (frameCounter / QUARTER_ANIM_PERIOD).floor
when 1 then self.y = @spriteY - 2
when 3 then self.y = @spriteY + 2
end
end
end
def update(frameCounter=0)
def update(frameCounter = 0)
super()
# Animate HP bar
updateHPAnimation
@@ -432,37 +425,35 @@ class PokemonDataBox < SpriteWrapper
end
end
#===============================================================================
# Splash bar to announce a triggered ability
#===============================================================================
class AbilitySplashBar < SpriteWrapper
attr_reader :battler
TEXT_BASE_COLOR = Color.new(0,0,0)
TEXT_SHADOW_COLOR = Color.new(248,248,248)
TEXT_BASE_COLOR = Color.new(0, 0, 0)
TEXT_SHADOW_COLOR = Color.new(248, 248, 248)
def initialize(side,viewport=nil, secondAbility=false)
def initialize(side, viewport = nil, secondAbility = false)
super(viewport)
@ability_name=nil
@secondAbility=secondAbility
@side = side
@ability_name = nil
@secondAbility = secondAbility
@side = side
@battler = nil
# Create sprite wrapper that displays background graphic
@bgBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/ability_bar")
@bgSprite = SpriteWrapper.new(viewport)
@bgSprite.bitmap = @bgBitmap.bitmap
@bgSprite.src_rect.y = (side==0) ? 0 : @bgBitmap.height/2
@bgSprite.src_rect.height = @bgBitmap.height/2
@bgSprite.src_rect.y = (side == 0) ? 0 : @bgBitmap.height / 2
@bgSprite.src_rect.height = @bgBitmap.height / 2
# Create bitmap that displays the text
@contents = BitmapWrapper.new(@bgBitmap.width,@bgBitmap.height/2)
@contents = BitmapWrapper.new(@bgBitmap.width, @bgBitmap.height / 2)
self.bitmap = @contents
pbSetSystemFont(self.bitmap)
# Position the bar
self.x = (side==0) ? -Graphics.width/2 : Graphics.width
self.y = (side==0) ? 180 : 80
self.z = 120
self.x = (side == 0) ? -Graphics.width / 2 : Graphics.width
self.y = (side == 0) ? 180 : 80
self.z = 120
self.visible = false
end
@@ -485,11 +476,11 @@ class AbilitySplashBar < SpriteWrapper
def z=(value)
super
@bgSprite.z = value-1
@bgSprite.z = value - 1
end
def ability_name=(value)
@ability_name=value
@ability_name = value
end
def opacity=(value)
@@ -515,21 +506,22 @@ class AbilitySplashBar < SpriteWrapper
def secondAbility=(value)
@secondAbility = value
end
def refresh
self.bitmap.clear
return if !@battler
textPos = []
textX = (@side==0) ? 10 : self.bitmap.width-8
textX = (@side == 0) ? 10 : self.bitmap.width - 8
# Draw Pokémon's name
textPos.push([_INTL("{1}'s",@battler.name),textX,-4,@side==1,
TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true]) if !@secondAbility
textPos.push([_INTL("{1}'s", @battler.name), textX, -4, @side == 1,
TEXT_BASE_COLOR, TEXT_SHADOW_COLOR, true]) if !@secondAbility
# Draw Pokémon's ability
abilityName = @secondAbility ? @battler.ability2Name : @battler.abilityName
abilityName = @battler.abilityName
abilityName = @ability_name if @ability_name
#return if abilityName ==""
textPos.push([abilityName,textX,26,@side==1,
TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
pbDrawTextPositions(self.bitmap,textPos)
# return if abilityName ==""
textPos.push([abilityName, textX, 26, @side == 1,
TEXT_BASE_COLOR, TEXT_SHADOW_COLOR, true])
pbDrawTextPositions(self.bitmap, textPos)
end
def update
@@ -538,35 +530,33 @@ class AbilitySplashBar < SpriteWrapper
end
end
#===============================================================================
# Pokémon sprite (used in battle)
#===============================================================================
class PokemonBattlerSprite < RPG::Sprite
attr_reader :pkmn
attr_reader :pkmn
attr_accessor :index
attr_accessor :selected
attr_reader :sideSize
attr_reader :sideSize
def initialize(viewport,sideSize,index,battleAnimations)
def initialize(viewport, sideSize, index, battleAnimations)
super(viewport)
@pkmn = nil
@sideSize = sideSize
@index = index
@pkmn = nil
@sideSize = sideSize
@index = index
@battleAnimations = battleAnimations
# @selected: 0 = not selected, 1 = choosing action bobbing for this Pokémon,
# 2 = flashing when targeted
@selected = 0
@frame = 0
@updating = false
@spriteX = 0 # Actual x coordinate
@spriteY = 0 # Actual y coordinate
@spriteXExtra = 0 # Offset due to "bobbing" animation
@spriteYExtra = 0 # Offset due to "bobbing" animation
@_iconBitmap = nil
self.visible = false
@back=false
@selected = 0
@frame = 0
@updating = false
@spriteX = 0 # Actual x coordinate
@spriteY = 0 # Actual y coordinate
@spriteXExtra = 0 # Offset due to "bobbing" animation
@spriteYExtra = 0 # Offset due to "bobbing" animation
@_iconBitmap = nil
self.visible = false
@back = false
end
def dispose
@@ -576,65 +566,75 @@ class PokemonBattlerSprite < RPG::Sprite
super
end
def x; return @spriteX; end
def y; return @spriteY; end
def x
return @spriteX;
end
def y
return @spriteY;
end
def x=(value)
@spriteX = value
self.mirror=true if @back
super(value+@spriteXExtra)
self.mirror = true if @back
super(value + @spriteXExtra)
end
def y=(value)
@spriteY = value
self.mirror=true if @back
super(value+@spriteYExtra)
self.mirror = true if @back
super(value + @spriteYExtra)
end
def width; return (self.bitmap) ? self.bitmap.width : 0; end
def height; return (self.bitmap) ? self.bitmap.height : 0; end
def width
return (self.bitmap) ? self.bitmap.width : 0;
end
def height
return (self.bitmap) ? self.bitmap.height : 0;
end
def visible=(value)
@spriteVisible = value if !@updating # For selection/targeting flashing
@spriteVisible = value if !@updating # For selection/targeting flashing
super
end
# Set sprite's origin to bottom middle
def pbSetOrigin
return if !@_iconBitmap
self.mirror=true if @back
self.ox = @_iconBitmap.width/2
self.mirror = true if @back
self.ox = @_iconBitmap.width / 2
self.oy = @_iconBitmap.height
end
def pbSetPosition
return if !@_iconBitmap
pbSetOrigin
if (@index%2)==0
self.z = 50+5*@index/2
if (@index % 2) == 0
self.z = 50 + 5 * @index / 2
else
self.z = 50-5*(@index+1)/2
self.z = 50 - 5 * (@index + 1) / 2
end
# Set original position
p = PokeBattle_SceneConstants.pbBattlerPosition(@index,@sideSize)
p = PokeBattle_SceneConstants.pbBattlerPosition(@index, @sideSize)
@spriteX = p[0]
@spriteY = p[1]
# Apply metrics
@pkmn.species_data.apply_metrics_to_sprite(self, @index)
end
def setPokemonBitmap(pkmn,back=false)
def setPokemonBitmap(pkmn, back = false)
@back = back
self.mirror=true if @back
self.mirror = true if @back
@pkmn = pkmn
@_iconBitmap.dispose if @_iconBitmap
@_iconBitmap = GameData::Species.sprite_bitmap_from_pokemon(@pkmn, back)
scale =Settings::FRONTSPRITE_SCALE
scale = Settings::FRONTSPRITE_SCALE
scale = Settings::BACKRPSPRITE_SCALE if @back
@_iconBitmap.scale_bitmap(scale)
self.bitmap = (@_iconBitmap) ? @_iconBitmap.bitmap : nil
add_hat_to_bitmap(self.bitmap,pkmn.hat,pkmn.hat_x,pkmn.hat_y,scale,pkmn.hat_mirrored_horizontal,pkmn.hat_mirrored_vertical) if self.bitmap && pkmn.hat
add_hat_to_bitmap(self.bitmap, pkmn.hat, pkmn.hat_x, pkmn.hat_y, scale, pkmn.hat_mirrored_horizontal, pkmn.hat_mirrored_vertical) if self.bitmap && pkmn.hat
pbSetPosition
end
@@ -643,14 +643,14 @@ class PokemonBattlerSprite < RPG::Sprite
# this is just playing the Pokémon's cry, but you can expand on it. The
# recommendation is to create a PictureEx animation and push it into
# the @battleAnimations array.
def pbPlayIntroAnimation(pictureEx=nil)
def pbPlayIntroAnimation(pictureEx = nil)
@pkmn.play_cry if @pkmn
end
QUARTER_ANIM_PERIOD = Graphics.frame_rate*3/20
SIXTH_ANIM_PERIOD = Graphics.frame_rate*2/20
QUARTER_ANIM_PERIOD = Graphics.frame_rate * 3 / 20
SIXTH_ANIM_PERIOD = Graphics.frame_rate * 2 / 20
def update(frameCounter=0)
def update(frameCounter = 0)
return if !@_iconBitmap
@updating = true
# Update bitmap
@@ -658,41 +658,54 @@ class PokemonBattlerSprite < RPG::Sprite
self.bitmap = @_iconBitmap.bitmap
# Pokémon sprite bobbing while Pokémon is selected
@spriteYExtra = 0
if @selected==1 # When choosing commands for this Pokémon
case (frameCounter/QUARTER_ANIM_PERIOD).floor
# Pokémon sprite bobbing — faster when selected, gentle idle bob otherwise
if @selected == 1 # When choosing commands for this Pokémon
case (frameCounter / QUARTER_ANIM_PERIOD).floor
when 1 then @spriteYExtra = 2
when 3 then @spriteYExtra = -2
else @spriteYExtra = 0
end
elsif !($PokemonSystem.nobattlemovement)
idle_period = Graphics.frame_rate * 4
amplitude = 2
phase_offset = (@index * idle_period * 0.7 / (2 * Math::PI)).round # frame offset instead of radian offset
t = (frameCounter + phase_offset) % idle_period
half = idle_period / 2.0
if t < half
@spriteYExtra = ((t / half) * amplitude * 2 - amplitude).round
else
@spriteYExtra = (amplitude - ((t - half) / half) * amplitude * 2).round
end
end
self.x = self.x
self.y = self.y
self.x = self.x
self.y = self.y
self.visible = @spriteVisible
# Pokémon sprite blinking when targeted
if @selected==2 && @spriteVisible
case (frameCounter/SIXTH_ANIM_PERIOD).floor
if @selected == 2 && @spriteVisible
case (frameCounter / SIXTH_ANIM_PERIOD).floor
when 2, 5 then self.visible = false
else self.visible = true
else self.visible = true
end
end
@updating = false
end
end
#===============================================================================
# Shadow sprite for Pokémon (used in battle)
#===============================================================================
class PokemonBattlerShadowSprite < RPG::Sprite
attr_reader :pkmn
attr_reader :pkmn
attr_accessor :index
attr_accessor :selected
def initialize(viewport,sideSize,index)
def initialize(viewport, sideSize, index)
super(viewport)
@pkmn = nil
@sideSize = sideSize
@index = index
@pkmn = nil
@sideSize = sideSize
@index = index
@_iconBitmap = nil
self.visible = false
end
@@ -704,14 +717,19 @@ class PokemonBattlerShadowSprite < RPG::Sprite
super
end
def width; return (self.bitmap) ? self.bitmap.width : 0; end
def height; return (self.bitmap) ? self.bitmap.height : 0; end
def width
return (self.bitmap) ? self.bitmap.width : 0;
end
def height
return (self.bitmap) ? self.bitmap.height : 0;
end
# Set sprite's origin to centre
def pbSetOrigin
return if !@_iconBitmap
self.ox = @_iconBitmap.width/2
self.oy = @_iconBitmap.height/2
self.ox = @_iconBitmap.width / 2
self.oy = @_iconBitmap.height / 2
end
def pbSetPosition
@@ -719,7 +737,7 @@ class PokemonBattlerShadowSprite < RPG::Sprite
pbSetOrigin
self.z = 3
# Set original position
p = PokeBattle_SceneConstants.pbBattlerPosition(@index,@sideSize)
p = PokeBattle_SceneConstants.pbBattlerPosition(@index, @sideSize)
self.x = p[0]
self.y = p[1]
# Apply metrics
@@ -734,7 +752,7 @@ class PokemonBattlerShadowSprite < RPG::Sprite
pbSetPosition
end
def update(frameCounter=0)
def update(frameCounter = 0)
return if !@_iconBitmap
# Update bitmap
@_iconBitmap.update
@@ -112,15 +112,28 @@ class CommandMenuDisplay < BattleMenuBase
[0,8,1,3] # 4 = Bug Catching Contest
]
def initialize(viewport,z)
def initialize(viewport,z,baseColor=nil,shadowColor=nil)
super(viewport)
self.x = 0
self.y = Graphics.height-96
# Create message box (shows "What will X do?")
@msgBox = Window_UnformattedTextPokemon.newWithSize("",
self.x+16,self.y+2,220,Graphics.height-self.y,viewport)
@msgBox.baseColor = TEXT_BASE_COLOR
@msgBox.shadowColor = TEXT_SHADOW_COLOR
@baseColor = baseColor || PokeBattle_SceneConstants::MESSAGE_BASE_COLOR
@shadowColor = shadowColor || PokeBattle_SceneConstants::MESSAGE_SHADOW_COLOR
if isDarkMode
@baseColor, @shadowColor = @shadowColor, @baseColor
end
@msgBox.baseColor = @baseColor
@msgBox.shadowColor = @shadowColor
if isDarkMode
@msgBox.baseColor, @msgBox.shadowColor = @msgBox.shadowColor, @msgBox.baseColor
end
@msgBox.windowskin = nil
addSprite("msgBox",@msgBox)
if USE_GRAPHICS
@@ -128,8 +141,11 @@ class CommandMenuDisplay < BattleMenuBase
background = IconSprite.new(self.x,self.y,viewport)
background.setBitmap("Graphics/Pictures/Battle/overlay_command")
addSprite("background",background)
commands_img_path = "Graphics/Pictures/Battle/cursor_command"
commands_img_path += "_dark" if isDarkMode
# Create bitmaps
@buttonBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/cursor_command")
@buttonBitmap = AnimatedBitmap.new(commands_img_path)
# Create action buttons
@buttons = Array.new(4) do |i| # 4 command options, therefore 4 buttons
button = SpriteWrapper.new(viewport)
@@ -229,8 +245,14 @@ class FightMenuDisplay < BattleMenuBase
# 0=don't show, 1=show unpressed, 2=show pressed
if USE_GRAPHICS
# Create bitmaps
@buttonBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/cursor_fight")
@typeBitmap = AnimatedBitmap.new("Graphics/Pictures/types")
button_path = "Graphics/Pictures/Battle/cursor_fight"
type_path = "Graphics/Pictures/types"
if isDarkMode
button_path += "_dark"
end
@buttonBitmap = AnimatedBitmap.new(button_path)
@typeBitmap = AnimatedBitmap.new(type_path)
@megaEvoBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/cursor_mega")
@shiftBitmap = AnimatedBitmap.new("Graphics/Pictures/Battle/cursor_shift")
# Create background graphic
@@ -358,7 +380,11 @@ class FightMenuDisplay < BattleMenuBase
# of code to ensure the font is an appropriate colour.
moveNameBase = button.bitmap.get_pixel(10,button.src_rect.y+34)
end
textPos.push([moves[i].name,x,y,2,moveNameBase,TEXT_SHADOW_COLOR])
if isDarkMode
textPos.push([moves[i].name,x,y,2,TEXT_SHADOW_COLOR,moveNameBase])
else
textPos.push([moves[i].name,x,y,2,moveNameBase,TEXT_SHADOW_COLOR])
end
end
pbDrawTextPositions(@pokemon_name_overlay.bitmap, textPos)
end
@@ -406,8 +432,15 @@ class FightMenuDisplay < BattleMenuBase
if move.total_pp>0
ppFraction = [(4.0*move.pp/move.total_pp).ceil,3].min
textPos = []
ppColorBase = PP_COLORS[ppFraction*2]
ppColorShadow = PP_COLORS[ppFraction*2+1]
if isDarkMode
ppColorBase, ppColorShadow = ppColorShadow, ppColorBase
end
textPos.push([_INTL("PP: {1}/{2}",move.pp,move.total_pp),
448,44,2,PP_COLORS[ppFraction*2],PP_COLORS[ppFraction*2+1]])
448,44,2,ppColorBase,ppColorShadow])
pbDrawTextPositions(@infoOverlay.bitmap,textPos)
end
end
@@ -174,7 +174,7 @@ class PokeBattle_Scene
yielded = true
end
if !@battleEnd
if i>=MESSAGE_PAUSE_TIME*3 # Autoclose after 3 seconds
if i>=MESSAGE_PAUSE_TIME*2 # Autoclose after 3 seconds
cw.text = ""
cw.visible = false
break
@@ -348,4 +348,31 @@ class PokeBattle_Scene
@battleEnd = true
pbBGMPlay(pbGetTrainerVictoryME(@battle.opponent))
end
def pbShowAbilitySplash(battler,secondAbility=false, abilityName=nil)
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
side = battler.index%2
if secondAbility
pbHideAbilitySplash(battler) if @sprites["ability2Bar_#{side}"].visible
else
pbHideAbilitySplash(battler) if @sprites["abilityBar_#{side}"].visible
end
if abilityName
@sprites["abilityBar_#{side}"].ability_name = abilityName if !secondAbility
@sprites["ability2Bar_#{side}"].ability_name = abilityName if secondAbility
end
@sprites["abilityBar_#{side}"].battler = battler
@sprites["ability2Bar_#{side}"].battler = battler if @sprites["ability2Bar_#{side}"]
abilitySplashAnim = AbilitySplashAppearAnimation.new(@sprites,@viewport,side,secondAbility)
loop do
abilitySplashAnim.update
pbUpdate
break if abilitySplashAnim.animDone?
end
abilitySplashAnim.dispose
end
end
@@ -35,12 +35,20 @@ class PokeBattle_Scene
16, Graphics.height - 96 + 2, Graphics.width - 32, 96, @viewport)
msgWindow.z = 200
msgWindow.opacity = 0
msgWindow.baseColor = PokeBattle_SceneConstants::MESSAGE_BASE_COLOR
msgWindow.shadowColor = PokeBattle_SceneConstants::MESSAGE_SHADOW_COLOR
base_color = PokeBattle_SceneConstants::MESSAGE_BASE_COLOR
shadow_color = PokeBattle_SceneConstants::MESSAGE_SHADOW_COLOR
if isDarkMode
base_color, shadow_color = shadow_color, base_color
end
msgWindow.baseColor = base_color
msgWindow.shadowColor = shadow_color
msgWindow.letterbyletter = true
@sprites["messageWindow"] = msgWindow
# Create command window
@sprites["commandWindow"] = CommandMenuDisplay.new(@viewport, 200)
@sprites["commandWindow"] = CommandMenuDisplay.new(@viewport, 200,base_color,shadow_color)
# Create fight window
@sprites["fightWindow"] = FightMenuDisplay.new(@viewport, 200)
# Create targeting window
@@ -61,10 +69,6 @@ class PokeBattle_Scene
# Ability splash bars
if PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@sprites["abilityBar_#{side}"] = AbilitySplashBar.new(side, @viewport)
if $game_switches[SWITCH_DOUBLE_ABILITIES]
@sprites["ability2Bar_#{side}"] = AbilitySplashBar.new(side, @viewport, true)
@sprites["ability2Bar_#{side}"].y = @sprites["ability2Bar_#{side}"].y + 30
end
end
end
# Player's and partner trainer's back sprite
@@ -111,11 +115,11 @@ class PokeBattle_Scene
when :BACKGROUND then
base_path = "Graphics/Battlebacks/battlebg/"
when :ENEMYBASE then
base_path = "Graphics/Battlebacks/enemybase/"
base_path = "Graphics/Battlebacks/base/"
when :PLAYERBASE then
base_path = "Graphics/Battlebacks/playerbase/"
base_path = "Graphics/Battlebacks/base/"
when :MESSAGE then
base_path = "Graphics/Battlebacks/"
base_path = "Graphics/Battlebacks/message/"
end
return base_path
end
@@ -124,6 +128,8 @@ class PokeBattle_Scene
time = getBackdropTimeSuffix()
base_path = getBackdropBasePath(backdrop_type)
default_name = base_path + filename
echoln default_name
time_adjusted_name = "#{base_path}#{filename}_#{time}"
if pbResolveBitmap(time_adjusted_name)
return time_adjusted_name
@@ -142,6 +148,13 @@ class PokeBattle_Scene
baseX, baseY = PokeBattle_SceneConstants.pbBattlerPosition(side)
base = pbAddSprite("base_#{side}", baseX, baseY,
(side == 0) ? playerBase : enemyBase, @viewport)
player_side = side == 0
if player_side
base.zoom_x = 1.5
base.zoom_y = 1.5
base.x -= 50
base.y+= 70
end
base.z = 1
if base.bitmap
base.ox = base.bitmap.width / 2
@@ -156,15 +169,22 @@ class PokeBattle_Scene
DEFAULT_MESSAGE_NAME = "default_message"
def pbCreateBackdropSprites
background_name = @battle.backdrop ? @battle.backdrop.downcase : DEFAULT_BACKGROUND_NAME
battlebase_name = @battle.backdropBase ? @battle.backdropBase.downcase : background_name
simplified_name = background_name.downcase.split("-")[0]
battlebase_name = @battle.backdropBase ? @battle.backdropBase.downcase : simplified_name
message_name = background_name + "_message"
#To avoid duplicating files too much, some backgrounds have a common prefix separated by -
# Ex: city-rustboro
# Will use the full name (city-rustboro) for the background, but "city" for the bases
battleBG =getBackdropSpriteFullPath(background_name, :BACKGROUND)
playerBase =getBackdropSpriteFullPath(battlebase_name, :PLAYERBASE)
enemyBase =getBackdropSpriteFullPath(battlebase_name, :ENEMYBASE)
messageBG =getBackdropSpriteFullPath(message_name, :MESSAGE)
messageBG =getBackdropSpriteFullPath(simplified_name, :MESSAGE)
if !pbResolveBitmap(messageBG)
messageBG = "Graphics/Battlebacks/default_message"
messageBG = "Graphics/Battlebacks/message/default_message"
end
apply_backdrop_graphics(battleBG,playerBase,enemyBase,messageBG)
end
@@ -244,7 +264,7 @@ class PokeBattle_Scene
trainer = pbAddSprite("trainer_#{idxTrainer + 1}", spriteX, spriteY, trainerFile, @viewport)
spriteOverrideBitmap = setTrainerSpriteOverrides(trainerType)
trainer.bitmap = spriteOverrideBitmap if spriteOverrideBitmap
trainer.bitmap = generate_front_trainer_sprite_bitmap_from_appearance(custom_appearance,true).bitmap if custom_appearance
trainer.bitmap = generate_front_trainer_sprite_bitmap_from_appearance(custom_appearance,false).bitmap if custom_appearance
return if !trainer.bitmap
# Alter position of sprite
trainer.z = 7 + idxTrainer
@@ -465,11 +465,11 @@ class PokeBattle_Scene
#=============================================================================
# Shows the Pokédex entry screen for a newly caught Pokémon
#=============================================================================
def pbShowPokedex(species)
def pbShowPokedex(pokemon)
pbFadeOutIn {
scene = PokemonPokedexInfo_Scene.new
screen = PokemonPokedexInfoScreen.new(scene)
screen.pbDexEntry(species)
screen.pbDexEntry(pokemon)
}
end
end
@@ -1,4 +1,5 @@
class PokeBattle_Scene
attr_reader :battle
#=============================================================================
# Animates the battle intro
#=============================================================================
@@ -311,6 +311,7 @@ class PokeBattle_SafariZone
attr_accessor :moneyGain # Whether the player can gain/lose money
attr_accessor :rules
attr_accessor :ballCount
attr_accessor :caughtOffGuard
include PokeBattle_BattleCommon
@@ -338,6 +339,13 @@ class PokeBattle_SafariZone
]
@rules = {}
@ballCount = 0
@caughtOffGuard = false
@turn_count = 0
end
def balls_thrown
return 30-@ballCount
end
def defaultWeather=(value); @weather = value; end
@@ -478,6 +486,8 @@ class PokeBattle_SafariZone
if @ballCount<=0
pbDisplay(_INTL("PA: You have no Safari Balls left! Game over!"))
@decision = 2
elsif @caughtOffGuard && @turn_count == 0
pbDisplay(_INTL("{1} was caught off guard and couldn't move!",pbThis))
elsif can_escape(pkmn, escapeFactor)
pbSEPlay("Battle flee")
pbDisplay(_INTL("{1} fled!",pkmn.name))
@@ -494,6 +504,7 @@ class PokeBattle_SafariZone
@scene.pbCommonAnimation(weather_data.animation) if weather_data
end
break if @decision > 0
@turn_count+=1
end
@scene.pbEndBattle(@decision)
rescue BattleAbortedException
@@ -23,6 +23,7 @@ class PokeBattle_Battle
end
def pbJudgeCheckpoint(user,move=nil)
if pbAllFainted?(0) && pbAllFainted?(1)
if @rules["drawclause"] # NOTE: Also includes Life Orb (not implemented)
if !(move && move.function=="0DD") # Not a draw if fainting occurred due to Liquid Ooze
@@ -193,7 +194,7 @@ class PokeBattle_Move_0E0 # Self-Destruct
count = @battle.pbAbleNonActiveCount(user.idxOwnSide)
count += @battle.pbAbleNonActiveCount(user.idxOpposingSide)
if count==0
@battle.pbDisplay("But it failed!")
@battle.pbDisplay(_INTL("But it failed!"))
return false
end
end