mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-11 23:24:59 +00:00
Merge branch 'ai' into dev
This commit is contained in:
178
Data/Scripts/011_Battle/007_Other battle code/001_PBEffects.rb
Normal file
178
Data/Scripts/011_Battle/007_Other battle code/001_PBEffects.rb
Normal file
@@ -0,0 +1,178 @@
|
||||
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
|
||||
ExtraType = 26
|
||||
FirstPledge = 27
|
||||
FlashFire = 28
|
||||
Flinch = 29
|
||||
FocusEnergy = 30
|
||||
FocusPunch = 31
|
||||
FollowMe = 32
|
||||
Foresight = 33
|
||||
FuryCutter = 34
|
||||
GastroAcid = 35
|
||||
GemConsumed = 36
|
||||
Grudge = 37
|
||||
HealBlock = 38
|
||||
HelpingHand = 39
|
||||
HyperBeam = 40
|
||||
Illusion = 41
|
||||
Imprison = 42
|
||||
Ingrain = 43
|
||||
Instruct = 44
|
||||
Instructed = 45
|
||||
JawLock = 46
|
||||
KingsShield = 47
|
||||
LaserFocus = 48
|
||||
LeechSeed = 49
|
||||
LockOn = 50
|
||||
LockOnPos = 51
|
||||
MagicBounce = 52
|
||||
MagicCoat = 53
|
||||
MagnetRise = 54
|
||||
MeanLook = 55
|
||||
MeFirst = 56
|
||||
Metronome = 57
|
||||
MicleBerry = 58
|
||||
Minimize = 59
|
||||
MiracleEye = 60
|
||||
MirrorCoat = 61
|
||||
MirrorCoatTarget = 62
|
||||
MoveNext = 63
|
||||
MudSport = 64
|
||||
Nightmare = 65
|
||||
NoRetreat = 66
|
||||
Obstruct = 67
|
||||
Octolock = 68
|
||||
Outrage = 69
|
||||
ParentalBond = 70
|
||||
PerishSong = 71
|
||||
PerishSongUser = 72
|
||||
PickupItem = 73
|
||||
PickupUse = 74
|
||||
Pinch = 75 # Battle Palace only
|
||||
Powder = 76
|
||||
PowerTrick = 77
|
||||
Prankster = 78
|
||||
PriorityAbility = 79
|
||||
PriorityItem = 80
|
||||
Protect = 81
|
||||
ProtectRate = 82
|
||||
Quash = 83
|
||||
Rage = 84
|
||||
RagePowder = 85 # Used along with FollowMe
|
||||
Rollout = 86
|
||||
Roost = 87
|
||||
ShellTrap = 88
|
||||
SkyDrop = 89
|
||||
SlowStart = 90
|
||||
SmackDown = 91
|
||||
Snatch = 92
|
||||
SpikyShield = 93
|
||||
Spotlight = 94
|
||||
Stockpile = 95
|
||||
StockpileDef = 96
|
||||
StockpileSpDef = 97
|
||||
Substitute = 98
|
||||
TarShot = 99
|
||||
Taunt = 100
|
||||
Telekinesis = 101
|
||||
ThroatChop = 102
|
||||
Torment = 103
|
||||
Toxic = 104
|
||||
Transform = 105
|
||||
TransformSpecies = 106
|
||||
Trapping = 107 # Trapping move that deals EOR damage
|
||||
TrappingMove = 108
|
||||
TrappingUser = 109
|
||||
Truant = 110
|
||||
TwoTurnAttack = 111
|
||||
Unburden = 112
|
||||
Uproar = 113
|
||||
WaterSport = 114
|
||||
WeightChange = 115
|
||||
Yawn = 116
|
||||
|
||||
#=============================================================================
|
||||
# These effects apply to a battler position
|
||||
#=============================================================================
|
||||
FutureSightCounter = 700
|
||||
FutureSightMove = 701
|
||||
FutureSightUserIndex = 702
|
||||
FutureSightUserPartyIndex = 703
|
||||
HealingWish = 704
|
||||
LunarDance = 705
|
||||
Wish = 706
|
||||
WishAmount = 707
|
||||
WishMaker = 708
|
||||
|
||||
#=============================================================================
|
||||
# These effects apply to a side
|
||||
#=============================================================================
|
||||
AuroraVeil = 800
|
||||
CraftyShield = 801
|
||||
EchoedVoiceCounter = 802
|
||||
EchoedVoiceUsed = 803
|
||||
LastRoundFainted = 804
|
||||
LightScreen = 805
|
||||
LuckyChant = 806
|
||||
MatBlock = 807
|
||||
Mist = 808
|
||||
QuickGuard = 809
|
||||
Rainbow = 810
|
||||
Reflect = 811
|
||||
Round = 812
|
||||
Safeguard = 813
|
||||
SeaOfFire = 814
|
||||
Spikes = 815
|
||||
StealthRock = 816
|
||||
StickyWeb = 817
|
||||
Swamp = 818
|
||||
Tailwind = 819
|
||||
ToxicSpikes = 820
|
||||
WideGuard = 821
|
||||
|
||||
#=============================================================================
|
||||
# These effects apply to the battle (i.e. both sides)
|
||||
#=============================================================================
|
||||
AmuletCoin = 900
|
||||
FairyLock = 901
|
||||
FusionBolt = 902
|
||||
FusionFlare = 903
|
||||
Gravity = 904
|
||||
HappyHour = 905
|
||||
IonDeluge = 906
|
||||
MagicRoom = 907
|
||||
MudSportField = 908
|
||||
PayDay = 909
|
||||
TrickRoom = 910
|
||||
WaterSportField = 911
|
||||
WonderRoom = 912
|
||||
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_MULTIPLIER
|
||||
@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,77 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
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 pbOnStartingBattle(battle, pkmn, wild = false)
|
||||
f = MultipleForms.call("getFormOnStartingBattle", pkmn, wild)
|
||||
pkmn.form = f if f
|
||||
MultipleForms.call("changePokemonOnStartingBattle", pkmn, battle)
|
||||
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,265 @@
|
||||
module Battle::CatchAndStoreMixin
|
||||
#=============================================================================
|
||||
# Store caught Pokémon
|
||||
#=============================================================================
|
||||
def pbStorePokemon(pkmn)
|
||||
# Nickname the Pokémon (unless it's a Shadow Pokémon)
|
||||
if !pkmn.shadowPokemon?
|
||||
if $PokemonSystem.givenicknames == 0 &&
|
||||
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
|
||||
# Store the Pokémon
|
||||
if pbPlayer.party_full? && (@sendToBoxes == 0 || @sendToBoxes == 2) # Ask/must add to party
|
||||
cmds = [_INTL("Add to your party"),
|
||||
_INTL("Send to a Box"),
|
||||
_INTL("See {1}'s summary", pkmn.name),
|
||||
_INTL("Check party")]
|
||||
cmds.delete_at(1) if @sendToBoxes == 2
|
||||
loop do
|
||||
cmd = pbShowCommands(_INTL("Where do you want to send {1} to?", pkmn.name), cmds, 99)
|
||||
break if cmd == 99 # Cancelling = send to a Box
|
||||
cmd += 1 if cmd >= 1 && @sendToBoxes == 2
|
||||
case cmd
|
||||
when 0 # Add to your party
|
||||
pbDisplay(_INTL("Choose a Pokémon in your party to send to your Boxes."))
|
||||
party_index = -1
|
||||
@scene.pbPartyScreen(0, (@sendToBoxes != 2), 1) do |idxParty, _partyScene|
|
||||
party_index = idxParty
|
||||
next true
|
||||
end
|
||||
next if party_index < 0 # Cancelled
|
||||
party_size = pbPlayer.party.length
|
||||
# Send chosen Pokémon to storage
|
||||
send_pkmn = pbPlayer.party[party_index]
|
||||
stored_box = @peer.pbStorePokemon(pbPlayer, send_pkmn)
|
||||
pbPlayer.party.delete_at(party_index)
|
||||
box_name = @peer.pbBoxName(stored_box)
|
||||
pbDisplayPaused(_INTL("{1} has been sent to Box \"{2}\".", send_pkmn.name, box_name))
|
||||
# Rearrange all remembered properties of party Pokémon
|
||||
(party_index...party_size).each do |idx|
|
||||
if idx < party_size - 1
|
||||
@initialItems[0][idx] = @initialItems[0][idx + 1]
|
||||
$game_temp.party_levels_before_battle[idx] = $game_temp.party_levels_before_battle[idx + 1]
|
||||
$game_temp.party_critical_hits_dealt[idx] = $game_temp.party_critical_hits_dealt[idx + 1]
|
||||
$game_temp.party_direct_damage_taken[idx] = $game_temp.party_direct_damage_taken[idx + 1]
|
||||
else
|
||||
@initialItems[0][idx] = nil
|
||||
$game_temp.party_levels_before_battle[idx] = nil
|
||||
$game_temp.party_critical_hits_dealt[idx] = nil
|
||||
$game_temp.party_direct_damage_taken[idx] = nil
|
||||
end
|
||||
end
|
||||
break
|
||||
when 1 # Send to a Box
|
||||
break
|
||||
when 2 # See X's summary
|
||||
pbFadeOutIn do
|
||||
summary_scene = PokemonSummary_Scene.new
|
||||
summary_screen = PokemonSummaryScreen.new(summary_scene, true)
|
||||
summary_screen.pbStartScreen([pkmn], 0)
|
||||
end
|
||||
when 3 # Check party
|
||||
@scene.pbPartyScreen(0, true, 2)
|
||||
end
|
||||
end
|
||||
end
|
||||
# Store as normal (add to party if there's space, or send to a Box if not)
|
||||
stored_box = @peer.pbStorePokemon(pbPlayer, pkmn)
|
||||
if stored_box < 0
|
||||
pbDisplayPaused(_INTL("{1} has been added to your party.", pkmn.name))
|
||||
@initialItems[0][pbPlayer.party.length - 1] = pkmn.item_id if @initialItems
|
||||
return
|
||||
end
|
||||
# Messages saying the Pokémon was stored in a PC box
|
||||
box_name = @peer.pbBoxName(stored_box)
|
||||
pbDisplayPaused(_INTL("{1} has been sent to Box \"{2}\"!", pkmn.name, box_name))
|
||||
end
|
||||
|
||||
# Register all caught Pokémon in the Pokédex, and store them.
|
||||
def pbRecordAndStoreCaughtPokemon
|
||||
@caughtPokemon.each do |pkmn|
|
||||
pbSetCaught(pkmn)
|
||||
pbSetSeen(pkmn) # In case the form changed upon leaving battle
|
||||
# Record the Pokémon's species as owned in the Pokédex
|
||||
if !pbPlayer.owned?(pkmn.species)
|
||||
pbPlayer.pokedex.set_owned(pkmn.species)
|
||||
if $player.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)
|
||||
end
|
||||
end
|
||||
# Record a Shadow Pokémon's species as having been caught
|
||||
pbPlayer.pokedex.set_shadow_pokemon_owned(pkmn.species) if pkmn.shadowPokemon?
|
||||
# Store caught Pokémon
|
||||
pbStorePokemon(pkmn)
|
||||
end
|
||||
@caughtPokemon.clear
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Throw a Poké Ball
|
||||
#=============================================================================
|
||||
def pbThrowPokeBall(idxBattler, ball, catch_rate = nil, showPlayer = false)
|
||||
# Determine which Pokémon you're throwing the Poké Ball at
|
||||
battler = nil
|
||||
if opposes?(idxBattler)
|
||||
battler = @battlers[idxBattler]
|
||||
else
|
||||
battler = @battlers[idxBattler].pbDirectOpposing(true)
|
||||
end
|
||||
battler = battler.allAllies[0] if battler.fainted?
|
||||
# Messages
|
||||
itemName = GameData::Item.get(ball).name
|
||||
if battler.fainted?
|
||||
if itemName.starts_with_vowel?
|
||||
pbDisplay(_INTL("{1} threw an {2}!", pbPlayer.name, itemName))
|
||||
else
|
||||
pbDisplay(_INTL("{1} threw a {2}!", pbPlayer.name, itemName))
|
||||
end
|
||||
pbDisplay(_INTL("But there was no target..."))
|
||||
return
|
||||
end
|
||||
if itemName.starts_with_vowel?
|
||||
pbDisplayBrief(_INTL("{1} threw an {2}!", pbPlayer.name, itemName))
|
||||
else
|
||||
pbDisplayBrief(_INTL("{1} threw a {2}!", pbPlayer.name, itemName))
|
||||
end
|
||||
# Animation of opposing trainer blocking Poké Balls (unless it's a Snag Ball
|
||||
# at a Shadow Pokémon)
|
||||
if trainerBattle? && !(GameData::Item.get(ball).is_snag_ball? && battler.shadowPokemon?)
|
||||
@scene.pbThrowAndDeflect(ball, 1)
|
||||
pbDisplay(_INTL("The Trainer blocked your Poké Ball! Don't be a thief!"))
|
||||
return
|
||||
end
|
||||
# Calculate the number of shakes (4=capture)
|
||||
pkmn = battler.pokemon
|
||||
@criticalCapture = false
|
||||
numShakes = pbCaptureCalc(pkmn, battler, catch_rate, ball)
|
||||
PBDebug.log("[Threw Poké Ball] #{itemName}, #{numShakes} shakes (4=capture)")
|
||||
# Animation of Ball throw, absorb, shake and capture/burst out
|
||||
@scene.pbThrow(ball, numShakes, @criticalCapture, battler.index, showPlayer)
|
||||
# Outcome message
|
||||
case numShakes
|
||||
when 0
|
||||
pbDisplay(_INTL("Oh no! The Pokémon broke free!"))
|
||||
Battle::PokeBallEffects.onFailCatch(ball, self, battler)
|
||||
when 1
|
||||
pbDisplay(_INTL("Aww! It appeared to be caught!"))
|
||||
Battle::PokeBallEffects.onFailCatch(ball, self, battler)
|
||||
when 2
|
||||
pbDisplay(_INTL("Aargh! Almost had it!"))
|
||||
Battle::PokeBallEffects.onFailCatch(ball, self, battler)
|
||||
when 3
|
||||
pbDisplay(_INTL("Gah! It was so close, too!"))
|
||||
Battle::PokeBallEffects.onFailCatch(ball, self, battler)
|
||||
when 4
|
||||
pbDisplayBrief(_INTL("Gotcha! {1} was caught!", pkmn.name))
|
||||
@scene.pbThrowSuccess # Play capture success jingle
|
||||
pbRemoveFromParty(battler.index, battler.pokemonIndex)
|
||||
# Gain Exp
|
||||
if Settings::GAIN_EXP_FOR_CAPTURE
|
||||
battler.captured = true
|
||||
pbGainExp
|
||||
battler.captured = false
|
||||
end
|
||||
battler.pbReset
|
||||
if pbAllFainted?(battler.index)
|
||||
@decision = (trainerBattle?) ? 1 : 4 # Battle ended by win/capture
|
||||
end
|
||||
# Modify the Pokémon's properties because of the capture
|
||||
if GameData::Item.get(ball).is_snag_ball?
|
||||
pkmn.owner = Pokemon::Owner.new_from_trainer(pbPlayer)
|
||||
end
|
||||
Battle::PokeBallEffects.onCatch(ball, self, pkmn)
|
||||
pkmn.poke_ball = ball
|
||||
pkmn.makeUnmega if pkmn.mega?
|
||||
pkmn.makeUnprimal
|
||||
pkmn.update_shadow_moves if pkmn.shadowPokemon?
|
||||
pkmn.record_first_moves
|
||||
# Reset form
|
||||
pkmn.forced_form = nil if MultipleForms.hasFunction?(pkmn.species, "getForm")
|
||||
@peer.pbOnLeavingBattle(self, pkmn, true, true)
|
||||
# Make the Poké Ball and data box disappear
|
||||
@scene.pbHideCaptureBall(idxBattler)
|
||||
# Save the Pokémon for storage at the end of battle
|
||||
@caughtPokemon.push(pkmn)
|
||||
end
|
||||
if numShakes != 4
|
||||
@first_poke_ball = ball if !@poke_ball_failed
|
||||
@poke_ball_failed = true
|
||||
end
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
# Calculate how many shakes a thrown Poké Ball will make (4 = capture)
|
||||
#=============================================================================
|
||||
def pbCaptureCalc(pkmn, battler, catch_rate, ball)
|
||||
return 4 if $DEBUG && Input.press?(Input::CTRL)
|
||||
# Get a catch rate if one wasn't provided
|
||||
catch_rate = pkmn.species_data.catch_rate if !catch_rate
|
||||
# Modify catch_rate depending on the Poké Ball's effect
|
||||
if !pkmn.species_data.has_flag?("UltraBeast") || ball == :BEASTBALL
|
||||
catch_rate = Battle::PokeBallEffects.modifyCatchRate(ball, catch_rate, self, battler)
|
||||
else
|
||||
catch_rate /= 10
|
||||
end
|
||||
# First half of the shakes calculation
|
||||
a = battler.totalhp
|
||||
b = battler.hp
|
||||
x = (((3 * a) - (2 * b)) * catch_rate.to_f) / (3 * a)
|
||||
# Calculation modifiers
|
||||
if battler.status == :SLEEP || battler.status == :FROZEN
|
||||
x *= 2.5
|
||||
elsif battler.status != :NONE
|
||||
x *= 1.5
|
||||
end
|
||||
x = x.floor
|
||||
x = 1 if x < 1
|
||||
# Definite capture, no need to perform randomness checks
|
||||
return 4 if x >= 255 || Battle::PokeBallEffects.isUnconditional?(ball, self, battler)
|
||||
# Second half of the shakes calculation
|
||||
y = (65_536 / ((255.0 / x)**0.1875)).floor
|
||||
# Critical capture check
|
||||
if Settings::ENABLE_CRITICAL_CAPTURES
|
||||
dex_modifier = 0
|
||||
numOwned = $player.pokedex.owned_count
|
||||
if numOwned > 600
|
||||
dex_modifier = 5
|
||||
elsif numOwned > 450
|
||||
dex_modifier = 4
|
||||
elsif numOwned > 300
|
||||
dex_modifier = 3
|
||||
elsif numOwned > 150
|
||||
dex_modifier = 2
|
||||
elsif numOwned > 30
|
||||
dex_modifier = 1
|
||||
end
|
||||
dex_modifier *= 2 if $bag.has?(:CATCHINGCHARM)
|
||||
c = x * dex_modifier / 12
|
||||
# Calculate the number of shakes
|
||||
if c > 0 && pbRandom(256) < c
|
||||
@criticalCapture = true
|
||||
return 4 if pbRandom(65_536) < y
|
||||
return 0
|
||||
end
|
||||
end
|
||||
# Calculate the number of shakes
|
||||
numShakes = 0
|
||||
4.times do |i|
|
||||
break if numShakes < i
|
||||
numShakes += 1 if pbRandom(65_536) < y
|
||||
end
|
||||
return numShakes
|
||||
end
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class Battle
|
||||
include Battle::CatchAndStoreMixin
|
||||
end
|
||||
@@ -0,0 +1,306 @@
|
||||
#===============================================================================
|
||||
# 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
|
||||
|
||||
#===============================================================================
|
||||
# Double Team
|
||||
#===============================================================================
|
||||
class Battle::Move::RaiseUserEvasion1
|
||||
unless method_defined?(:__clauses__pbMoveFailed?)
|
||||
alias __clauses__pbMoveFailed? pbMoveFailed?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Minimize
|
||||
#===============================================================================
|
||||
class Battle::Move::RaiseUserEvasion2MinimizeUser
|
||||
unless method_defined?(:__clauses__pbMoveFailed?)
|
||||
alias __clauses__pbMoveFailed? pbMoveFailed?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Skill Swap
|
||||
#===============================================================================
|
||||
class Battle::Move::UserTargetSwapAbilities
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Sonic Boom
|
||||
#===============================================================================
|
||||
class Battle::Move::FixedDamage20
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Dragon Rage
|
||||
#===============================================================================
|
||||
class Battle::Move::FixedDamage40
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Self-Destruct
|
||||
#===============================================================================
|
||||
class Battle::Move::UserFaintsExplosive
|
||||
unless method_defined?(:__clauses__pbMoveFailed?)
|
||||
alias __clauses__pbMoveFailed? pbMoveFailed?
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Perish Song
|
||||
#===============================================================================
|
||||
class Battle::Move::StartPerishCountsForAllBattlers
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
#===============================================================================
|
||||
# Destiny Bond
|
||||
#===============================================================================
|
||||
class Battle::Move::AttackerFaintsIfUserFaints
|
||||
unless method_defined?(:__clauses__pbFailsAgainstTarget?)
|
||||
alias __clauses__pbFailsAgainstTarget? pbFailsAgainstTarget?
|
||||
end
|
||||
|
||||
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,845 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
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
|
||||
animation.frames.length.times do |i|
|
||||
frame = pbAnim.addFrame
|
||||
animFrame = animation.frames[i]
|
||||
animFrame.cell_max.times do |j|
|
||||
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
|
||||
animation.timings.each do |timing|
|
||||
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
|
||||
(totalframes - self.frames.length).times do
|
||||
self.frames.push(RPG::Animation::Frame.new)
|
||||
end
|
||||
end
|
||||
self.frame_max = self.frames.length
|
||||
otherAnim.frame_max.times do |i|
|
||||
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)
|
||||
otherframe.cell_max.times do |j|
|
||||
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
|
||||
otherAnim.timings.each do |othertiming|
|
||||
timing = RPG::Animation::Timing.new
|
||||
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.white
|
||||
@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 || "-",
|
||||
@colorGreen || "-",
|
||||
@colorBlue || "-",
|
||||
@colorAlpha || "-")
|
||||
text += sprintf(" (opacity=%d)", @opacity)
|
||||
text += sprintf(" (coords=%s,%s)", @bgX || "-", @bgY || "-")
|
||||
return text
|
||||
when 2
|
||||
text = sprintf("[%d] Change BG: @%d", @frame + 1, duration)
|
||||
if @colorRed || @colorGreen || @colorBlue || @colorAlpha
|
||||
text += sprintf(" (color=%s,%s,%s,%s)",
|
||||
@colorRed || "-",
|
||||
@colorGreen || "-",
|
||||
@colorBlue || "-",
|
||||
@colorAlpha || "-")
|
||||
end
|
||||
text += sprintf(" (opacity=%d)", @opacity) if @opacity
|
||||
text += sprintf(" (coords=%s,%s)", @bgX || "-", @bgY || "-") if @bgX || @bgY
|
||||
return text
|
||||
when 3
|
||||
text = sprintf("[%d] Set FG: \"%s\"", @frame + 1, name)
|
||||
text += sprintf(" (color=%s,%s,%s,%s)",
|
||||
@colorRed || "-",
|
||||
@colorGreen || "-",
|
||||
@colorBlue || "-",
|
||||
@colorAlpha || "-")
|
||||
text += sprintf(" (opacity=%d)", @opacity)
|
||||
text += sprintf(" (coords=%s,%s)", @bgX || "-", @bgY || "-")
|
||||
return text
|
||||
when 4
|
||||
text = sprintf("[%d] Change FG: @%d", @frame + 1, duration)
|
||||
if @colorRed || @colorGreen || @colorBlue || @colorAlpha
|
||||
text += sprintf(" (color=%s,%s,%s,%s)",
|
||||
@colorRed || "-",
|
||||
@colorGreen || "-",
|
||||
@colorBlue || "-",
|
||||
@colorAlpha || "-")
|
||||
end
|
||||
text += sprintf(" (opacity=%d)", @opacity) if @opacity
|
||||
text += sprintf(" (coords=%s,%s)", @bgX || "-", @bgY || "-") if @bgX || @bgY
|
||||
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 get_from_name(name)
|
||||
@array.each { |i| return i if i&.name == name }
|
||||
return nil
|
||||
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
|
||||
(idxStart - idxEnd).times { @array.pop }
|
||||
else
|
||||
(idxEnd - idxStart).times { @array.push(PBAnimation.new) }
|
||||
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)
|
||||
@timing.each do |i|
|
||||
next if !i.duration || i.duration <= 0
|
||||
next if i.frame + i.duration < frame || i.frame >= frame
|
||||
fraction = (frame - i.frame).to_f / i.duration
|
||||
case i.timingType
|
||||
when 2
|
||||
if bgGraphic.bitmap.nil?
|
||||
bgColor.opacity = oldbg[2] + ((i.opacity - oldbg[2]) * fraction) if i.opacity
|
||||
cr = (i.colorRed) ? oldbg[3].red + ((i.colorRed - oldbg[3].red) * fraction) : oldbg[3].red
|
||||
cg = (i.colorGreen) ? oldbg[3].green + ((i.colorGreen - oldbg[3].green) * fraction) : oldbg[3].green
|
||||
cb = (i.colorBlue) ? oldbg[3].blue + ((i.colorBlue - oldbg[3].blue) * fraction) : oldbg[3].blue
|
||||
ca = (i.colorAlpha) ? oldbg[3].alpha + ((i.colorAlpha - oldbg[3].alpha) * fraction) : oldbg[3].alpha
|
||||
bgColor.color = Color.new(cr, cg, cb, ca)
|
||||
else
|
||||
bgGraphic.ox = oldbg[0] - ((i.bgX - oldbg[0]) * fraction) if i.bgX
|
||||
bgGraphic.oy = oldbg[1] - ((i.bgY - oldbg[1]) * fraction) if i.bgY
|
||||
bgGraphic.opacity = oldbg[2] + ((i.opacity - oldbg[2]) * fraction) if i.opacity
|
||||
cr = (i.colorRed) ? oldbg[3].red + ((i.colorRed - oldbg[3].red) * fraction) : oldbg[3].red
|
||||
cg = (i.colorGreen) ? oldbg[3].green + ((i.colorGreen - oldbg[3].green) * fraction) : oldbg[3].green
|
||||
cb = (i.colorBlue) ? oldbg[3].blue + ((i.colorBlue - oldbg[3].blue) * fraction) : oldbg[3].blue
|
||||
ca = (i.colorAlpha) ? oldbg[3].alpha + ((i.colorAlpha - oldbg[3].alpha) * fraction) : oldbg[3].alpha
|
||||
bgGraphic.color = Color.new(cr, cg, cb, ca)
|
||||
end
|
||||
when 4
|
||||
if foGraphic.bitmap.nil?
|
||||
foColor.opacity = oldfo[2] + ((i.opacity - oldfo[2]) * fraction) if i.opacity
|
||||
cr = (i.colorRed) ? oldfo[3].red + ((i.colorRed - oldfo[3].red) * fraction) : oldfo[3].red
|
||||
cg = (i.colorGreen) ? oldfo[3].green + ((i.colorGreen - oldfo[3].green) * fraction) : oldfo[3].green
|
||||
cb = (i.colorBlue) ? oldfo[3].blue + ((i.colorBlue - oldfo[3].blue) * fraction) : oldfo[3].blue
|
||||
ca = (i.colorAlpha) ? oldfo[3].alpha + ((i.colorAlpha - oldfo[3].alpha) * fraction) : oldfo[3].alpha
|
||||
foColor.color = Color.new(cr, cg, cb, ca)
|
||||
else
|
||||
foGraphic.ox = oldfo[0] - ((i.bgX - oldfo[0]) * fraction) if i.bgX
|
||||
foGraphic.oy = oldfo[1] - ((i.bgY - oldfo[1]) * fraction) if i.bgY
|
||||
foGraphic.opacity = oldfo[2] + ((i.opacity - oldfo[2]) * fraction) if i.opacity
|
||||
cr = (i.colorRed) ? oldfo[3].red + ((i.colorRed - oldfo[3].red) * fraction) : oldfo[3].red
|
||||
cg = (i.colorGreen) ? oldfo[3].green + ((i.colorGreen - oldfo[3].green) * fraction) : oldfo[3].green
|
||||
cb = (i.colorBlue) ? oldfo[3].blue + ((i.colorBlue - oldfo[3].blue) * fraction) : oldfo[3].blue
|
||||
ca = (i.colorAlpha) ? oldfo[3].alpha + ((i.colorAlpha - oldfo[3].alpha) * fraction) : oldfo[3].alpha
|
||||
foGraphic.color = Color.new(cr, cg, cb, ca)
|
||||
end
|
||||
end
|
||||
end
|
||||
@timing.each do |i|
|
||||
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&.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] = 0
|
||||
oldbg[1] = 0
|
||||
oldbg[2] = bgColor.opacity || 0
|
||||
oldbg[3] = bgColor.color.clone || Color.new(0, 0, 0, 0)
|
||||
else
|
||||
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)
|
||||
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] = 0
|
||||
oldfo[1] = 0
|
||||
oldfo[2] = foColor.opacity || 0
|
||||
oldfo[3] = foColor.color.clone || Color.new(0, 0, 0, 0)
|
||||
else
|
||||
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)
|
||||
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&.bitmap # not to be disposed
|
||||
@targetbitmap = @targetsprite&.bitmap # not to be disposed
|
||||
@scene = scene
|
||||
@viewport = scene&.viewport
|
||||
@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
|
||||
(2...MAX_SPRITES).each do |i|
|
||||
@animsprites[i] = Sprite.new(@viewport)
|
||||
@animsprites[i].bitmap = nil
|
||||
@animsprites[i].visible = false
|
||||
end
|
||||
# Create background colour sprite
|
||||
@bgColor = ColoredPlane.new(Color.black, @viewport)
|
||||
@bgColor.z = 5
|
||||
@bgColor.opacity = 0
|
||||
@bgColor.refresh
|
||||
# Create background graphic sprite
|
||||
@bgGraphic = AnimatedPlane.new(@viewport)
|
||||
@bgGraphic.setBitmap(nil)
|
||||
@bgGraphic.z = 5
|
||||
@bgGraphic.opacity = 0
|
||||
@bgGraphic.refresh
|
||||
# Create foreground colour sprite
|
||||
@foColor = ColoredPlane.new(Color.black, @viewport)
|
||||
@foColor.z = 85
|
||||
@foColor.opacity = 0
|
||||
@foColor.refresh
|
||||
# Create foreground graphic sprite
|
||||
@foGraphic = AnimatedPlane.new(@viewport)
|
||||
@foGraphic.setBitmap(nil)
|
||||
@foGraphic.z = 85
|
||||
@foGraphic.opacity = 0
|
||||
@foGraphic.refresh
|
||||
end
|
||||
|
||||
def dispose
|
||||
@animbitmap&.dispose
|
||||
(2...MAX_SPRITES).each do |i|
|
||||
@animsprites[i]&.dispose
|
||||
end
|
||||
@bgGraphic.dispose
|
||||
@bgColor.dispose
|
||||
@foGraphic.dispose
|
||||
@foColor.dispose
|
||||
end
|
||||
|
||||
# Makes the original user and target sprites be uninvolved with the animation.
|
||||
# The animation shows just its particles.
|
||||
def discard_user_and_target_sprites
|
||||
@animsprites[0] = nil
|
||||
@animsprites[1] = nil
|
||||
end
|
||||
|
||||
def set_target_origin(x, y)
|
||||
@targetOrig = [x, y]
|
||||
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
|
||||
@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
|
||||
MAX_SPRITES.times do |i|
|
||||
@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
|
||||
MAX_SPRITES.times do |i|
|
||||
@animsprites[i].visible = false if @animsprites[i]
|
||||
end
|
||||
# Set each cel sprite acoordingly
|
||||
thisframe.length.times do |i|
|
||||
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
|
||||
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 Battle::PokeBallEffects
|
||||
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)
|
||||
ret = ModifyCatchRate.trigger(ball, catchRate, battle, battler)
|
||||
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
|
||||
#===============================================================================
|
||||
Battle::PokeBallEffects::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.
|
||||
#===============================================================================
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:GREATBALL, proc { |ball, catchRate, battle, battler|
|
||||
next catchRate * 1.5
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:ULTRABALL, proc { |ball, catchRate, battle, battler|
|
||||
next catchRate * 2
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:SAFARIBALL, proc { |ball, catchRate, battle, battler|
|
||||
next catchRate * 1.5
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:NETBALL, proc { |ball, catchRate, battle, battler|
|
||||
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3.5 : 3
|
||||
catchRate *= multiplier if battler.pbHasType?(:BUG) || battler.pbHasType?(:WATER)
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:DIVEBALL, proc { |ball, catchRate, battle, battler|
|
||||
catchRate *= 3.5 if battle.environment == :Underwater
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:NESTBALL, proc { |ball, catchRate, battle, battler|
|
||||
if battler.level <= 30
|
||||
catchRate *= [(41 - battler.level) / 10.0, 1].max
|
||||
end
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:REPEATBALL, proc { |ball, catchRate, battle, battler|
|
||||
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3.5 : 3
|
||||
catchRate *= multiplier if battle.pbPlayer.owned?(battler.species)
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:TIMERBALL, proc { |ball, catchRate, battle, battler|
|
||||
multiplier = [1 + (0.3 * battle.turnCount), 4].min
|
||||
catchRate *= multiplier
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:DUSKBALL, proc { |ball, catchRate, battle, battler|
|
||||
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 3 : 3.5
|
||||
catchRate *= multiplier if battle.time == 2 # Night or in cave
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:QUICKBALL, proc { |ball, catchRate, battle, battler|
|
||||
catchRate *= 5 if battle.turnCount == 0
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:FASTBALL, proc { |ball, catchRate, battle, battler|
|
||||
baseStats = battler.pokemon.baseStats
|
||||
baseSpeed = baseStats[:SPEED]
|
||||
catchRate *= 4 if baseSpeed >= 100
|
||||
next [catchRate, 255].min
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:LEVELBALL, proc { |ball, catchRate, battle, battler|
|
||||
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
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:LUREBALL, proc { |ball, catchRate, battle, battler|
|
||||
if $game_temp.encounter_type &&
|
||||
GameData::EncounterType.get($game_temp.encounter_type).type == :fishing
|
||||
multiplier = (Settings::NEW_POKE_BALL_CATCH_RATES) ? 5 : 3
|
||||
catchRate *= multiplier
|
||||
end
|
||||
next [catchRate, 255].min
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:HEAVYBALL, proc { |ball, catchRate, battle, battler|
|
||||
next 0 if catchRate == 0
|
||||
weight = battler.pbWeight
|
||||
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
|
||||
next catchRate.clamp(1, 255)
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:LOVEBALL, proc { |ball, catchRate, battle, battler|
|
||||
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
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:MOONBALL, proc { |ball, catchRate, battle, battler|
|
||||
# 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
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:SPORTBALL, proc { |ball, catchRate, battle, battler|
|
||||
next catchRate * 1.5
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:DREAMBALL, proc { |ball, catchRate, battle, battler|
|
||||
catchRate *= 4 if battler.asleep?
|
||||
next catchRate
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::ModifyCatchRate.add(:BEASTBALL, proc { |ball, catchRate, battle, battler|
|
||||
if battler.pokemon.species_data.has_flag?("UltraBeast")
|
||||
catchRate *= 5
|
||||
else
|
||||
catchRate /= 10
|
||||
end
|
||||
next catchRate
|
||||
})
|
||||
|
||||
#===============================================================================
|
||||
# OnCatch
|
||||
#===============================================================================
|
||||
Battle::PokeBallEffects::OnCatch.add(:HEALBALL, proc { |ball, battle, pkmn|
|
||||
pkmn.heal
|
||||
})
|
||||
|
||||
Battle::PokeBallEffects::OnCatch.add(:FRIENDBALL, proc { |ball, battle, pkmn|
|
||||
pkmn.happiness = (Settings::APPLY_HAPPINESS_SOFT_CAP) ? 150 : 200
|
||||
})
|
||||
Reference in New Issue
Block a user