Fixed Beak Blast/Shell Trap always failing, typo in Brick Break

This commit is contained in:
Maruno17
2021-04-18 16:30:17 +01:00
parent f10fe5c491
commit 66ee5937bc
17 changed files with 3 additions and 10 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
#}

View File

@@ -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
})