Renamed all battle-related classes and modules

This commit is contained in:
Maruno17
2021-11-16 23:05:16 +00:00
parent 6dacd6a139
commit 1c4819e5f0
79 changed files with 1270 additions and 1310 deletions
@@ -0,0 +1,179 @@
module PBEffects
#===========================================================================
# These effects apply to a battler
#===========================================================================
AquaRing = 0
Attract = 1
BanefulBunker = 2
BeakBlast = 3
Bide = 4
BideDamage = 5
BideTarget = 6
BurnUp = 7
Charge = 8
ChoiceBand = 9
Confusion = 10
Counter = 11
CounterTarget = 12
Curse = 13
Dancer = 14
DefenseCurl = 15
DestinyBond = 16
DestinyBondPrevious = 17
DestinyBondTarget = 18
Disable = 19
DisableMove = 20
Electrify = 21
Embargo = 22
Encore = 23
EncoreMove = 24
Endure = 25
FirstPledge = 26
FlashFire = 27
Flinch = 28
FocusEnergy = 29
FocusPunch = 30
FollowMe = 31
Foresight = 32
FuryCutter = 33
GastroAcid = 34
GemConsumed = 35
Grudge = 36
HealBlock = 37
HelpingHand = 38
HyperBeam = 39
Illusion = 40
Imprison = 41
Ingrain = 42
Instruct = 43
Instructed = 44
JawLock = 994
KingsShield = 45
LaserFocus = 46
LeechSeed = 47
LockOn = 48
LockOnPos = 49
MagicBounce = 50
MagicCoat = 51
MagnetRise = 52
MeanLook = 53
MeFirst = 54
Metronome = 55
MicleBerry = 56
Minimize = 57
MiracleEye = 58
MirrorCoat = 59
MirrorCoatTarget = 60
MoveNext = 61
MudSport = 62
Nightmare = 63
NoRetreat = 990
Obstruct = 992
Octolock = 993
Outrage = 64
ParentalBond = 65
PerishSong = 66
PerishSongUser = 67
PickupItem = 68
PickupUse = 69
Pinch = 70 # Battle Palace only
Powder = 71
PowerTrick = 72
Prankster = 73
PriorityAbility = 74
PriorityItem = 75
Protect = 76
ProtectRate = 77
Pursuit = 78
Quash = 79
Rage = 80
RagePowder = 81 # Used along with FollowMe
Rollout = 82
Roost = 83
ShellTrap = 84
SkyDrop = 85
SlowStart = 86
SmackDown = 87
Snatch = 88
SpikyShield = 89
Spotlight = 90
Stockpile = 91
StockpileDef = 92
StockpileSpDef = 93
Substitute = 94
TarShot = 991
Taunt = 95
Telekinesis = 96
ThroatChop = 97
Torment = 98
Toxic = 99
Transform = 100
TransformSpecies = 101
Trapping = 102 # Trapping move
TrappingMove = 103
TrappingUser = 104
Truant = 105
TwoTurnAttack = 106
Type3 = 107
Unburden = 108
Uproar = 109
WaterSport = 110
WeightChange = 111
Yawn = 112
#=============================================================================
# These effects apply to a battler position
#=============================================================================
FutureSightCounter = 0
FutureSightMove = 1
FutureSightUserIndex = 2
FutureSightUserPartyIndex = 3
HealingWish = 4
LunarDance = 5
Wish = 6
WishAmount = 7
WishMaker = 8
#=============================================================================
# These effects apply to a side
#=============================================================================
AuroraVeil = 0
CraftyShield = 1
EchoedVoiceCounter = 2
EchoedVoiceUsed = 3
LastRoundFainted = 4
LightScreen = 5
LuckyChant = 6
MatBlock = 7
Mist = 8
QuickGuard = 9
Rainbow = 10
Reflect = 11
Round = 12
Safeguard = 13
SeaOfFire = 14
Spikes = 15
StealthRock = 16
StickyWeb = 17
Swamp = 18
Tailwind = 19
ToxicSpikes = 20
WideGuard = 21
#=============================================================================
# These effects apply to the battle (i.e. both sides)
#=============================================================================
AmuletCoin = 0
FairyLock = 1
FusionBolt = 2
FusionFlare = 3
Gravity = 4
HappyHour = 5
IonDeluge = 6
MagicRoom = 7
MudSportField = 8
PayDay = 9
TrickRoom = 10
WaterSportField = 11
WonderRoom = 12
end
@@ -0,0 +1,88 @@
#===============================================================================
#
#===============================================================================
class Battle::ActiveField
attr_accessor :effects
attr_accessor :defaultWeather
attr_accessor :weather
attr_accessor :weatherDuration
attr_accessor :defaultTerrain
attr_accessor :terrain
attr_accessor :terrainDuration
def initialize
@effects = []
@effects[PBEffects::AmuletCoin] = false
@effects[PBEffects::FairyLock] = 0
@effects[PBEffects::FusionBolt] = false
@effects[PBEffects::FusionFlare] = false
@effects[PBEffects::Gravity] = 0
@effects[PBEffects::HappyHour] = false
@effects[PBEffects::IonDeluge] = false
@effects[PBEffects::MagicRoom] = 0
@effects[PBEffects::MudSportField] = 0
@effects[PBEffects::PayDay] = 0
@effects[PBEffects::TrickRoom] = 0
@effects[PBEffects::WaterSportField] = 0
@effects[PBEffects::WonderRoom] = 0
@defaultWeather = :None
@weather = :None
@weatherDuration = 0
@defaultTerrain = :None
@terrain = :None
@terrainDuration = 0
end
end
#===============================================================================
#
#===============================================================================
class Battle::ActiveSide
attr_accessor :effects
def initialize
@effects = []
@effects[PBEffects::AuroraVeil] = 0
@effects[PBEffects::CraftyShield] = false
@effects[PBEffects::EchoedVoiceCounter] = 0
@effects[PBEffects::EchoedVoiceUsed] = false
@effects[PBEffects::LastRoundFainted] = -1
@effects[PBEffects::LightScreen] = 0
@effects[PBEffects::LuckyChant] = 0
@effects[PBEffects::MatBlock] = false
@effects[PBEffects::Mist] = 0
@effects[PBEffects::QuickGuard] = false
@effects[PBEffects::Rainbow] = 0
@effects[PBEffects::Reflect] = 0
@effects[PBEffects::Round] = false
@effects[PBEffects::Safeguard] = 0
@effects[PBEffects::SeaOfFire] = 0
@effects[PBEffects::Spikes] = 0
@effects[PBEffects::StealthRock] = false
@effects[PBEffects::StickyWeb] = false
@effects[PBEffects::Swamp] = 0
@effects[PBEffects::Tailwind] = 0
@effects[PBEffects::ToxicSpikes] = 0
@effects[PBEffects::WideGuard] = false
end
end
#===============================================================================
#
#===============================================================================
class Battle::ActivePosition
attr_accessor :effects
def initialize
@effects = []
@effects[PBEffects::FutureSightCounter] = 0
@effects[PBEffects::FutureSightMove] = nil
@effects[PBEffects::FutureSightUserIndex] = -1
@effects[PBEffects::FutureSightUserPartyIndex] = -1
@effects[PBEffects::HealingWish] = false
@effects[PBEffects::LunarDance] = false
@effects[PBEffects::Wish] = 0
@effects[PBEffects::WishAmount] = 0
@effects[PBEffects::WishMaker] = -1
end
end
@@ -0,0 +1,61 @@
#===============================================================================
#
#===============================================================================
class Battle::DamageState
attr_accessor :typeMod # Type effectiveness
attr_accessor :unaffected
attr_accessor :protected
attr_accessor :magicCoat
attr_accessor :magicBounce
attr_accessor :totalHPLost # Like hpLost, but cumulative over all hits
attr_accessor :fainted # Whether battler was knocked out by the move
attr_accessor :missed # Whether the move failed the accuracy check
attr_accessor :affection_missed
attr_accessor :invulnerable # If the move missed due to two turn move invulnerability
attr_accessor :calcDamage # Calculated damage
attr_accessor :hpLost # HP lost by opponent, inc. HP lost by a substitute
attr_accessor :critical # Critical hit flag
attr_accessor :affection_critical
attr_accessor :substitute # Whether a substitute took the damage
attr_accessor :focusBand # Focus Band used
attr_accessor :focusSash # Focus Sash used
attr_accessor :sturdy # Sturdy ability used
attr_accessor :disguise # Disguise ability used
attr_accessor :iceFace # Ice Face ability used
attr_accessor :endured # Damage was endured
attr_accessor :affection_endured
attr_accessor :berryWeakened # Whether a type-resisting berry was used
def initialize; reset; end
def reset
@typeMod = Effectiveness::INEFFECTIVE
@unaffected = false
@protected = false
@missed = false
@affection_missed = false
@invulnerable = false
@magicCoat = false
@magicBounce = false
@totalHPLost = 0
@fainted = false
resetPerHit
end
def resetPerHit
@calcDamage = 0
@hpLost = 0
@critical = false
@affection_critical = false
@substitute = false
@focusBand = false
@focusSash = false
@sturdy = false
@disguise = false
@iceFace = false
@endured = false
@affection_endured = false
@berryWeakened = false
end
end
@@ -0,0 +1,71 @@
#===============================================================================
#
#===============================================================================
class Battle::Peer
def pbStorePokemon(player,pkmn)
if !player.party_full?
player.party[player.party.length] = pkmn
return -1
end
if Settings::HEAL_STORED_POKEMON
old_ready_evo = pkmn.ready_to_evolve
pkmn.heal
pkmn.ready_to_evolve = old_ready_evo
end
oldCurBox = pbCurrentBox
storedBox = $PokemonStorage.pbStoreCaught(pkmn)
if storedBox<0
# NOTE: Poké Balls can't be used if storage is full, so you shouldn't ever
# see this message.
pbDisplayPaused(_INTL("Can't catch any more..."))
return oldCurBox
end
return storedBox
end
def pbGetStorageCreatorName
return pbGetStorageCreator if $player.seen_storage_creator
return nil
end
def pbCurrentBox
return $PokemonStorage.currentBox
end
def pbBoxName(box)
return (box<0) ? "" : $PokemonStorage[box].name
end
def pbOnEnteringBattle(battle, battler, pkmn, wild = false)
f = MultipleForms.call("getFormOnEnteringBattle",pkmn,wild)
pkmn.form = f if f
battler.form = pkmn.form if battler.form != pkmn.form
MultipleForms.call("changePokemonOnEnteringBattle", battler, pkmn, battle)
end
# For switching out, including due to fainting, and for the end of battle
def pbOnLeavingBattle(battle,pkmn,usedInBattle,endBattle=false)
return if !pkmn
f = MultipleForms.call("getFormOnLeavingBattle",pkmn,battle,usedInBattle,endBattle)
pkmn.form = f if f && pkmn.form!=f
pkmn.hp = pkmn.totalhp if pkmn.hp>pkmn.totalhp
MultipleForms.call("changePokemonOnLeavingBattle", pkmn, battle, usedInBattle, endBattle)
end
end
#===============================================================================
# Unused class.
#===============================================================================
class Battle::NullPeer
def pbOnEnteringBattle(battle, battler, pkmn, wild = false); end
def pbOnLeavingBattle(battle,pkmn,usedInBattle,endBattle=false); end
def pbStorePokemon(player,pkmn)
player.party[player.party.length] = pkmn if !player.party_full?
return -1
end
def pbGetStorageCreatorName; return nil; end
def pbCurrentBox; return -1; end
def pbBoxName(box); return ""; end
end
@@ -0,0 +1,275 @@
#===============================================================================
# This script modifies the battle system to implement battle rules
#===============================================================================
class Battle
unless @__clauses__aliased
alias __clauses__pbDecisionOnDraw pbDecisionOnDraw
alias __clauses__pbEndOfRoundPhase pbEndOfRoundPhase
@__clauses__aliased = true
end
def pbDecisionOnDraw
if @rules["selfkoclause"]
if self.lastMoveUser<0
# in extreme cases there may be no last move user
return 5 # game is a draw
elsif opposes?(self.lastMoveUser)
return 2 # loss
else
return 1 # win
end
end
return __clauses__pbDecisionOnDraw
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=="HealUserByHalfOfDamageDone")
# Not a draw if fainting occurred due to Liquid Ooze
@decision = (user.opposes?) ? 1 : 2 # win / loss
end
elsif @rules["modifiedselfdestructclause"]
if move && move.function=="UserFaintsExplosive" # Self-Destruct
@decision = (user.opposes?) ? 1 : 2 # win / loss
end
end
end
end
def pbEndOfRoundPhase
__clauses__pbEndOfRoundPhase
if @rules["suddendeath"] && @decision==0
p1able = pbAbleCount(0)
p2able = pbAbleCount(1)
if p1able>p2able
@decision = 1 # loss
elsif p1able<p2able
@decision = 2 # win
end
end
end
end
class Battle::Battler
unless @__clauses__aliased
alias __clauses__pbCanSleep? pbCanSleep?
alias __clauses__pbCanSleepYawn? pbCanSleepYawn?
alias __clauses__pbCanFreeze? pbCanFreeze?
alias __clauses__pbUseMove pbUseMove
@__clauses__aliased = true
end
def pbCanSleep?(user,showMessages,move=nil,ignoreStatus=false)
selfsleep = (user && user.index==@index)
if ((@battle.rules["modifiedsleepclause"]) || (!selfsleep && @battle.rules["sleepclause"])) &&
pbHasStatusPokemon?(:SLEEP)
if showMessages
@battle.pbDisplay(_INTL("But {1} couldn't sleep!",pbThis(true)))
end
return false
end
return __clauses__pbCanSleep?(user,showMessages,move,ignoreStatus)
end
def pbCanSleepYawn?
if (@battle.rules["sleepclause"] || @battle.rules["modifiedsleepclause"]) &&
pbHasStatusPokemon?(:SLEEP)
return false
end
return __clauses__pbCanSleepYawn?
end
def pbCanFreeze?(*arg)
if @battle.rules["freezeclause"] && pbHasStatusPokemon?(:FROZEN)
return false
end
return __clauses__pbCanFreeze?(*arg)
end
def pbHasStatusPokemon?(status)
count = 0
@battle.pbParty(@index).each do |pkmn|
next if !pkmn || pkmn.egg?
next if pkmn.status!=status
count += 1
end
return count>0
end
end
class Battle::Move::RaiseUserEvasion1 # Double Team
alias __clauses__pbMoveFailed? pbMoveFailed?
def pbMoveFailed?(user,targets)
if !damagingMove? && @battle.rules["evasionclause"]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return __clauses__pbMoveFailed?(user,targets)
end
end
class Battle::Move::RaiseUserEvasion2MinimizeUser # Minimize
alias __clauses__pbMoveFailed? pbMoveFailed?
def pbMoveFailed?(user,targets)
if !damagingMove? && @battle.rules["evasionclause"]
@battle.pbDisplay(_INTL("But it failed!"))
return true
end
return __clauses__pbMoveFailed?(user,targets)
end
end
class Battle::Move::UserTargetSwapAbilities # Skill Swap
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["skillswapclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::FixedDamage20 # Sonic Boom
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["sonicboomclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::FixedDamage40 # Dragon Rage
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["sonicboomclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::OHKO
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["ohkoclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::OHKOIce
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["ohkoclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::OHKOHitsUndergroundTarget
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["ohkoclause"]
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::UserFaintsExplosive # Self-Destruct
unless @__clauses__aliased
alias __clauses__pbMoveFailed? pbMoveFailed?
@__clauses__aliased = true
end
def pbMoveFailed?(user,targets)
if @battle.rules["selfkoclause"]
# Check whether no unfainted Pokemon remain in either party
count = @battle.pbAbleNonActiveCount(user.idxOwnSide)
count += @battle.pbAbleNonActiveCount(user.idxOpposingSide)
if count==0
@battle.pbDisplay("But it failed!")
return false
end
end
if @battle.rules["selfdestructclause"]
# Check whether no unfainted Pokemon remain in either party
count = @battle.pbAbleNonActiveCount(user.idxOwnSide)
count += @battle.pbAbleNonActiveCount(user.idxOpposingSide)
if count==0
@battle.pbDisplay(_INTL("{1}'s team was disqualified!",user.pbThis))
@battle.decision = (user.opposes?) ? 1 : 2
return false
end
end
return __clauses__pbMoveFailed?(user,targets)
end
end
class Battle::Move::StartPerishCountsForAllBattlers # Perish Song
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["perishsongclause"] &&
@battle.pbAbleNonActiveCount(user.idxOwnSide)==0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
class Battle::Move::AttackerFaintsIfUserFaints # Destiny Bond
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
def pbFailsAgainstTarget?(user, target, show_message)
if @battle.rules["perishsongclause"] &&
@battle.pbAbleNonActiveCount(user.idxOwnSide)==0
@battle.pbDisplay(_INTL("But it failed!")) if show_message
return true
end
return __clauses__pbFailsAgainstTarget?(user, target, show_message)
end
end
@@ -0,0 +1,872 @@
#===============================================================================
#
#===============================================================================
class AnimFrame
X = 0
Y = 1
ZOOMX = 2
ANGLE = 3
MIRROR = 4
BLENDTYPE = 5
VISIBLE = 6
PATTERN = 7
OPACITY = 8
ZOOMY = 11
COLORRED = 12
COLORGREEN = 13
COLORBLUE = 14
COLORALPHA = 15
TONERED = 16
TONEGREEN = 17
TONEBLUE = 18
TONEGRAY = 19
LOCKED = 20
FLASHRED = 21
FLASHGREEN = 22
FLASHBLUE = 23
FLASHALPHA = 24
PRIORITY = 25
FOCUS = 26
end
#===============================================================================
#
#===============================================================================
def yaxisIntersect(x1,y1,x2,y2,px,py)
dx = x2-x1
dy = y2-y1
x = (dx==0) ? 0.0 : (px-x1).to_f/dx
y = (dy==0) ? 0.0 : (py-y1).to_f/dy
return [x,y]
end
def repositionY(x1,y1,x2,y2,tx,ty)
dx = x2-x1
dy = y2-y1
x = x1+tx*dx.to_f
y = y1+ty*dy.to_f
return [x,y]
end
def transformPoint(x1,y1,x2,y2, # Source line
x3,y3,x4,y4, # Destination line
px,py) # Source point
ret = yaxisIntersect(x1,y1,x2,y2,px,py)
ret2 = repositionY(x3,y3,x4,y4,ret[0],ret[1])
return ret2
end
def getSpriteCenter(sprite)
return [0,0] if !sprite || sprite.disposed?
return [sprite.x,sprite.y] if !sprite.bitmap || sprite.bitmap.disposed?
centerX = sprite.src_rect.width/2
centerY = sprite.src_rect.height/2
offsetX = (centerX-sprite.ox)*sprite.zoom_x
offsetY = (centerY-sprite.oy)*sprite.zoom_y
return [sprite.x+offsetX,sprite.y+offsetY]
end
def isReversed(src0,src1,dst0,dst1)
return false if src0==src1
return (dst0>dst1) if src0<src1
return (dst0<dst1)
end
def pbCreateCel(x,y,pattern,focus=4)
frame = []
frame[AnimFrame::X] = x
frame[AnimFrame::Y] = y
frame[AnimFrame::PATTERN] = pattern
frame[AnimFrame::FOCUS] = focus # 1=target, 2=user, 3=user and target, 4=screen
frame[AnimFrame::LOCKED] = 0
pbResetCel(frame)
return frame
end
def pbResetCel(frame)
return if !frame
frame[AnimFrame::ZOOMX] = 100
frame[AnimFrame::ZOOMY] = 100
frame[AnimFrame::BLENDTYPE] = 0
frame[AnimFrame::VISIBLE] = 1
frame[AnimFrame::ANGLE] = 0
frame[AnimFrame::MIRROR] = 0
frame[AnimFrame::OPACITY] = 255
frame[AnimFrame::COLORRED] = 0
frame[AnimFrame::COLORGREEN] = 0
frame[AnimFrame::COLORBLUE] = 0
frame[AnimFrame::COLORALPHA] = 0
frame[AnimFrame::TONERED] = 0
frame[AnimFrame::TONEGREEN] = 0
frame[AnimFrame::TONEBLUE] = 0
frame[AnimFrame::TONEGRAY] = 0
frame[AnimFrame::FLASHRED] = 0
frame[AnimFrame::FLASHGREEN] = 0
frame[AnimFrame::FLASHBLUE] = 0
frame[AnimFrame::FLASHALPHA] = 0
frame[AnimFrame::PRIORITY] = 1 # 0=back, 1=front, 2=behind focus, 3=before focus
end
#===============================================================================
#
#===============================================================================
def pbConvertRPGAnimation(animation)
pbAnim = PBAnimation.new
pbAnim.id = animation.id
pbAnim.name = animation.name.clone
pbAnim.graphic = animation.animation_name
pbAnim.hue = animation.animation_hue
pbAnim.array.clear
yOffset = 0
pbAnim.position = animation.position
yOffset = -64 if animation.position==0
yOffset = 64 if animation.position==2
for i in 0...animation.frames.length
frame = pbAnim.addFrame
animFrame = animation.frames[i]
for j in 0...animFrame.cell_max
data = animFrame.cell_data
if data[j,0]==-1
frame.push(nil)
next
end
if animation.position==3 # Screen
point = transformPoint(
-160,80,160,-80,
Battle::Scene::FOCUSUSER_X,Battle::Scene::FOCUSUSER_Y,
Battle::Scene::FOCUSTARGET_X,Battle::Scene::FOCUSTARGET_Y,
data[j,1],data[j,2]
)
cel = pbCreateCel(point[0],point[1],data[j,0])
else
cel = pbCreateCel(data[j,1],data[j,2]+yOffset,data[j,0])
end
cel[AnimFrame::ZOOMX] = data[j,3]
cel[AnimFrame::ZOOMY] = data[j,3]
cel[AnimFrame::ANGLE] = data[j,4]
cel[AnimFrame::MIRROR] = data[j,5]
cel[AnimFrame::OPACITY] = data[j,6]
cel[AnimFrame::BLENDTYPE] = 0
frame.push(cel)
end
end
for i in 0...animation.timings.length
timing = animation.timings[i]
newTiming = PBAnimTiming.new
newTiming.frame = timing.frame
newTiming.name = timing.se.name
newTiming.volume = timing.se.volume
newTiming.pitch = timing.se.pitch
newTiming.flashScope = timing.flash_scope
newTiming.flashColor = timing.flash_color.clone
newTiming.flashDuration = timing.flash_duration
pbAnim.timing.push(newTiming)
end
return pbAnim
end
#===============================================================================
#
#===============================================================================
class RPG::Animation
def self.fromOther(otherAnim,id)
ret = RPG::Animation.new
ret.id = id
ret.name = otherAnim.name.clone
ret.animation_name = otherAnim.animation_name.clone
ret.animation_hue = otherAnim.animation_hue
ret.position = otherAnim.position
return ret
end
def addSound(frame,se)
timing = RPG::Animation::Timing.new
timing.frame = frame
timing.se = RPG::AudioFile.new(se,100)
self.timings.push(timing)
end
def addAnimation(otherAnim,frame,x,y) # frame is zero-based
if frame+otherAnim.frames.length>=self.frames.length
totalframes = frame+otherAnim.frames.length+1
for i in self.frames.length...totalframes
self.frames.push(RPG::Animation::Frame.new)
end
end
self.frame_max = self.frames.length
for i in 0...otherAnim.frame_max
thisframe = self.frames[frame+i]
otherframe = otherAnim.frames[i]
cellStart = thisframe.cell_max
thisframe.cell_max += otherframe.cell_max
thisframe.cell_data.resize(thisframe.cell_max,8)
for j in 0...otherframe.cell_max
thisframe.cell_data[cellStart+j,0] = otherframe.cell_data[j,0]
thisframe.cell_data[cellStart+j,1] = otherframe.cell_data[j,1]+x
thisframe.cell_data[cellStart+j,2] = otherframe.cell_data[j,2]+y
thisframe.cell_data[cellStart+j,3] = otherframe.cell_data[j,3]
thisframe.cell_data[cellStart+j,4] = otherframe.cell_data[j,4]
thisframe.cell_data[cellStart+j,5] = otherframe.cell_data[j,5]
thisframe.cell_data[cellStart+j,6] = otherframe.cell_data[j,6]
thisframe.cell_data[cellStart+j,7] = otherframe.cell_data[j,7]
end
end
for i in 0...otherAnim.timings.length
timing = RPG::Animation::Timing.new
othertiming = otherAnim.timings[i]
timing.frame = frame+othertiming.frame
timing.se = RPG::AudioFile.new(
othertiming.se.name.clone,
othertiming.se.volume,
othertiming.se.pitch)
timing.flash_scope = othertiming.flash_scope
timing.flash_color = othertiming.flash_color.clone
timing.flash_duration = othertiming.flash_duration
timing.condition = othertiming.condition
self.timings.push(timing)
end
self.timings.sort! { |a,b| a.frame<=>b.frame }
end
end
#===============================================================================
#
#===============================================================================
class PBAnimTiming
attr_accessor :frame
attr_writer :timingType # 0=play SE, 1=set bg, 2=bg mod
attr_accessor :name # Name of SE file or BG file
attr_accessor :volume
attr_accessor :pitch
attr_accessor :bgX # x coordinate of bg (or to move bg to)
attr_accessor :bgY # y coordinate of bg (or to move bg to)
attr_accessor :opacity # Opacity of bg (or to change bg to)
attr_accessor :colorRed # Color of bg (or to change bg to)
attr_accessor :colorGreen # Color of bg (or to change bg to)
attr_accessor :colorBlue # Color of bg (or to change bg to)
attr_accessor :colorAlpha # Color of bg (or to change bg to)
attr_writer :duration # How long to spend changing to the new bg coords/color
attr_accessor :flashScope
attr_accessor :flashColor
attr_accessor :flashDuration
def initialize(type=0)
@frame = 0
@timingType = type
@name = ""
@volume = 80
@pitch = 100
@bgX = nil
@bgY = nil
@opacity = nil
@colorRed = nil
@colorGreen = nil
@colorBlue = nil
@colorAlpha = nil
@duration = 5
@flashScope = 0
@flashColor = Color.new(255,255,255,255)
@flashDuration = 5
end
def timingType
return @timingType || 0
end
def duration
return @duration || 5
end
def to_s
case self.timingType
when 0
return "[#{@frame+1}] Play SE: #{name} (volume #{@volume}, pitch #{@pitch})"
when 1
text = sprintf("[%d] Set BG: \"%s\"",@frame+1,name)
text += sprintf(" (color=%s,%s,%s,%s)",
(@colorRed!=nil) ? @colorRed.to_i : "-",
(@colorGreen!=nil) ? @colorGreen.to_i : "-",
(@colorBlue!=nil) ? @colorBlue.to_i : "-",
(@colorAlpha!=nil) ? @colorAlpha.to_i : "-")
text += sprintf(" (opacity=%s)",@opacity.to_i)
text += sprintf(" (coords=%s,%s)",
(@bgX!=nil) ? @bgX : "-",
(@bgY!=nil) ? @bgY : "-")
return text
when 2
text = sprintf("[%d] Change BG: @%d",@frame+1,duration)
if @colorRed!=nil || @colorGreen!=nil || @colorBlue!=nil || @colorAlpha!=nil
text += sprintf(" (color=%s,%s,%s,%s)",
(@colorRed!=nil) ? @colorRed.to_i : "-",
(@colorGreen!=nil) ? @colorGreen.to_i : "-",
(@colorBlue!=nil) ? @colorBlue.to_i : "-",
(@colorAlpha!=nil) ? @colorAlpha.to_i : "-")
end
text += sprintf(" (opacity=%s)",@opacity.to_i) if @opacity!=nil
if @bgX!=nil || @bgY!=nil
text += sprintf(" (coords=%s,%s)",
(@bgX!=nil) ? @bgX : "-",
(@bgY!=nil) ? @bgY : "-")
end
return text
when 3
text = sprintf("[%d] Set FG: \"%s\"",@frame+1,name)
text += sprintf(" (color=%s,%s,%s,%s)",
(@colorRed!=nil) ? @colorRed.to_i : "-",
(@colorGreen!=nil) ? @colorGreen.to_i : "-",
(@colorBlue!=nil) ? @colorBlue.to_i : "-",
(@colorAlpha!=nil) ? @colorAlpha.to_i : "-")
text += sprintf(" (opacity=%s)",@opacity.to_i)
text += sprintf(" (coords=%s,%s)",
(@bgX!=nil) ? @bgX : "-",
(@bgY!=nil) ? @bgY : "-")
return text
when 4
text = sprintf("[%d] Change FG: @%d",@frame+1,duration)
if @colorRed!=nil || @colorGreen!=nil || @colorBlue!=nil || @colorAlpha!=nil
text += sprintf(" (color=%s,%s,%s,%s)",
(@colorRed!=nil) ? @colorRed.to_i : "-",
(@colorGreen!=nil) ? @colorGreen.to_i : "-",
(@colorBlue!=nil) ? @colorBlue.to_i : "-",
(@colorAlpha!=nil) ? @colorAlpha.to_i : "-")
end
text += sprintf(" (opacity=%s)",@opacity.to_i) if @opacity!=nil
if @bgX!=nil || @bgY!=nil
text += sprintf(" (coords=%s,%s)",
(@bgX!=nil) ? @bgX : "-",
(@bgY!=nil) ? @bgY : "-")
end
return text
end
return ""
end
end
#===============================================================================
#
#===============================================================================
class PBAnimations < Array
include Enumerable
attr_reader :array
attr_accessor :selected
def initialize(size=1)
@array = []
@selected = 0
size = 1 if size<1 # Always create at least one animation
size.times do
@array.push(PBAnimation.new)
end
end
def length
return @array.length
end
def each
@array.each { |i| yield i }
end
def [](i)
return @array[i]
end
def []=(i,value)
@array[i] = value
end
def compact
@array.compact!
end
def insert(index,val)
@array.insert(index,val)
end
def delete_at(index)
@array.delete_at(index)
end
def resize(len)
idxStart = @array.length
idxEnd = len
if idxStart>idxEnd
for i in idxEnd...idxStart
@array.pop
end
else
for i in idxStart...idxEnd
@array.push(PBAnimation.new)
end
end
self.selected = len if self.selected>=len
end
end
#===============================================================================
#
#===============================================================================
class PBAnimation < Array
include Enumerable
attr_accessor :id
attr_accessor :name
attr_accessor :graphic
attr_accessor :hue
attr_accessor :position
attr_writer :speed
attr_reader :array
attr_reader :timing
MAX_SPRITES = 60
def speed
return @speed || 20
end
def initialize(size=1)
@id = -1
@name = ""
@graphic = ""
@hue = 0
@position = 4 # 1=target, 2=user, 3=user and target, 4=screen
@array = []
size = 1 if size<1 # Always create at least one frame
size.times { addFrame }
@timing = []
@scope = 0
end
def length
return @array.length
end
def each
@array.each { |i| yield i }
end
def [](i)
return @array[i]
end
def []=(i,value)
@array[i] = value
end
def insert(*arg)
return @array.insert(*arg)
end
def delete_at(*arg)
return @array.delete_at(*arg)
end
def resize(len)
if len<@array.length
@array[len,@array.length-len] = []
elsif len>@array.length
(len-@array.length).times do
addFrame
end
end
end
def addFrame
pos = @array.length
@array[pos] = []
# Move's user
@array[pos][0] = pbCreateCel(Battle::Scene::FOCUSUSER_X, Battle::Scene::FOCUSUSER_Y,-1)
@array[pos][0][AnimFrame::FOCUS] = 2
@array[pos][0][AnimFrame::LOCKED] = 1
# Move's target
@array[pos][1] = pbCreateCel(Battle::Scene::FOCUSTARGET_X, Battle::Scene::FOCUSTARGET_Y,-2)
@array[pos][1][AnimFrame::FOCUS] = 1
@array[pos][1][AnimFrame::LOCKED] = 1
return @array[pos]
end
def playTiming(frame,bgGraphic,bgColor,foGraphic,foColor,oldbg=[],oldfo=[],user=nil)
for i in @timing
next if i.frame!=frame
case i.timingType
when 0 # Play SE
if i.name && i.name!=""
pbSEPlay("Anim/"+i.name,i.volume,i.pitch)
elsif user && user.pokemon
name = GameData::Species.cry_filename_from_pokemon(user.pokemon)
pbSEPlay(name,i.volume,i.pitch) if name
end
# if sprite
# sprite.flash(i.flashColor,i.flashDuration*2) if i.flashScope==1
# sprite.flash(nil,i.flashDuration*2) if i.flashScope==3
# end
when 1 # Set background graphic (immediate)
if i.name && i.name!=""
bgGraphic.setBitmap("Graphics/Animations/"+i.name)
bgGraphic.ox = -i.bgX || 0
bgGraphic.oy = -i.bgY || 0
bgGraphic.color = Color.new(i.colorRed || 0,i.colorGreen || 0,i.colorBlue || 0,i.colorAlpha || 0)
bgGraphic.opacity = i.opacity || 0
bgColor.opacity = 0
else
bgGraphic.setBitmap(nil)
bgGraphic.opacity = 0
bgColor.color = Color.new(i.colorRed || 0,i.colorGreen || 0,i.colorBlue || 0,i.colorAlpha || 0)
bgColor.opacity = i.opacity || 0
end
when 2 # Move/recolour background graphic
if bgGraphic.bitmap!=nil
oldbg[0] = bgGraphic.ox || 0
oldbg[1] = bgGraphic.oy || 0
oldbg[2] = bgGraphic.opacity || 0
oldbg[3] = bgGraphic.color.clone || Color.new(0,0,0,0)
else
oldbg[0] = 0
oldbg[1] = 0
oldbg[2] = bgColor.opacity || 0
oldbg[3] = bgColor.color.clone || Color.new(0,0,0,0)
end
when 3 # Set foreground graphic (immediate)
if i.name && i.name!=""
foGraphic.setBitmap("Graphics/Animations/"+i.name)
foGraphic.ox = -i.bgX || 0
foGraphic.oy = -i.bgY || 0
foGraphic.color = Color.new(i.colorRed || 0,i.colorGreen || 0,i.colorBlue || 0,i.colorAlpha || 0)
foGraphic.opacity = i.opacity || 0
foColor.opacity = 0
else
foGraphic.setBitmap(nil)
foGraphic.opacity = 0
foColor.color = Color.new(i.colorRed || 0,i.colorGreen || 0,i.colorBlue || 0,i.colorAlpha || 0)
foColor.opacity = i.opacity || 0
end
when 4 # Move/recolour foreground graphic
if foGraphic.bitmap!=nil
oldfo[0] = foGraphic.ox || 0
oldfo[1] = foGraphic.oy || 0
oldfo[2] = foGraphic.opacity || 0
oldfo[3] = foGraphic.color.clone || Color.new(0,0,0,0)
else
oldfo[0] = 0
oldfo[1] = 0
oldfo[2] = foColor.opacity || 0
oldfo[3] = foColor.color.clone || Color.new(0,0,0,0)
end
end
end
for i in @timing
case i.timingType
when 2
next if !i.duration || i.duration<=0
next if frame<i.frame || frame>i.frame+i.duration
fraction = (frame-i.frame).to_f/i.duration
if bgGraphic.bitmap!=nil
bgGraphic.ox = oldbg[0]-(i.bgX-oldbg[0])*fraction if i.bgX!=nil
bgGraphic.oy = oldbg[1]-(i.bgY-oldbg[1])*fraction if i.bgY!=nil
bgGraphic.opacity = oldbg[2]+(i.opacity-oldbg[2])*fraction if i.opacity!=nil
cr = (i.colorRed!=nil) ? oldbg[3].red+(i.colorRed-oldbg[3].red)*fraction : oldbg[3].red
cg = (i.colorGreen!=nil) ? oldbg[3].green+(i.colorGreen-oldbg[3].green)*fraction : oldbg[3].green
cb = (i.colorBlue!=nil) ? oldbg[3].blue+(i.colorBlue-oldbg[3].blue)*fraction : oldbg[3].blue
ca = (i.colorAlpha!=nil) ? oldbg[3].alpha+(i.colorAlpha-oldbg[3].alpha)*fraction : oldbg[3].alpha
bgGraphic.color = Color.new(cr,cg,cb,ca)
else
bgColor.opacity = oldbg[2]+(i.opacity-oldbg[2])*fraction if i.opacity!=nil
cr = (i.colorRed!=nil) ? oldbg[3].red+(i.colorRed-oldbg[3].red)*fraction : oldbg[3].red
cg = (i.colorGreen!=nil) ? oldbg[3].green+(i.colorGreen-oldbg[3].green)*fraction : oldbg[3].green
cb = (i.colorBlue!=nil) ? oldbg[3].blue+(i.colorBlue-oldbg[3].blue)*fraction : oldbg[3].blue
ca = (i.colorAlpha!=nil) ? oldbg[3].alpha+(i.colorAlpha-oldbg[3].alpha)*fraction : oldbg[3].alpha
bgColor.color = Color.new(cr,cg,cb,ca)
end
when 4
next if !i.duration || i.duration<=0
next if frame<i.frame || frame>i.frame+i.duration
fraction = (frame-i.frame).to_f/i.duration
if foGraphic.bitmap!=nil
foGraphic.ox = oldfo[0]-(i.bgX-oldfo[0])*fraction if i.bgX!=nil
foGraphic.oy = oldfo[1]-(i.bgY-oldfo[1])*fraction if i.bgY!=nil
foGraphic.opacity = oldfo[2]+(i.opacity-oldfo[2])*fraction if i.opacity!=nil
cr = (i.colorRed!=nil) ? oldfo[3].red+(i.colorRed-oldfo[3].red)*fraction : oldfo[3].red
cg = (i.colorGreen!=nil) ? oldfo[3].green+(i.colorGreen-oldfo[3].green)*fraction : oldfo[3].green
cb = (i.colorBlue!=nil) ? oldfo[3].blue+(i.colorBlue-oldfo[3].blue)*fraction : oldfo[3].blue
ca = (i.colorAlpha!=nil) ? oldfo[3].alpha+(i.colorAlpha-oldfo[3].alpha)*fraction : oldfo[3].alpha
foGraphic.color = Color.new(cr,cg,cb,ca)
else
foColor.opacity = oldfo[2]+(i.opacity-oldfo[2])*fraction if i.opacity!=nil
cr = (i.colorRed!=nil) ? oldfo[3].red+(i.colorRed-oldfo[3].red)*fraction : oldfo[3].red
cg = (i.colorGreen!=nil) ? oldfo[3].green+(i.colorGreen-oldfo[3].green)*fraction : oldfo[3].green
cb = (i.colorBlue!=nil) ? oldfo[3].blue+(i.colorBlue-oldfo[3].blue)*fraction : oldfo[3].blue
ca = (i.colorAlpha!=nil) ? oldfo[3].alpha+(i.colorAlpha-oldfo[3].alpha)*fraction : oldfo[3].alpha
foColor.color = Color.new(cr,cg,cb,ca)
end
end
end
end
end
#===============================================================================
#
#===============================================================================
def pbSpriteSetAnimFrame(sprite,frame,user=nil,target=nil,inEditor=false)
return if !sprite
if !frame
sprite.visible = false
sprite.src_rect = Rect.new(0,0,1,1)
return
end
sprite.blend_type = frame[AnimFrame::BLENDTYPE]
sprite.angle = frame[AnimFrame::ANGLE]
sprite.mirror = (frame[AnimFrame::MIRROR]>0)
sprite.opacity = frame[AnimFrame::OPACITY]
sprite.visible = true
if !frame[AnimFrame::VISIBLE]==1 && inEditor
sprite.opacity /= 2
else
sprite.visible = (frame[AnimFrame::VISIBLE]==1)
end
pattern = frame[AnimFrame::PATTERN]
if pattern>=0
animwidth = 192
sprite.src_rect.set((pattern%5)*animwidth,(pattern/5)*animwidth,
animwidth,animwidth)
else
sprite.src_rect.set(0,0,
(sprite.bitmap) ? sprite.bitmap.width : 128,
(sprite.bitmap) ? sprite.bitmap.height : 128)
end
sprite.zoom_x = frame[AnimFrame::ZOOMX]/100.0
sprite.zoom_y = frame[AnimFrame::ZOOMY]/100.0
sprite.color.set(
frame[AnimFrame::COLORRED],
frame[AnimFrame::COLORGREEN],
frame[AnimFrame::COLORBLUE],
frame[AnimFrame::COLORALPHA]
)
sprite.tone.set(
frame[AnimFrame::TONERED],
frame[AnimFrame::TONEGREEN],
frame[AnimFrame::TONEBLUE],
frame[AnimFrame::TONEGRAY]
)
sprite.ox = sprite.src_rect.width/2
sprite.oy = sprite.src_rect.height/2
sprite.x = frame[AnimFrame::X]
sprite.y = frame[AnimFrame::Y]
if sprite!=user && sprite!=target
case frame[AnimFrame::PRIORITY]
when 0 # Behind everything
sprite.z = 10
when 1 # In front of everything
sprite.z = 80
when 2 # Just behind focus
case frame[AnimFrame::FOCUS]
when 1 # Focused on target
sprite.z = (target) ? target.z-1 : 20
when 2 # Focused on user
sprite.z = (user) ? user.z-1 : 20
else # Focused on user and target, or screen
sprite.z = 20
end
when 3 # Just in front of focus
case frame[AnimFrame::FOCUS]
when 1 # Focused on target
sprite.z = (target) ? target.z+1 : 80
when 2 # Focused on user
sprite.z = (user) ? user.z+1 : 80
else # Focused on user and target, or screen
sprite.z = 80
end
else
sprite.z = 80
end
end
end
#===============================================================================
# Animation player
#===============================================================================
class PBAnimationPlayerX
attr_accessor :looping
MAX_SPRITES = 60
def initialize(animation,user,target,scene=nil,oppMove=false,inEditor=false)
@animation = animation
@user = (oppMove) ? target : user # Just used for playing user's cry
@usersprite = (user) ? scene.sprites["pokemon_#{user.index}"] : nil
@targetsprite = (target) ? scene.sprites["pokemon_#{target.index}"] : nil
@userbitmap = (@usersprite && @usersprite.bitmap) ? @usersprite.bitmap : nil # not to be disposed
@targetbitmap = (@targetsprite && @targetsprite.bitmap) ? @targetsprite.bitmap : nil # not to be disposed
@scene = scene
@viewport = (scene) ? scene.viewport : nil
@inEditor = inEditor
@looping = false
@animbitmap = nil # Animation sheet graphic
@frame = -1
@framesPerTick = [Graphics.frame_rate/20,1].max # 20 ticks per second
@srcLine = nil
@dstLine = nil
@userOrig = getSpriteCenter(@usersprite)
@targetOrig = getSpriteCenter(@targetsprite)
@oldbg = []
@oldfo = []
initializeSprites
end
def initializeSprites
# Create animation sprites (0=user's sprite, 1=target's sprite)
@animsprites = []
@animsprites[0] = @usersprite
@animsprites[1] = @targetsprite
for i in 2...MAX_SPRITES
@animsprites[i] = Sprite.new(@viewport)
@animsprites[i].bitmap = nil
@animsprites[i].visible = false
end
# Create background colour sprite
@bgColor = ColoredPlane.new(Color.new(0,0,0),@viewport)
@bgColor.borderX = 64 if @inEditor
@bgColor.borderY = 64 if @inEditor
@bgColor.z = 5
@bgColor.opacity = 0
@bgColor.refresh
# Create background graphic sprite
@bgGraphic = AnimatedPlane.new(@viewport)
@bgGraphic.setBitmap(nil)
@bgGraphic.borderX = 64 if @inEditor
@bgGraphic.borderY = 64 if @inEditor
@bgGraphic.z = 5
@bgGraphic.opacity = 0
@bgGraphic.refresh
# Create foreground colour sprite
@foColor = ColoredPlane.new(Color.new(0,0,0),@viewport)
@foColor.borderX = 64 if @inEditor
@foColor.borderY = 64 if @inEditor
@foColor.z = 85
@foColor.opacity = 0
@foColor.refresh
# Create foreground graphic sprite
@foGraphic = AnimatedPlane.new(@viewport)
@foGraphic.setBitmap(nil)
@foGraphic.borderX = 64 if @inEditor
@foGraphic.borderY = 64 if @inEditor
@foGraphic.z = 85
@foGraphic.opacity = 0
@foGraphic.refresh
end
def dispose
@animbitmap.dispose if @animbitmap
for i in 2...MAX_SPRITES
@animsprites[i].dispose if @animsprites[i]
end
@bgGraphic.dispose
@bgColor.dispose
@foGraphic.dispose
@foColor.dispose
end
def start
@frame = 0
end
def animDone?
return @frame<0
end
def setLineTransform(x1,y1,x2,y2,x3,y3,x4,y4)
@srcLine = [x1,y1,x2,y2]
@dstLine = [x3,y3,x4,y4]
end
def update
return if @frame<0
animFrame = @frame/@framesPerTick
# Loop or end the animation if the animation has reached the end
if animFrame >= @animation.length
@frame = (@looping) ? 0 : -1
if @frame<0
@animbitmap.dispose if @animbitmap
@animbitmap = nil
return
end
end
# Load the animation's spritesheet and assign it to all the sprites.
if !@animbitmap || @animbitmap.disposed?
@animbitmap = AnimatedBitmap.new("Graphics/Animations/"+@animation.graphic,
@animation.hue).deanimate
for i in 0...MAX_SPRITES
@animsprites[i].bitmap = @animbitmap if @animsprites[i]
end
end
# Update background and foreground graphics
@bgGraphic.update
@bgColor.update
@foGraphic.update
@foColor.update
# Update all the sprites to depict the animation's next frame
if @framesPerTick==1 || (@frame%@framesPerTick)==0
thisframe = @animation[animFrame]
# Make all cel sprites invisible
for i in 0...MAX_SPRITES
@animsprites[i].visible = false if @animsprites[i]
end
# Set each cel sprite acoordingly
for i in 0...thisframe.length
cel = thisframe[i]
next if !cel
sprite = @animsprites[i]
next if !sprite
# Set cel sprite's graphic
case cel[AnimFrame::PATTERN]
when -1
sprite.bitmap = @userbitmap
when -2
sprite.bitmap = @targetbitmap
else
sprite.bitmap = @animbitmap
end
# Apply settings to the cel sprite
pbSpriteSetAnimFrame(sprite,cel,@usersprite,@targetsprite)
case cel[AnimFrame::FOCUS]
when 1 # Focused on target
sprite.x = cel[AnimFrame::X] + @targetOrig[0] - Battle::Scene::FOCUSTARGET_X
sprite.y = cel[AnimFrame::Y] + @targetOrig[1] - Battle::Scene::FOCUSTARGET_Y
when 2 # Focused on user
sprite.x = cel[AnimFrame::X] + @userOrig[0] - Battle::Scene::FOCUSUSER_X
sprite.y = cel[AnimFrame::Y] + @userOrig[1] - Battle::Scene::FOCUSUSER_Y
when 3 # Focused on user and target
next if !@srcLine || !@dstLine
point = transformPoint(
@srcLine[0],@srcLine[1],@srcLine[2],@srcLine[3],
@dstLine[0],@dstLine[1],@dstLine[2],@dstLine[3],
sprite.x,sprite.y)
sprite.x = point[0]
sprite.y = point[1]
if isReversed(@srcLine[0],@srcLine[2],@dstLine[0],@dstLine[2]) &&
cel[AnimFrame::PATTERN]>=0
# Reverse direction
sprite.mirror = !sprite.mirror
end
end
sprite.x += 64 if @inEditor
sprite.y += 64 if @inEditor
end
# Play timings
@animation.playTiming(animFrame,@bgGraphic,@bgColor,@foGraphic,@foColor,@oldbg,@oldfo,@user)
end
@frame += 1
end
end
@@ -0,0 +1,657 @@
module BattleHandlers
# Battler's speed calculation
SpeedCalcAbility = AbilityHandlerHash.new
SpeedCalcItem = ItemHandlerHash.new
# Battler's weight calculation
WeightCalcAbility = AbilityHandlerHash.new
WeightCalcItem = ItemHandlerHash.new # Float Stone
# Battler's HP/stat changed
HPHealItem = ItemHandlerHash.new
AbilityOnHPDroppedBelowHalf = AbilityHandlerHash.new
ItemOnStatDropped = ItemHandlerHash.new
# Battler's status problem
StatusCheckAbilityNonIgnorable = AbilityHandlerHash.new # Comatose
StatusImmunityAbility = AbilityHandlerHash.new
StatusImmunityAbilityNonIgnorable = AbilityHandlerHash.new
StatusImmunityAllyAbility = AbilityHandlerHash.new
AbilityOnStatusInflicted = AbilityHandlerHash.new # Synchronize
StatusCureItem = ItemHandlerHash.new
StatusCureAbility = AbilityHandlerHash.new
# Battler's stat stages
StatLossImmunityAbility = AbilityHandlerHash.new
StatLossImmunityAbilityNonIgnorable = AbilityHandlerHash.new # Full Metal Body
StatLossImmunityAllyAbility = AbilityHandlerHash.new # Flower Veil
AbilityOnStatGain = AbilityHandlerHash.new # None!
AbilityOnStatLoss = AbilityHandlerHash.new
# Priority and turn order
PriorityChangeAbility = AbilityHandlerHash.new
PriorityBracketChangeAbility = AbilityHandlerHash.new # Stall
PriorityBracketChangeItem = ItemHandlerHash.new
PriorityBracketUseAbility = AbilityHandlerHash.new # None!
PriorityBracketUseItem = ItemHandlerHash.new
# Move usage failures
AbilityOnFlinch = AbilityHandlerHash.new # Steadfast
MoveBlockingAbility = AbilityHandlerHash.new
MoveImmunityTargetAbility = AbilityHandlerHash.new
UserItemOnMissing = ItemHandlerHash.new # Blunder Policy
# Move usage
MoveBaseTypeModifierAbility = AbilityHandlerHash.new
# Accuracy calculation
AccuracyCalcUserAbility = AbilityHandlerHash.new
AccuracyCalcUserAllyAbility = AbilityHandlerHash.new # Victory Star
AccuracyCalcTargetAbility = AbilityHandlerHash.new
AccuracyCalcUserItem = ItemHandlerHash.new
AccuracyCalcTargetItem = ItemHandlerHash.new
# Damage calculation
DamageCalcUserAbility = AbilityHandlerHash.new
DamageCalcUserAllyAbility = AbilityHandlerHash.new
DamageCalcTargetAbility = AbilityHandlerHash.new
DamageCalcTargetAbilityNonIgnorable = AbilityHandlerHash.new
DamageCalcTargetAllyAbility = AbilityHandlerHash.new
DamageCalcUserItem = ItemHandlerHash.new
DamageCalcTargetItem = ItemHandlerHash.new
# Critical hit calculation
CriticalCalcUserAbility = AbilityHandlerHash.new
CriticalCalcTargetAbility = AbilityHandlerHash.new
CriticalCalcUserItem = ItemHandlerHash.new
CriticalCalcTargetItem = ItemHandlerHash.new # None!
# Upon a move hitting a target
TargetAbilityOnHit = AbilityHandlerHash.new
UserAbilityOnHit = AbilityHandlerHash.new # Poison Touch
TargetItemOnHit = ItemHandlerHash.new
TargetItemOnHitPositiveBerry = ItemHandlerHash.new
# Abilities/items that trigger at the end of using a move
UserAbilityEndOfMove = AbilityHandlerHash.new
TargetItemAfterMoveUse = ItemHandlerHash.new
UserItemAfterMoveUse = ItemHandlerHash.new
TargetAbilityAfterMoveUse = AbilityHandlerHash.new
EndOfMoveItem = ItemHandlerHash.new # Leppa Berry
EndOfMoveStatRestoreItem = ItemHandlerHash.new # White Herb
# Experience and EV gain
ExpGainModifierItem = ItemHandlerHash.new # Lucky Egg
EVGainModifierItem = ItemHandlerHash.new
# Weather and terrin
WeatherExtenderItem = ItemHandlerHash.new
TerrainExtenderItem = ItemHandlerHash.new # Terrain Extender
TerrainStatBoostItem = ItemHandlerHash.new
# End Of Round
EORWeatherAbility = AbilityHandlerHash.new
EORHealingAbility = AbilityHandlerHash.new
EORHealingItem = ItemHandlerHash.new
EOREffectAbility = AbilityHandlerHash.new
EOREffectItem = ItemHandlerHash.new
EORGainItemAbility = AbilityHandlerHash.new
# Switching and fainting
CertainSwitchingUserAbility = AbilityHandlerHash.new # None!
CertainSwitchingUserItem = ItemHandlerHash.new # Shed Shell
TrappingTargetAbility = AbilityHandlerHash.new
TrappingTargetItem = ItemHandlerHash.new # None!
AbilityOnSwitchIn = AbilityHandlerHash.new
ItemOnSwitchIn = ItemHandlerHash.new # Air Balloon
ItemOnIntimidated = ItemHandlerHash.new # Adrenaline Orb
AbilityOnSwitchOut = AbilityHandlerHash.new
AbilityChangeOnBattlerFainting = AbilityHandlerHash.new
AbilityOnBattlerFainting = AbilityHandlerHash.new # Soul-Heart
AbilityOnTerrainChange = AbilityHandlerHash.new # Mimicry
AbilityOnIntimidated = AbilityHandlerHash.new # Rattled (Gen 8)
# Running from battle
RunFromBattleAbility = AbilityHandlerHash.new # Run Away
RunFromBattleItem = ItemHandlerHash.new # Smoke Ball
#=============================================================================
def self.triggerSpeedCalcAbility(ability,battler,mult)
ret = SpeedCalcAbility.trigger(ability,battler,mult)
return (ret!=nil) ? ret : mult
end
def self.triggerSpeedCalcItem(item,battler,mult)
ret = SpeedCalcItem.trigger(item,battler,mult)
return (ret!=nil) ? ret : mult
end
#=============================================================================
def self.triggerWeightCalcAbility(ability,battler,w)
ret = WeightCalcAbility.trigger(ability,battler,w)
return (ret!=nil) ? ret : w
end
def self.triggerWeightCalcItem(item,battler,w)
ret = WeightCalcItem.trigger(item,battler,w)
return (ret!=nil) ? ret : w
end
#=============================================================================
def self.triggerHPHealItem(item,battler,battle,forced)
ret = HPHealItem.trigger(item,battler,battle,forced)
return (ret!=nil) ? ret : false
end
def self.triggerAbilityOnHPDroppedBelowHalf(ability, user, move_user, battle)
ret = AbilityOnHPDroppedBelowHalf.trigger(ability, user, move_user, battle)
return (ret!=nil) ? ret : false
end
def self.triggerItemOnStatDropped(item, user, move_user, battle)
ret = ItemOnStatDropped.trigger(item, user, move_user, battle)
return (ret != nil) ? ret : false
end
#=============================================================================
def self.triggerStatusCheckAbilityNonIgnorable(ability,battler,status)
ret = StatusCheckAbilityNonIgnorable.trigger(ability,battler,status)
return (ret!=nil) ? ret : false
end
def self.triggerStatusImmunityAbility(ability,battler,status)
ret = StatusImmunityAbility.trigger(ability,battler,status)
return (ret!=nil) ? ret : false
end
def self.triggerStatusImmunityAbilityNonIgnorable(ability,battler,status)
ret = StatusImmunityAbilityNonIgnorable.trigger(ability,battler,status)
return (ret!=nil) ? ret : false
end
def self.triggerStatusImmunityAllyAbility(ability,battler,status)
ret = StatusImmunityAllyAbility.trigger(ability,battler,status)
return (ret!=nil) ? ret : false
end
def self.triggerAbilityOnStatusInflicted(ability,battler,user,status)
AbilityOnStatusInflicted.trigger(ability,battler,user,status)
end
def self.triggerStatusCureItem(item,battler,battle,forced)
ret = StatusCureItem.trigger(item,battler,battle,forced)
return (ret!=nil) ? ret : false
end
def self.triggerStatusCureAbility(ability,battler)
ret = StatusCureAbility.trigger(ability,battler)
return (ret!=nil) ? ret : false
end
#=============================================================================
def self.triggerStatLossImmunityAbility(ability,battler,stat,battle,showMessages)
ret = StatLossImmunityAbility.trigger(ability,battler,stat,battle,showMessages)
return (ret!=nil) ? ret : false
end
def self.triggerStatLossImmunityAbilityNonIgnorable(ability,battler,stat,battle,showMessages)
ret = StatLossImmunityAbilityNonIgnorable.trigger(ability,battler,stat,battle,showMessages)
return (ret!=nil) ? ret : false
end
def self.triggerStatLossImmunityAllyAbility(ability,bearer,battler,stat,battle,showMessages)
ret = StatLossImmunityAllyAbility.trigger(ability,bearer,battler,stat,battle,showMessages)
return (ret!=nil) ? ret : false
end
def self.triggerAbilityOnStatGain(ability,battler,stat,user)
AbilityOnStatGain.trigger(ability,battler,stat,user)
end
def self.triggerAbilityOnStatLoss(ability,battler,stat,user)
AbilityOnStatLoss.trigger(ability,battler,stat,user)
end
#=============================================================================
def self.triggerPriorityChangeAbility(ability,battler,move,pri)
ret = PriorityChangeAbility.trigger(ability,battler,move,pri)
return (ret!=nil) ? ret : pri
end
def self.triggerPriorityBracketChangeAbility(ability,battler,subPri,battle)
ret = PriorityBracketChangeAbility.trigger(ability,battler,subPri,battle)
return (ret!=nil) ? ret : subPri
end
def self.triggerPriorityBracketChangeItem(item,battler,subPri,battle)
ret = PriorityBracketChangeItem.trigger(item,battler,subPri,battle)
return (ret!=nil) ? ret : subPri
end
def self.triggerPriorityBracketUseAbility(ability,battler,battle)
PriorityBracketUseAbility.trigger(ability,battler,battle)
end
def self.triggerPriorityBracketUseItem(item,battler,battle)
PriorityBracketUseItem.trigger(item,battler,battle)
end
#=============================================================================
def self.triggerAbilityOnFlinch(ability,battler,battle)
AbilityOnFlinch.trigger(ability,battler,battle)
end
def self.triggerMoveBlockingAbility(ability,bearer,user,targets,move,battle)
ret = MoveBlockingAbility.trigger(ability,bearer,user,targets,move,battle)
return (ret!=nil) ? ret : false
end
def self.triggerMoveImmunityTargetAbility(ability, user, target, move, type, battle, show_message)
ret = MoveImmunityTargetAbility.trigger(ability, user, target, move, type, battle, show_message)
return (ret!=nil) ? ret : false
end
def self.triggerUserItemOnMissing(item, user, target, move, hit_num, battle)
UserItemOnMissing.trigger(item, user, target, move, hit_num, battle)
end
#=============================================================================
def self.triggerMoveBaseTypeModifierAbility(ability,user,move,type)
ret = MoveBaseTypeModifierAbility.trigger(ability,user,move,type)
return (ret!=nil) ? ret : type
end
#=============================================================================
def self.triggerAccuracyCalcUserAbility(ability,mods,user,target,move,type)
AccuracyCalcUserAbility.trigger(ability,mods,user,target,move,type)
end
def self.triggerAccuracyCalcUserAllyAbility(ability,mods,user,target,move,type)
AccuracyCalcUserAllyAbility.trigger(ability,mods,user,target,move,type)
end
def self.triggerAccuracyCalcTargetAbility(ability,mods,user,target,move,type)
AccuracyCalcTargetAbility.trigger(ability,mods,user,target,move,type)
end
def self.triggerAccuracyCalcUserItem(item,mods,user,target,move,type)
AccuracyCalcUserItem.trigger(item,mods,user,target,move,type)
end
def self.triggerAccuracyCalcTargetItem(item,mods,user,target,move,type)
AccuracyCalcTargetItem.trigger(item,mods,user,target,move,type)
end
#=============================================================================
def self.triggerDamageCalcUserAbility(ability,user,target,move,mults,baseDmg,type)
DamageCalcUserAbility.trigger(ability,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcUserAllyAbility(ability,user,target,move,mults,baseDmg,type)
DamageCalcUserAllyAbility.trigger(ability,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcTargetAbility(ability,user,target,move,mults,baseDmg,type)
DamageCalcTargetAbility.trigger(ability,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcTargetAbilityNonIgnorable(ability,user,target,move,mults,baseDmg,type)
DamageCalcTargetAbilityNonIgnorable.trigger(ability,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcTargetAllyAbility(ability,user,target,move,mults,baseDmg,type)
DamageCalcTargetAllyAbility.trigger(ability,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcUserItem(item,user,target,move,mults,baseDmg,type)
DamageCalcUserItem.trigger(item,user,target,move,mults,baseDmg,type)
end
def self.triggerDamageCalcTargetItem(item,user,target,move,mults,baseDmg,type)
DamageCalcTargetItem.trigger(item,user,target,move,mults,baseDmg,type)
end
#=============================================================================
def self.triggerCriticalCalcUserAbility(ability,user,target,c)
ret = CriticalCalcUserAbility.trigger(ability,user,target,c)
return (ret!=nil) ? ret : c
end
def self.triggerCriticalCalcTargetAbility(ability,user,target,c)
ret = CriticalCalcTargetAbility.trigger(ability,user,target,c)
return (ret!=nil) ? ret : c
end
def self.triggerCriticalCalcUserItem(item,user,target,c)
ret = CriticalCalcUserItem.trigger(item,user,target,c)
return (ret!=nil) ? ret : c
end
def self.triggerCriticalCalcTargetItem(item,user,target,c)
ret = CriticalCalcTargetItem.trigger(item,user,target,c)
return (ret!=nil) ? ret : c
end
#=============================================================================
def self.triggerTargetAbilityOnHit(ability,user,target,move,battle)
TargetAbilityOnHit.trigger(ability,user,target,move,battle)
end
def self.triggerUserAbilityOnHit(ability,user,target,move,battle)
UserAbilityOnHit.trigger(ability,user,target,move,battle)
end
def self.triggerTargetItemOnHit(item,user,target,move,battle)
TargetItemOnHit.trigger(item,user,target,move,battle)
end
def self.triggerTargetItemOnHitPositiveBerry(item,battler,battle,forced)
ret = TargetItemOnHitPositiveBerry.trigger(item,battler,battle,forced)
return (ret!=nil) ? ret : false
end
#=============================================================================
def self.triggerUserAbilityEndOfMove(ability,user,targets,move,battle)
UserAbilityEndOfMove.trigger(ability,user,targets,move,battle)
end
def self.triggerTargetItemAfterMoveUse(item, battler, user, move, switched_battlers, battle)
TargetItemAfterMoveUse.trigger(item, battler, user, move, switched_battlers, battle)
end
def self.triggerUserItemAfterMoveUse(item,user,targets,move,numHits,battle)
UserItemAfterMoveUse.trigger(item,user,targets,move,numHits,battle)
end
def self.triggerTargetAbilityAfterMoveUse(ability, target, user, move, switched_battlers, battle)
TargetAbilityAfterMoveUse.trigger(ability, target, user, move, switched_battlers, battle)
end
def self.triggerEndOfMoveItem(item,battler,battle,forced)
ret = EndOfMoveItem.trigger(item,battler,battle,forced)
return (ret!=nil) ? ret : false
end
def self.triggerEndOfMoveStatRestoreItem(item,battler,battle,forced)
ret = EndOfMoveStatRestoreItem.trigger(item,battler,battle,forced)
return (ret!=nil) ? ret : false
end
#=============================================================================
def self.triggerExpGainModifierItem(item,battler,exp)
ret = ExpGainModifierItem.trigger(item,battler,exp)
return (ret!=nil) ? ret : -1
end
def self.triggerEVGainModifierItem(item,battler,evarray)
return false if !EVGainModifierItem[item]
EVGainModifierItem.trigger(item,battler,evarray)
return true
end
#=============================================================================
def self.triggerWeatherExtenderItem(item,weather,duration,battler,battle)
ret = WeatherExtenderItem.trigger(item,weather,duration,battler,battle)
return (ret!=nil) ? ret : duration
end
def self.triggerTerrainExtenderItem(item,terrain,duration,battler,battle)
ret = TerrainExtenderItem.trigger(item,terrain,duration,battler,battle)
return (ret!=nil) ? ret : duration
end
def self.triggerTerrainStatBoostItem(item,battler,battle)
ret = TerrainStatBoostItem.trigger(item,battler,battle)
return (ret!=nil) ? ret : false
end
#=============================================================================
def self.triggerEORWeatherAbility(ability,weather,battler,battle)
EORWeatherAbility.trigger(ability,weather,battler,battle)
end
def self.triggerEORHealingAbility(ability,battler,battle)
EORHealingAbility.trigger(ability,battler,battle)
end
def self.triggerEORHealingItem(item,battler,battle)
EORHealingItem.trigger(item,battler,battle)
end
def self.triggerEOREffectAbility(ability,battler,battle)
EOREffectAbility.trigger(ability,battler,battle)
end
def self.triggerEOREffectItem(item,battler,battle)
EOREffectItem.trigger(item,battler,battle)
end
def self.triggerEORGainItemAbility(ability,battler,battle)
EORGainItemAbility.trigger(ability,battler,battle)
end
#=============================================================================
def self.triggerCertainSwitchingUserAbility(ability,switcher,battle)
ret = CertainSwitchingUserAbility.trigger(ability,switcher,battle)
return (ret!=nil) ? ret : false
end
def self.triggerCertainSwitchingUserItem(item,switcher,battle)
ret = CertainSwitchingUserItem.trigger(item,switcher,battle)
return (ret!=nil) ? ret : false
end
def self.triggerTrappingTargetAbility(ability,switcher,bearer,battle)
ret = TrappingTargetAbility.trigger(ability,switcher,bearer,battle)
return (ret!=nil) ? ret : false
end
def self.triggerTrappingTargetItem(item,switcher,bearer,battle)
ret = TrappingTargetItem.trigger(item,switcher,bearer,battle)
return (ret!=nil) ? ret : false
end
def self.triggerAbilityOnSwitchIn(ability,battler,battle)
AbilityOnSwitchIn.trigger(ability,battler,battle)
end
def self.triggerItemOnSwitchIn(item,battler,battle)
ItemOnSwitchIn.trigger(item,battler,battle)
end
def self.triggerItemOnIntimidated(item,battler,battle)
ret = ItemOnIntimidated.trigger(item,battler,battle)
return (ret!=nil) ? ret : false
end
def self.triggerAbilityOnSwitchOut(ability,battler,endOfBattle)
AbilityOnSwitchOut.trigger(ability,battler,endOfBattle)
end
def self.triggerAbilityChangeOnBattlerFainting(ability,battler,fainted,battle)
AbilityChangeOnBattlerFainting.trigger(ability,battler,fainted,battle)
end
def self.triggerAbilityOnBattlerFainting(ability,battler,fainted,battle)
AbilityOnBattlerFainting.trigger(ability,battler,fainted,battle)
end
def self.triggerAbilityOnTerrainChange(ability, battler, battle, ability_changed)
AbilityOnTerrainChange.trigger(ability, battler, battle, ability_changed)
end
def self.triggerAbilityOnIntimidated(ability,battler,battle)
AbilityOnIntimidated.trigger(ability,battler,battle)
end
#=============================================================================
def self.triggerRunFromBattleAbility(ability,battler)
ret = RunFromBattleAbility.trigger(ability,battler)
return (ret!=nil) ? ret : false
end
def self.triggerRunFromBattleItem(item,battler)
ret = RunFromBattleItem.trigger(item,battler)
return (ret!=nil) ? ret : false
end
end
def pbBattleConfusionBerry(battler,battle,item,forced,flavor,confuseMsg)
return false if !forced && !battler.canHeal?
return false if !forced && !battler.canConsumePinchBerry?(Settings::MECHANICS_GENERATION >= 7)
itemName = GameData::Item.get(item).name
fraction_to_heal = 8 # Gens 6 and lower
if Settings::MECHANICS_GENERATION == 7
fraction_to_heal = 2
elsif Settings::MECHANICS_GENERATION >= 8
fraction_to_heal = 3
end
amt = battler.totalhp / fraction_to_heal
ripening = false
if battler.hasActiveAbility?(:RIPEN)
battle.pbShowAbilitySplash(battler, forced)
amt *= 2
ripening = true
end
battle.pbCommonAnimation("EatBerry", battler) if !forced
battle.pbHideAbilitySplash(battler) if ripening
amt = battler.pbRecoverHP(amt)
if amt>0
if forced
PBDebug.log("[Item triggered] Forced consuming of #{itemName}")
battle.pbDisplay(_INTL("{1}'s HP was restored.",battler.pbThis))
else
battle.pbDisplay(_INTL("{1} restored its health using its {2}!",battler.pbThis,itemName))
end
end
flavor_stat = [:ATTACK, :DEFENSE, :SPEED, :SPECIAL_ATTACK, :SPECIAL_DEFENSE][flavor]
battler.nature.stat_changes.each do |change|
next if change[1] > 0 || change[0] != flavor_stat
battle.pbDisplay(confuseMsg)
battler.pbConfuse if battler.pbCanConfuseSelf?(false)
break
end
return true
end
def pbBattleStatIncreasingBerry(battler,battle,item,forced,stat,increment=1)
return false if !forced && !battler.canConsumePinchBerry?
return false if !battler.pbCanRaiseStatStage?(stat,battler)
itemName = GameData::Item.get(item).name
ripening = false
if battler.hasActiveAbility?(:RIPEN)
battle.pbShowAbilitySplash(battler, forced)
increment *= 2
ripening = true
end
battle.pbCommonAnimation("EatBerry", battler) if !forced
battle.pbHideAbilitySplash(battler) if ripening
return battler.pbRaiseStatStageByCause(stat, increment, battler, itemName) if !forced
PBDebug.log("[Item triggered] Forced consuming of #{itemName}")
return battler.pbRaiseStatStage(stat, increment, battler)
end
# For abilities that grant immunity to moves of a particular type, and raises
# one of the ability's bearer's stats instead.
def pbBattleMoveImmunityStatAbility(user, target, move, moveType, immuneType,
stat, increment, battle, show_message)
return false if user.index==target.index
return false if moveType != immuneType
# NOTE: If show_message is false (Dragon Darts only), the stat will not be
# raised. This is not how the official games work, but I'm considering
# that a bug because Dragon Darts won't be fired at target in the first
# place if it's immune, so why would this ability be triggered by them?
if show_message
battle.pbShowAbilitySplash(target)
if target.pbCanRaiseStatStage?(stat, target)
if Battle::Scene::USE_ABILITY_SPLASH
target.pbRaiseStatStage(stat, increment, target)
else
target.pbRaiseStatStageByCause(stat, increment, target, target.abilityName)
end
else
if Battle::Scene::USE_ABILITY_SPLASH
battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true)))
else
battle.pbDisplay(_INTL("{1}'s {2} made {3} ineffective!",
target.pbThis, target.abilityName, move.name))
end
end
battle.pbHideAbilitySplash(target)
end
return true
end
# For abilities that grant immunity to moves of a particular type, and heals the
# ability's bearer by 1/4 of its total HP instead.
def pbBattleMoveImmunityHealAbility(user, target, move, moveType, immuneType, battle, show_message)
return false if user.index==target.index
return false if moveType != immuneType
# NOTE: If show_message is false (Dragon Darts only), HP will not be healed.
# This is not how the official games work, but I'm considering that a
# bug because Dragon Darts won't be fired at target in the first place
# if it's immune, so why would this ability be triggered by them?
if show_message
battle.pbShowAbilitySplash(target)
if target.canHeal? && target.pbRecoverHP(target.totalhp / 4) > 0
if Battle::Scene::USE_ABILITY_SPLASH
battle.pbDisplay(_INTL("{1}'s HP was restored.", target.pbThis))
else
battle.pbDisplay(_INTL("{1}'s {2} restored its HP.", target.pbThis, target.abilityName))
end
else
if Battle::Scene::USE_ABILITY_SPLASH
battle.pbDisplay(_INTL("It doesn't affect {1}...", target.pbThis(true)))
else
battle.pbDisplay(_INTL("{1}'s {2} made {3} ineffective!",
target.pbThis, target.abilityName, move.name))
end
end
battle.pbHideAbilitySplash(target)
end
return true
end
def pbBattleGem(user,type,move,mults,moveType)
# Pledge moves never consume Gems
return if move.is_a?(Battle::Move::PledgeMove)
return if moveType != type
user.effects[PBEffects::GemConsumed] = user.item_id
if Settings::MECHANICS_GENERATION >= 6
mults[:base_damage_multiplier] *= 1.3
else
mults[:base_damage_multiplier] *= 1.5
end
end
def pbBattleTypeWeakingBerry(type,moveType,target,mults)
return if moveType != type
return if !Effectiveness.super_effective?(target.damageState.typeMod) && moveType != :NORMAL
mults[:final_damage_multiplier] /= 2
target.damageState.berryWeakened = true
ripening = false
if target.hasActiveAbility?(:RIPEN)
target.battle.pbShowAbilitySplash(target)
mults[:final_damage_multiplier] /= 2
ripening = true
end
target.battle.pbCommonAnimation("EatBerry",target)
target.battle.pbHideAbilitySplash(target) if ripening
end
def pbBattleWeatherAbility(weather,battler,battle,ignorePrimal=false)
return if !ignorePrimal && [:HarshSun, :HeavyRain, :StrongWinds].include?(battle.field.weather)
return if battle.field.weather==weather
battle.pbShowAbilitySplash(battler)
if !Battle::Scene::USE_ABILITY_SPLASH
battle.pbDisplay(_INTL("{1}'s {2} activated!",battler.pbThis,battler.abilityName))
end
fixedDuration = false
fixedDuration = true if Settings::FIXED_DURATION_WEATHER_FROM_ABILITY &&
![:HarshSun, :HeavyRain, :StrongWinds].include?(weather)
battle.pbStartWeather(battler,weather,fixedDuration)
# NOTE: The ability splash is hidden again in def pbStartWeather.
end
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,198 @@
#===============================================================================
#
#===============================================================================
module BallHandlers
IsUnconditional = ItemHandlerHash.new
ModifyCatchRate = ItemHandlerHash.new
OnCatch = ItemHandlerHash.new
OnFailCatch = ItemHandlerHash.new
def self.isUnconditional?(ball,battle,battler)
ret = IsUnconditional.trigger(ball,battle,battler)
return (ret!=nil) ? ret : false
end
def self.modifyCatchRate(ball,catchRate,battle,battler,ultraBeast)
ret = ModifyCatchRate.trigger(ball,catchRate,battle,battler,ultraBeast)
return (ret!=nil) ? ret : catchRate
end
def self.onCatch(ball,battle,pkmn)
OnCatch.trigger(ball,battle,pkmn)
end
def self.onFailCatch(ball,battle,battler)
$stats.failed_poke_ball_count += 1
OnFailCatch.trigger(ball,battle,battler)
end
end
#===============================================================================
# IsUnconditional
#===============================================================================
BallHandlers::IsUnconditional.add(:MASTERBALL,proc { |ball,battle,battler|
next true
})
#===============================================================================
# ModifyCatchRate
# NOTE: This code is not called if the battler is an Ultra Beast (except if the
# Ball is a Beast Ball). In this case, all Balls' catch rates are set
# elsewhere to 0.1x.
#===============================================================================
BallHandlers::ModifyCatchRate.add(:GREATBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
next catchRate*1.5
})
BallHandlers::ModifyCatchRate.add(:ULTRABALL,proc { |ball,catchRate,battle,battler,ultraBeast|
next catchRate*2
})
BallHandlers::ModifyCatchRate.add(:SAFARIBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
next catchRate*1.5
})
BallHandlers::ModifyCatchRate.add(:NETBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3.5 : 3
catchRate *= multiplier if battler.pbHasType?(:BUG) || battler.pbHasType?(:WATER)
next catchRate
})
BallHandlers::ModifyCatchRate.add(:DIVEBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
catchRate *= 3.5 if battle.environment == :Underwater
next catchRate
})
BallHandlers::ModifyCatchRate.add(:NESTBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
if battler.level <= 30
catchRate *= [(41 - battler.level) / 10.0, 1].max
end
next catchRate
})
BallHandlers::ModifyCatchRate.add(:REPEATBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3.5 : 3
catchRate *= multiplier if battle.pbPlayer.owned?(battler.species)
next catchRate
})
BallHandlers::ModifyCatchRate.add(:TIMERBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
multiplier = [1+(0.3*battle.turnCount),4].min
catchRate *= multiplier
next catchRate
})
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
next catchRate
})
BallHandlers::ModifyCatchRate.add(:QUICKBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
catchRate *= 5 if battle.turnCount==0
next catchRate
})
BallHandlers::ModifyCatchRate.add(:FASTBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
baseStats = battler.pokemon.baseStats
baseSpeed = baseStats[:SPEED]
catchRate *= 4 if baseSpeed >= 100
next [catchRate, 255].min
})
BallHandlers::ModifyCatchRate.add(:LEVELBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
maxlevel = 0
battle.allSameSideBattlers.each { |b| maxlevel = b.level if b.level > maxlevel }
if maxlevel >= battler.level * 4
catchRate *= 8
elsif maxlevel >= battler.level * 2
catchRate *= 4
elsif maxlevel > battler.level
catchRate *= 2
end
next [catchRate,255].min
})
BallHandlers::ModifyCatchRate.add(:LUREBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 5 : 3
catchRate *= multiplier if GameData::EncounterType.get($game_temp.encounter_type).type == :fishing
next [catchRate,255].min
})
BallHandlers::ModifyCatchRate.add(:HEAVYBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
next 0 if catchRate==0
weight = battler.pokemon.species_data.base_stats[:SPEED]
if Settings::NEW_POKE_BALL_CATCH_RATES
if weight >= 3000
catchRate += 30
elsif weight >= 2000
catchRate += 20
elsif weight < 1000
catchRate -= 20
end
else
if weight >= 4096
catchRate += 40
elsif weight >= 3072
catchRate += 30
elsif weight >= 2048
catchRate += 20
else
catchRate -= 20
end
end
catchRate = [catchRate,1].max
next [catchRate,255].min
})
BallHandlers::ModifyCatchRate.add(:LOVEBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
battle.allSameSideBattlers.each do |b|
next if b.species!=battler.species
next if b.gender==battler.gender || b.gender==2 || battler.gender==2
catchRate *= 8
break
end
next [catchRate,255].min
})
BallHandlers::ModifyCatchRate.add(:MOONBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
# NOTE: Moon Ball cares about whether any species in the target's evolutionary
# family can evolve with the Moon Stone, not whether the target itself
# can immediately evolve with the Moon Stone.
moon_stone = GameData::Item.try_get(:MOONSTONE)
if moon_stone && battler.pokemon.species_data.family_item_evolutions_use_item?(moon_stone.id)
catchRate *= 4
end
next [catchRate, 255].min
})
BallHandlers::ModifyCatchRate.add(:SPORTBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
next catchRate*1.5
})
BallHandlers::ModifyCatchRate.add(:DREAMBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
catchRate *= 4 if battler.asleep?
next catchRate
})
BallHandlers::ModifyCatchRate.add(:BEASTBALL,proc { |ball,catchRate,battle,battler,ultraBeast|
if ultraBeast
catchRate *= 5
else
catchRate /= 10
end
next catchRate
})
#===============================================================================
# OnCatch
#===============================================================================
BallHandlers::OnCatch.add(:HEALBALL,proc { |ball,battle,pkmn|
pkmn.heal
})
BallHandlers::OnCatch.add(:FRIENDBALL,proc { |ball,battle,pkmn|
pkmn.happiness = 200
})