mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-07 21:24:59 +00:00
Fixed Beak Blast/Shell Trap always failing, typo in Brick Break
This commit is contained in:
@@ -0,0 +1,686 @@
|
||||
#===============================================================================
|
||||
# Battle preparation
|
||||
#===============================================================================
|
||||
class PokemonGlobalMetadata
|
||||
attr_accessor :nextBattleBGM
|
||||
attr_accessor :nextBattleME
|
||||
attr_accessor :nextBattleCaptureME
|
||||
attr_accessor :nextBattleBack
|
||||
end
|
||||
|
||||
|
||||
|
||||
class PokemonTemp
|
||||
attr_accessor :encounterTriggered
|
||||
attr_accessor :encounterType
|
||||
attr_accessor :evolutionLevels
|
||||
|
||||
def battleRules
|
||||
@battleRules = {} if !@battleRules
|
||||
return @battleRules
|
||||
end
|
||||
|
||||
def clearBattleRules
|
||||
self.battleRules.clear
|
||||
end
|
||||
|
||||
def recordBattleRule(rule,var=nil)
|
||||
rules = self.battleRules
|
||||
case rule.to_s.downcase
|
||||
when "single", "1v1", "1v2", "2v1", "1v3", "3v1",
|
||||
"double", "2v2", "2v3", "3v2", "triple", "3v3"
|
||||
rules["size"] = rule.to_s.downcase
|
||||
when "canlose" then rules["canLose"] = true
|
||||
when "cannotlose" then rules["canLose"] = false
|
||||
when "canrun" then rules["canRun"] = true
|
||||
when "cannotrun" then rules["canRun"] = false
|
||||
when "roamerflees" then rules["roamerFlees"] = true
|
||||
when "noexp" then rules["expGain"] = false
|
||||
when "nomoney" then rules["moneyGain"] = false
|
||||
when "switchstyle" then rules["switchStyle"] = true
|
||||
when "setstyle" then rules["switchStyle"] = false
|
||||
when "anims" then rules["battleAnims"] = true
|
||||
when "noanims" then rules["battleAnims"] = false
|
||||
when "terrain"
|
||||
terrain_data = GameData::BattleTerrain.try_get(var)
|
||||
rules["defaultTerrain"] = (terrain_data) ? terrain_data.id : nil
|
||||
when "weather"
|
||||
weather_data = GameData::BattleWeather.try_get(var)
|
||||
rules["defaultWeather"] = (weather_data) ? weather_data.id : nil
|
||||
when "environment", "environ"
|
||||
environment_data = GameData::Environment.try_get(var)
|
||||
rules["environment"] = (environment_data) ? environment_data.id : nil
|
||||
when "backdrop", "battleback" then rules["backdrop"] = var
|
||||
when "base" then rules["base"] = var
|
||||
when "outcome", "outcomevar" then rules["outcomeVar"] = var
|
||||
when "nopartner" then rules["noPartner"] = true
|
||||
else
|
||||
raise _INTL("Battle rule \"{1}\" does not exist.", rule)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
def setBattleRule(*args)
|
||||
r = nil
|
||||
for arg in args
|
||||
if r
|
||||
$PokemonTemp.recordBattleRule(r,arg)
|
||||
r = nil
|
||||
else
|
||||
case arg.downcase
|
||||
when "terrain", "weather", "environment", "environ", "backdrop",
|
||||
"battleback", "base", "outcome", "outcomevar"
|
||||
r = arg
|
||||
next
|
||||
end
|
||||
$PokemonTemp.recordBattleRule(arg)
|
||||
end
|
||||
end
|
||||
raise _INTL("Argument {1} expected a variable after it but didn't have one.",r) if r
|
||||
end
|
||||
|
||||
def pbNewBattleScene
|
||||
return PokeBattle_Scene.new
|
||||
end
|
||||
|
||||
# Sets up various battle parameters and applies special rules.
|
||||
def pbPrepareBattle(battle)
|
||||
battleRules = $PokemonTemp.battleRules
|
||||
# The size of the battle, i.e. how many Pokémon on each side (default: "single")
|
||||
battle.setBattleMode(battleRules["size"]) if !battleRules["size"].nil?
|
||||
# Whether the game won't black out even if the player loses (default: false)
|
||||
battle.canLose = battleRules["canLose"] if !battleRules["canLose"].nil?
|
||||
# Whether the player can choose to run from the battle (default: true)
|
||||
battle.canRun = battleRules["canRun"] if !battleRules["canRun"].nil?
|
||||
# Whether wild Pokémon always try to run from battle (default: nil)
|
||||
battle.rules["alwaysflee"] = battleRules["roamerFlees"]
|
||||
# Whether Pokémon gain Exp/EVs from defeating/catching a Pokémon (default: true)
|
||||
battle.expGain = battleRules["expGain"] if !battleRules["expGain"].nil?
|
||||
# Whether the player gains/loses money at the end of the battle (default: true)
|
||||
battle.moneyGain = battleRules["moneyGain"] if !battleRules["moneyGain"].nil?
|
||||
# Whether the player is able to switch when an opponent's Pokémon faints
|
||||
battle.switchStyle = ($PokemonSystem.battlestyle==0)
|
||||
battle.switchStyle = battleRules["switchStyle"] if !battleRules["switchStyle"].nil?
|
||||
# Whether battle animations are shown
|
||||
battle.showAnims = ($PokemonSystem.battlescene==0)
|
||||
battle.showAnims = battleRules["battleAnims"] if !battleRules["battleAnims"].nil?
|
||||
# Terrain
|
||||
battle.defaultTerrain = battleRules["defaultTerrain"] if !battleRules["defaultTerrain"].nil?
|
||||
# Weather
|
||||
if battleRules["defaultWeather"].nil?
|
||||
case GameData::Weather.get($game_screen.weather_type).category
|
||||
when :Rain
|
||||
battle.defaultWeather = :Rain
|
||||
when :Hail
|
||||
battle.defaultWeather = :Hail
|
||||
when :Sandstorm
|
||||
battle.defaultWeather = :Sandstorm
|
||||
when :Sun
|
||||
battle.defaultWeather = :Sun
|
||||
end
|
||||
else
|
||||
battle.defaultWeather = battleRules["defaultWeather"]
|
||||
end
|
||||
# Environment
|
||||
if battleRules["environment"].nil?
|
||||
battle.environment = pbGetEnvironment
|
||||
else
|
||||
battle.environment = battleRules["environment"]
|
||||
end
|
||||
# Backdrop graphic filename
|
||||
if !battleRules["backdrop"].nil?
|
||||
backdrop = battleRules["backdrop"]
|
||||
elsif $PokemonGlobal.nextBattleBack
|
||||
backdrop = $PokemonGlobal.nextBattleBack
|
||||
elsif $PokemonGlobal.surfing
|
||||
backdrop = "water" # This applies wherever you are, including in caves
|
||||
elsif GameData::MapMetadata.exists?($game_map.map_id)
|
||||
back = GameData::MapMetadata.get($game_map.map_id).battle_background
|
||||
backdrop = back if back && back != ""
|
||||
end
|
||||
backdrop = "indoor1" if !backdrop
|
||||
battle.backdrop = backdrop
|
||||
# Choose a name for bases depending on environment
|
||||
if battleRules["base"].nil?
|
||||
environment_data = GameData::Environment.try_get(battle.environment)
|
||||
base = environment_data.battle_base if environment_data
|
||||
else
|
||||
base = battleRules["base"]
|
||||
end
|
||||
battle.backdropBase = base if base
|
||||
# Time of day
|
||||
if GameData::MapMetadata.exists?($game_map.map_id) &&
|
||||
GameData::MapMetadata.get($game_map.map_id).battle_environment == :Cave
|
||||
battle.time = 2 # This makes Dusk Balls work properly in caves
|
||||
elsif Settings::TIME_SHADING
|
||||
timeNow = pbGetTimeNow
|
||||
if PBDayNight.isNight?(timeNow); battle.time = 2
|
||||
elsif PBDayNight.isEvening?(timeNow); battle.time = 1
|
||||
else; battle.time = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Used to determine the environment in battle, and also the form of Burmy/
|
||||
# Wormadam.
|
||||
def pbGetEnvironment
|
||||
ret = :None
|
||||
map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
|
||||
ret = map_metadata.battle_environment if map_metadata && map_metadata.battle_environment
|
||||
if $PokemonTemp.encounterType &&
|
||||
GameData::EncounterType.get($PokemonTemp.encounterType).type == :fishing
|
||||
terrainTag = $game_player.pbFacingTerrainTag
|
||||
else
|
||||
terrainTag = $game_player.terrain_tag
|
||||
end
|
||||
tile_environment = terrainTag.battle_environment
|
||||
if ret == :Forest && [:Grass, :TallGrass].include?(tile_environment)
|
||||
ret = :ForestGrass
|
||||
else
|
||||
ret = tile_environment if tile_environment
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
Events.onStartBattle += proc { |_sender|
|
||||
# Record current levels of Pokémon in party, to see if they gain a level
|
||||
# during battle and may need to evolve afterwards
|
||||
$PokemonTemp.evolutionLevels = []
|
||||
for i in 0...$Trainer.party.length
|
||||
$PokemonTemp.evolutionLevels[i] = $Trainer.party[i].level
|
||||
end
|
||||
}
|
||||
|
||||
def pbCanDoubleBattle?
|
||||
return $PokemonGlobal.partner || $Trainer.able_pokemon_count >= 2
|
||||
end
|
||||
|
||||
def pbCanTripleBattle?
|
||||
return true if $Trainer.able_pokemon_count >= 3
|
||||
return $PokemonGlobal.partner && $Trainer.able_pokemon_count >= 2
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Start a wild battle
|
||||
#===============================================================================
|
||||
def pbWildBattleCore(*args)
|
||||
outcomeVar = $PokemonTemp.battleRules["outcomeVar"] || 1
|
||||
canLose = $PokemonTemp.battleRules["canLose"] || false
|
||||
# Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode
|
||||
if $Trainer.able_pokemon_count == 0 || ($DEBUG && Input.press?(Input::CTRL))
|
||||
pbMessage(_INTL("SKIPPING BATTLE...")) if $Trainer.pokemon_count > 0
|
||||
pbSet(outcomeVar,1) # Treat it as a win
|
||||
$PokemonTemp.clearBattleRules
|
||||
$PokemonGlobal.nextBattleBGM = nil
|
||||
$PokemonGlobal.nextBattleME = nil
|
||||
$PokemonGlobal.nextBattleCaptureME = nil
|
||||
$PokemonGlobal.nextBattleBack = nil
|
||||
return 1 # Treat it as a win
|
||||
end
|
||||
# Record information about party Pokémon to be used at the end of battle (e.g.
|
||||
# comparing levels for an evolution check)
|
||||
Events.onStartBattle.trigger(nil)
|
||||
# Generate wild Pokémon based on the species and level
|
||||
foeParty = []
|
||||
sp = nil
|
||||
for arg in args
|
||||
if arg.is_a?(Pokemon)
|
||||
foeParty.push(arg)
|
||||
elsif arg.is_a?(Array)
|
||||
species = GameData::Species.get(arg[0]).id
|
||||
pkmn = pbGenerateWildPokemon(species,arg[1])
|
||||
foeParty.push(pkmn)
|
||||
elsif sp
|
||||
species = GameData::Species.get(sp).id
|
||||
pkmn = pbGenerateWildPokemon(species,arg)
|
||||
foeParty.push(pkmn)
|
||||
sp = nil
|
||||
else
|
||||
sp = arg
|
||||
end
|
||||
end
|
||||
raise _INTL("Expected a level after being given {1}, but one wasn't found.",sp) if sp
|
||||
# Calculate who the trainers and their party are
|
||||
playerTrainers = [$Trainer]
|
||||
playerParty = $Trainer.party
|
||||
playerPartyStarts = [0]
|
||||
room_for_partner = (foeParty.length > 1)
|
||||
if !room_for_partner && $PokemonTemp.battleRules["size"] &&
|
||||
!["single", "1v1", "1v2", "1v3"].include?($PokemonTemp.battleRules["size"])
|
||||
room_for_partner = true
|
||||
end
|
||||
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && room_for_partner
|
||||
ally = NPCTrainer.new($PokemonGlobal.partner[1],$PokemonGlobal.partner[0])
|
||||
ally.id = $PokemonGlobal.partner[2]
|
||||
ally.party = $PokemonGlobal.partner[3]
|
||||
playerTrainers.push(ally)
|
||||
playerParty = []
|
||||
$Trainer.party.each { |pkmn| playerParty.push(pkmn) }
|
||||
playerPartyStarts.push(playerParty.length)
|
||||
ally.party.each { |pkmn| playerParty.push(pkmn) }
|
||||
setBattleRule("double") if !$PokemonTemp.battleRules["size"]
|
||||
end
|
||||
# Create the battle scene (the visual side of it)
|
||||
scene = pbNewBattleScene
|
||||
# Create the battle class (the mechanics side of it)
|
||||
battle = PokeBattle_Battle.new(scene,playerParty,foeParty,playerTrainers,nil)
|
||||
battle.party1starts = playerPartyStarts
|
||||
# Set various other properties in the battle class
|
||||
pbPrepareBattle(battle)
|
||||
$PokemonTemp.clearBattleRules
|
||||
# Perform the battle itself
|
||||
decision = 0
|
||||
pbBattleAnimation(pbGetWildBattleBGM(foeParty),(foeParty.length==1) ? 0 : 2,foeParty) {
|
||||
pbSceneStandby {
|
||||
decision = battle.pbStartBattle
|
||||
}
|
||||
pbAfterBattle(decision,canLose)
|
||||
}
|
||||
Input.update
|
||||
# Save the result of the battle in a Game Variable (1 by default)
|
||||
# 0 - Undecided or aborted
|
||||
# 1 - Player won
|
||||
# 2 - Player lost
|
||||
# 3 - Player or wild Pokémon ran from battle, or player forfeited the match
|
||||
# 4 - Wild Pokémon was caught
|
||||
# 5 - Draw
|
||||
pbSet(outcomeVar,decision)
|
||||
return decision
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Standard methods that start a wild battle of various sizes
|
||||
#===============================================================================
|
||||
# Used when walking in tall grass, hence the additional code.
|
||||
def pbWildBattle(species, level, outcomeVar=1, canRun=true, canLose=false)
|
||||
species = GameData::Species.get(species).id
|
||||
# Potentially call a different pbWildBattle-type method instead (for roaming
|
||||
# Pokémon, Safari battles, Bug Contest battles)
|
||||
handled = [nil]
|
||||
Events.onWildBattleOverride.trigger(nil,species,level,handled)
|
||||
return handled[0] if handled[0]!=nil
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("cannotRun") if !canRun
|
||||
setBattleRule("canLose") if canLose
|
||||
# Perform the battle
|
||||
decision = pbWildBattleCore(species, level)
|
||||
# Used by the Poké Radar to update/break the chain
|
||||
Events.onWildBattleEnd.trigger(nil,species,level,decision)
|
||||
# Return false if the player lost or drew the battle, and true if any other result
|
||||
return (decision!=2 && decision!=5)
|
||||
end
|
||||
|
||||
def pbDoubleWildBattle(species1, level1, species2, level2,
|
||||
outcomeVar=1, canRun=true, canLose=false)
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("cannotRun") if !canRun
|
||||
setBattleRule("canLose") if canLose
|
||||
setBattleRule("double")
|
||||
# Perform the battle
|
||||
decision = pbWildBattleCore(species1, level1, species2, level2)
|
||||
# Return false if the player lost or drew the battle, and true if any other result
|
||||
return (decision!=2 && decision!=5)
|
||||
end
|
||||
|
||||
def pbTripleWildBattle(species1, level1, species2, level2, species3, level3,
|
||||
outcomeVar=1, canRun=true, canLose=false)
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("cannotRun") if !canRun
|
||||
setBattleRule("canLose") if canLose
|
||||
setBattleRule("triple")
|
||||
# Perform the battle
|
||||
decision = pbWildBattleCore(species1, level1, species2, level2, species3, level3)
|
||||
# Return false if the player lost or drew the battle, and true if any other result
|
||||
return (decision!=2 && decision!=5)
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Start a trainer battle
|
||||
#===============================================================================
|
||||
def pbTrainerBattleCore(*args)
|
||||
outcomeVar = $PokemonTemp.battleRules["outcomeVar"] || 1
|
||||
canLose = $PokemonTemp.battleRules["canLose"] || false
|
||||
# Skip battle if the player has no able Pokémon, or if holding Ctrl in Debug mode
|
||||
if $Trainer.able_pokemon_count == 0 || ($DEBUG && Input.press?(Input::CTRL))
|
||||
pbMessage(_INTL("SKIPPING BATTLE...")) if $DEBUG
|
||||
pbMessage(_INTL("AFTER WINNING...")) if $DEBUG && $Trainer.able_pokemon_count > 0
|
||||
pbSet(outcomeVar,($Trainer.able_pokemon_count == 0) ? 0 : 1) # Treat it as undecided/a win
|
||||
$PokemonTemp.clearBattleRules
|
||||
$PokemonGlobal.nextBattleBGM = nil
|
||||
$PokemonGlobal.nextBattleME = nil
|
||||
$PokemonGlobal.nextBattleCaptureME = nil
|
||||
$PokemonGlobal.nextBattleBack = nil
|
||||
return ($Trainer.able_pokemon_count == 0) ? 0 : 1 # Treat it as undecided/a win
|
||||
end
|
||||
# Record information about party Pokémon to be used at the end of battle (e.g.
|
||||
# comparing levels for an evolution check)
|
||||
Events.onStartBattle.trigger(nil)
|
||||
# Generate trainers and their parties based on the arguments given
|
||||
foeTrainers = []
|
||||
foeItems = []
|
||||
foeEndSpeeches = []
|
||||
foeParty = []
|
||||
foePartyStarts = []
|
||||
for arg in args
|
||||
raise _INTL("Expected an array of trainer data, got {1}.",arg) if !arg.is_a?(Array)
|
||||
if arg.is_a?(NPCTrainer)
|
||||
foeTrainers.push(arg)
|
||||
foePartyStarts.push(foeParty.length)
|
||||
arg.party.each { |pkmn| foeParty.push(pkmn) }
|
||||
foeEndSpeeches.push(arg.lose_text)
|
||||
foeItems.push(arg.items)
|
||||
else
|
||||
# [trainer type, trainer name, ID, speech (optional)]
|
||||
trainer = pbLoadTrainer(arg[0],arg[1],arg[2])
|
||||
pbMissingTrainer(arg[0],arg[1],arg[2]) if !trainer
|
||||
return 0 if !trainer
|
||||
Events.onTrainerPartyLoad.trigger(nil,trainer)
|
||||
foeTrainers.push(trainer)
|
||||
foePartyStarts.push(foeParty.length)
|
||||
trainer.party.each { |pkmn| foeParty.push(pkmn) }
|
||||
foeEndSpeeches.push(arg[3] || trainer.lose_text)
|
||||
foeItems.push(trainer.items)
|
||||
end
|
||||
end
|
||||
# Calculate who the player trainer(s) and their party are
|
||||
playerTrainers = [$Trainer]
|
||||
playerParty = $Trainer.party
|
||||
playerPartyStarts = [0]
|
||||
room_for_partner = (foeParty.length > 1)
|
||||
if !room_for_partner && $PokemonTemp.battleRules["size"] &&
|
||||
!["single", "1v1", "1v2", "1v3"].include?($PokemonTemp.battleRules["size"])
|
||||
room_for_partner = true
|
||||
end
|
||||
if $PokemonGlobal.partner && !$PokemonTemp.battleRules["noPartner"] && room_for_partner
|
||||
ally = NPCTrainer.new($PokemonGlobal.partner[1], $PokemonGlobal.partner[0])
|
||||
ally.id = $PokemonGlobal.partner[2]
|
||||
ally.party = $PokemonGlobal.partner[3]
|
||||
playerTrainers.push(ally)
|
||||
playerParty = []
|
||||
$Trainer.party.each { |pkmn| playerParty.push(pkmn) }
|
||||
playerPartyStarts.push(playerParty.length)
|
||||
ally.party.each { |pkmn| playerParty.push(pkmn) }
|
||||
setBattleRule("double") if !$PokemonTemp.battleRules["size"]
|
||||
end
|
||||
# Create the battle scene (the visual side of it)
|
||||
scene = pbNewBattleScene
|
||||
# Create the battle class (the mechanics side of it)
|
||||
battle = PokeBattle_Battle.new(scene,playerParty,foeParty,playerTrainers,foeTrainers)
|
||||
battle.party1starts = playerPartyStarts
|
||||
battle.party2starts = foePartyStarts
|
||||
battle.items = foeItems
|
||||
battle.endSpeeches = foeEndSpeeches
|
||||
# Set various other properties in the battle class
|
||||
pbPrepareBattle(battle)
|
||||
$PokemonTemp.clearBattleRules
|
||||
# End the trainer intro music
|
||||
Audio.me_stop
|
||||
# Perform the battle itself
|
||||
decision = 0
|
||||
pbBattleAnimation(pbGetTrainerBattleBGM(foeTrainers),(battle.singleBattle?) ? 1 : 3,foeTrainers) {
|
||||
pbSceneStandby {
|
||||
decision = battle.pbStartBattle
|
||||
}
|
||||
pbAfterBattle(decision,canLose)
|
||||
}
|
||||
Input.update
|
||||
# Save the result of the battle in a Game Variable (1 by default)
|
||||
# 0 - Undecided or aborted
|
||||
# 1 - Player won
|
||||
# 2 - Player lost
|
||||
# 3 - Player or wild Pokémon ran from battle, or player forfeited the match
|
||||
# 5 - Draw
|
||||
pbSet(outcomeVar,decision)
|
||||
return decision
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Standard methods that start a trainer battle of various sizes
|
||||
#===============================================================================
|
||||
# Used by most trainer events, which can be positioned in such a way that
|
||||
# multiple trainer events spot the player at once. The extra code in this method
|
||||
# deals with that case and can cause a double trainer battle instead.
|
||||
def pbTrainerBattle(trainerID, trainerName, endSpeech=nil,
|
||||
doubleBattle=false, trainerPartyID=0, canLose=false, outcomeVar=1)
|
||||
# If there is another NPC trainer who spotted the player at the same time, and
|
||||
# it is possible to have a double battle (the player has 2+ able Pokémon or
|
||||
# has a partner trainer), then record this first NPC trainer into
|
||||
# $PokemonTemp.waitingTrainer and end this method. That second NPC event will
|
||||
# then trigger and cause the battle to happen against this first trainer and
|
||||
# themselves.
|
||||
if !$PokemonTemp.waitingTrainer && pbMapInterpreterRunning? &&
|
||||
($Trainer.able_pokemon_count > 1 ||
|
||||
($Trainer.able_pokemon_count > 0 && $PokemonGlobal.partner))
|
||||
thisEvent = pbMapInterpreter.get_character(0)
|
||||
# Find all other triggered trainer events
|
||||
triggeredEvents = $game_player.pbTriggeredTrainerEvents([2],false)
|
||||
otherEvent = []
|
||||
for i in triggeredEvents
|
||||
next if i.id==thisEvent.id
|
||||
next if $game_self_switches[[$game_map.map_id,i.id,"A"]]
|
||||
otherEvent.push(i)
|
||||
end
|
||||
# Load the trainer's data, and call an event which might modify it
|
||||
trainer = pbLoadTrainer(trainerID,trainerName,trainerPartyID)
|
||||
pbMissingTrainer(trainerID,trainerName,trainerPartyID) if !trainer
|
||||
return false if !trainer
|
||||
Events.onTrainerPartyLoad.trigger(nil,trainer)
|
||||
# If there is exactly 1 other triggered trainer event, and this trainer has
|
||||
# 6 or fewer Pokémon, record this trainer for a double battle caused by the
|
||||
# other triggered trainer event
|
||||
if otherEvent.length == 1 && trainer.party.length <= Settings::MAX_PARTY_SIZE
|
||||
trainer.lose_text = endSpeech if endSpeech && !endSpeech.empty?
|
||||
$PokemonTemp.waitingTrainer = [trainer, thisEvent.id]
|
||||
return false
|
||||
end
|
||||
end
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("canLose") if canLose
|
||||
setBattleRule("double") if doubleBattle || $PokemonTemp.waitingTrainer
|
||||
# Perform the battle
|
||||
if $PokemonTemp.waitingTrainer
|
||||
waitingTrainer = $PokemonTemp.waitingTrainer
|
||||
decision = pbTrainerBattleCore($PokemonTemp.waitingTrainer,
|
||||
[trainerID,trainerName,trainerPartyID,endSpeech]
|
||||
)
|
||||
else
|
||||
decision = pbTrainerBattleCore([trainerID,trainerName,trainerPartyID,endSpeech])
|
||||
end
|
||||
# Finish off the recorded waiting trainer, because they have now been battled
|
||||
if decision==1 && $PokemonTemp.waitingTrainer # Win
|
||||
pbMapInterpreter.pbSetSelfSwitch($PokemonTemp.waitingTrainer[1], "A", true)
|
||||
end
|
||||
$PokemonTemp.waitingTrainer = nil
|
||||
# Return true if the player won the battle, and false if any other result
|
||||
return (decision==1)
|
||||
end
|
||||
|
||||
def pbDoubleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1,
|
||||
trainerID2, trainerName2, trainerPartyID2=0, endSpeech2=nil,
|
||||
canLose=false, outcomeVar=1)
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("canLose") if canLose
|
||||
setBattleRule("double")
|
||||
# Perform the battle
|
||||
decision = pbTrainerBattleCore(
|
||||
[trainerID1,trainerName1,trainerPartyID1,endSpeech1],
|
||||
[trainerID2,trainerName2,trainerPartyID2,endSpeech2]
|
||||
)
|
||||
# Return true if the player won the battle, and false if any other result
|
||||
return (decision==1)
|
||||
end
|
||||
|
||||
def pbTripleTrainerBattle(trainerID1, trainerName1, trainerPartyID1, endSpeech1,
|
||||
trainerID2, trainerName2, trainerPartyID2, endSpeech2,
|
||||
trainerID3, trainerName3, trainerPartyID3=0, endSpeech3=nil,
|
||||
canLose=false, outcomeVar=1)
|
||||
# Set some battle rules
|
||||
setBattleRule("outcomeVar",outcomeVar) if outcomeVar!=1
|
||||
setBattleRule("canLose") if canLose
|
||||
setBattleRule("triple")
|
||||
# Perform the battle
|
||||
decision = pbTrainerBattleCore(
|
||||
[trainerID1,trainerName1,trainerPartyID1,endSpeech1],
|
||||
[trainerID2,trainerName2,trainerPartyID2,endSpeech2],
|
||||
[trainerID3,trainerName3,trainerPartyID3,endSpeech3]
|
||||
)
|
||||
# Return true if the player won the battle, and false if any other result
|
||||
return (decision==1)
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# After battles
|
||||
#===============================================================================
|
||||
def pbAfterBattle(decision,canLose)
|
||||
$Trainer.party.each do |pkmn|
|
||||
pkmn.statusCount = 0 if pkmn.status == :POISON # Bad poison becomes regular
|
||||
pkmn.makeUnmega
|
||||
pkmn.makeUnprimal
|
||||
end
|
||||
if $PokemonGlobal.partner
|
||||
$Trainer.heal_party
|
||||
$PokemonGlobal.partner[3].each do |pkmn|
|
||||
pkmn.heal
|
||||
pkmn.makeUnmega
|
||||
pkmn.makeUnprimal
|
||||
end
|
||||
end
|
||||
if decision==2 || decision==5 # if loss or draw
|
||||
if canLose
|
||||
$Trainer.party.each { |pkmn| pkmn.heal }
|
||||
(Graphics.frame_rate/4).times { Graphics.update }
|
||||
end
|
||||
end
|
||||
Events.onEndBattle.trigger(nil,decision,canLose)
|
||||
$game_player.straighten
|
||||
end
|
||||
|
||||
Events.onEndBattle += proc { |_sender,e|
|
||||
decision = e[0]
|
||||
canLose = e[1]
|
||||
if Settings::CHECK_EVOLUTION_AFTER_ALL_BATTLES || (decision!=2 && decision!=5) # not a loss or a draw
|
||||
if $PokemonTemp.evolutionLevels
|
||||
pbEvolutionCheck($PokemonTemp.evolutionLevels)
|
||||
$PokemonTemp.evolutionLevels = nil
|
||||
end
|
||||
end
|
||||
case decision
|
||||
when 1, 4 # Win, capture
|
||||
$Trainer.pokemon_party.each do |pkmn|
|
||||
pbPickup(pkmn)
|
||||
pbHoneyGather(pkmn)
|
||||
end
|
||||
when 2, 5 # Lose, draw
|
||||
if !canLose
|
||||
$game_system.bgm_unpause
|
||||
$game_system.bgs_unpause
|
||||
pbStartOver
|
||||
end
|
||||
end
|
||||
}
|
||||
|
||||
def pbEvolutionCheck(currentLevels)
|
||||
for i in 0...currentLevels.length
|
||||
pkmn = $Trainer.party[i]
|
||||
next if !pkmn || (pkmn.hp==0 && !Settings::CHECK_EVOLUTION_FOR_FAINTED_POKEMON)
|
||||
next if currentLevels[i] && pkmn.level==currentLevels[i]
|
||||
newSpecies = pkmn.check_evolution_on_level_up
|
||||
next if !newSpecies
|
||||
evo = PokemonEvolutionScene.new
|
||||
evo.pbStartScreen(pkmn,newSpecies)
|
||||
evo.pbEvolution
|
||||
evo.pbEndScreen
|
||||
end
|
||||
end
|
||||
|
||||
def pbDynamicItemList(*args)
|
||||
ret = []
|
||||
for i in 0...args.length
|
||||
ret.push(i) if GameData::Item.exists?(args[i])
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
# Try to gain an item after a battle if a Pokemon has the ability Pickup.
|
||||
def pbPickup(pkmn)
|
||||
return if pkmn.egg? || !pkmn.hasAbility?(:PICKUP)
|
||||
return if pkmn.hasItem?
|
||||
return unless rand(100)<10 # 10% chance
|
||||
# Common items to find (9 items from this list are added to the pool)
|
||||
pickupList = pbDynamicItemList(
|
||||
:POTION,
|
||||
:ANTIDOTE,
|
||||
:SUPERPOTION,
|
||||
:GREATBALL,
|
||||
:REPEL,
|
||||
:ESCAPEROPE,
|
||||
:FULLHEAL,
|
||||
:HYPERPOTION,
|
||||
:ULTRABALL,
|
||||
:REVIVE,
|
||||
:RARECANDY,
|
||||
:SUNSTONE,
|
||||
:MOONSTONE,
|
||||
:HEARTSCALE,
|
||||
:FULLRESTORE,
|
||||
:MAXREVIVE,
|
||||
:PPUP,
|
||||
:MAXELIXIR
|
||||
)
|
||||
# Rare items to find (2 items from this list are added to the pool)
|
||||
pickupListRare = pbDynamicItemList(
|
||||
:HYPERPOTION,
|
||||
:NUGGET,
|
||||
:KINGSROCK,
|
||||
:FULLRESTORE,
|
||||
:ETHER,
|
||||
:IRONBALL,
|
||||
:DESTINYKNOT,
|
||||
:ELIXIR,
|
||||
:DESTINYKNOT,
|
||||
:LEFTOVERS,
|
||||
:DESTINYKNOT
|
||||
)
|
||||
return if pickupList.length<18
|
||||
return if pickupListRare.length<11
|
||||
# Generate a pool of items depending on the Pokémon's level
|
||||
items = []
|
||||
pkmnLevel = [100,pkmn.level].min
|
||||
itemStartIndex = (pkmnLevel-1)/10
|
||||
itemStartIndex = 0 if itemStartIndex<0
|
||||
for i in 0...9
|
||||
items.push(pickupList[itemStartIndex+i])
|
||||
end
|
||||
for i in 0...2
|
||||
items.push(pickupListRare[itemStartIndex+i])
|
||||
end
|
||||
# Probabilities of choosing each item in turn from the pool
|
||||
chances = [30,10,10,10,10,10,10,4,4,1,1] # Needs to be 11 numbers
|
||||
chanceSum = 0
|
||||
chances.each { |c| chanceSum += c }
|
||||
# Randomly choose an item from the pool to give to the Pokémon
|
||||
rnd = rand(chanceSum)
|
||||
cumul = 0
|
||||
chances.each_with_index do |c,i|
|
||||
cumul += c
|
||||
next if rnd>=cumul
|
||||
pkmn.item = items[i]
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
# Try to gain a Honey item after a battle if a Pokemon has the ability Honey Gather.
|
||||
def pbHoneyGather(pkmn)
|
||||
return if !GameData::Item.exists?(:HONEY)
|
||||
return if pkmn.egg? || !pkmn.hasAbility?(:HONEYGATHER) || pkmn.hasItem?
|
||||
chance = 5 + ((pkmn.level - 1) / 10) * 5
|
||||
return unless rand(100) < chance
|
||||
pkmn.item = :HONEY
|
||||
end
|
||||
@@ -0,0 +1,310 @@
|
||||
#===============================================================================
|
||||
# Battle intro animation
|
||||
#===============================================================================
|
||||
def pbSceneStandby
|
||||
$scene.disposeSpritesets if $scene && $scene.is_a?(Scene_Map)
|
||||
RPG::Cache.clear
|
||||
Graphics.frame_reset
|
||||
yield
|
||||
$scene.createSpritesets if $scene && $scene.is_a?(Scene_Map)
|
||||
end
|
||||
|
||||
def pbBattleAnimation(bgm=nil,battletype=0,foe=nil)
|
||||
$game_temp.in_battle = true
|
||||
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
|
||||
viewport.z = 99999
|
||||
# Set up audio
|
||||
playingBGS = nil
|
||||
playingBGM = nil
|
||||
if $game_system && $game_system.is_a?(Game_System)
|
||||
playingBGS = $game_system.getPlayingBGS
|
||||
playingBGM = $game_system.getPlayingBGM
|
||||
$game_system.bgm_pause
|
||||
$game_system.bgs_pause
|
||||
end
|
||||
pbMEFade(0.25)
|
||||
pbWait(Graphics.frame_rate/4)
|
||||
pbMEStop
|
||||
# Play battle music
|
||||
bgm = pbGetWildBattleBGM([]) if !bgm
|
||||
pbBGMPlay(bgm)
|
||||
# Take screenshot of game, for use in some animations
|
||||
$game_temp.background_bitmap.dispose if $game_temp.background_bitmap
|
||||
$game_temp.background_bitmap = Graphics.snap_to_bitmap
|
||||
# Check for custom battle intro animations
|
||||
handled = pbBattleAnimationOverride(viewport,battletype,foe)
|
||||
# Default battle intro animation
|
||||
if !handled
|
||||
# Determine which animation is played
|
||||
location = 0 # 0=outside, 1=inside, 2=cave, 3=water
|
||||
if $PokemonGlobal.surfing || $PokemonGlobal.diving
|
||||
location = 3
|
||||
elsif $PokemonTemp.encounterType &&
|
||||
GameData::EncounterType.get($PokemonTemp.encounterType).type == :fishing
|
||||
location = 3
|
||||
elsif $PokemonEncounters.has_cave_encounters?
|
||||
location = 2
|
||||
elsif !GameData::MapMetadata.exists?($game_map.map_id) ||
|
||||
!GameData::MapMetadata.get($game_map.map_id).outdoor_map
|
||||
location = 1
|
||||
end
|
||||
anim = ""
|
||||
if PBDayNight.isDay?
|
||||
case battletype
|
||||
when 0, 2 # Wild, double wild
|
||||
anim = ["SnakeSquares","DiagonalBubbleTL","DiagonalBubbleBR","RisingSplash"][location]
|
||||
when 1 # Trainer
|
||||
anim = ["TwoBallPass","ThreeBallDown","BallDown","WavyThreeBallUp"][location]
|
||||
when 3 # Double trainer
|
||||
anim = "FourBallBurst"
|
||||
end
|
||||
else
|
||||
case battletype
|
||||
when 0, 2 # Wild, double wild
|
||||
anim = ["SnakeSquares","DiagonalBubbleBR","DiagonalBubbleBR","RisingSplash"][location]
|
||||
when 1 # Trainer
|
||||
anim = ["SpinBallSplit","BallDown","BallDown","WavySpinBall"][location]
|
||||
when 3 # Double trainer
|
||||
anim = "FourBallBurst"
|
||||
end
|
||||
end
|
||||
# Initial screen flashing
|
||||
if location==2 || PBDayNight.isNight?
|
||||
viewport.color = Color.new(0,0,0) # Fade to black a few times
|
||||
else
|
||||
viewport.color = Color.new(255,255,255) # Fade to white a few times
|
||||
end
|
||||
halfFlashTime = Graphics.frame_rate*2/10 # 0.2 seconds, 8 frames
|
||||
alphaDiff = (255.0/halfFlashTime).ceil
|
||||
2.times do
|
||||
viewport.color.alpha = 0
|
||||
for i in 0...halfFlashTime*2
|
||||
if i<halfFlashTime; viewport.color.alpha += alphaDiff
|
||||
else; viewport.color.alpha -= alphaDiff
|
||||
end
|
||||
Graphics.update
|
||||
pbUpdateSceneMap
|
||||
end
|
||||
end
|
||||
# Play main animation
|
||||
Graphics.freeze
|
||||
Graphics.transition(Graphics.frame_rate*1.25,sprintf("Graphics/Transitions/%s",anim))
|
||||
viewport.color = Color.new(0,0,0,255) # Ensure screen is black
|
||||
# Slight pause after animation before starting up the battle scene
|
||||
(Graphics.frame_rate/10).times do
|
||||
Graphics.update
|
||||
Input.update
|
||||
pbUpdateSceneMap
|
||||
end
|
||||
end
|
||||
pbPushFade
|
||||
# Yield to the battle scene
|
||||
yield if block_given?
|
||||
# After the battle
|
||||
pbPopFade
|
||||
if $game_system && $game_system.is_a?(Game_System)
|
||||
$game_system.bgm_resume(playingBGM)
|
||||
$game_system.bgs_resume(playingBGS)
|
||||
end
|
||||
$PokemonGlobal.nextBattleBGM = nil
|
||||
$PokemonGlobal.nextBattleME = nil
|
||||
$PokemonGlobal.nextBattleCaptureME = nil
|
||||
$PokemonGlobal.nextBattleBack = nil
|
||||
$PokemonEncounters.reset_step_count
|
||||
# Fade back to the overworld
|
||||
viewport.color = Color.new(0,0,0,255)
|
||||
numFrames = Graphics.frame_rate*4/10 # 0.4 seconds, 16 frames
|
||||
alphaDiff = (255.0/numFrames).ceil
|
||||
numFrames.times do
|
||||
viewport.color.alpha -= alphaDiff
|
||||
Graphics.update
|
||||
Input.update
|
||||
pbUpdateSceneMap
|
||||
end
|
||||
viewport.dispose
|
||||
$game_temp.in_battle = false
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Vs. battle intro animation
|
||||
#===============================================================================
|
||||
def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
|
||||
##### VS. animation, by Luka S.J. #####
|
||||
##### Tweaked by Maruno #####
|
||||
if (battletype==1 || battletype==3) && foe.length==1 # Against single trainer
|
||||
tr_type = foe[0].trainer_type
|
||||
if tr_type
|
||||
tbargraphic = sprintf("vsBar_%s", tr_type.to_s) rescue nil
|
||||
tgraphic = sprintf("vsTrainer_%s", tr_type.to_s) rescue nil
|
||||
if pbResolveBitmap(tbargraphic) && pbResolveBitmap(tgraphic)
|
||||
player_tr_type = $Trainer.trainer_type
|
||||
outfit = $Trainer.outfit
|
||||
# Set up
|
||||
viewplayer = Viewport.new(0,Graphics.height/3,Graphics.width/2,128)
|
||||
viewplayer.z = viewport.z
|
||||
viewopp = Viewport.new(Graphics.width/2,Graphics.height/3,Graphics.width/2,128)
|
||||
viewopp.z = viewport.z
|
||||
viewvs = Viewport.new(0,0,Graphics.width,Graphics.height)
|
||||
viewvs.z = viewport.z
|
||||
fade = Sprite.new(viewport)
|
||||
fade.bitmap = RPG::Cache.transition("vsFlash")
|
||||
fade.tone = Tone.new(-255,-255,-255)
|
||||
fade.opacity = 100
|
||||
overlay = Sprite.new(viewport)
|
||||
overlay.bitmap = Bitmap.new(Graphics.width,Graphics.height)
|
||||
pbSetSystemFont(overlay.bitmap)
|
||||
pbargraphic = sprintf("vsBar_%s_%d", player_tr_type.to_s, outfit) rescue nil
|
||||
if !pbResolveBitmap(pbargraphic)
|
||||
pbargraphic = sprintf("vsBar_%s", player_tr_type.to_s) rescue nil
|
||||
end
|
||||
xoffset = ((Graphics.width/2)/10)*10
|
||||
bar1 = Sprite.new(viewplayer)
|
||||
bar1.bitmap = RPG::Cache.transition(pbargraphic)
|
||||
bar1.x = -xoffset
|
||||
bar2 = Sprite.new(viewopp)
|
||||
bar2.bitmap = RPG::Cache.transition(tbargraphic)
|
||||
bar2.x = xoffset
|
||||
vs = Sprite.new(viewvs)
|
||||
vs.bitmap = RPG::Cache.transition("vs")
|
||||
vs.ox = vs.bitmap.width/2
|
||||
vs.oy = vs.bitmap.height/2
|
||||
vs.x = Graphics.width/2
|
||||
vs.y = Graphics.height/1.5
|
||||
vs.visible = false
|
||||
flash = Sprite.new(viewvs)
|
||||
flash.bitmap = RPG::Cache.transition("vsFlash")
|
||||
flash.opacity = 0
|
||||
# Animate bars sliding in from either side
|
||||
slideInTime = (Graphics.frame_rate*0.25).floor
|
||||
for i in 0...slideInTime
|
||||
bar1.x = xoffset*(i+1-slideInTime)/slideInTime
|
||||
bar2.x = xoffset*(slideInTime-i-1)/slideInTime
|
||||
pbWait(1)
|
||||
end
|
||||
bar1.dispose
|
||||
bar2.dispose
|
||||
# Make whole screen flash white
|
||||
pbSEPlay("Vs flash")
|
||||
pbSEPlay("Vs sword")
|
||||
flash.opacity = 255
|
||||
# Replace bar sprites with AnimatedPlanes, set up trainer sprites
|
||||
bar1 = AnimatedPlane.new(viewplayer)
|
||||
bar1.bitmap = RPG::Cache.transition(pbargraphic)
|
||||
bar2 = AnimatedPlane.new(viewopp)
|
||||
bar2.bitmap = RPG::Cache.transition(tbargraphic)
|
||||
pgraphic = sprintf("vsTrainer_%s_%d", player_tr_type.to_s, outfit) rescue nil
|
||||
if !pbResolveBitmap(pgraphic)
|
||||
pgraphic = sprintf("vsTrainer_%s", player_tr_type.to_s) rescue nil
|
||||
end
|
||||
player = Sprite.new(viewplayer)
|
||||
player.bitmap = RPG::Cache.transition(pgraphic)
|
||||
player.x = -xoffset
|
||||
trainer = Sprite.new(viewopp)
|
||||
trainer.bitmap = RPG::Cache.transition(tgraphic)
|
||||
trainer.x = xoffset
|
||||
trainer.tone = Tone.new(-255,-255,-255)
|
||||
# Dim the flash and make the trainer sprites appear, while animating bars
|
||||
animTime = (Graphics.frame_rate*1.2).floor
|
||||
for i in 0...animTime
|
||||
flash.opacity -= 52*20/Graphics.frame_rate if flash.opacity>0
|
||||
bar1.ox -= 32*20/Graphics.frame_rate
|
||||
bar2.ox += 32*20/Graphics.frame_rate
|
||||
if i>=animTime/2 && i<slideInTime+animTime/2
|
||||
player.x = xoffset*(i+1-slideInTime-animTime/2)/slideInTime
|
||||
trainer.x = xoffset*(slideInTime-i-1+animTime/2)/slideInTime
|
||||
end
|
||||
pbWait(1)
|
||||
end
|
||||
player.x = 0
|
||||
trainer.x = 0
|
||||
# Make whole screen flash white again
|
||||
flash.opacity = 255
|
||||
pbSEPlay("Vs sword")
|
||||
# Make the Vs logo and trainer names appear, and reset trainer's tone
|
||||
vs.visible = true
|
||||
trainer.tone = Tone.new(0,0,0)
|
||||
trainername = foe[0].name
|
||||
textpos = [
|
||||
[$Trainer.name,Graphics.width/4,(Graphics.height/1.5)+4,2,
|
||||
Color.new(248,248,248),Color.new(12*6,12*6,12*6)],
|
||||
[trainername,(Graphics.width/4)+(Graphics.width/2),(Graphics.height/1.5)+4,2,
|
||||
Color.new(248,248,248),Color.new(12*6,12*6,12*6)]
|
||||
]
|
||||
pbDrawTextPositions(overlay.bitmap,textpos)
|
||||
# Fade out flash, shudder Vs logo and expand it, and then fade to black
|
||||
animTime = (Graphics.frame_rate*2.75).floor
|
||||
shudderTime = (Graphics.frame_rate*1.75).floor
|
||||
zoomTime = (Graphics.frame_rate*2.5).floor
|
||||
shudderDelta = [4*20/Graphics.frame_rate,1].max
|
||||
for i in 0...animTime
|
||||
if i<shudderTime # Fade out the white flash
|
||||
flash.opacity -= 52*20/Graphics.frame_rate if flash.opacity>0
|
||||
elsif i==shudderTime # Make the flash black
|
||||
flash.tone = Tone.new(-255,-255,-255)
|
||||
elsif i>=zoomTime # Fade to black
|
||||
flash.opacity += 52*20/Graphics.frame_rate if flash.opacity<255
|
||||
end
|
||||
bar1.ox -= 32*20/Graphics.frame_rate
|
||||
bar2.ox += 32*20/Graphics.frame_rate
|
||||
if i<shudderTime
|
||||
j = i%(2*Graphics.frame_rate/20)
|
||||
if j>=0.5*Graphics.frame_rate/20 && j<1.5*Graphics.frame_rate/20
|
||||
vs.x += shudderDelta
|
||||
vs.y -= shudderDelta
|
||||
else
|
||||
vs.x -= shudderDelta
|
||||
vs.y += shudderDelta
|
||||
end
|
||||
elsif i<zoomTime
|
||||
vs.zoom_x += 0.4*20/Graphics.frame_rate
|
||||
vs.zoom_y += 0.4*20/Graphics.frame_rate
|
||||
end
|
||||
pbWait(1)
|
||||
end
|
||||
# End of animation
|
||||
player.dispose
|
||||
trainer.dispose
|
||||
flash.dispose
|
||||
vs.dispose
|
||||
bar1.dispose
|
||||
bar2.dispose
|
||||
overlay.dispose
|
||||
fade.dispose
|
||||
viewvs.dispose
|
||||
viewopp.dispose
|
||||
viewplayer.dispose
|
||||
viewport.color = Color.new(0,0,0,255)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#===============================================================================
|
||||
# Override battle intro animation
|
||||
#===============================================================================
|
||||
# If you want to add a custom battle intro animation, copy the following alias
|
||||
# line and method into a new script section. Change the name of the alias part
|
||||
# ("__over1__") in your copied code in both places. Then add in your custom
|
||||
# transition code in the place shown.
|
||||
# Note that $game_temp.background_bitmap contains an image of the current game
|
||||
# screen.
|
||||
# When the custom animation has finished, the screen should have faded to black
|
||||
# somehow.
|
||||
|
||||
alias __over1__pbBattleAnimationOverride pbBattleAnimationOverride
|
||||
|
||||
def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
|
||||
# The following example runs a common event that ought to do a custom
|
||||
# animation if some condition is true:
|
||||
#
|
||||
# if $game_map.map_id==20 # If on map 20
|
||||
# pbCommonEvent(20)
|
||||
# return true # Note that the battle animation is done
|
||||
# end
|
||||
#
|
||||
# The following line needs to call the aliased method if the custom transition
|
||||
# animation was NOT shown.
|
||||
return __over1__pbBattleAnimationOverride(viewport,battletype,foe)
|
||||
end
|
||||
@@ -0,0 +1,432 @@
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
class PokemonEncounters
|
||||
attr_reader :step_count
|
||||
|
||||
def initialize
|
||||
@step_chances = {}
|
||||
@encounter_tables = {}
|
||||
@chance_accumulator = 0
|
||||
end
|
||||
|
||||
def setup(map_ID)
|
||||
@step_count = 0
|
||||
@step_chances = {}
|
||||
@encounter_tables = {}
|
||||
encounter_data = GameData::Encounter.get(map_ID, $PokemonGlobal.encounter_version)
|
||||
if encounter_data
|
||||
encounter_data.step_chances.each { |type, value| @step_chances[type] = value }
|
||||
@encounter_tables = Marshal.load(Marshal.dump(encounter_data.types))
|
||||
end
|
||||
end
|
||||
|
||||
def reset_step_count
|
||||
@step_count = 0
|
||||
@chance_accumulator = 0
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
# Returns whether encounters for the given encounter type have been defined
|
||||
# for the current map.
|
||||
def has_encounter_type?(enc_type)
|
||||
return false if !enc_type
|
||||
return @encounter_tables[enc_type] && @encounter_tables[enc_type].length > 0
|
||||
end
|
||||
|
||||
# Returns whether encounters for the given encounter type have been defined
|
||||
# for the given map. Only called by Bug Catching Contest to see if it can use
|
||||
# the map's BugContest encounter type to generate caught Pokémon for the other
|
||||
# contestants.
|
||||
def map_has_encounter_type?(map_ID, enc_type)
|
||||
return false if !enc_type
|
||||
encounter_data = GameData::Encounter.get(map_ID, $PokemonGlobal.encounter_version)
|
||||
return false if !encounter_data
|
||||
return encounter_data.types[enc_type] && encounter_data.types[enc_type].length > 0
|
||||
end
|
||||
|
||||
# Returns whether land-like encounters have been defined for the current map.
|
||||
# Applies only to encounters triggered by moving around.
|
||||
def has_land_encounters?
|
||||
GameData::EncounterType.each do |enc_type|
|
||||
next if ![:land, :contest].include?(enc_type.type)
|
||||
return true if has_encounter_type?(enc_type.id)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns whether land-like encounters have been defined for the current map
|
||||
# (ignoring the Bug Catching Contest one).
|
||||
# Applies only to encounters triggered by moving around.
|
||||
def has_normal_land_encounters?
|
||||
GameData::EncounterType.each do |enc_type|
|
||||
return true if enc_type.type == :land && has_encounter_type?(enc_type.id)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns whether cave-like encounters have been defined for the current map.
|
||||
# Applies only to encounters triggered by moving around.
|
||||
def has_cave_encounters?
|
||||
GameData::EncounterType.each do |enc_type|
|
||||
return true if enc_type.type == :cave && has_encounter_type?(enc_type.id)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns whether water-like encounters have been defined for the current map.
|
||||
# Applies only to encounters triggered by moving around (i.e. not fishing).
|
||||
def has_water_encounters?
|
||||
GameData::EncounterType.each do |enc_type|
|
||||
return true if enc_type.type == :water && has_encounter_type?(enc_type.id)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
# Returns whether the player's current location allows wild encounters to
|
||||
# trigger upon taking a step.
|
||||
def encounter_possible_here?
|
||||
return true if $PokemonGlobal.surfing
|
||||
terrain_tag = $game_map.terrain_tag($game_player.x, $game_player.y)
|
||||
return false if terrain_tag.ice
|
||||
return true if has_cave_encounters? # i.e. this map is a cave
|
||||
return true if has_land_encounters? && terrain_tag.land_wild_encounters
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns whether a wild encounter should happen, based on its encounter
|
||||
# chance. Called when taking a step and by Rock Smash.
|
||||
def encounter_triggered?(enc_type, repel_active = false, triggered_by_step = true)
|
||||
if !enc_type || !GameData::EncounterType.exists?(enc_type)
|
||||
raise ArgumentError.new(_INTL("Encounter type {1} does not exist", enc_type))
|
||||
end
|
||||
return false if $game_system.encounter_disabled
|
||||
return false if !$Trainer
|
||||
return false if $DEBUG && Input.press?(Input::CTRL)
|
||||
# Check if enc_type has a defined step chance/encounter table
|
||||
return false if !@step_chances[enc_type] || @step_chances[enc_type] == 0
|
||||
return false if !has_encounter_type?(enc_type)
|
||||
# Get base encounter chance and minimum steps grace period
|
||||
encounter_chance = @step_chances[enc_type].to_f
|
||||
min_steps_needed = (8 - encounter_chance / 10).clamp(0, 8).to_f
|
||||
# Apply modifiers to the encounter chance and the minimum steps amount
|
||||
if triggered_by_step
|
||||
encounter_chance += @chance_accumulator / 200
|
||||
encounter_chance *= 0.8 if $PokemonGlobal.bicycle
|
||||
end
|
||||
if !Settings::FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS
|
||||
encounter_chance /= 2 if $PokemonMap.blackFluteUsed
|
||||
min_steps_needed *= 2 if $PokemonMap.blackFluteUsed
|
||||
encounter_chance *= 1.5 if $PokemonMap.whiteFluteUsed
|
||||
min_steps_needed /= 2 if $PokemonMap.whiteFluteUsed
|
||||
end
|
||||
first_pkmn = $Trainer.first_pokemon
|
||||
if first_pkmn
|
||||
case first_pkmn.item_id
|
||||
when :CLEANSETAG
|
||||
encounter_chance *= 2.0 / 3
|
||||
min_steps_needed *= 4 / 3.0
|
||||
when :PUREINCENSE
|
||||
encounter_chance *= 2.0 / 3
|
||||
min_steps_needed *= 4 / 3.0
|
||||
else # Ignore ability effects if an item effect applies
|
||||
case first_pkmn.ability_id
|
||||
when :STENCH, :WHITESMOKE, :QUICKFEET
|
||||
encounter_chance /= 2
|
||||
min_steps_needed *= 2
|
||||
when :SNOWCLOAK
|
||||
if GameData::Weather.get($game_screen.weather_type).category == :Hail
|
||||
encounter_chance /= 2
|
||||
min_steps_needed *= 2
|
||||
end
|
||||
when :SANDVEIL
|
||||
if GameData::Weather.get($game_screen.weather_type).category == :Sandstorm
|
||||
encounter_chance /= 2
|
||||
min_steps_needed *= 2
|
||||
end
|
||||
when :SWARM
|
||||
encounter_chance *= 1.5
|
||||
min_steps_needed /= 2
|
||||
when :ILLUMINATE, :ARENATRAP, :NOGUARD
|
||||
encounter_chance *= 2
|
||||
min_steps_needed /= 2
|
||||
end
|
||||
end
|
||||
end
|
||||
# Wild encounters are much less likely to happen for the first few steps
|
||||
# after a previous wild encounter
|
||||
if triggered_by_step && @step_count < min_steps_needed
|
||||
@step_count += 1
|
||||
return false if rand(100) >= encounter_chance * 5 / (@step_chances[enc_type] + @chance_accumulator / 200)
|
||||
end
|
||||
# Decide whether the wild encounter should actually happen
|
||||
return true if rand(100) < encounter_chance
|
||||
# If encounter didn't happen, make the next step more likely to produce one
|
||||
if triggered_by_step
|
||||
@chance_accumulator += @step_chances[enc_type]
|
||||
@chance_accumulator = 0 if repel_active
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
# Returns whether an encounter with the given Pokémon should be allowed after
|
||||
# taking into account Repels and ability effects.
|
||||
def allow_encounter?(enc_data, repel_active = false)
|
||||
return false if !enc_data
|
||||
# Repel
|
||||
if repel_active && !pbPokeRadarOnShakingGrass
|
||||
first_pkmn = (Settings::REPEL_COUNTS_FAINTED_POKEMON) ? $Trainer.first_pokemon : $Trainer.first_able_pokemon
|
||||
if first_pkmn && enc_data[1] < first_pkmn.level
|
||||
@chance_accumulator = 0
|
||||
return false
|
||||
end
|
||||
end
|
||||
# Some abilities make wild encounters less likely if the wild Pokémon is
|
||||
# sufficiently weaker than the Pokémon with the ability
|
||||
first_pkmn = $Trainer.first_pokemon
|
||||
if first_pkmn
|
||||
case first_pkmn.ability_id
|
||||
when :INTIMIDATE, :KEENEYE
|
||||
return false if enc_data[1] <= first_pkmn.level - 5 && rand(100) < 50
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
# Returns whether a wild encounter should be turned into a double wild
|
||||
# encounter.
|
||||
def have_double_wild_battle?
|
||||
return false if $PokemonTemp.forceSingleBattle
|
||||
return false if pbInSafari?
|
||||
return true if $PokemonGlobal.partner
|
||||
return false if $Trainer.able_pokemon_count <= 1
|
||||
return true if $game_player.pbTerrainTag.double_wild_encounters && rand(100) < 30
|
||||
return false
|
||||
end
|
||||
|
||||
# Checks the defined encounters for the current map and returns the encounter
|
||||
# type that the given time should produce. Only returns an encounter type if
|
||||
# it has been defined for the current map.
|
||||
def find_valid_encounter_type_for_time(base_type, time)
|
||||
ret = nil
|
||||
if PBDayNight.isDay?(time)
|
||||
try_type = nil
|
||||
if PBDayNight.isMorning?(time)
|
||||
try_type = (base_type.to_s + "Morning").to_sym
|
||||
elsif PBDayNight.isAfternoon?(time)
|
||||
try_type = (base_type.to_s + "Afternoon").to_sym
|
||||
elsif PBDayNight.isEvening?(time)
|
||||
try_type = (base_type.to_s + "Evening").to_sym
|
||||
end
|
||||
ret = try_type if try_type && has_encounter_type?(try_type)
|
||||
if !ret
|
||||
try_type = (base_type.to_s + "Day").to_sym
|
||||
ret = try_type if has_encounter_type?(try_type)
|
||||
end
|
||||
else
|
||||
try_type = (base_type.to_s + "Night").to_sym
|
||||
ret = try_type if has_encounter_type?(try_type)
|
||||
end
|
||||
return ret if ret
|
||||
return (has_encounter_type?(base_type)) ? base_type : nil
|
||||
end
|
||||
|
||||
# Returns the encounter method that the current encounter should be generated
|
||||
# from, depending on the player's current location.
|
||||
def encounter_type
|
||||
time = pbGetTimeNow
|
||||
ret = nil
|
||||
if $PokemonGlobal.surfing
|
||||
ret = find_valid_encounter_type_for_time(:Water, time)
|
||||
else # Land/Cave (can have both in the same map)
|
||||
if has_land_encounters? && $game_map.terrain_tag($game_player.x, $game_player.y).land_wild_encounters
|
||||
ret = :BugContest if pbInBugContest? && has_encounter_type?(:BugContest)
|
||||
ret = find_valid_encounter_type_for_time(:Land, time) if !ret
|
||||
end
|
||||
if !ret && has_cave_encounters?
|
||||
ret = find_valid_encounter_type_for_time(:Cave, time)
|
||||
end
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
#=============================================================================
|
||||
|
||||
# For the current map, randomly chooses a species and level from the encounter
|
||||
# list for the given encounter type. Returns nil if there are none defined.
|
||||
# A higher chance_rolls makes this method prefer rarer encounter slots.
|
||||
def choose_wild_pokemon(enc_type, chance_rolls = 1)
|
||||
if !enc_type || !GameData::EncounterType.exists?(enc_type)
|
||||
raise ArgumentError.new(_INTL("Encounter type {1} does not exist", enc_type))
|
||||
end
|
||||
enc_list = @encounter_tables[enc_type]
|
||||
return nil if !enc_list || enc_list.length == 0
|
||||
# Static/Magnet Pull prefer wild encounters of certain types, if possible.
|
||||
# If they activate, they remove all Pokémon from the encounter table that do
|
||||
# not have the type they favor. If none have that type, nothing is changed.
|
||||
first_pkmn = $Trainer.first_pokemon
|
||||
if first_pkmn
|
||||
favored_type = nil
|
||||
case first_pkmn.ability_id
|
||||
when :STATIC
|
||||
favored_type = :ELECTRIC if GameData::Type.exists?(:ELECTRIC) && rand(100) < 50
|
||||
when :MAGNETPULL
|
||||
favored_type = :STEEL if GameData::Type.exists?(:STEEL) && rand(100) < 50
|
||||
end
|
||||
if favored_type
|
||||
new_enc_list = []
|
||||
enc_list.each do |enc|
|
||||
species_data = GameData::Species.get(enc[0])
|
||||
t1 = species_data.type1
|
||||
t2 = species_data.type2
|
||||
new_enc_list.push(enc) if t1 == favored_type || t2 == favored_type
|
||||
end
|
||||
enc_list = new_enc_list if new_enc_list.length > 0
|
||||
end
|
||||
end
|
||||
enc_list.sort! { |a, b| b[0] <=> a[0] } # Highest probability first
|
||||
# Calculate the total probability value
|
||||
chance_total = 0
|
||||
enc_list.each { |a| chance_total += a[0] }
|
||||
# Choose a random entry in the encounter table based on entry probabilities
|
||||
rnd = 0
|
||||
chance_rolls.times do
|
||||
r = rand(chance_total)
|
||||
rnd = r if r > rnd # Prefer rarer entries if rolling repeatedly
|
||||
end
|
||||
encounter = nil
|
||||
enc_list.each do |enc|
|
||||
rnd -= enc[0]
|
||||
next if rnd >= 0
|
||||
encounter = enc
|
||||
break
|
||||
end
|
||||
# Get the chosen species and level
|
||||
level = rand(encounter[2]..encounter[3])
|
||||
# Some abilities alter the level of the wild Pokémon
|
||||
if first_pkmn
|
||||
case first_pkmn.ability_id
|
||||
when :HUSTLE, :PRESSURE, :VITALSPIRIT
|
||||
level = encounter[3] if rand(100) < 50 # Highest possible level
|
||||
end
|
||||
end
|
||||
# Black Flute and White Flute alter the level of the wild Pokémon
|
||||
if Settings::FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS
|
||||
if $PokemonMap.blackFluteUsed
|
||||
level = [level + rand(1..4), GameData::GrowthRate.max_level].min
|
||||
elsif $PokemonMap.whiteFluteUsed
|
||||
level = [level - rand(1..4), 1].max
|
||||
end
|
||||
end
|
||||
# Return [species, level]
|
||||
return [encounter[1], level]
|
||||
end
|
||||
|
||||
# For the given map, randomly chooses a species and level from the encounter
|
||||
# list for the given encounter type. Returns nil if there are none defined.
|
||||
# Used by the Bug Catching Contest to choose what the other participants
|
||||
# caught.
|
||||
def choose_wild_pokemon_for_map(map_ID, enc_type)
|
||||
if !enc_type || !GameData::EncounterType.exists?(enc_type)
|
||||
raise ArgumentError.new(_INTL("Encounter type {1} does not exist", enc_type))
|
||||
end
|
||||
# Get the encounter table
|
||||
encounter_data = GameData::Encounter.get(map_ID, $PokemonGlobal.encounter_version)
|
||||
return nil if !encounter_data
|
||||
enc_list = encounter_data.types[enc_type]
|
||||
return nil if !enc_list || enc_list.length == 0
|
||||
# Calculate the total probability value
|
||||
chance_total = 0
|
||||
enc_list.each { |a| chance_total += a[0] }
|
||||
# Choose a random entry in the encounter table based on entry probabilities
|
||||
rnd = 0
|
||||
chance_rolls.times do
|
||||
r = rand(chance_total)
|
||||
rnd = r if r > rnd # Prefer rarer entries if rolling repeatedly
|
||||
end
|
||||
encounter = nil
|
||||
enc_list.each do |enc|
|
||||
rnd -= enc[0]
|
||||
next if rnd >= 0
|
||||
encounter = enc
|
||||
break
|
||||
end
|
||||
# Return [species, level]
|
||||
level = rand(encounter[2]..encounter[3])
|
||||
return [encounter[1], level]
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
#
|
||||
#===============================================================================
|
||||
# Creates and returns a Pokémon based on the given species and level.
|
||||
# Applies wild Pokémon modifiers (wild held item, shiny chance modifiers,
|
||||
# Pokérus, gender/nature forcing because of player's lead Pokémon).
|
||||
def pbGenerateWildPokemon(species,level,isRoamer=false)
|
||||
genwildpoke = Pokemon.new(species,level)
|
||||
# Give the wild Pokémon a held item
|
||||
items = genwildpoke.wildHoldItems
|
||||
first_pkmn = $Trainer.first_pokemon
|
||||
chances = [50,5,1]
|
||||
chances = [60,20,5] if first_pkmn && first_pkmn.hasAbility?(:COMPOUNDEYES)
|
||||
itemrnd = rand(100)
|
||||
if (items[0]==items[1] && items[1]==items[2]) || itemrnd<chances[0]
|
||||
genwildpoke.item = items[0]
|
||||
elsif itemrnd<(chances[0]+chances[1])
|
||||
genwildpoke.item = items[1]
|
||||
elsif itemrnd<(chances[0]+chances[1]+chances[2])
|
||||
genwildpoke.item = items[2]
|
||||
end
|
||||
# Shiny Charm makes shiny Pokémon more likely to generate
|
||||
if GameData::Item.exists?(:SHINYCHARM) && $PokemonBag.pbHasItem?(:SHINYCHARM)
|
||||
2.times do # 3 times as likely
|
||||
break if genwildpoke.shiny?
|
||||
genwildpoke.personalID = rand(2**16) | rand(2**16) << 16
|
||||
end
|
||||
end
|
||||
# Give Pokérus
|
||||
genwildpoke.givePokerus if rand(65536) < Settings::POKERUS_CHANCE
|
||||
# Change wild Pokémon's gender/nature depending on the lead party Pokémon's
|
||||
# ability
|
||||
if first_pkmn
|
||||
if first_pkmn.hasAbility?(:CUTECHARM) && !genwildpoke.singleGendered?
|
||||
if first_pkmn.male?
|
||||
(rand(3)<2) ? genwildpoke.makeFemale : genwildpoke.makeMale
|
||||
elsif first_pkmn.female?
|
||||
(rand(3)<2) ? genwildpoke.makeMale : genwildpoke.makeFemale
|
||||
end
|
||||
elsif first_pkmn.hasAbility?(:SYNCHRONIZE)
|
||||
genwildpoke.nature = first_pkmn.nature if !isRoamer && rand(100)<50
|
||||
end
|
||||
end
|
||||
# Trigger events that may alter the generated Pokémon further
|
||||
Events.onWildPokemonCreate.trigger(nil,genwildpoke)
|
||||
return genwildpoke
|
||||
end
|
||||
|
||||
# Used by fishing rods and Headbutt/Rock Smash/Sweet Scent to generate a wild
|
||||
# Pokémon (or two) for a triggered wild encounter.
|
||||
def pbEncounter(enc_type)
|
||||
$PokemonTemp.encounterType = enc_type
|
||||
encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type)
|
||||
encounter1 = EncounterModifier.trigger(encounter1)
|
||||
return false if !encounter1
|
||||
if $PokemonEncounters.have_double_wild_battle?
|
||||
encounter2 = $PokemonEncounters.choose_wild_pokemon(enc_type)
|
||||
encounter2 = EncounterModifier.trigger(encounter2)
|
||||
return false if !encounter2
|
||||
pbDoubleWildBattle(encounter1[0], encounter1[1], encounter2[0], encounter2[1])
|
||||
else
|
||||
pbWildBattle(encounter1[0], encounter1[1])
|
||||
end
|
||||
$PokemonTemp.encounterType = nil
|
||||
$PokemonTemp.forceSingleBattle = false
|
||||
EncounterModifier.triggerEncounterEnd
|
||||
return true
|
||||
end
|
||||
@@ -0,0 +1,40 @@
|
||||
################################################################################
|
||||
# This section was created solely for you to put various bits of code that
|
||||
# modify various wild Pokémon and trainers immediately prior to battling them.
|
||||
# Be sure that any code you use here ONLY applies to the Pokémon/trainers you
|
||||
# want it to apply to!
|
||||
################################################################################
|
||||
|
||||
# Make all wild Pokémon shiny while a certain Switch is ON (see Settings).
|
||||
Events.onWildPokemonCreate += proc { |_sender, e|
|
||||
pokemon = e[0]
|
||||
if $game_switches[Settings::SHINY_WILD_POKEMON_SWITCH]
|
||||
pokemon.shiny = true
|
||||
end
|
||||
}
|
||||
|
||||
# Used in the random dungeon map. Makes the levels of all wild Pokémon in that
|
||||
# map depend on the levels of Pokémon in the player's party.
|
||||
# This is a simple method, and can/should be modified to account for evolutions
|
||||
# and other such details. Of course, you don't HAVE to use this code.
|
||||
Events.onWildPokemonCreate += proc { |_sender, e|
|
||||
pokemon = e[0]
|
||||
if $game_map.map_id == 51
|
||||
new_level = pbBalancedLevel($Trainer.party) - 4 + rand(5) # For variety
|
||||
new_level = new_level.clamp(1, GameData::GrowthRate.max_level)
|
||||
pokemon.level = new_level
|
||||
pokemon.calc_stats
|
||||
pokemon.reset_moves
|
||||
end
|
||||
}
|
||||
|
||||
# This is the basis of a trainer modifier. It works both for trainers loaded
|
||||
# when you battle them, and for partner trainers when they are registered.
|
||||
# Note that you can only modify a partner trainer's Pokémon, and not the trainer
|
||||
# themselves nor their items this way, as those are generated from scratch
|
||||
# before each battle.
|
||||
#Events.onTrainerPartyLoad += proc { |_sender, trainer|
|
||||
# if trainer # An NPCTrainer object containing party/items/lose text, etc.
|
||||
# YOUR CODE HERE
|
||||
# end
|
||||
#}
|
||||
@@ -0,0 +1,225 @@
|
||||
class PokemonGlobalMetadata
|
||||
attr_accessor :roamPosition
|
||||
attr_accessor :roamedAlready # Whether a roamer has been encountered on current map
|
||||
attr_accessor :roamEncounter
|
||||
attr_accessor :roamPokemon
|
||||
attr_writer :roamPokemonCaught
|
||||
|
||||
def roamPokemonCaught
|
||||
return @roamPokemonCaught || []
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Making roaming Pokémon roam around.
|
||||
#===============================================================================
|
||||
# Resets all roaming Pokemon that were defeated without having been caught.
|
||||
def pbResetAllRoamers
|
||||
return if !$PokemonGlobal.roamPokemon
|
||||
for i in 0...$PokemonGlobal.roamPokemon.length
|
||||
next if $PokemonGlobal.roamPokemon[i]!=true || !$PokemonGlobal.roamPokemonCaught[i]
|
||||
$PokemonGlobal.roamPokemon[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
# Gets the roaming areas for a particular Pokémon.
|
||||
def pbRoamingAreas(idxRoamer)
|
||||
# [species ID, level, Game Switch, encounter type, battle BGM, area maps hash]
|
||||
roamData = Settings::ROAMING_SPECIES[idxRoamer]
|
||||
return roamData[5] if roamData && roamData[5]
|
||||
return Settings::ROAMING_AREAS
|
||||
end
|
||||
|
||||
# Puts a roamer in a completely random map available to it.
|
||||
def pbRandomRoam(index)
|
||||
return if !$PokemonGlobal.roamPosition
|
||||
keys = pbRoamingAreas(index).keys
|
||||
$PokemonGlobal.roamPosition[index] = keys[rand(keys.length)]
|
||||
end
|
||||
|
||||
# Makes all roaming Pokémon roam to another map.
|
||||
def pbRoamPokemon
|
||||
$PokemonGlobal.roamPokemon = [] if !$PokemonGlobal.roamPokemon
|
||||
# Start all roamers off in random maps
|
||||
if !$PokemonGlobal.roamPosition
|
||||
$PokemonGlobal.roamPosition = {}
|
||||
for i in 0...Settings::ROAMING_SPECIES.length
|
||||
next if !GameData::Species.exists?(i[0])
|
||||
keys = pbRoamingAreas(i).keys
|
||||
$PokemonGlobal.roamPosition[i] = keys[rand(keys.length)]
|
||||
end
|
||||
end
|
||||
# Roam each Pokémon in turn
|
||||
for i in 0...Settings::ROAMING_SPECIES.length
|
||||
pbRoamPokemonOne(i)
|
||||
end
|
||||
end
|
||||
|
||||
# Makes a single roaming Pokémon roam to another map. Doesn't roam if it isn't
|
||||
# currently possible to encounter it (i.e. its Game Switch is off).
|
||||
def pbRoamPokemonOne(idxRoamer)
|
||||
# [species ID, level, Game Switch, encounter type, battle BGM, area maps hash]
|
||||
roamData = Settings::ROAMING_SPECIES[idxRoamer]
|
||||
return if roamData[2]>0 && !$game_switches[roamData[2]] # Game Switch is off
|
||||
return if !GameData::Species.exists?(roamData[0])
|
||||
# Get hash of area patrolled by the roaming Pokémon
|
||||
mapIDs = pbRoamingAreas(idxRoamer).keys
|
||||
return if !mapIDs || mapIDs.length==0 # No roaming area defined somehow
|
||||
# Get the roaming Pokémon's current map
|
||||
currentMap = $PokemonGlobal.roamPosition[idxRoamer]
|
||||
if !currentMap
|
||||
currentMap = mapIDs[rand(mapIDs.length)]
|
||||
$PokemonGlobal.roamPosition[idxRoamer] = currentMap
|
||||
end
|
||||
# Make an array of all possible maps the roaming Pokémon could roam to
|
||||
newMapChoices = []
|
||||
nextMaps = pbRoamingAreas(idxRoamer)[currentMap]
|
||||
return if !nextMaps
|
||||
for map in nextMaps
|
||||
# Only add map as a choice if the player hasn't been there recently
|
||||
newMapChoices.push(map)
|
||||
end
|
||||
# Rarely, add a random possible map into the mix
|
||||
if rand(32)==0
|
||||
newMapChoices.push(mapIDs[rand(mapIDs.length)])
|
||||
end
|
||||
# Choose a random new map to roam to
|
||||
if newMapChoices.length>0
|
||||
$PokemonGlobal.roamPosition[idxRoamer] = newMapChoices[rand(newMapChoices.length)]
|
||||
end
|
||||
end
|
||||
|
||||
# When the player moves to a new map (with a different name), make all roaming
|
||||
# Pokémon roam.
|
||||
Events.onMapChange += proc { |_sender,e|
|
||||
oldMapID = e[0]
|
||||
# Get and compare map names
|
||||
mapInfos = pbLoadMapInfos
|
||||
next if mapInfos && oldMapID>0 && mapInfos[oldMapID] &&
|
||||
mapInfos[oldMapID].name && $game_map.name==mapInfos[oldMapID].name
|
||||
# Make roaming Pokémon roam
|
||||
pbRoamPokemon
|
||||
$PokemonGlobal.roamedAlready = false
|
||||
}
|
||||
|
||||
|
||||
|
||||
#===============================================================================
|
||||
# Encountering a roaming Pokémon in a wild battle.
|
||||
#===============================================================================
|
||||
class PokemonTemp
|
||||
attr_accessor :roamerIndex # Index of roaming Pokémon to encounter next
|
||||
end
|
||||
|
||||
|
||||
|
||||
# Returns whether the given category of encounter contains the actual encounter
|
||||
# method that will occur in the player's current position.
|
||||
def pbRoamingMethodAllowed(roamer_method)
|
||||
enc_type = $PokemonEncounters.encounter_type
|
||||
type = GameData::EncounterType.get(enc_type).type
|
||||
case roamer_method
|
||||
when 0 # Any step-triggered method (except Bug Contest)
|
||||
return [:land, :cave, :water].include?(type)
|
||||
when 1 # Walking (except Bug Contest)
|
||||
return [:land, :cave].include?(type)
|
||||
when 2 # Surfing
|
||||
return type == :water
|
||||
when 3 # Fishing
|
||||
return type == :fishing
|
||||
when 4 # Water-based
|
||||
return [:water, :fishing].include?(type)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
EncounterModifier.register(proc { |encounter|
|
||||
$PokemonTemp.roamerIndex = nil
|
||||
next nil if !encounter
|
||||
# Give the regular encounter if encountering a roaming Pokémon isn't possible
|
||||
next encounter if $PokemonGlobal.roamedAlready
|
||||
next encounter if $PokemonGlobal.partner
|
||||
next encounter if $PokemonTemp.pokeradar
|
||||
next encounter if rand(100) < 75 # 25% chance of encountering a roaming Pokémon
|
||||
# Look at each roaming Pokémon in turn and decide whether it's possible to
|
||||
# encounter it
|
||||
currentRegion = pbGetCurrentRegion
|
||||
currentMapName = pbGetMessage(MessageTypes::MapNames, $game_map.map_id)
|
||||
possible_roamers = []
|
||||
Settings::ROAMING_SPECIES.each_with_index do |data, i|
|
||||
# data = [species, level, Game Switch, roamer method, battle BGM, area maps hash]
|
||||
next if !GameData::Species.exists?(data[0])
|
||||
next if data[2] > 0 && !$game_switches[data[2]] # Isn't roaming
|
||||
next if $PokemonGlobal.roamPokemon[i] == true # Roaming Pokémon has been caught
|
||||
# Get the roamer's current map
|
||||
roamerMap = $PokemonGlobal.roamPosition[i]
|
||||
if !roamerMap
|
||||
mapIDs = pbRoamingAreas(i).keys # Hash of area patrolled by the roaming Pokémon
|
||||
next if !mapIDs || mapIDs.length == 0 # No roaming area defined somehow
|
||||
roamerMap = mapIDs[rand(mapIDs.length)]
|
||||
$PokemonGlobal.roamPosition[i] = roamerMap
|
||||
end
|
||||
# If roamer isn't on the current map, check if it's on a map with the same
|
||||
# name and in the same region
|
||||
if roamerMap != $game_map.map_id
|
||||
map_metadata = GameData::MapMetadata.try_get(roamerMap)
|
||||
next if !map_metadata || !map_metadata.town_map_position ||
|
||||
map_metadata.town_map_position[0] != currentRegion
|
||||
next if pbGetMessage(MessageTypes::MapNames, roamerMap) != currentMapName
|
||||
end
|
||||
# Check whether the roamer's roamer method is currently possible
|
||||
next if !pbRoamingMethodAllowed(data[3])
|
||||
# Add this roaming Pokémon to the list of possible roaming Pokémon to encounter
|
||||
possible_roamers.push([i, data[0], data[1], data[4]]) # [i, species, level, BGM]
|
||||
end
|
||||
# No encounterable roaming Pokémon were found, just have the regular encounter
|
||||
next encounter if possible_roamers.length == 0
|
||||
# Pick a roaming Pokémon to encounter out of those available
|
||||
roamer = possible_roamers[rand(possible_roamers.length)]
|
||||
$PokemonGlobal.roamEncounter = roamer
|
||||
$PokemonTemp.roamerIndex = roamer[0]
|
||||
$PokemonGlobal.nextBattleBGM = roamer[3] if roamer[3] && !roamer[3].empty?
|
||||
$PokemonTemp.forceSingleBattle = true
|
||||
next [roamer[1], roamer[2]] # Species, level
|
||||
})
|
||||
|
||||
Events.onWildBattleOverride += proc { |_sender,e|
|
||||
species = e[0]
|
||||
level = e[1]
|
||||
handled = e[2]
|
||||
next if handled[0]!=nil
|
||||
next if !$PokemonGlobal.roamEncounter || $PokemonTemp.roamerIndex.nil?
|
||||
handled[0] = pbRoamingPokemonBattle(species, level)
|
||||
}
|
||||
|
||||
def pbRoamingPokemonBattle(species, level)
|
||||
# Get the roaming Pokémon to encounter; generate it based on the species and
|
||||
# level if it doesn't already exist
|
||||
idxRoamer = $PokemonTemp.roamerIndex
|
||||
if !$PokemonGlobal.roamPokemon[idxRoamer] ||
|
||||
!$PokemonGlobal.roamPokemon[idxRoamer].is_a?(Pokemon)
|
||||
$PokemonGlobal.roamPokemon[idxRoamer] = pbGenerateWildPokemon(species,level,true)
|
||||
end
|
||||
# Set some battle rules
|
||||
setBattleRule("single")
|
||||
setBattleRule("roamerFlees")
|
||||
# Perform the battle
|
||||
decision = pbWildBattleCore($PokemonGlobal.roamPokemon[idxRoamer])
|
||||
# Update Roaming Pokémon data based on result of battle
|
||||
if decision==1 || decision==4 # Defeated or caught
|
||||
$PokemonGlobal.roamPokemon[idxRoamer] = true
|
||||
$PokemonGlobal.roamPokemonCaught[idxRoamer] = (decision==4)
|
||||
end
|
||||
$PokemonGlobal.roamEncounter = nil
|
||||
$PokemonGlobal.roamedAlready = true
|
||||
# Used by the Poké Radar to update/break the chain
|
||||
Events.onWildBattleEnd.trigger(nil,species,level,decision)
|
||||
# Return false if the player lost or drew the battle, and true if any other result
|
||||
return (decision!=2 && decision!=5)
|
||||
end
|
||||
|
||||
EncounterModifier.registerEncounterEnd(proc {
|
||||
$PokemonTemp.roamerIndex = nil
|
||||
})
|
||||
Reference in New Issue
Block a user