Implemented GameData::Encounter, created new encounters.txt format, tweaked Vs animation filenames

This commit is contained in:
Maruno17
2021-01-30 17:06:00 +00:00
parent 4098b1cd11
commit 6d3ff0c724
25 changed files with 1500 additions and 1427 deletions

View File

@@ -462,6 +462,7 @@ def pbMountBike
pbUpdateVehicle
bike_bgm = GameData::Metadata.get.bicycle_BGM
pbCueBGM(bike_bgm, 0.5) if bike_bgm
pbPokeRadarCancel
end
def pbDismountBike

View File

@@ -3,7 +3,6 @@
#===============================================================================
class PokemonTemp
attr_accessor :townMapData
attr_accessor :encountersData
attr_accessor :phoneData
attr_accessor :regionalDexes
attr_accessor :speciesShadowMovesets
@@ -14,7 +13,6 @@ end
def pbClearData
if $PokemonTemp
$PokemonTemp.townMapData = nil
$PokemonTemp.encountersData = nil
$PokemonTemp.phoneData = nil
$PokemonTemp.regionalDexes = nil
$PokemonTemp.speciesShadowMovesets = nil
@@ -42,19 +40,6 @@ def pbLoadTownMapData
return $PokemonTemp.townMapData
end
#===============================================================================
# Method to get wild encounter data.
#===============================================================================
def pbLoadEncountersData
$PokemonTemp = PokemonTemp.new if !$PokemonTemp
if !$PokemonTemp.encountersData
if pbRgssExists?("Data/encounters.dat")
$PokemonTemp.encountersData = load_data("Data/encounters.dat")
end
end
return $PokemonTemp.encountersData
end
#===============================================================================
# Method to get phone call data.
#===============================================================================

View File

@@ -40,6 +40,7 @@ module GameData
return (self::DATA.has_key?(other)) ? self::DATA[other] : nil
end
# Yields all data in order of their id_number.
def each
keys = self::DATA.keys.sort { |a, b| self::DATA[a].id_number <=> self::DATA[b].id_number }
keys.each { |key| yield self::DATA[key] if !key.is_a?(Integer) }
@@ -130,5 +131,6 @@ module GameData
Type.load
Species.load
Trainer.load
Encounter.load
end
end

View File

@@ -0,0 +1,78 @@
# $PokemonGlobal.encounter_version
module GameData
class Encounter
attr_accessor :id
attr_accessor :map
attr_accessor :version
attr_reader :step_chances
attr_reader :types
DATA = {}
DATA_FILENAME = "encounters.dat"
extend ClassMethods
include InstanceMethods
# @param map_id [Integer]
# @param map_version [Integer]
# @return [Boolean] whether there is encounter data for the given map ID/version
def self.exists?(map_id, map_version = 0)
validate map_id => [Integer]
validate map_version => [Integer]
key = sprintf("%s_%d", map_id, map_version).to_sym
return !self::DATA[key].nil?
end
# @param map_id [Integer]
# @param version [Integer]
# @return [self, nil]
def self.get(map_id, map_version = 0)
validate map_id => Integer
validate map_version => Integer
trial_key = sprintf("%s_%d", map_id, map_version).to_sym
key = (self::DATA.has_key?(trial_key)) ? trial_key : sprintf("%s_0", map_id).to_sym
return self::DATA[key]
end
# Yields all encounter data in order of their map and version numbers.
def self.each
keys = self::DATA.keys.sort do |a, b|
if self::DATA[a].map == self::DATA[b].map
self::DATA[a].version <=> self::DATA[b].version
else
self::DATA[a].map <=> self::DATA[b].map
end
end
keys.each { |key| yield self::DATA[key] }
end
# Yields all encounter data for the given version. Also yields encounter
# data for version 0 of a map if that map doesn't have encounter data for
# the given version.
def self.each_of_version(version = 0)
self.each do |data|
yield data if data.version == version
if version > 0
yield data if data.version == 0 && !self::DATA.has_key?([data.map, version])
end
end
end
def initialize(hash)
@id = hash[:id]
@map = hash[:map]
@version = hash[:version] || 0
@step_chances = hash[:step_chances]
@types = hash[:types] || []
end
end
end
#===============================================================================
# Deprecated methods
#===============================================================================
def pbLoadEncountersData
Deprecation.warn_method('pbLoadEncountersData', 'v20', 'GameData::Encounter.get(map_id, version)')
return nil
end

View File

@@ -361,34 +361,32 @@ def pbOnStepTaken(eventTriggered)
$PokemonGlobal.stepcount = 0 if !$PokemonGlobal.stepcount
$PokemonGlobal.stepcount += 1
$PokemonGlobal.stepcount &= 0x7FFFFFFF
repel = ($PokemonGlobal.repel>0)
Events.onStepTaken.trigger(nil)
# Events.onStepTakenFieldMovement.trigger(nil,$game_player)
handled = [nil]
Events.onStepTakenTransferPossible.trigger(nil,handled)
return if handled[0]
pbBattleOnStepTaken(repel) if !eventTriggered && !$game_temp.in_menu
$PokemonTemp.encounterTriggered = false # This info isn't needed
pbBattleOnStepTaken if !eventTriggered && !$game_temp.in_menu
$PokemonTemp.encounterTriggered = false # This info isn't needed here
end
# Start wild encounters while turning on the spot
Events.onChangeDirection += proc {
repel = ($PokemonGlobal.repel > 0)
pbBattleOnStepTaken(repel) if !$game_temp.in_menu
pbBattleOnStepTaken if !$game_temp.in_menu
}
def pbBattleOnStepTaken(repel = false)
def pbBattleOnStepTaken
return if $Trainer.able_pokemon_count == 0
encounterType = $PokemonEncounters.pbEncounterType
return if !$PokemonEncounters.encounter_possible_here?
encounterType = $PokemonEncounters.encounter_type
return if encounterType < 0
return if !$PokemonEncounters.isEncounterPossibleHere?
return if !$PokemonEncounter.step_triggers_encounter?(encounterType)
$PokemonTemp.encounterType = encounterType
encounter = $PokemonEncounters.pbGenerateEncounter(encounterType)
encounter = $PokemonEncounters.choose_wild_pokemon(encounterType)
encounter = EncounterModifier.trigger(encounter)
if $PokemonEncounters.pbCanEncounter?(encounter, repel)
if !$PokemonTemp.forceSingleBattle && !pbInSafari? && ($PokemonGlobal.partner ||
($Trainer.able_pokemon_count > 1 && PBTerrain.isDoubleWildBattle?(pbGetTerrainTag) && rand(100) < 30))
encounter2 = $PokemonEncounters.pbEncounteredPokemon(encounterType)
if $PokemonEncounter.allow_encounter?(encounter)
if $PokemonEncounter.have_double_wild_battle?
encounter2 = $PokemonEncounters.choose_wild_pokemon(encounterType)
encounter2 = EncounterModifier.trigger(encounter2)
pbDoubleWildBattle(encounter[0], encounter[1], encounter2[0], encounter2[1])
else
@@ -851,7 +849,7 @@ def pbJumpToward(dist=1,playSound=false,cancelSurf=false)
end
if $game_player.x!=x || $game_player.y!=y
pbSEPlay("Player jump") if playSound
$PokemonEncounters.clearStepCount if cancelSurf
$PokemonEncounters.reset_step_count if cancelSurf
$PokemonTemp.endSurf = true if cancelSurf
while $game_player.jumping?
Graphics.update

View File

@@ -44,7 +44,7 @@ def pbBattleAnimation(bgm=nil,battletype=0,foe=nil)
$PokemonTemp.encounterType==EncounterTypes::GoodRod ||
$PokemonTemp.encounterType==EncounterTypes::SuperRod)
location = 3
elsif $PokemonEncounters.isCave?
elsif $PokemonEncounters.has_cave_encounters?
location = 2
elsif !GameData::MapMetadata.exists?($game_map.map_id) ||
!GameData::MapMetadata.get($game_map.map_id).outdoor_map
@@ -112,7 +112,7 @@ def pbBattleAnimation(bgm=nil,battletype=0,foe=nil)
$PokemonGlobal.nextBattleME = nil
$PokemonGlobal.nextBattleCaptureME = nil
$PokemonGlobal.nextBattleBack = nil
$PokemonEncounters.clearStepCount
$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
@@ -134,10 +134,10 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
tr_type = foe[0].trainer_type
tr_type_id = GameData::TrainerType.get(tr_type).id_number
if tr_type
tbargraphic = sprintf("Graphics/Transitions/vsBar%s", tr_type.to_s) rescue nil
tbargraphic = sprintf("Graphics/Transitions/vsBar%d", tr_type_id) if !pbResolveBitmap(tbargraphic)
tgraphic = sprintf("Graphics/Transitions/vsTrainer%s", tr_type.to_s) rescue nil
tgraphic = sprintf("Graphics/Transitions/vsTrainer%d", tr_type_id) if !pbResolveBitmap(tgraphic)
tbargraphic = sprintf("Graphics/Transitions/vsBar_%s", tr_type.to_s) rescue nil
tbargraphic = sprintf("Graphics/Transitions/vsBar_%d", tr_type_id) if !pbResolveBitmap(tbargraphic)
tgraphic = sprintf("Graphics/Transitions/vsTrainer_%s", tr_type.to_s) rescue nil
tgraphic = sprintf("Graphics/Transitions/vsTrainer_%d", tr_type_id) if !pbResolveBitmap(tgraphic)
if pbResolveBitmap(tbargraphic) && pbResolveBitmap(tgraphic)
player_tr_type = $Trainer.trainer_type
player_tr_type_id = GameData::TrainerType.get(player_tr_type).id_number
@@ -156,11 +156,11 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
overlay = Sprite.new(viewport)
overlay.bitmap = Bitmap.new(Graphics.width,Graphics.height)
pbSetSystemFont(overlay.bitmap)
pbargraphic = sprintf("Graphics/Transitions/vsBar%s_%d", player_tr_type.to_s, outfit) rescue nil
pbargraphic = sprintf("Graphics/Transitions/vsBar%d_%d", player_tr_type_id, outfit) if !pbResolveBitmap(pbargraphic)
pbargraphic = sprintf("Graphics/Transitions/vsBar_%s_%d", player_tr_type.to_s, outfit) rescue nil
pbargraphic = sprintf("Graphics/Transitions/vsBar_%d_%d", player_tr_type_id, outfit) if !pbResolveBitmap(pbargraphic)
if !pbResolveBitmap(pbargraphic)
pbargraphic = sprintf("Graphics/Transitions/vsBar%s", player_tr_type.to_s) rescue nil
pbargraphic = sprintf("Graphics/Transitions/vsBar%d", player_tr_type_id) if !pbResolveBitmap(pbargraphic)
pbargraphic = sprintf("Graphics/Transitions/vsBar_%s", player_tr_type.to_s) rescue nil
pbargraphic = sprintf("Graphics/Transitions/vsBar_%d", player_tr_type_id) if !pbResolveBitmap(pbargraphic)
end
xoffset = ((Graphics.width/2)/10)*10
bar1 = Sprite.new(viewplayer)
@@ -197,11 +197,11 @@ def pbBattleAnimationOverride(viewport,battletype=0,foe=nil)
bar1.bitmap = BitmapCache.load_bitmap(pbargraphic)
bar2 = AnimatedPlane.new(viewopp)
bar2.bitmap = BitmapCache.load_bitmap(tbargraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer%s_%d", player_tr_type.to_s, outfit) rescue nil
pgraphic = sprintf("Graphics/Transitions/vsTrainer%d_%d", player_tr_type_id, outfit) if !pbResolveBitmap(pgraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer_%s_%d", player_tr_type.to_s, outfit) rescue nil
pgraphic = sprintf("Graphics/Transitions/vsTrainer_%d_%d", player_tr_type_id, outfit) if !pbResolveBitmap(pgraphic)
if !pbResolveBitmap(pgraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer%s", player_tr_type.to_s) rescue nil
pgraphic = sprintf("Graphics/Transitions/vsTrainer%d", player_tr_type_id) if !pbResolveBitmap(pgraphic)
pgraphic = sprintf("Graphics/Transitions/vsTrainer_%s", player_tr_type.to_s) rescue nil
pgraphic = sprintf("Graphics/Transitions/vsTrainer_%d", player_tr_type_id) if !pbResolveBitmap(pgraphic)
end
player = Sprite.new(viewplayer)
player.bitmap = BitmapCache.load_bitmap(pgraphic)

View File

@@ -46,6 +46,7 @@ class PokemonGlobalMetadata
attr_writer :bridge
attr_accessor :repel
attr_accessor :flashUsed
attr_accessor :encounter_version
# Map transfers
attr_accessor :healingSpot
attr_accessor :escapePoint
@@ -111,6 +112,7 @@ class PokemonGlobalMetadata
@bridge = 0
@repel = 0
@flashused = false
@encounter_version = 0
# Map transfers
@healingSpot = nil
@escapePoint = []

View File

@@ -1,49 +1,96 @@
module EncounterTypes
Land = 0
Cave = 1
Water = 2
RockSmash = 3
OldRod = 4
GoodRod = 5
SuperRod = 6
HeadbuttLow = 7
HeadbuttHigh = 8
LandMorning = 9
LandDay = 10
LandNight = 11
BugContest = 12
Land = 0
LandDay = 1
LandNight = 2
LandMorning = 3
LandAfternoon = 4
LandEvening = 5
Cave = 6
CaveDay = 7
CaveNight = 8
CaveMorning = 9
CaveAfternoon = 10
CaveEvening = 11
Water = 12
WaterDay = 13
WaterNight = 14
WaterMorning = 15
WaterAfternoon = 16
WaterEvening = 17
OldRod = 18
GoodRod = 19
SuperRod = 20
RockSmash = 21
HeadbuttLow = 22
HeadbuttHigh = 23
BugContest = 24
Names = [
"Land",
"Cave",
"Water",
"RockSmash",
"OldRod",
"GoodRod",
"SuperRod",
"HeadbuttLow",
"HeadbuttHigh",
"LandMorning",
"LandDay",
"LandNight",
"BugContest"
"Land", "LandDay", "LandNight", "LandMorning", "LandAfternoon", "LandEvening",
"Cave", "CaveDay", "CaveNight", "CaveMorning", "CaveAfternoon", "CaveEvening",
"Water", "WaterDay", "WaterNight", "WaterMorning", "WaterAfternoon", "WaterEvening",
"OldRod", "GoodRod", "SuperRod", "RockSmash", "HeadbuttLow", "HeadbuttHigh",
"BugContest"
]
EnctypeChances = [
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[60,30,5,4,1],
[60,30,5,4,1],
[70,30],
[60,20,20],
[40,40,15,4,1],
[30,25,20,10,5,5,4,1],
[30,25,20,10,5,5,4,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1],
[20,20,10,10,10,10,5,5,4,4,1,1]
Probabilities = [
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1],
[60, 30, 5, 4, 1],
[60, 30, 5, 4, 1],
[60, 30, 5, 4, 1],
[60, 30, 5, 4, 1],
[60, 30, 5, 4, 1],
[60, 30, 5, 4, 1],
[70, 30],
[60, 20, 20],
[40, 40, 15, 4, 1],
[60, 30, 5, 4, 1],
[30, 25, 20, 10, 5, 5, 4, 1],
[30, 25, 20, 10, 5, 5, 4, 1],
[20, 20, 10, 10, 10, 10, 5, 5, 4, 4, 1, 1]
]
EnctypeDensities = [25, 10, 10, 0, 0, 0, 0, 0, 0, 25, 25, 25, 25]
EnctypeCompileDens = [ 1, 2, 3, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]
Chances_Per_Step = [
25, 25, 25, 25, 25, 25, # Lands
10, 10, 10, 10, 10, 10, # Caves
10, 10, 10, 10, 10, 10, # Waters
0, 0, 0, 0, 0, 0, 25
]
Kinds = [
1, 1, 1, 1, 1, 1, # Lands
2, 2, 2, 2, 2, 2, # Caves
3, 3, 3, 3, 3, 3, # Waters
0, 0, 0, 0, 0, 0, 1
]
def self.is_land_type?(enc_type)
return self.is_normal_land_type?(enc_type) || enc_type == BugContest
end
def self.is_normal_land_type?(enc_type)
return [Land, LandDay, LandNight, LandMorning, LandAfternoon, LandEvening].include?(enc_type)
end
def self.is_cave_type?(enc_type)
return [Cave, CaveDay, CaveNight, CaveMorning, CaveAfternoon, CaveEvening].include?(enc_type)
end
def self.is_water_type?(enc_type)
return [Water, WaterDay, WaterNight, WaterMorning, WaterAfternoon, WaterEvening].include?(enc_type)
end
def self.is_fishing_type?(enc_type)
return [OldRod, GoodRod, SuperRod].include?(enc_type)
end
end
@@ -52,306 +99,143 @@ end
#
#===============================================================================
class PokemonEncounters
attr_reader :stepcount
attr_reader :step_count
def initialize
@enctypes = []
@density = nil
@step_chances = nil
@encounter_tables = []
end
def setup(mapID)
@stepcount = 0
@density = nil
@enctypes = []
begin
data = pbLoadEncountersData
if data.is_a?(Hash) && data[mapID]
@density = data[mapID][0]
@enctypes = data[mapID][1]
else
@density = nil
@enctypes = []
end
rescue
@density = nil
@enctypes = []
def setup(map_ID)
@step_count = 0
@step_chances = nil
@encounter_tables = []
encounter_data = GameData::Encounter.get(map_ID, $PokemonGlobal.encounter_version)
if encounter_data
@step_chances = encounter_data.step_chances.clone
@encounter_tables = Marshal.load(Marshal.dump(encounter_data.types))
end
end
def clearStepCount; @stepcount = 0; end
def reset_step_count
@step_count = 0
end
#=============================================================================
# Returns whether encounters for the given encounter type have been defined
# for the current map.
def hasEncounter?(enc)
return false if @density==nil || enc<0
return @enctypes[enc] ? true : false
def has_encounter_type?(enc_type)
return false if enc_type < 0
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 pbMapHasEncounter?(mapID,enctype)
data = pbLoadEncountersData
if data.is_a?(Hash) && data[mapID]
density = data[mapID][0]
enctypes = data[mapID][1]
else
return false
end
return false if density==nil || enctype<0
return enctypes[enctype] ? true : false
def map_has_encounter_type?(map_ID, enc_type)
return false if enc_type < 0
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?
return has_normal_land_encounters? ||
has_encounter_type?(EncounterTypes::BugContest)
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?
return has_encounter_type?(EncounterTypes::Land) ||
has_encounter_type?(EncounterTypes::LandDay) ||
has_encounter_type?(EncounterTypes::LandNight) ||
has_encounter_type?(EncounterTypes::LandMorning) ||
has_encounter_type?(EncounterTypes::LandAfternoon) ||
has_encounter_type?(EncounterTypes::LandEvening)
end
# Returns whether cave-like encounters have been defined for the current map.
# Applies only to encounters triggered by moving around.
def isCave?
return false if @density==nil
return @enctypes[EncounterTypes::Cave] ? true : false
end
# Returns whether grass-like encounters have been defined for the current map.
# Applies only to encounters triggered by moving around.
def isGrass?
return false if @density==nil
return (@enctypes[EncounterTypes::Land] ||
@enctypes[EncounterTypes::LandMorning] ||
@enctypes[EncounterTypes::LandDay] ||
@enctypes[EncounterTypes::LandNight] ||
@enctypes[EncounterTypes::BugContest]) ? true : false
end
# Returns whether grass-like encounters have been defined for the current map
# (ignoring the Bug Catching Contest one).
# Applies only to encounters triggered by moving around.
def isRegularGrass?
return false if @density==nil
return (@enctypes[EncounterTypes::Land] ||
@enctypes[EncounterTypes::LandMorning] ||
@enctypes[EncounterTypes::LandDay] ||
@enctypes[EncounterTypes::LandNight]) ? true : false
def has_cave_encounters?
return has_encounter_type?(EncounterTypes::Cave) ||
has_encounter_type?(EncounterTypes::CaveDay) ||
has_encounter_type?(EncounterTypes::CaveNight) ||
has_encounter_type?(EncounterTypes::CaveMorning) ||
has_encounter_type?(EncounterTypes::CaveAfternoon) ||
has_encounter_type?(EncounterTypes::CaveEvening)
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 isWater?
return false if @density==nil
return @enctypes[EncounterTypes::Water] ? true : false
def has_water_encounters?
return has_encounter_type?(EncounterTypes::Water) ||
has_encounter_type?(EncounterTypes::WaterDay) ||
has_encounter_type?(EncounterTypes::WaterNight) ||
has_encounter_type?(EncounterTypes::WaterMorning) ||
has_encounter_type?(EncounterTypes::WaterAfternoon) ||
has_encounter_type?(EncounterTypes::WaterEvening)
end
# Returns whether it is theoretically possible to have an encounter in the
# player's current location.
def isEncounterPossibleHere?
if $PokemonGlobal.surfing
return true
elsif PBTerrain.isIce?(pbGetTerrainTag($game_player))
return false
elsif self.isCave?
return true
elsif self.isGrass?
return PBTerrain.isGrass?($game_map.terrain_tag($game_player.x,$game_player.y))
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 PBTerrain.isIce?(terrain_tag)
return true if has_cave_encounters? # i.e. this map is a cave
return true if PBTerrain.isGrass?(terrain_tag) && has_land_encounters?
return false
end
# Returns the encounter method that the current encounter should be generated
# from, depending on the player's current location.
def pbEncounterType
if $PokemonGlobal.surfing
return EncounterTypes::Water
elsif self.isCave?
return EncounterTypes::Cave
elsif self.isGrass?
time = pbGetTimeNow
enctype = EncounterTypes::Land
enctype = EncounterTypes::LandNight if self.hasEncounter?(EncounterTypes::LandNight) && PBDayNight.isNight?(time)
enctype = EncounterTypes::LandDay if self.hasEncounter?(EncounterTypes::LandDay) && PBDayNight.isDay?(time)
enctype = EncounterTypes::LandMorning if self.hasEncounter?(EncounterTypes::LandMorning) && PBDayNight.isMorning?(time)
if pbInBugContest? && self.hasEncounter?(EncounterTypes::BugContest)
enctype = EncounterTypes::BugContest
end
return enctype
end
return -1
end
# Returns all the encounter tables for the given map.
# You can alias this method and modify the returned array's contents if you
# want to change the encounter table for some reason. Note that each sub-array
# should contain the right number of entries for that encounter type.
# Each encounter table element is an array: [species, minLevel, maxLevel]
def pbGetEncounterTables(mapID=-1)
if mapID>0
data = pbLoadEncountersData
return nil if !data.is_a?(Hash) || !data[mapID]
return data[mapID][1]
else # Current map
return Marshal.load(Marshal.dump(@enctypes))
end
end
# Returns an array of the encounter table for the given map/encounter type.
def pbGetEncounterTable(encType,mapID=-1)
ret = pbGetEncounterTables(mapID)
return ret[encType]
end
# Only called by Bug Catching Contest, when determining what the other
# contestants caught.
def pbMapEncounter(mapID,encType)
if encType<0 || encType>EncounterTypes::EnctypeChances.length
# Returns whether a wild encounter should happen, based on the probability of
# one triggering upon taking a step.
def step_triggers_encounter?(enc_type)
if enc_type < 0 || enc_type > EncounterTypes::Probabilities.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Get the encounter table
encList = pbGetEncounterTable(encType,mapID)
return nil if encList==nil
# Calculate the total probability value
chances = EncounterTypes::EnctypeChances[encType]
chanceTotal = 0
chances.each { |a| chanceTotal += a }
# Choose a random entry in the encounter table based on entry weights
rnd = rand(chanceTotal)
chance = 0
chosenPkmn = 0 # Index of the chosen entry
for i in 0...chances.length
chance += chances[i]
if rnd<chance
chosenPkmn = i
break
end
end
# Return the chosen species and level
encounter = encList[chosenPkmn]
level = encounter[1]+rand(1+encounter[2]-encounter[1])
return [encounter[0],level]
end
# Determines the species and level of the Pokémon to be encountered on the
# current map, given the encounter type. May return nil if the given encounter
# type has no encounters defined for it for the current map.
def pbEncounteredPokemon(enctype,tries=1)
if enctype<0 || enctype>EncounterTypes::EnctypeChances.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Get the encounter table
encList = pbGetEncounterTable(enctype)
return nil if encList==nil
chances = EncounterTypes::EnctypeChances[enctype]
# 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.
firstPkmn = $Trainer.first_pokemon
if firstPkmn && rand(100)<50 # 50% chance of happening
favoredType = nil
if firstPkmn.hasAbility?(:STATIC) && GameData::Type.exists?(:ELECTRIC)
favoredType = :ELECTRIC
elsif firstPkmn.hasAbility?(:MAGNETPULL) && GameData::Type.exists?(:STEEL)
favoredType = :STEEL
end
if favoredType
newEncList = []
newChances = []
for i in 0...encList.length
speciesData = GameData::Species.get(encList[i][0])
t1 = speciesData.type1
t2 = speciesData.type2
next if t1 != favoredType && (!t2 || t2 != favoredType)
newEncList.push(encList[i])
newChances.push(chances[i])
end
if newEncList.length>0
encList = newEncList
chances = newChances
end
end
end
# Calculate the total probability value
chanceTotal = 0
chances.each { |a| chanceTotal += a }
# Choose a random entry in the encounter table based on entry weights
rnd = 0
tries.times do
r = rand(chanceTotal)
rnd = r if rnd<r
end
chance = 0
chosenPkmn = 0 # Index of the chosen entry
for i in 0...chances.length
chance += chances[i]
if rnd<chance
chosenPkmn = i
break
end
end
# Get the chosen species and level
encounter = encList[chosenPkmn]
return nil if !encounter
level = encounter[1]+rand(1+encounter[2]-encounter[1])
# Some abilities alter the level of the wild Pokémon
if firstPkmn && rand(100)<50 # 50% chance of happening
if firstPkmn.hasAbility?(:HUSTLE) ||
firstPkmn.hasAbility?(:PRESSURE) ||
firstPkmn.hasAbility?(:VITALSPIRIT)
level2 = encounter[1]+rand(1+encounter[2]-encounter[1])
level = level2 if level2>level # Higher level is more likely
end
end
# Black Flute and White Flute alter the level of the wild Pokémon
if FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS
if $PokemonMap.blackFluteUsed
level = [level + 1 + rand(4), PBExperience.maxLevel].min
elsif $PokemonMap.whiteFluteUsed
level = [level - 1 - rand(4), 1].max
end
end
# Return [species, level]
return [encounter[0],level]
end
# Returns the encountered Pokémon's species/level, taking into account factors
# that alter the probability of an encounter (cycling, Flutes, lead party
# Pokémon's item/ability).
def pbGenerateEncounter(enctype)
if enctype<0 || enctype>EncounterTypes::EnctypeChances.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
end
# Check if an encounter table is defined
return nil if @density==nil
return nil if @density[enctype]==0 || !@density[enctype]
return nil if @enctypes[enctype]==nil
return false if $game_system.encounter_disabled
return false if !$Trainer
return false if $DEBUG && Input.press?(Input::CTRL)
# Wild encounters cannot happen for the first 3 steps after a previous wild
# encounter
@stepcount += 1
return nil if @stepcount<=3
# Determine the encounter density (probability of a wild encounter
# happening). The actual probability is the written encounter density, with
# modifiers applied, divided by 180 (numbers are multiplied by 16 below to
# increase precision).
encount = @density[enctype]*16
@step_count += 1
return false if @step_count <= 3
# 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)
# Determine the encounter step chance (probability of a wild encounter
# happening). The actual probability is the written encounter step chance,
# with modifiers applied, divided by 180.
encount = @step_chances[enc_type].to_f
encount *= 0.8 if $PokemonGlobal.bicycle
if !FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS
if $PokemonMap.blackFluteUsed
encount /= 2
elsif $PokemonMap.whiteFluteUsed
encount *= 1.5
end
encount /= 2 if $PokemonMap.blackFluteUsed
encount *= 1.5 if $PokemonMap.whiteFluteUsed
end
firstPkmn = $Trainer.first_pokemon
if firstPkmn
case firstPkmn.item_id
first_pkmn = $Trainer.first_pokemon
if first_pkmn
case first_pkmn.item_id
when :CLEANSETAG
encount *= 2.0 / 3
when :PUREINCENSE
encount *= 2.0 / 3
else # Ignore ability effects if an item effect applies
case firstPkmn.ability_id
case first_pkmn.ability_id
when :STENCH, :WHITESMOKE, :QUICKFEET
encount /= 2
when :SNOWCLOAK
encount /= 2 if $game_screen.weather_type==PBFieldWeather::Snow ||
$game_screen.weather_type==PBFieldWeather::Blizzard
encount /= 2 if $game_screen.weather_type == PBFieldWeather::Snow ||
$game_screen.weather_type == PBFieldWeather::Blizzard
when :SANDVEIL
encount /= 2 if $game_screen.weather_type==PBFieldWeather::Sandstorm
encount /= 2 if $game_screen.weather_type == PBFieldWeather::Sandstorm
when :SWARM
encount *= 1.5
when :ILLUMINATE, :ARENATRAP, :NOGUARD
@@ -360,34 +244,206 @@ class PokemonEncounters
end
end
# Decide whether the wild encounter should actually happen
return nil if rand(180*16)>=encount
# A wild encounter will happen; choose a species and level for it
encPkmn = pbEncounteredPokemon(enctype)
return nil if !encPkmn
# Some abilities make wild encounters less likely if the wild Pokémon is
# sufficiently weaker than the Pokémon with the ability
if firstPkmn && rand(100)<50 # 50% chance of happening
if firstPkmn.hasAbility?(:INTIMIDATE) || firstPkmn.hasAbility?(:KEENEYE)
return nil if encPkmn[1]<=firstPkmn.level-5 # 5 or more levels weaker
end
end
return encPkmn
return rand(180) < encount
end
# Returns whether it is possible to have an encounter, based on some factors
# that would prevent it (holding Ctrl in Debug mode, Repels).
def pbCanEncounter?(encounter,repel)
return false if $game_system.encounter_disabled
return false if !encounter || !$Trainer
return false if $DEBUG && Input.press?(Input::CTRL)
if !pbPokeRadarOnShakingGrass
if $PokemonGlobal.repel>0 || repel
firstPkmn = (REPEL_COUNTS_FAINTED_POKEMON) ? $Trainer.first_pokemon : $Trainer.first_able_pokemon
return false if firstPkmn && encounter[1]<firstPkmn.level
# 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, ignore_repel = false)
return false if !enc_data
# Repel
if !ignore_repel && $PokemonGlobal.repel > 0 && !pbPokeRadarOnShakingGrass
first_pkmn = (REPEL_COUNTS_FAINTED_POKEMON) ? $Trainer.first_pokemon : $Trainer.first_able_pokemon
return false if first_pkmn && enc_data[1] < first_pkmn.level
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 PBTerrain.isDoubleWildBattle?(pbGetTerrainTag) && rand(100) < 30
return false
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 = -1
if $PokemonGlobal.surfing
ret = EncounterTypes::Water if has_encounter_type?(EncounterTypes::Water)
if PBDayNight.isDay?(time)
ret = EncounterTypes::WaterDay if has_encounter_type?(EncounterTypes::WaterDay)
if PBDayNight.isMorning?(time)
ret = EncounterTypes::WaterMorning if has_encounter_type?(EncounterTypes::WaterMorning)
elsif PBDayNight.isAfternoon?(time)
ret = EncounterTypes::WaterAfternoon if has_encounter_type?(EncounterTypes::WaterAfternoon)
elsif PBDayNight.isEvening?(time)
ret = EncounterTypes::WaterEvening if has_encounter_type?(EncounterTypes::WaterEvening)
end
else
ret = EncounterTypes::WaterNight if has_encounter_type?(EncounterTypes::WaterNight)
end
else
check_land = false
if has_cave_encounters?
check_land = PBTerrain.isGrass?($game_map.terrain_tag($game_player.x, $game_player.y))
ret = EncounterTypes::Cave if has_encounter_type?(EncounterTypes::Cave)
if PBDayNight.isDay?(time)
ret = EncounterTypes::CaveDay if has_encounter_type?(EncounterTypes::CaveDay)
if PBDayNight.isMorning?(time)
ret = EncounterTypes::CaveMorning if has_encounter_type?(EncounterTypes::CaveMorning)
elsif PBDayNight.isAfternoon?(time)
ret = EncounterTypes::CaveAfternoon if has_encounter_type?(EncounterTypes::CaveAfternoon)
elsif PBDayNight.isEvening?(time)
ret = EncounterTypes::CaveEvening if has_encounter_type?(EncounterTypes::CaveEvening)
end
else
ret = EncounterTypes::CaveNight if has_encounter_type?(EncounterTypes::CaveNight)
end
end
# Land
if has_land_encounters? || check_land
ret = EncounterTypes::Land if has_encounter_type?(EncounterTypes::Land)
if PBDayNight.isDay?(time)
ret = EncounterTypes::LandDay if has_encounter_type?(EncounterTypes::LandDay)
if PBDayNight.isMorning?(time)
ret = EncounterTypes::LandMorning if has_encounter_type?(EncounterTypes::LandMorning)
elsif PBDayNight.isAfternoon?(time)
ret = EncounterTypes::LandAfternoon if has_encounter_type?(EncounterTypes::LandAfternoon)
elsif PBDayNight.isEvening?(time)
ret = EncounterTypes::LandEvening if has_encounter_type?(EncounterTypes::LandEvening)
end
else
ret = EncounterTypes::LandNight if has_encounter_type?(EncounterTypes::LandNight)
end
if pbInBugContest? && has_encounter_type?(EncounterTypes::BugContest)
ret = EncounterTypes::BugContest
end
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 < 0 || enc_type > EncounterTypes::Probabilities.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
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 FLUTES_CHANGE_WILD_ENCOUNTER_LEVELS
if $PokemonMap.blackFluteUsed
level = [level + rand(1, 4), PBExperience.maxLevel].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 < 0 || enc_type > EncounterTypes::Probabilities.length
raise ArgumentError.new(_INTL("Encounter type out of range"))
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
@@ -395,14 +451,16 @@ end
#===============================================================================
#
#===============================================================================
# Returns a Pokémon generated by a wild encounter, given its species and level.
# 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
firstPkmn = $Trainer.first_pokemon
first_pkmn = $Trainer.first_pokemon
chances = [50,5,1]
chances = [60,20,5] if firstPkmn && firstPkmn.hasAbility?(:COMPOUNDEYES)
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]
@@ -424,15 +482,15 @@ def pbGenerateWildPokemon(species,level,isRoamer=false)
end
# Change wild Pokémon's gender/nature depending on the lead party Pokémon's
# ability
if firstPkmn
if firstPkmn.hasAbility?(:CUTECHARM) && !genwildpoke.singleGendered?
if firstPkmn.male?
if first_pkmn
if first_pkmn.hasAbility?(:CUTECHARM) && !genwildpoke.singleGendered?
if first_pkmn.male?
(rand(3)<2) ? genwildpoke.makeFemale : genwildpoke.makeMale
elsif firstPkmn.female?
elsif first_pkmn.female?
(rand(3)<2) ? genwildpoke.makeMale : genwildpoke.makeFemale
end
elsif firstPkmn.hasAbility?(:SYNCHRONIZE)
genwildpoke.nature = firstPkmn.nature if !isRoamer && rand(100)<50
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
@@ -441,20 +499,22 @@ def pbGenerateWildPokemon(species,level,isRoamer=false)
end
# Used by fishing rods and Headbutt/Rock Smash/Sweet Scent. Skips the
# probability checks in def pbGenerateEncounter above.
def pbEncounter(enctype)
$PokemonTemp.encounterType = enctype
encounter1 = $PokemonEncounters.pbEncounteredPokemon(enctype)
# probability checks in def step_triggers_encounter? above.
def pbEncounter(enc_type)
$PokemonTemp.encounterType = enc_type
encounter1 = $PokemonEncounters.choose_wild_pokemon(enc_type)
encounter1 = EncounterModifier.trigger(encounter1)
return false if !encounter1
if $PokemonGlobal.partner
encounter2 = $PokemonEncounters.pbEncounteredPokemon(enctype)
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])
pbDoubleWildBattle(encounter1[0], encounter1[1], encounter2[0], encounter2[1])
else
pbWildBattle(encounter1[0],encounter1[1])
pbWildBattle(encounter1[0], encounter1[1])
end
$PokemonTemp.encounterType = -1
$PokemonTemp.forceSingleBattle = false
EncounterModifier.triggerEncounterEnd
return true
end

View File

@@ -117,33 +117,23 @@ end
# Returns whether the given category of encounter contains the actual encounter
# method that will occur in the player's current position.
def pbRoamingMethodAllowed(encType)
encounter = $PokemonEncounters.pbEncounterType
case encType
when 0 # Any encounter method (except triggered ones and Bug Contest)
return true if encounter==EncounterTypes::Land ||
encounter==EncounterTypes::LandMorning ||
encounter==EncounterTypes::LandDay ||
encounter==EncounterTypes::LandNight ||
encounter==EncounterTypes::Water ||
encounter==EncounterTypes::Cave
when 1 # Grass (except Bug Contest)/walking in caves only
return true if encounter==EncounterTypes::Land ||
encounter==EncounterTypes::LandMorning ||
encounter==EncounterTypes::LandDay ||
encounter==EncounterTypes::LandNight ||
encounter==EncounterTypes::Cave
when 2 # Surfing only
return true if encounter==EncounterTypes::Water
when 3 # Fishing only
return true if encounter==EncounterTypes::OldRod ||
encounter==EncounterTypes::GoodRod ||
encounter==EncounterTypes::SuperRod
when 4 # Water-based only
return true if encounter==EncounterTypes::Water ||
encounter==EncounterTypes::OldRod ||
encounter==EncounterTypes::GoodRod ||
encounter==EncounterTypes::SuperRod
def pbRoamingMethodAllowed(roamer_method)
enc_type = $PokemonEncounters.encounter_type
case roamer_method
when 0 # Any step-triggered method (except Bug Contest)
return EncounterTypes.is_normal_land_type?(enc_type) ||
EncounterTypes.is_cave_type?(enc_type) ||
EncounterTypes.is_water_type?(enc_type)
when 1 # Walking (except Bug Contest)
return EncounterTypes.is_normal_land_type?(enc_type) ||
EncounterTypes.is_cave_type?(enc_type)
when 2 # Surfing
return EncounterTypes.is_water_type?(enc_type)
when 3 # Fishing
return EncounterTypes.is_fishing_type?(enc_type)
when 4 # Water-based
return EncounterTypes.is_water_type?(enc_type) ||
EncounterTypes.is_fishing_type?(enc_type)
end
return false
end
@@ -155,51 +145,47 @@ EncounterModifier.register(proc { |encounter|
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
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
roamerChoices = []
for i in 0...ROAMING_SPECIES.length
# [species ID, level, Game Switch, encounter type, battle BGM, area maps hash]
roamData = ROAMING_SPECIES[i]
next if roamData[2]>0 && !$game_switches[roamData[2]] # Game Switch is off
next if $PokemonGlobal.roamPokemon[i]==true # Roaming Pokémon has been caught
next if !GameData::Species.exists?(roamData[0])
# Get the roaming Pokémon's current map
currentRegion = pbGetCurrentRegion
currentMapName = pbGetMessage(MessageTypes::MapNames, $game_map.map_id)
possible_roamers = []
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
next if !mapIDs || mapIDs.length == 0 # No roaming area defined somehow
roamerMap = mapIDs[rand(mapIDs.length)]
$PokemonGlobal.roamPosition[i] = roamerMap
end
# Check if roaming Pokémon is on the current map. If not, check if roaming
# Pokémon is on a map with the same name as the current map and both maps
# are in the same region
if roamerMap!=$game_map.map_id
currentRegion = pbGetCurrentRegion
# 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
currentMapName = pbGetMessage(MessageTypes::MapNames,$game_map.map_id)
next if pbGetMessage(MessageTypes::MapNames,roamerMap)!=currentMapName
next if pbGetMessage(MessageTypes::MapNames, roamerMap) != currentMapName
end
# Check whether the roaming Pokémon's category of encounter is currently possible
next if !pbRoamingMethodAllowed(roamData[3])
# 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
roamerChoices.push([i,roamData[0],roamData[1],roamData[4]])
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 roamerChoices.length==0
next encounter if possible_roamers.length == 0
# Pick a roaming Pokémon to encounter out of those available
chosenRoamer = roamerChoices[rand(roamerChoices.length)]
$PokemonGlobal.roamEncounter = chosenRoamer
$PokemonTemp.roamerIndex = chosenRoamer[0] # Roaming Pokémon's index
if chosenRoamer[3] && chosenRoamer[3]!=""
$PokemonGlobal.nextBattleBGM = chosenRoamer[3]
end
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 [chosenRoamer[1],chosenRoamer[2]] # Species, level
next [roamer[1], roamer[2]] # Species, level
})
Events.onWildBattleOverride += proc { |_sender,e|
@@ -207,9 +193,8 @@ Events.onWildBattleOverride += proc { |_sender,e|
level = e[1]
handled = e[2]
next if handled[0]!=nil
next if !$PokemonGlobal.roamEncounter
next if $PokemonTemp.roamerIndex==nil
handled[0] = pbRoamingPokemonBattle(species,level)
next if !$PokemonGlobal.roamEncounter || $PokemonTemp.roamerIndex.nil?
handled[0] = pbRoamingPokemonBattle(species, level)
}
def pbRoamingPokemonBattle(species, level)

View File

@@ -714,7 +714,7 @@ end
def pbStartSurfing
pbCancelVehicles
$PokemonEncounters.clearStepCount
$PokemonEncounters.reset_step_count
$PokemonGlobal.surfing = true
pbUpdateVehicle
$PokemonTemp.surfJump = $MapFactory.getFacingCoords($game_player.x,$game_player.y,$game_player.direction)
@@ -831,8 +831,8 @@ def pbSweetScent
break if viewport.color.alpha<=0
end
viewport.dispose
enctype = $PokemonEncounters.pbEncounterType
if enctype<0 || !$PokemonEncounters.isEncounterPossibleHere? ||
enctype = $PokemonEncounters.encounter_type
if enctype < 0 || !$PokemonEncounters.encounter_possible_here? ||
!pbEncounter(enctype)
pbMessage(_INTL("There appears to be nothing here..."))
end

View File

@@ -242,7 +242,7 @@ ItemHandlers::UseInField.add(:OLDROD,proc { |item|
pbMessage(_INTL("Can't use that here."))
next 0
end
encounter = $PokemonEncounters.hasEncounter?(EncounterTypes::OldRod)
encounter = $PokemonEncounters.has_encounter_type?(EncounterTypes::OldRod)
if pbFishing(encounter,1)
pbEncounter(EncounterTypes::OldRod)
end
@@ -256,7 +256,7 @@ ItemHandlers::UseInField.add(:GOODROD,proc { |item|
pbMessage(_INTL("Can't use that here."))
next 0
end
encounter = $PokemonEncounters.hasEncounter?(EncounterTypes::GoodRod)
encounter = $PokemonEncounters.has_encounter_type?(EncounterTypes::GoodRod)
if pbFishing(encounter,2)
pbEncounter(EncounterTypes::GoodRod)
end
@@ -270,7 +270,7 @@ ItemHandlers::UseInField.add(:SUPERROD,proc { |item|
pbMessage(_INTL("Can't use that here."))
next 0
end
encounter = $PokemonEncounters.hasEncounter?(EncounterTypes::SuperRod)
encounter = $PokemonEncounters.has_encounter_type?(EncounterTypes::SuperRod)
if pbFishing(encounter,3)
pbEncounter(EncounterTypes::SuperRod)
end

View File

@@ -243,27 +243,34 @@ def pbRandomPhoneItem(array)
return pbGetMessageFromHash(MessageTypes::PhoneMessages,ret)
end
def pbRandomEncounterSpecies(enctype)
return 0 if !enctype
len = [enctype.length,4].min
return enctype[rand(len)][0]
def pbRandomEncounterSpecies(enc_table)
return nil if !enc_table || enc_table.length == 0
len = [enc_table.length, 4].min
return enc_table[rand(len)][1]
end
def pbEncounterSpecies(phonenum)
return "" if !phonenum[6] || phonenum[6]==0
begin
enctypes = $PokemonEncounters.pbGetEncounterTables(phonenum[6])
return "" if !enctypes
rescue
return ""
return "" if !phonenum[6] || phonenum[6] == 0
encounter_data = GameData::Encounter.get(phonenum[6], $PokemonGlobal.encounter_version)
return "" if !encounter_data
enc_tables = encounter_data.types
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::Land])
if !species
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::Cave])
if !species
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::LandDay])
if !species
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::LandMorning])
if !species
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::LandNight])
if !species
species = pbRandomEncounterSpecies(enc_tables[EncounterTypes::Water])
end
end
end
end
end
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::Land])
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::Cave]) if species==0
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::LandDay]) if species==0
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::LandMorning]) if species==0
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::LandNight]) if species==0
species = pbRandomEncounterSpecies(enctypes[EncounterTypes::Water]) if species==0
return "" if species==0
return "" if !species
return GameData::Species.get(species).name
end

View File

@@ -20,7 +20,7 @@ def pbCanUsePokeRadar?
return false
end
# Can't use Radar if map has no grass-based encounters (ignoring Bug Contest)
if !$PokemonEncounters.isRegularGrass?
if !$PokemonEncounters.has_normal_land_encounters?
pbMessage(_INTL("Can't use that here."))
return false
end
@@ -48,6 +48,10 @@ def pbUsePokeRadar
return true
end
def pbPokeRadarCancel
$PokemonTemp.pokeradar = nil
end
def pbPokeRadarHighlightGrass(showmessage=true)
grasses = [] # x, y, ring (0-3 inner to outer), rarity
# Choose 1 random tile from each ring around the player
@@ -71,7 +75,7 @@ def pbPokeRadarHighlightGrass(showmessage=true)
y>=0 && y<$game_map.height
if PBTerrain.isJustGrass?($game_map.terrain_tag(x,y))
# Choose a rarity for the grass (0=normal, 1=rare, 2=shiny)
s = (rand(4)==0) ? 1 : 0
s = (rand(100) < 25) ? 1 : 0
if $PokemonTemp.pokeradar && $PokemonTemp.pokeradar[2]>0
v = [(65536/SHINY_POKEMON_CHANCE)-$PokemonTemp.pokeradar[2]*200,200].max
v = 0xFFFF/v
@@ -103,88 +107,79 @@ def pbPokeRadarHighlightGrass(showmessage=true)
end
end
def pbPokeRadarCancel
$PokemonTemp.pokeradar = nil
end
def pbPokeRadarGetShakingGrass
return -1 if !$PokemonTemp.pokeradar
grasses = $PokemonTemp.pokeradar[3]
return -1 if grasses.length==0
return -1 if grasses.length == 0
for i in grasses
return i[2] if $game_player.x==i[0] && $game_player.y==i[1]
return i[2] if $game_player.x == i[0] && $game_player.y == i[1]
end
return -1
end
def pbPokeRadarOnShakingGrass
return pbPokeRadarGetShakingGrass>=0
return pbPokeRadarGetShakingGrass >= 0
end
def pbPokeRadarGetEncounter(rarity=0)
def pbPokeRadarGetEncounter(rarity = 0)
# Poké Radar-exclusive encounters can only be found in vigorously-shaking grass
if rarity>0
if rarity > 0
# Get all Poké Radar-exclusive encounters for this map
map = $game_map.map_id rescue 0
map = $game_map.map_id
array = []
for enc in POKE_RADAR_ENCOUNTERS
array.push(enc) if enc.length>=4 && enc[0]==map && GameData::Species.exists?(enc[2])
POKE_RADAR_ENCOUNTERS.each do |enc|
array.push(enc) if enc[0] == map && GameData::Species.exists?(enc[2])
end
# If there are any exclusives, first have a chance of encountering those
if array.length>0
if array.length > 0
rnd = rand(100)
chance = 0
for enc in array
chance += enc[1]
if rnd<chance
level = (enc[4] && enc[4] > enc[3]) ? rand(enc[3], enc[4]) : enc[3]
return [enc[2], level]
end
array.each do |enc|
rnd -= enc[1]
next if rnd >= 0
level = (enc[4] && enc[4] > enc[3]) ? rand(enc[3], enc[4]) : enc[3]
return [enc[2], level]
end
end
end
# Didn't choose a Poké Radar-exclusive species, choose a regular encounter instead
return $PokemonEncounters.pbEncounteredPokemon($PokemonEncounters.pbEncounterType,rarity+1)
return $PokemonEncounters.choose_wild_pokemon($PokemonEncounters.encounter_type, rarity + 1)
end
################################################################################
# Event handlers
################################################################################
EncounterModifier.register(proc { |encounter|
next encounter if EncounterTypes::EnctypeCompileDens[$PokemonTemp.encounterType]!=1
if !$PokemonEncounters.isRegularGrass? ||
!$PokemonEncounters.isEncounterPossibleHere? ||
$PokemonGlobal.partner
if !EncounterTypes.is_normal_land_type?($PokemonTemp.encounterType) ||
$PokemonGlobal.bicycle || $PokemonGlobal.partner
pbPokeRadarCancel
next encounter
end
grass = pbPokeRadarGetShakingGrass
if grass>=0
ring = pbPokeRadarGetShakingGrass
if ring >= 0 # Encounter triggered by stepping into rustling grass
# Get rarity of shaking grass
s = 0
for g in $PokemonTemp.pokeradar[3]
s = g[3] if g[2]==grass
end
if $PokemonTemp.pokeradar[2]>0
if s==2 || rand(100)<86+grass*4+($PokemonTemp.pokeradar[2]/4).floor
rarity = 0 # 0 = rustle, 1 = vigorous rustle, 2 = shiny rustle
$PokemonTemp.pokeradar[3].each { |g| rarity = g[3] if g[2] == ring }
if $PokemonTemp.pokeradar[2] > 0 # Chain count, i.e. is chaining
if rarity == 2 || rand(100) < 86 + ring * 4 + ($PokemonTemp.pokeradar[2] / 4).floor
# Continue the chain
encounter = [$PokemonTemp.pokeradar[0],$PokemonTemp.pokeradar[1]]
$PokemonTemp.forceSingleBattle = true
encounter = [$PokemonTemp.pokeradar[0], $PokemonTemp.pokeradar[1]]
$PokemonTemp.forceSingleBattle = true
else
# Break the chain, force an encounter with a different species
100.times do
break if encounter && encounter[0]!=$PokemonTemp.pokeradar[0]
encounter = $PokemonEncounters.pbEncounteredPokemon($PokemonEncounters.pbEncounterType)
break if encounter && encounter[0] != $PokemonTemp.pokeradar[0]
encounter = $PokemonEncounters.choose_wild_pokemon($PokemonEncounters.encounter_type)
end
pbPokeRadarCancel
end
else
else # Not chaining; will start one
# Force random wild encounter, vigorous shaking means rarer species
encounter = pbPokeRadarGetEncounter(s)
encounter = pbPokeRadarGetEncounter(rarity)
$PokemonTemp.forceSingleBattle = true
end
else
pbPokeRadarCancel if encounter # Encounter is not in shaking grass
else # Encounter triggered by stepping in non-rustling grass
pbPokeRadarCancel if encounter
end
next encounter
})
@@ -205,10 +200,6 @@ Events.onWildBattleEnd += proc { |_sender,e|
species = e[0]
level = e[1]
decision = e[2]
if !$PokemonEncounters.isRegularGrass? || $PokemonGlobal.bicycle
pbPokeRadarCancel
next
end
if $PokemonTemp.pokeradar && (decision==1 || decision==4) # Defeated/caught
$PokemonTemp.pokeradar[0] = species
$PokemonTemp.pokeradar[1] = level
@@ -221,20 +212,15 @@ Events.onWildBattleEnd += proc { |_sender,e|
}
Events.onStepTaken += proc { |_sender,_e|
if $PokemonGlobal.pokeradarBattery && $PokemonGlobal.pokeradarBattery>0 &&
if $PokemonGlobal.pokeradarBattery && $PokemonGlobal.pokeradarBattery > 0 &&
!$PokemonTemp.pokeradar
$PokemonGlobal.pokeradarBattery -= 1
end
if !$PokemonEncounters.isRegularGrass? ||
!PBTerrain.isJustGrass?($game_map.terrain_tag($game_player.x,$game_player.y))
if !PBTerrain.isJustGrass?($game_map.terrain_tag($game_player.x, $game_player.y))
pbPokeRadarCancel
end
}
Events.onMapUpdate += proc { |_sender,_e|
pbPokeRadarCancel if $PokemonGlobal.bicycle
}
Events.onMapChange += proc { |_sender,_e|
pbPokeRadarCancel
}

View File

@@ -277,12 +277,12 @@ class PokemonPokedexInfo_Scene
pbDrawImagePositions(overlay, imagepos)
end
def pbFindEncounter(encounter,species)
return false if !encounter
for i in 0...encounter.length
next if !encounter[i]
for j in 0...encounter[i].length
return true if encounter[i][j][0]==species
def pbFindEncounter(enc_types, species)
return false if !enc_types
enc_types.each do |enc_type|
next if !enc_type
enc_type.each do |slot|
return true if GameData::Species.get(slot[1]).species == species
end
end
return false
@@ -298,11 +298,9 @@ class PokemonPokedexInfo_Scene
# species can be found
points = []
mapwidth = 1+PokemonRegionMap_Scene::RIGHT-PokemonRegionMap_Scene::LEFT
encdata = pbLoadEncountersData
for enc in encdata.keys
enctypes = encdata[enc][1]
next if !pbFindEncounter(enctypes, @species)
map_metadata = GameData::MapMetadata.try_get(enc)
GameData::Encounter.each_of_version($PokemonGlobal.encounter_version) do |enc_data|
next if !pbFindEncounter(enc_data.types, @species)
map_metadata = GameData::MapMetadata.try_get(enc_data.id)
mappos = (map_metadata) ? map_metadata.town_map_position : nil
next if !mappos || mappos[0] != @region
showpoint = true

View File

@@ -106,16 +106,16 @@ class BugContestState
end
end
enctype=EncounterTypes::BugContest
if !$PokemonEncounters.pbMapHasEncounter?(@contestMap,enctype)
if !$PokemonEncounters.map_has_encounter_type?(@contestMap, enctype)
enctype=EncounterTypes::Land
end
for cont in @contestants
enc=$PokemonEncounters.pbMapEncounter(@contestMap,enctype)
enc=$PokemonEncounters.choose_wild_pokemon_for_map(@contestMap,enctype)
if !enc
raise _INTL("No encounters for map {1}, so can't judge contest",@contestMap)
end
pokemon=Pokemon.new(enc[0],enc[1])
pokemon.hp=1+rand(pokemon.totalhp-1)
pokemon.hp = rand(1, pokemon.totalhp - 1)
score=pbBugContestScore(pokemon)
judgearray.push([cont,pokemon.species,score])
end

View File

@@ -887,16 +887,7 @@ DebugMenuCommands.register("setencounters", {
"description" => _INTL("Edit the wild Pokémon that can be found on maps, and how they are encountered."),
"always_show" => true,
"effect" => proc {
encdata = pbLoadEncountersData
map = pbDefaultMap
loop do
map = pbListScreen(_INTL("SET ENCOUNTERS"), MapLister.new(map))
break if map <= 0
pbEncounterEditorMap(encdata, map)
end
save_data(encdata, "Data/encounters.dat")
$PokemonTemp.encountersData = nil
Compiler.write_encounters # Rewrite PBS file encounters.txt
pbFadeOutIn { pbEncountersEditor }
}
})

View File

@@ -1,217 +1,334 @@
#===============================================================================
# Wild encounters editor
#===============================================================================
def pbEncounterEditorTypes(enc,enccmd)
# Main editor method for editing wild encounters. Lists all defined encounter
# sets, and edits them.
def pbEncountersEditor
map_infos = load_data("Data/MapInfos.rxdata")
commands = []
indexes = []
haveblank = false
if enc
commands.push(_INTL("Density: {1},{2},{3}",
enc[0][EncounterTypes::Land],
enc[0][EncounterTypes::Cave],
enc[0][EncounterTypes::Water]))
indexes.push(-2)
for i in 0...EncounterTypes::EnctypeChances.length
if enc[1][i]
commands.push(EncounterTypes::Names[i])
indexes.push(i)
else
haveblank = true
end
end
else
commands.push(_INTL("Density: Not Defined Yet"))
indexes.push(-2)
haveblank = true
end
if haveblank
commands.push(_INTL("[New Encounter Type]"))
indexes.push(-3)
end
enccmd.x = 0
enccmd.y = 0
enccmd.height = Graphics.height if enccmd.height>Graphics.height
enccmd.z = 99999
enccmd.commands = commands
enccmd.active = true
enccmd.index = 0
enccmd.visible = true
command = 0
maps = []
list = pbListWindow([])
help_window = Window_UnformattedTextPokemon.newWithSize(_INTL("Edit wild encounters"),
Graphics.width / 2, 0, Graphics.width / 2, 96)
help_window.z = 99999
ret = 0
need_refresh = true
loop do
Graphics.update
Input.update
enccmd.update
if Input.trigger?(Input::A) && indexes[enccmd.index]>=0
if pbConfirmMessage(_INTL("Delete the encounter type {1}?",commands[enccmd.index]))
enc[1][indexes[enccmd.index]] = nil
commands.delete_at(enccmd.index)
indexes.delete_at(enccmd.index)
enccmd.commands = commands
if enccmd.index>=enccmd.commands.length
enccmd.index = enccmd.commands.length
if need_refresh
commands.clear
maps.clear
commands.push(_INTL("[Add new encounter set]"))
GameData::Encounter.each do |enc_data|
name = (map_infos[enc_data.map]) ? map_infos[enc_data.map].name : nil
if enc_data.version > 0 && name
commands.push(sprintf("%03d (v.%d): %s", enc_data.map, enc_data.version, name))
elsif enc_data.version > 0
commands.push(sprintf("%03d (v.%d)", enc_data.map, enc_data.version))
elsif name
commands.push(sprintf("%03d: %s", enc_data.map, name))
else
commands.push(sprintf("%03d", enc_data.map))
end
maps.push([enc_data.map, enc_data.version])
end
need_refresh = false
end
ret = pbCommands2(list, commands, -1, ret)
if ret == 0 # Add new encounter set
new_map_ID = pbListScreen(_INTL("Choose a map"), MapLister.new(pbDefaultMap))
if new_map_ID > 0
new_version = LimitProperty2.new(999).set(_INTL("version number"), 0)
if new_version && new_version >= 0
if GameData::Encounter.exists?(new_map_ID, new_version)
pbMessage(_INTL("A set of encounters for map {1} version {2} already exists.", new_map_ID, new_version))
else
# Construct encounter hash
key = sprintf("%s_%d", new_map_ID, new_version).to_sym
encounter_hash = {
:id => key,
:map => new_map_ID,
:version => new_version,
:step_chances => [],
:types => []
}
GameData::Encounter::DATA[encounter_hash[:id]] = GameData::Encounter.new(encounter_hash)
maps.push([new_map_ID, new_version])
maps.sort! { |a, b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
ret = maps.index([new_map_ID, new_version]) + 1
need_refresh = true
end
end
end
elsif Input.trigger?(Input::B)
command = -1
break
elsif Input.trigger?(Input::C) || (enccmd.doubleclick? rescue false)
command = enccmd.index
break
end
end
ret = command
enccmd.active = false
return (ret<0) ? -1 : indexes[ret]
end
def pbNewEncounterType(enc)
cmdwin = pbListWindow([])
commands =[]
indexes = []
for i in 0...EncounterTypes::EnctypeChances.length
dogen = false
if !enc[1][i]
if i==0
dogen = true unless enc[1][EncounterTypes::Cave]
elsif i==1
dogen = true unless enc[1][EncounterTypes::Land] ||
enc[1][EncounterTypes::LandMorning] ||
enc[1][EncounterTypes::LandDay] ||
enc[1][EncounterTypes::LandNight] ||
enc[1][EncounterTypes::BugContest]
else
dogen = true
end
end
if dogen
commands.push(EncounterTypes::Names[i])
indexes.push(i)
end
end
ret = pbCommands2(cmdwin,commands,-1)
ret = (ret<0) ? -1 : indexes[ret]
if ret>=0
chances = EncounterTypes::EnctypeChances[ret]
enc[1][ret] = []
chances.length.times do
enc[1][ret].push([1,5,5])
end
end
cmdwin.dispose
return ret
end
def pbEditEncounterType(enc,etype)
commands = []
cmdwin = pbListWindow([])
chances = EncounterTypes::EnctypeChances[etype]
chancetotal = 0
chances.each { |a| chancetotal += a }
enctype = enc[1][etype]
for i in 0...chances.length
enctype[i] = [1,5,5] if !enctype[i]
end
ret = 0
loop do
commands.clear
for i in 0...enctype.length
ch = chances[i]
ch = sprintf("%.1f",100.0*chances[i]/chancetotal) if chancetotal!=100
if enctype[i][1]==enctype[i][2]
commands.push(_INTL("{1}% {2} (Lv.{3})", ch,
GameData::Species.get(enctype[i][0]).real_name, enctype[i][1]))
else
commands.push(_INTL("{1}% {2} (Lv.{3}-Lv.{4})", ch,
GameData::Species.get(enctype[i][0]).real_name, enctype[i][1], enctype[i][2]))
end
end
ret = pbCommands2(cmdwin,commands,-1,ret)
break if ret<0
species = pbChooseSpeciesList(enctype[ret][0])
next if !species
enctype[ret][0] = species
mLevel = PBExperience.maxLevel
params = ChooseNumberParams.new
params.setRange(1,mLevel)
params.setDefaultValue(enctype[ret][1])
minlevel = pbMessageChooseNumber(_INTL("Set the minimum level."),params)
params = ChooseNumberParams.new
params.setRange(minlevel,mLevel)
params.setDefaultValue(minlevel)
maxlevel = pbMessageChooseNumber(_INTL("Set the maximum level."),params)
enctype[ret][1] = minlevel
enctype[ret][2] = maxlevel
end
cmdwin.dispose
end
def pbEncounterEditorDensity(enc)
params = ChooseNumberParams.new
params.setRange(0,100)
params.setDefaultValue(enc[0][EncounterTypes::Land])
enc[0][EncounterTypes::Land] = pbMessageChooseNumber(
_INTL("Set the density of Pokémon on land (default {1}).",
EncounterTypes::EnctypeDensities[EncounterTypes::Land]),params)
params = ChooseNumberParams.new
params.setRange(0,100)
params.setDefaultValue(enc[0][EncounterTypes::Cave])
enc[0][EncounterTypes::Cave] = pbMessageChooseNumber(
_INTL("Set the density of Pokémon in caves (default {1}).",
EncounterTypes::EnctypeDensities[EncounterTypes::Cave]),params)
params = ChooseNumberParams.new
params.setRange(0,100)
params.setDefaultValue(enc[0][EncounterTypes::Water])
enc[0][EncounterTypes::Water] = pbMessageChooseNumber(
_INTL("Set the density of Pokémon on water (default {1}).",
EncounterTypes::EnctypeDensities[EncounterTypes::Water]),params)
for i in 0...EncounterTypes::EnctypeCompileDens.length
t = EncounterTypes::EnctypeCompileDens[i]
next if !t || t==0
enc[0][i] = enc[0][EncounterTypes::Land] if t==1
enc[0][i] = enc[0][EncounterTypes::Cave] if t==2
enc[0][i] = enc[0][EncounterTypes::Water] if t==3
end
end
def pbEncounterEditorMap(encdata,map)
enccmd = pbListWindow([])
# This window displays the help text
enchelp = Window_UnformattedTextPokemon.new("")
enchelp.x = Graphics.width/2
enchelp.y = 0
enchelp.width = Graphics.width/2 - 32
enchelp.height = 96
enchelp.z = 99999
mapinfos = load_data("Data/MapInfos.rxdata")
mapname = mapinfos[map].name
loop do
enc = encdata[map]
enchelp.text = _ISPRINTF("{1:03d}: {2:s}\r\nChoose a method",map,mapname)
choice = pbEncounterEditorTypes(enc,enccmd)
if !enc
enc = [EncounterTypes::EnctypeDensities.clone,[]]
encdata[map] = enc
end
if choice==-2
pbEncounterEditorDensity(enc)
elsif choice==-1
break
elsif choice==-3
ret = pbNewEncounterType(enc)
if ret>=0
enchelp.text = _ISPRINTF("{1:03d}: {2:s}\r\n{3:s}",map,mapname,EncounterTypes::Names[ret])
pbEditEncounterType(enc,ret)
elsif ret > 0 # Edit an encounter set
this_set = maps[ret - 1]
case pbShowCommands(nil, [_INTL("Edit"), _INTL("Copy"), _INTL("Delete"), _INTL("Cancel")], 4)
when 0 # Edit
pbEncounterMapVersionEditor(GameData::Encounter.get(this_set[0], this_set[1]))
need_refresh = true
when 1 # Copy
new_map_ID = pbListScreen(_INTL("Copy to which map?"), MapLister.new(this_set[0]))
if new_map_ID > 0
new_version = LimitProperty2.new(999).set(_INTL("version number"), 0)
if new_version && new_version >= 0
if GameData::Encounter.exists?(new_map_ID, new_version)
pbMessage(_INTL("A set of encounters for map {1} version {2} already exists.", new_map_ID, new_version))
else
types = []
GameData::Encounter.get(this_set[0], this_set[1]).types.each_with_index do |enc_type, i|
next if !enc_type
types[i] = []
enc_type.each { |slot| types[i].push(slot.clone) }
end
# Construct encounter hash
key = sprintf("%s_%d", new_map_ID, new_version).to_sym
encounter_hash = {
:id => key,
:map => new_map_ID,
:version => new_version,
:step_chances => GameData::Encounter.get(this_set[0], this_set[1]).step_chances.clone,
:types => types
}
GameData::Encounter::DATA[encounter_hash[:id]] = GameData::Encounter.new(encounter_hash)
maps.push([new_map_ID, new_version])
maps.sort! { |a, b| (a[0] == b[0]) ? a[1] <=> b[1] : a[0] <=> b[0] }
ret = maps.index([new_map_ID, new_version]) + 1
need_refresh = true
end
end
end
when 2 # Delete
if pbConfirmMessage(_INTL("Delete the encounter set for map {1} version {2}?", this_set[0], this_set[1]))
key = sprintf("%s_%d", this_set[0], this_set[1]).to_sym
GameData::Encounter::DATA.delete(key)
ret -= 1
need_refresh = true
end
end
else
enchelp.text = _ISPRINTF("{1:03d}: {2:s}\r\n{3:s}",map,mapname,EncounterTypes::Names[choice])
pbEditEncounterType(enc,choice)
break
end
end
if encdata[map][1].length==0
encdata[map] = nil
if pbConfirmMessage(_INTL("Save changes?"))
GameData::Encounter.save
Compiler.write_encounters # Rewrite PBS file encounters.txt
else
GameData::Encounter.load
end
enccmd.dispose
enchelp.dispose
list.dispose
help_window.dispose
Input.update
end
# Lists the map ID, version number and defined encounter types for the given
# encounter data (a GameData::Encounter instance), and edits them.
def pbEncounterMapVersionEditor(enc_data)
map_infos = load_data("Data/MapInfos.rxdata")
commands = []
enc_types = []
list = pbListWindow([])
help_window = Window_UnformattedTextPokemon.newWithSize(_INTL("Edit map's encounters"),
Graphics.width / 2, 0, Graphics.width / 2, 96)
help_window.z = 99999
ret = 0
need_refresh = true
loop do
if need_refresh
commands.clear
enc_types.clear
map_name = (map_infos[enc_data.map]) ? map_infos[enc_data.map].name : nil
if map_name
commands.push(_INTL("Map ID={1} ({2})", enc_data.map, map_name))
else
commands.push(_INTL("Map ID={1}", enc_data.map))
end
commands.push(_INTL("Version={1}", enc_data.version))
enc_data.types.each_with_index do |enc_type, i|
next if !enc_type
commands.push(_INTL("{1} (x{2})", EncounterTypes::Names[i], enc_type.length))
enc_types.push(i)
end
commands.push(_INTL("[Add new encounter type]"))
need_refresh = false
end
ret = pbCommands2(list, commands, -1, ret)
if ret == 0 # Edit map ID
old_map_ID = enc_data.map
new_map_ID = pbListScreen(_INTL("Choose a new map"), MapLister.new(old_map_ID))
if new_map_ID > 0 && new_map_ID != old_map_ID
if GameData::Encounter.exists?(new_map_ID, enc_data.version)
pbMessage(_INTL("A set of encounters for map {1} version {2} already exists.", new_map_ID, enc_data.version))
else
GameData::Encounter::DATA.delete(enc_data.id)
enc_data.map = new_map_ID
enc_data.id = sprintf("%s_%d", enc_data.map, enc_data.version).to_sym
GameData::Encounter::DATA[enc_data.id] = enc_data
need_refresh = true
end
end
elsif ret == 1 # Edit version number
old_version = enc_data.version
new_version = LimitProperty2.new(999).set(_INTL("version number"), old_version)
if new_version && new_version != old_version
if GameData::Encounter.exists?(enc_data.map, new_version)
pbMessage(_INTL("A set of encounters for map {1} version {2} already exists.", enc_data.map, new_version))
else
GameData::Encounter::DATA.delete(enc_data.id)
enc_data.version = new_version
enc_data.id = sprintf("%s_%d", enc_data.map, enc_data.version).to_sym
GameData::Encounter::DATA[enc_data.id] = enc_data
need_refresh = true
end
end
elsif ret == commands.length - 1 # Add new encounter type
new_type_commands = []
new_types = []
EncounterTypes::Names.each_with_index do |new_type, i|
next if enc_data.types[i]
new_type_commands.push(new_type)
new_types.push(i)
end
if new_type_commands.length > 0
chosen_type_cmd = pbShowCommands(nil, new_type_commands, -1)
if chosen_type_cmd >= 0
new_type = new_types[chosen_type_cmd]
enc_data.step_chances[new_type] = 0
enc_data.types[new_type] = []
pbEncounterTypeEditor(enc_data, new_type)
enc_types.push(new_type)
ret = enc_types.sort.index(new_type) + 2
need_refresh = true
end
else
pbMessage(_INTL("There are no unused encounter types to add."))
end
elsif ret > 0 # Edit an encounter type (its step chance and slots)
this_type = enc_types[ret - 2]
case pbShowCommands(nil, [_INTL("Edit"), _INTL("Copy"), _INTL("Delete"), _INTL("Cancel")], 4)
when 0 # Edit
pbEncounterTypeEditor(enc_data, this_type)
need_refresh = true
when 1 # Copy
new_type_commands = []
new_types = []
EncounterTypes::Names.each_with_index do |new_type, i|
next if enc_data.types[i]
new_type_commands.push(new_type)
new_types.push(i)
end
if new_type_commands.length > 0
chosen_type_cmd = pbMessage(_INTL("Choose an encounter type to copy to."),
new_type_commands, -1)
if chosen_type_cmd >= 0
new_type = new_types[chosen_type_cmd]
enc_data.step_chances[new_type] = enc_data.step_chances[this_type]
enc_data.types[new_type] = []
enc_data.types[this_type].each { |enc| enc_data.types[new_type].push(enc.clone) }
enc_types.push(new_type)
ret = enc_types.sort.index(new_type) + 2
need_refresh = true
end
else
pbMessage(_INTL("There are no unused encounter types to copy to."))
end
when 2 # Delete
if pbConfirmMessage(_INTL("Delete the encounter type {1}?", EncounterTypes::Names[this_type]))
enc_data.step_chances[this_type] = nil
enc_data.types[this_type] = nil
need_refresh = true
end
end
else
break
end
end
list.dispose
help_window.dispose
Input.update
end
# Lists the step chance and encounter slots for the given encounter type in the
# given encounter data (a GameData::Encounter instance), and edits them.
def pbEncounterTypeEditor(enc_data, enc_type)
commands = []
list = pbListWindow([])
help_window = Window_UnformattedTextPokemon.newWithSize(_INTL("Edit encounter slots"),
Graphics.width / 2, 0, Graphics.width / 2, 96)
help_window.z = 99999
ret = 0
need_refresh = true
loop do
if need_refresh
commands.clear
commands.push(_INTL("Step chance={1}", enc_data.step_chances[enc_type] || 0))
commands.push(_INTL("Encounter type={1}", EncounterTypes::Names[enc_type]))
if enc_data.types[enc_type] && enc_data.types[enc_type].length > 0
enc_data.types[enc_type].each do |slot|
commands.push(EncounterSlotProperty.format(slot))
end
end
commands.push(_INTL("[Add new slot]"))
need_refresh = false
end
ret = pbCommands2(list, commands, -1, ret)
if ret == 0 # Edit step chance
old_step_chance = enc_data.step_chances[enc_type] || 0
new_step_chance = LimitProperty.new(180).set(_INTL("Step chance"), old_step_chance)
if new_step_chance != old_step_chance
enc_data.step_chances[enc_type] = new_step_chance
need_refresh = true
end
elsif ret == 1 # Edit encounter type
new_type_commands = []
new_types = []
chosen_type_cmd = 0
EncounterTypes::Names.each_with_index do |type_name, i|
next if enc_data.types[i] && i != enc_type
new_type_commands.push(type_name)
new_types.push(i)
chosen_type_cmd = new_type_commands.length - 1 if i == enc_type
end
chosen_type_cmd = pbShowCommands(nil, new_type_commands, -1, chosen_type_cmd)
if chosen_type_cmd >= 0 && new_types[chosen_type_cmd] != enc_type
new_type = new_types[chosen_type_cmd]
enc_data.step_chances[new_type] = enc_data.step_chances[enc_type]
enc_data.step_chances[enc_type] = nil
enc_data.types[new_type] = enc_data.types[enc_type]
enc_data.types[enc_type] = nil
enc_type = new_type
need_refresh = true
end
elsif ret == commands.length - 1 # Add new encounter slot
new_slot_data = EncounterSlotProperty.set(EncounterTypes::Names[enc_type], nil)
if new_slot_data
enc_data.types[enc_type].push(new_slot_data)
need_refresh = true
end
elsif ret > 0 # Edit a slot
case pbShowCommands(nil, [_INTL("Edit"), _INTL("Copy"), _INTL("Delete"), _INTL("Cancel")], 4)
when 0 # Edit
old_slot_data = enc_data.types[enc_type][ret - 2]
new_slot_data = EncounterSlotProperty.set(EncounterTypes::Names[enc_type], old_slot_data.clone)
if new_slot_data && new_slot_data != old_slot_data
enc_data.types[enc_type][ret - 2] = new_slot_data
need_refresh = true
end
when 1 # Copy
enc_data.types[enc_type].insert(ret, enc_data.types[enc_type][ret - 2].clone)
ret += 1
need_refresh = true
when 2 # Delete
if pbConfirmMessage(_INTL("Delete this encounter slot?"))
enc_data.types[enc_type][ret - 2] = nil
enc_data.types[enc_type].compact!
need_refresh = true
end
end
else
break
end
end
list.dispose
help_window.dispose
Input.update
end

View File

@@ -35,7 +35,7 @@ class UIntProperty
def set(settingname,oldsetting)
params = ChooseNumberParams.new
params.setMaxDigits(@maxdigits)
params.setDefaultValue(oldsetting||0)
params.setDefaultValue(oldsetting || 0)
return pbMessageChooseNumber(_INTL("Set the value for {1}.",settingname),params)
end
@@ -278,6 +278,31 @@ end
module SpeciesFormProperty
def self.set(_settingname,oldsetting)
ret = pbChooseSpeciesFormList(oldsetting || nil)
return ret || oldsetting
end
def self.defaultValue
return nil
end
def self.format(value)
if value && GameData::Species.exists?(value)
species_data = GameData::Species.get(value)
if species_data.form > 0
return sprintf("%s_%d", species_data.real_name, species_data.form)
else
return species_data.real_name
end
end
return "-"
end
end
module TypeProperty
def self.set(_settingname, oldsetting)
ret = pbChooseTypeList(oldsetting || nil)
@@ -1112,105 +1137,6 @@ end
module FormNamesProperty
def self.set(_settingname,oldsetting)
ret = oldsetting
cmdwin = pbListWindow([],200)
commands = []
realcmds = []
realcmds.push([_INTL("[ADD FORM]"),-1])
for i in 0...oldsetting.length
realcmds.push([oldsetting[i],i])
end
refreshlist = true; oldsel = -1
cmd = [0,0]
loop do
if refreshlist
realcmds.sort! { |a,b| a[1]<=>b[1] }
commands = []
for i in 0...realcmds.length
text = (realcmds[i][1]>=0) ? sprintf("#{realcmds[i][1]} - #{realcmds[i][0]}") : realcmds[i][0]
commands.push(text)
cmd[1] = i if oldsel>=0 && realcmds[i][1]==oldsel
end
end
refreshlist = false; oldsel = -1
cmd = pbCommands3(cmdwin,commands,-1,cmd[1],true)
if cmd[0]==1 # Swap name up
if cmd[1]<realcmds.length-1 && realcmds[cmd[1]][1]>=0 && realcmds[cmd[1]+1][1]>=0
realcmds[cmd[1]+1][1],realcmds[cmd[1]][1] = realcmds[cmd[1]][1],realcmds[cmd[1]+1][1]
refreshlist = true
end
elsif cmd[0]==2 # Swap name down
if cmd[1]>0 && realcmds[cmd[1]][1]>=0 && realcmds[cmd[1]-1][1]>=0
realcmds[cmd[1]-1][1],realcmds[cmd[1]][1] = realcmds[cmd[1]][1],realcmds[cmd[1]-1][1]
refreshlist = true
end
elsif cmd[0]==0
if cmd[1]>=0
entry = realcmds[cmd[1]]
if entry[1]<0 # Add new form
newname = pbMessageFreeText(_INTL("Choose a form name (no commas)."),"",false,250)
if newname!=""
realcmds.push([newname,realcmds.length-1])
refreshlist = true
end
else # Edit form name
cmd2 = pbMessage(_INTL("\\ts[]Do what with this form name?"),
[_INTL("Rename"),_INTL("Delete"),_INTL("Cancel")],3)
if cmd2==0
newname = pbMessageFreeText(_INTL("Choose a form name (no commas)."),entry[0],false,250)
if newname!=""
realcmds[cmd[1]][0] = newname
refreshlist = true
end
elsif cmd2==1
realcmds[cmd[1]] = nil
realcmds.compact!
cmd[1] = [cmd[1],realcmds.length-1].min
refreshlist = true
end
end
else
cmd2 = pbMessage(_INTL("Save changes?"),
[_INTL("Yes"),_INTL("No"),_INTL("Cancel")],3)
if cmd2==0 || cmd2==1
if cmd2==0
for i in 0...realcmds.length
if realcmds[i][1]<0
realcmds[i] = nil
else
realcmds[i] = realcmds[i][0]
end
end
realcmds.compact!
ret = realcmds
end
break
end
end
end
end
cmdwin.dispose
return ret
end
def self.defaultValue
return []
end
def self.format(value)
ret = ""
for i in 0...value.length
ret << "," if i>0
ret << sprintf("#{value[i]}")
end
return ret
end
end
class EvolutionsProperty
def initialize
@methods = []
@@ -1464,29 +1390,69 @@ end
module EncounterSlotProperty
def self.set(setting_name, data)
max_level = PBExperience.maxLevel
if !data
data = [20, nil, 5, 5]
GameData::Species.each do |species_data|
data[1] = species_data.species
break
end
end
data[3] = data[2] if !data[3]
properties = [
[_INTL("Probability"), NonzeroLimitProperty.new(999), _INTL("Relative probability of choosing this slot.")],
[_INTL("Species"), SpeciesFormProperty, _INTL("A Pokémon species/form.")],
[_INTL("Minimum level"), NonzeroLimitProperty.new(max_level), _INTL("Minimum level of this species (1-{1}).", max_level)],
[_INTL("Maximum level"), NonzeroLimitProperty.new(max_level), _INTL("Maximum level of this species (1-{1}).", max_level)]
]
pbPropertyList(setting_name, data, properties, false)
if data[2] > data[3]
data[3], data[2] = data[2], data[3]
end
return data
end
def self.defaultValue
return nil
end
def self.format(value)
return "-" if !value
species_data = GameData::Species.get(value[1])
if species_data.form > 0
if value[2] == value[3]
return sprintf("%d, %s_%d (Lv.%d)", value[0],
species_data.real_name, species_data.form, value[2])
end
return sprintf("%d, %s_%d (Lv.%d-%d)", value[0],
species_data.real_name, species_data.form, value[2], value[3])
end
if value[2] == value[3]
return sprintf("%d, %s (Lv.%d)", value[0], species_data.real_name, value[2])
end
return sprintf("%d, %s (Lv.%d-%d)", value[0], species_data.real_name, value[2], value[3])
end
end
#===============================================================================
# Core property editor script
#===============================================================================
def pbPropertyList(title,data,properties,saveprompt=false)
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
viewport.z = 99999
list = pbListWindow([],Graphics.width*5/10)
list = pbListWindow([], Graphics.width / 2)
list.viewport = viewport
list.z = 2
title = Window_UnformattedTextPokemon.new(title)
title.x = list.width
title.y = 0
title.width = Graphics.width*5/10
title.height = 64
title.viewport = viewport
title.z = 2
desc = Window_UnformattedTextPokemon.new("")
desc.x = list.width
desc.y = title.height
desc.width = Graphics.width*5/10
desc.height = Graphics.height-title.height
desc.viewport = viewport
desc.z = 2
title = Window_UnformattedTextPokemon.newWithSize(title,
list.width, 0, Graphics.width / 2, 64, viewport)
title.z = 2
desc = Window_UnformattedTextPokemon.newWithSize("",
list.width, title.height, Graphics.width / 2, Graphics.height - title.height, viewport)
desc.z = 2
selectedmap = -1
retval = nil
commands = []

View File

@@ -1,8 +1,8 @@
#===============================================================================
# Core lister script
#===============================================================================
def pbListWindow(cmds,width=Graphics.width/2)
list = Window_CommandPokemon.newWithSize(cmds,0,0,width,Graphics.height)
def pbListWindow(cmds, width = Graphics.width / 2)
list = Window_CommandPokemon.newWithSize(cmds, 0, 0, width, Graphics.height)
list.index = 0
list.rowHeight = 24
pbSetSmallFont(list.contents)
@@ -16,13 +16,9 @@ def pbListScreen(title,lister)
list = pbListWindow([])
list.viewport = viewport
list.z = 2
title = Window_UnformattedTextPokemon.new(title)
title.x = Graphics.width/2
title.y = 0
title.width = Graphics.width-title.x
title.height = 64
title.viewport = viewport
title.z = 2
title = Window_UnformattedTextPokemon.newWithSize(title,
Graphics.width / 2, 0, Graphics.width / 2, 64, viewport)
title.z = 2
lister.setViewport(viewport)
selectedmap = -1
commands = lister.commands
@@ -62,18 +58,14 @@ def pbListScreen(title,lister)
end
def pbListScreenBlock(title,lister)
viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
viewport.z = 99999
list = pbListWindow([],Graphics.width/2)
list = pbListWindow([], Graphics.width / 2)
list.viewport = viewport
list.z = 2
title = Window_UnformattedTextPokemon.new(title)
title.x = Graphics.width/2
title.y = 0
title.width = Graphics.width-title.x
title.height = 64
title.viewport = viewport
title.z = 2
title = Window_UnformattedTextPokemon.newWithSize(title,
Graphics.width / 2, 0, Graphics.width - title.x, 64, viewport)
title.z = 2
lister.setViewport(viewport)
selectedmap = -1
commands = lister.commands

View File

@@ -121,6 +121,15 @@ def pbChooseSpeciesList(default = nil)
return pbChooseList(commands, default, nil, -1)
end
def pbChooseSpeciesFormList(default = nil)
commands = []
GameData::Species.each do |s|
name = (s.form == 0) ? s.real_name : sprintf("%s_%d", s.real_name, s.form)
commands.push([s.id_number, name, s.id])
end
return pbChooseList(commands, default, nil, -1)
end
# Displays a list of all moves, and returns the ID of the move selected (or nil
# if the selection was canceled). "default", if specified, is the ID of the move
# to initially select. Pressing Input::A will toggle the list sorting between

View File

@@ -335,7 +335,6 @@ class MapScreenScene
@sprites["title"].viewport=@viewport
@sprites["title"].z=2
@mapinfos=load_data("Data/MapInfos.rxdata")
@encdata=pbLoadEncountersData
conns=MapFactoryHelper.getMapConnections
@mapconns=[]
for c in conns
@@ -361,7 +360,6 @@ class MapScreenScene
helptext+=_INTL("S: Go to another map\r\n")
helptext+=_INTL("Click to select a map\r\n")
helptext+=_INTL("Double-click: Edit map's metadata\r\n")
helptext+=_INTL("E: Edit map's encounters\r\n")
helptext+=_INTL("Drag map to move it\r\n")
helptext+=_INTL("Arrow keys/drag canvas: Move around canvas")
title=Window_UnformattedTextPokemon.new(helptext)
@@ -556,8 +554,6 @@ class MapScreenScene
@sprites["selsprite"].othersprite=nil
@selmapid=-1
end
elsif Input.triggerex?("E"[0])
pbEncounterEditorMap(@encdata,@selmapid) if @selmapid>=0
elsif Input.trigger?(Input::F5)
helpWindow
end
@@ -573,9 +569,8 @@ class MapScreenScene
if pbConfirmMessage(_INTL("Save changes?"))
serializeConnectionData
MapFactoryHelper.clear
save_data(@encdata,"Data/encounters.dat")
$PokemonTemp.encountersData = nil
Compiler.write_encounters
else
GameData.Encounter.load
end
break if pbConfirmMessage(_INTL("Exit from the editor?"))
end

View File

@@ -827,107 +827,194 @@ module Compiler
# Compile wild encounter data
#=============================================================================
def compile_encounters
lines = []
linenos = []
FileLineData.file = "PBS/encounters.txt"
File.open("PBS/encounters.txt","rb") { |f|
lineno = 1
f.each_line { |line|
if lineno==1 && line[0]==0xEF && line[1]==0xBB && line[2]==0xBF
line = line[3,line.length-3]
new_format = nil
encounter_hash = nil
step_chances = nil
need_step_chances = false # Not needed for new format only
probabilities = nil
current_type = -1
expected_lines = 0
max_level = PBExperience.maxLevel
pbCompilerEachPreppedLine("PBS/encounters.txt") { |line, line_no|
next if line.length == 0
if expected_lines > 0 && line[/^\d+,/] && new_format # Species line
values = line.split(',')
if !values || values.length < 3
raise _INTL("Expected a species entry line for encounter type {1} for map '{2}', got \"{3}\" instead.\r\n{4}",
EncounterTypes::Names[current_type], encounter_hash[:map], line, FileLineData.linereport)
end
line = prepline(line)
if line.length!=0
lines[lines.length] = line
linenos[linenos.length] = lineno
values = pbGetCsvRecord(line, line_no, [0, "vevV", nil, :Species])
values[3] = values[2] if !values[3]
if values[2] > max_level
raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[2], max_level, FileLineData.linereport)
elsif values[3] > max_level
raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[3], max_level, FileLineData.linereport)
elsif values[2] > values[3]
raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}", line, FileLineData.linereport)
end
lineno += 1
}
}
encounters = {}
thisenc = nil
needdensity = false
lastmapid = -1
i = 0
while i<lines.length
line = lines[i]
FileLineData.setLine(line,linenos[i])
mapid = line[/^\d+$/]
if mapid
lastmapid = mapid
if encounters[mapid.to_i]
raise _INTL("Encounters for map ID '{1}' are defined twice.\r\n{2}",mapid,FileLineData.linereport)
encounter_hash[:types][current_type].push(values)
elsif expected_lines > 0 && !new_format # Expect a species line and nothing else
values = line.split(',')
if !values || values.length < 2
raise _INTL("Expected a species entry line for encounter type {1} for map '{2}', got \"{3}\" instead.\r\n{4}",
EncounterTypes::Names[current_type], encounter_hash[:map], line, FileLineData.linereport)
end
if thisenc && (thisenc[1][EncounterTypes::Land] ||
thisenc[1][EncounterTypes::LandMorning] ||
thisenc[1][EncounterTypes::LandDay] ||
thisenc[1][EncounterTypes::LandNight] ||
thisenc[1][EncounterTypes::BugContest]) &&
thisenc[1][EncounterTypes::Cave]
raise _INTL("Can't define both Land and Cave encounters in the same area (map ID '{1}').",mapid)
values = pbGetCsvRecord(line, line_no, [0, "evV", :Species])
values[2] = values[1] if !values[2]
if values[1] > max_level
raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[1], max_level, FileLineData.linereport)
elsif values[2] > max_level
raise _INTL("Level number {1} is not valid (max. {2}).\r\n{3}", values[2], max_level, FileLineData.linereport)
elsif values[1] > values[2]
raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}", line, FileLineData.linereport)
end
thisenc = [EncounterTypes::EnctypeDensities.clone,[]]
encounters[mapid.to_i] = thisenc
needdensity = true
i += 1
next
end
enc = findIndex(EncounterTypes::Names) { |val| val==line }
if enc>=0
needdensity = false
enclines = EncounterTypes::EnctypeChances[enc].length
encarray = []
j = i+1; k = 0
while j<lines.length && k<enclines
line = lines[j]
FileLineData.setLine(lines[j],linenos[j])
splitarr = strsplit(line,/\s*,\s*/)
if !splitarr || splitarr.length<2
raise _INTL("Expected a species entry line, got \"{1}\" instead. Check the number of species lines in the previous section (number {2}).\r\n{3}",
line,lastmapid,FileLineData.linereport)
probability = probabilities[probabilities.length - expected_lines]
encounter_hash[:types][current_type].push([probability] + values)
expected_lines -= 1
elsif line[/^\[\s*(.+)\s*\]$/] # Map ID line (new format)
if new_format == false
raise _INTL("Can't mix old and new formats.\r\n{1}", FileLineData.linereport)
end
new_format = true
values = $~[1].split(',')
values.collect! { |v| v.strip.to_i }
values[1] = 0 if !values[1] || values[1] == ""
map_number = values[0]
map_version = values[1]
# Add map encounter's data to records
if encounter_hash
encounter_hash[:types].each do |encounters|
next if !encounters || encounters.length == 0
encounters.each_with_index do |enc, i|
next if !enc
encounters.each_with_index do |other_enc, j|
next if i == j || !other_enc
next if enc[1] != other_enc[1] || enc[2] != other_enc[2] || enc[3] != other_enc[3]
enc[0] += other_enc[0]
encounters[j] = nil
end
end
encounters.compact!
encounters.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] }
end
splitarr[2] = splitarr[1] if splitarr.length==2
splitarr[1] = splitarr[1].to_i
splitarr[2] = splitarr[2].to_i
maxlevel = PBExperience.maxLevel
if splitarr[1]<=0 || splitarr[1]>maxlevel
raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[1],FileLineData.linereport)
end
if splitarr[2]<=0 || splitarr[2]>maxlevel
raise _INTL("Level number is not valid: {1}\r\n{2}",splitarr[2],FileLineData.linereport)
end
if splitarr[1]>splitarr[2]
raise _INTL("Minimum level is greater than maximum level: {1}\r\n{2}",line,FileLineData.linereport)
end
splitarr[0] = parseSpecies(splitarr[0])
encarray.push(splitarr)
thisenc[1][enc] = encarray
j += 1; k += 1
GameData::Encounter::DATA[encounter_hash[:id]] = GameData::Encounter.new(encounter_hash)
end
if j==lines.length && k<enclines
raise _INTL("Reached end of file unexpectedly. There were too few species entry lines in the last section (number {1}), expected {2} entries.\r\n{3}",
lastmapid,enclines,FileLineData.linereport)
# Raise an error if a map/version combo is used twice
key = sprintf("%s_%d", map_number, map_version).to_sym
if GameData::Encounter::DATA[key]
raise _INTL("Encounters for map '{1}' are defined twice.\r\n{2}", map_number, FileLineData.linereport)
end
i = j
elsif needdensity
needdensity = false
nums = strsplit(line,/,/)
if nums && nums.length>=3
for j in 0...EncounterTypes::EnctypeChances.length
next if !EncounterTypes::EnctypeChances[j] ||
EncounterTypes::EnctypeChances[j].length==0
next if EncounterTypes::EnctypeCompileDens[j]==0
thisenc[0][j] = nums[EncounterTypes::EnctypeCompileDens[j]-1].to_i
step_chances = []
# Construct encounter hash
encounter_hash = {
:id => key,
:map => map_number,
:version => map_version,
:step_chances => step_chances,
:types => []
}
current_type = -1
need_step_chances = true
expected_lines = 0
elsif line[/^(\d+)$/] # Map ID line (old format)
if new_format == true
raise _INTL("Can't mix old and new formats.\r\n{1}", FileLineData.linereport)
end
new_format = false
map_number = $~[1].to_i
# Add map encounter's data to records
if encounter_hash
encounter_hash[:types].each do |encounters|
next if !encounters || encounters.length == 0
encounters.each_with_index do |enc, i|
next if !enc
encounters.each_with_index do |other_enc, j|
next if i == j || !other_enc
next if enc[1] != other_enc[1] || enc[2] != other_enc[2] || enc[3] != other_enc[3]
enc[0] += other_enc[0]
encounters[j] = nil
end
end
encounters.compact!
encounters.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] }
end
else
raise _INTL("Wrong syntax for densities in encounters.txt; got \"{1}\"\r\n{2}",line,FileLineData.linereport)
GameData::Encounter::DATA[encounter_hash[:id]] = GameData::Encounter.new(encounter_hash)
end
# Raise an error if a map/version combo is used twice
key = sprintf("%s_0", map_number).to_sym
if GameData::Encounter::DATA[key]
raise _INTL("Encounters for map '{1}' are defined twice.\r\n{2}", map_number, FileLineData.linereport)
end
step_chances = EncounterTypes::Chances_Per_Step.clone
# Construct encounter hash
encounter_hash = {
:id => key,
:map => map_number,
:version => 0,
:step_chances => step_chances,
:types => []
}
current_type = -1
need_step_chances = true
elsif !encounter_hash # File began with something other than a map ID line
raise _INTL("Expected a map number, got \"{1}\" instead.\r\n{2}", line, FileLineData.linereport)
elsif line[/^(\d+)\s*,/] && !new_format # Step chances line
if !need_step_chances
raise _INTL("Encounter densities are defined twice or\r\nnot immediately for map '{1}'.\r\n{2}",
encounter_hash[:map], FileLineData.linereport)
end
need_step_chances = false
values = pbGetCsvRecord(line, line_no, [0, "vvv"])
for type in 0...step_chances.length
next if EncounterTypes::Kinds[type] == 0
step_chances[type] = values[EncounterTypes::Kinds[type] - 1]
end
i += 1
else
raise _INTL("Undefined encounter type {1}, expected one of the following:\r\n{2}\r\n{3}",line,EncounterTypes::Names.inspect,FileLineData.linereport)
# Check if line is an encounter method name or not
values = line.split(',')
values.collect! { |v| v.strip }
current_type = findIndex(EncounterTypes::Names) { |val| val == values[0] }
if current_type >= 0 # Start of a new encounter method
need_step_chances = false
if values[1] && !values[1].empty?
step_chances[current_type] = values[1].to_i
elsif new_format
step_chances[current_type] = 0
end
probabilities = EncounterTypes::Probabilities[current_type].clone
expected_lines = probabilities.length
encounter_hash[:types][current_type] = []
else
raise _INTL("Undefined encounter type \"{1}\" for map '{2}'.\r\n{2}",
line, encounter_hash[:map], FileLineData.linereport)
end
end
}
if expected_lines > 0 && !new_format
raise _INTL("Not enough encounter lines given for encounter type {1} for map '{2}' (expected {3}).\r\n{4}",
EncounterTypes::Names[current_type], encounter_hash[:map], probabilities.length, FileLineData.linereport)
end
save_data(encounters,"Data/encounters.dat")
# Add last map's encounter data to records
if encounter_hash
encounter_hash[:types].each do |encounters|
next if !encounters || encounters.length == 0
encounters.each_with_index do |enc, i|
next if !enc
encounters.each_with_index do |other_enc, j|
next if i == j || !other_enc
next if enc[1] != other_enc[1] || enc[2] != other_enc[2] || enc[3] != other_enc[3]
enc[0] += other_enc[0]
encounters[j] = nil
end
end
encounters.compact!
encounters.sort! { |a, b| (a[0] == b[0]) ? a[1].to_s <=> b[1].to_s : b[0] <=> a[0] }
end
GameData::Encounter::DATA[encounter_hash[:id]] = GameData::Encounter.new(encounter_hash)
end
# Save all data
GameData::Encounter.save
Graphics.update
end
#=============================================================================

View File

@@ -507,35 +507,29 @@ module Compiler
# Save wild encounter data to PBS file
#===============================================================================
def write_encounters
encdata = pbLoadEncountersData
return if !encdata
mapinfos = load_data("Data/MapInfos.rxdata")
File.open("PBS/encounters.txt","wb") { |f|
map_infos = load_data("Data/MapInfos.rxdata")
File.open("PBS/encounters.txt", "wb") { |f|
add_PBS_header_to_file(f)
sortedkeys = encdata.keys.sort
for i in sortedkeys
next if !encdata[i]
e = encdata[i]
mapname = ""
if mapinfos[i]
map = mapinfos[i].name
mapname = " # #{map}"
end
GameData::Encounter.each do |encounter_data|
f.write("\#-------------------------------\r\n")
f.write(sprintf("%03d%s\r\n",i,mapname))
f.write(sprintf("%d,%d,%d\r\n",e[0][EncounterTypes::Land],
e[0][EncounterTypes::Cave],e[0][EncounterTypes::Water]))
for j in 0...e[1].length
enc = e[1][j]
next if !enc
f.write(sprintf("%s\r\n",EncounterTypes::Names[j]))
for k in 0...EncounterTypes::EnctypeChances[j].length
next if !enc[k]
encentry = enc[k]
if encentry[1]==encentry[2]
f.write(sprintf(" %s,%d\r\n",encentry[0],encentry[1]))
map_name = (map_infos[encounter_data.map]) ? " # #{map_infos[encounter_data.map].name}" : ""
if encounter_data.version > 0
f.write(sprintf("[%03d,%d]%s\r\n", encounter_data.map, encounter_data.version, map_name))
else
f.write(sprintf("[%03d]%s\r\n", encounter_data.map, map_name))
end
encounter_data.types.each_with_index do |entries, type|
next if !entries || entries.length == 0
if encounter_data.step_chances[type] && encounter_data.step_chances[type] > 0
f.write(sprintf("%s,%d\r\n", EncounterTypes::Names[type], encounter_data.step_chances[type]))
else
f.write(sprintf("%s\r\n", EncounterTypes::Names[type]))
end
entries.each do |entry|
if entry[2] == entry[3]
f.write(sprintf(" %d,%s,%d\r\n", entry[0], entry[1], entry[2]))
else
f.write(sprintf(" %s,%d,%d\r\n",encentry[0],encentry[1],encentry[2]))
f.write(sprintf(" %d,%s,%d,%d\r\n", entry[0], entry[1], entry[2], entry[3]))
end
end
end

View File

@@ -215,7 +215,7 @@ module Compiler
end
def convert_files
return if !pbConfirmMessage("Do you want to check for Pokémon graphics/cries and item icons that need renaming?")
return if !pbConfirmMessage("Check for Pokémon/item/trainer files that need renaming?")
# Rename and move Pokémon sprites/icons
dest_dir = "Graphics/Pokemon/"
Dir.mkdir(dest_dir) if !FileTest.directory?(dest_dir)

View File

@@ -1,471 +1,291 @@
# See the documentation on the wiki to learn how to edit this file.
#-------------------------------
002 # Lappet Town
25,10,10
Water
TENTACOOL,14,19
MANTYKE,15,16
REMORAID,14,16
REMORAID,14,16
REMORAID,14,16
[002] # Lappet Town
Water,10
60,TENTACOOL,14,19
30,MANTYKE,15,16
10,REMORAID,14,16
OldRod
MAGIKARP,16,19
MAGIKARP,16,19
100,MAGIKARP,16,19
GoodRod
BARBOACH,17,18
SHELLDER,16,19
KRABBY,15,16
60,BARBOACH,17,18
20,KRABBY,15,16
20,SHELLDER,16,19
SuperRod
CHINCHOU,17,19
QWILFISH,16,19
CORSOLA,15,18
STARYU,15,17
STARYU,15,17
40,CHINCHOU,17,19
40,QWILFISH,16,19
15,CORSOLA,15,18
5,STARYU,15,17
#-------------------------------
005 # Route 1
25,10,10
Land
RATTATA,11,14
PIDGEY,11,14
RATTATA,11,14
PIDGEY,11,14
RATTATA,11,14
PIDGEY,11,14
RATTATA,11,13
PIDGEY,11,13
RATTATA,11,13
PIDGEY,11,13
RATTATA,14
PIDGEY,14
LandNight
RATTATA,10,14
HOOTHOOT,10,13
RATTATA,10,14
HOOTHOOT,10,13
SPINARAK,8,12
SPINARAK,8,12
RATTATA,10,14
HOOTHOOT,10,14
RATTATA,10,14
HOOTHOOT,10,14
RATTATA,15
HOOTHOOT,14
[005] # Route 1
Land,25
40,PIDGEY,11,14
40,RATTATA,11,14
9,PIDGEY,11,13
9,RATTATA,11,13
1,PIDGEY,14
1,RATTATA,14
LandNight,25
39,RATTATA,10,14
30,HOOTHOOT,10,13
20,SPINARAK,8,12
9,HOOTHOOT,10,14
1,HOOTHOOT,14
1,RATTATA,15
#-------------------------------
021 # Route 2
25,10,10
Land
RATTATA,12,15
RATTATA,12,15
RATTATA,12,15
POOCHYENA,11,15
POOCHYENA,11,15
POOCHYENA,11,15
SHINX,10,12
SHINX,10,12
SHINX,10,11
SHINX,10,11
SHINX,10,11
SHINX,10,11
Water
MAGIKARP,7,10
GOLDEEN,11,14
STARYU,12,15
STARYU,12,15
STARYU,12,15
[021] # Route 2
Land,25
50,RATTATA,12,15
30,POOCHYENA,11,15
10,SHINX,10,12
10,SHINX,10,11
Water,10
60,MAGIKARP,7,10
30,GOLDEEN,11,14
10,STARYU,12,15
OldRod
MAGIKARP,7,10
MAGIKARP,9,15
70,MAGIKARP,7,10
30,MAGIKARP,9,15
GoodRod
GOLDEEN,12,14
FINNEON,12,15
MAGIKARP,12,17
60,GOLDEEN,12,14
20,FINNEON,12,15
20,MAGIKARP,12,17
SuperRod
GOLDEEN,12,14
FINNEON,12,15
STARYU,12,15
STARYU,14,17
STARYU,14,17
40,FINNEON,12,15
40,GOLDEEN,12,14
15,STARYU,12,15
5,STARYU,14,17
HeadbuttLow
PINECO,11,13
LEDYBA,6,8
PINECO,11,13
SPINARAK,9,12
LEDYBA,6,8
SPINARAK,9,12
SPINARAK,9,12
MUNCHLAX,11,14
50,PINECO,11,13
30,LEDYBA,6,8
19,SPINARAK,9,12
1,MUNCHLAX,11,14
HeadbuttHigh
PINECO,11,13
WURMPLE,6,8
PINECO,11,13
SPINARAK,9,12
WURMPLE,6,8
SPINARAK,9,12
SPINARAK,9,12
SPINARAK,9,12
50,PINECO,11,13
30,WURMPLE,6,8
20,SPINARAK,9,12
#-------------------------------
028 # Natural Park
25,10,10
Land
CATERPIE,10
WEEDLE,10
PIDGEY,10,14
PIDGEY,12,14
SUNKERN,12
SUNKERN,12
METAPOD,10
KAKUNA,10
PIDGEY,10,14
PIDGEY,12,14
PIDGEY,10,14
PIDGEY,12,14
LandMorning
CATERPIE,10,12
WEEDLE,10,12
PIDGEY,10,14
PIDGEY,10,14
METAPOD,10
KAKUNA,10
METAPOD,10
KAKUNA,10
CATERPIE,10,12
WEEDLE,10,12
CATERPIE,10,12
WEEDLE,10,12
LandNight
HOOTHOOT,10,14
SPINARAK,10,15
HOOTHOOT,10,14
SPINARAK,10,15
PINECO,9,13
PINECO,9,13
NATU,12,14
NATU,12,14
DROWZEE,9,15
DROWZEE,9,15
DROWZEE,9,15
DROWZEE,9,15
BugContest
CATERPIE,7,18
WEEDLE,7,18
METAPOD,9,18
KAKUNA,9,18
PARAS,10,17
VENONAT,10,16
BUTTERFREE,12,15
BEEDRILL,12,15
SCYTHER,13,14
PINSIR,13,14
SCYTHER,13,14
PINSIR,13,14
[028] # Natural Park
Land,25
20,CATERPIE,10
20,SUNKERN,12
20,WEEDLE,10
15,PIDGEY,10,14
15,PIDGEY,12,14
5,KAKUNA,10
5,METAPOD,10
LandNight,25
30,HOOTHOOT,10,14
30,SPINARAK,10,15
20,PINECO,9,13
10,DROWZEE,9,15
10,NATU,12,14
LandMorning,25
25,CATERPIE,10,12
25,WEEDLE,10,12
20,PIDGEY,10,14
15,KAKUNA,10
15,METAPOD,10
BugContest,25
20,CATERPIE,7,18
20,WEEDLE,7,18
10,KAKUNA,9,18
10,METAPOD,9,18
10,PARAS,10,17
10,VENONAT,10,16
5,BEEDRILL,12,15
5,BUTTERFREE,12,15
5,PINSIR,13,14
5,SCYTHER,13,14
#-------------------------------
031 # Route 3
25,10,10
Land
NIDORANfE,12,15
NIDORANmA,12,15
NIDORANfE,12,15
NIDORANmA,12,15
PIKACHU,14,17
PIKACHU,14,17
PONYTA,13,15
PONYTA,13,15
EEVEE,15
EEVEE,15
EEVEE,15
EEVEE,15
Water
SURSKIT,13,14
LOTAD,14
LOTAD,14
LOTAD,15
LOTAD,15
RockSmash
NOSEPASS,13,14
GEODUDE,12,15
GEODUDE,12,15
GEODUDE,12,15
GEODUDE,12,15
[031] # Route 3
Land,25
30,NIDORANfE,12,15
30,NIDORANmA,12,15
20,PIKACHU,14,17
10,EEVEE,15
10,PONYTA,13,15
Water,10
60,SURSKIT,13,14
35,LOTAD,14
5,LOTAD,15
OldRod
MAGIKARP,6,11
MAGIKARP,10,17
70,MAGIKARP,6,11
30,MAGIKARP,10,17
GoodRod
POLIWAG,12,15
PSYDUCK,11,14
WOOPER,13,17
60,POLIWAG,12,15
20,PSYDUCK,11,14
20,WOOPER,13,17
SuperRod
CHINCHOU,11,12
REMORAID,12,14
LUVDISC,10,16
LUVDISC,10,16
LUVDISC,10,16
40,CHINCHOU,11,12
40,REMORAID,12,14
20,LUVDISC,10,16
RockSmash
60,NOSEPASS,13,14
40,GEODUDE,12,15
HeadbuttLow
PINECO,14,17
COMBEE,15,17
PINECO,14,16
HERACROSS,16,18
COMBEE,15,16
HERACROSS,16,17
HERACROSS,16,17
MUNCHLAX,13,18
30,PINECO,14,17
25,COMBEE,15,17
20,PINECO,14,16
10,HERACROSS,16,18
9,HERACROSS,16,17
5,COMBEE,15,16
1,MUNCHLAX,13,18
HeadbuttHigh
SEEDOT,14,17
SHROOMISH,14,17
SEEDOT,14,17
BURMY,12,15
SHROOMISH,14,17
BURMY,12,15
BURMY,12,15
BURMY,12,15
50,SEEDOT,14,17
30,SHROOMISH,14,17
20,BURMY,12,15
#-------------------------------
034 # Ice Cave
25,10,10
Cave
SWINUB,16,18
SWINUB,16,18
SNEASEL,14,16
SNEASEL,14,16
SNORUNT,12,15
SNORUNT,12,15
SNOVER,14
SNOVER,14
SMOOCHUM,11,14
SMOOCHUM,11,14
SMOOCHUM,11,14
SMOOCHUM,11,14
[034] # Ice Cave
Cave,10
40,SWINUB,16,18
20,SNEASEL,14,16
20,SNORUNT,12,15
10,SMOOCHUM,11,14
10,SNOVER,14
#-------------------------------
039 # Route 4
25,10,10
Land
SHELLOS_1,12,15
SHELLOS_1,12,15
SHELLOS_1,12,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
MURKROW,12,14
MURKROW,12,14
MURKROW,12,14
MURKROW,12,14
[039] # Route 4
Land,25
50,SHELLOS_1,12,15
40,GRIMER,13,15
10,MURKROW,12,14
#-------------------------------
041 # Route 5
25,10,10
Land
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
SPEAROW,13,16
SPEAROW,13,16
SPEAROW,13,16
SPEAROW,13,16
SPEAROW,13,16
SLUGMA,13,14
SLUGMA,13,14
SLUGMA,13,14
SLUGMA,13,14
[041] # Route 5
Land,25
50,GRIMER,13,15
40,SPEAROW,13,16
10,SLUGMA,13,14
#-------------------------------
044 # Route 6
25,10,10
Land
SHELLOS_1,12,15
SHELLOS_1,12,15
SHELLOS_1,12,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
GRIMER,13,15
MURKROW,12,14
MURKROW,12,14
MURKROW,12,14
MURKROW,12,14
[044] # Route 6
Land,25
50,SHELLOS_1,12,15
40,GRIMER,13,15
10,MURKROW,12,14
#-------------------------------
047 # Route 7
25,10,10
Land
SHELLOS,12,15
SHELLOS,12,15
SHELLOS,12,15
BIDOOF,14,17
BIDOOF,14,17
BIDOOF,14,17
MURKROW,12,14
MURKROW,12,14
WURMPLE,9,12
WURMPLE,9,12
WURMPLE,9,12
WURMPLE,9,12
[047] # Route 7
Land,25
50,SHELLOS,12,15
30,BIDOOF,14,17
10,MURKROW,12,14
10,WURMPLE,9,12
RockSmash
NOSEPASS,13,14
NOSEPASS,13,14
GEODUDE,12,15
GEODUDE,12,15
GEODUDE,12,15
90,NOSEPASS,13,14
10,GEODUDE,12,15
#-------------------------------
049 # Rock Cave
25,10,10
Cave
NOSEPASS,14,15
NOSEPASS,13,14
MAGNETON,14,17
MAGNETON,14,17
MAGNETON,14,16
MAGNETON,14,16
GEODUDE,13,15
GEODUDE,13,15
MAWILE,14,16
MAWILE,14,16
MAWILE,14,16
MAWILE,14,16
[049] # Rock Cave
Cave,10
20,MAGNETON,14,16
20,MAGNETON,14,17
20,NOSEPASS,14,15
20,NOSEPASS,13,14
10,GEODUDE,13,15
10,MAWILE,14,16
#-------------------------------
050 # Rock Cave
25,10,10
Cave
NOSEPASS,14,15
NOSEPASS,13,14
MAGNETON,14,17
MAGNETON,14,17
MAGNETON,14,16
MAGNETON,14,16
GEODUDE,13,15
GEODUDE,13,15
BURMY,14,16
BURMY,14,16
BURMY,14,16
BURMY,14,16
[050] # Rock Cave
Cave,10
20,MAGNETON,14,16
20,MAGNETON,14,17
20,NOSEPASS,14,15
20,NOSEPASS,13,14
10,BURMY,14,16
10,GEODUDE,13,15
#-------------------------------
051 # Dungeon
25,10,10
Cave
PICHU,1
CLEFFA,1
IGGLYBUFF,1
IGGLYBUFF,1
CHINGLING,1
CHINGLING,1
RIOLU,1
RIOLU,1
TYROGUE,1
TYROGUE,1
TYROGUE,1
TYROGUE,1
[051] # Dungeon
Cave,10
20,CHINGLING,1
20,CLEFFA,1
20,IGGLYBUFF,1
20,PICHU,1
10,RIOLU,1
10,TYROGUE,1
#-------------------------------
066 # Safari Zone
25,10,10
Land
NIDORANfE,15,16
NIDORANmA,15,16
DODUO,13,15
DODUO,13,15
ABRA,12,15
ABRA,12,15
TANGELA,14,16
TANGELA,14,16
HOPPIP,13,17
HOPPIP,13,17
HOPPIP,13,17
HOPPIP,13,17
[066] # Safari Zone
Land,25
20,ABRA,12,15
20,DODUO,13,15
20,NIDORANfE,15,16
20,NIDORANmA,15,16
10,HOPPIP,13,17
10,TANGELA,14,16
#-------------------------------
068 # Safari Zone
25,10,10
Land
RHYHORN,16,18
EXEGGCUTE,15,18
VENONAT,15,17
VENONAT,15,18
AIPOM,14,17
GIRAFARIG,16,17
TAUROS,15,16
HERACROSS,15,17
SCYTHER,16
PINSIR,16
KANGASKHAN,19
CHANSEY,17
Water
PSYDUCK,16,18
MARILL,15,18
SLOWPOKE,14,16
BUIZEL,15,17
BUIZEL,15,17
[068] # Safari Zone
Land,25
20,EXEGGCUTE,15,18
20,RHYHORN,16,18
10,AIPOM,14,17
10,GIRAFARIG,16,17
10,VENONAT,15,17
10,VENONAT,15,18
5,HERACROSS,15,17
5,TAUROS,15,16
4,PINSIR,16
4,SCYTHER,16
1,CHANSEY,17
1,KANGASKHAN,19
Water,10
60,PSYDUCK,16,18
30,MARILL,15,18
5,BUIZEL,15,17
5,SLOWPOKE,14,16
OldRod
MAGIKARP,17,21
MAGIKARP,17,20
70,MAGIKARP,17,21
30,MAGIKARP,17,20
GoodRod
MAGIKARP,16,20
FEEBAS,16,20
POLIWAG,17,18
60,MAGIKARP,16,20
20,FEEBAS,16,20
20,POLIWAG,17,18
SuperRod
GOLDEEN,16,18
REMORAID,17,19
CARVANHA,16,17
FINNEON,15,18
DRATINI,17
40,GOLDEEN,16,18
40,REMORAID,17,19
15,CARVANHA,16,17
4,FINNEON,15,18
1,DRATINI,17
#-------------------------------
069 # Route 8
25,10,10
Land
ODDISH,15,17
MAREEP,16,18
LOTAD,15,17
LOTAD,15,18
DITTO,15,17
DITTO,16,18
BONSLY,14,17
BONSLY,14,16
BONSLY,14,16
BONSLY,14,16
BONSLY,15,16
BONSLY,15
Water
TENTACOOL,14,19
MANTYKE,15,16
REMORAID,14,16
REMORAID,14,16
REMORAID,14,16
[069] # Route 8
Land,25
20,MAREEP,16,18
20,ODDISH,15,17
13,BONSLY,14,16
10,DITTO,15,17
10,DITTO,16,18
10,LOTAD,15,18
10,LOTAD,15,17
5,BONSLY,14,17
1,BONSLY,15,16
1,BONSLY,15
Water,10
60,TENTACOOL,14,19
30,MANTYKE,15,16
10,REMORAID,14,16
OldRod
MAGIKARP,16,19
MAGIKARP,16,19
100,MAGIKARP,16,19
GoodRod
BARBOACH,17,18
SHELLDER,16,19
KRABBY,15,16
60,BARBOACH,17,18
20,KRABBY,15,16
20,SHELLDER,16,19
SuperRod
CHINCHOU,17,19
QWILFISH,16,19
CORSOLA,15,18
STARYU,15,17
STARYU,15,17
40,CHINCHOU,17,19
40,QWILFISH,16,19
15,CORSOLA,15,18
5,STARYU,15,17
#-------------------------------
070 # Underwater
25,10,10
Land
CLAMPERL,18,20
SHELLDER,18,20
CLAMPERL,18,19
SHELLDER,18,19
CHINCHOU,17,21
CHINCHOU,17,21
CORSOLA,17,20
CORSOLA,17,20
RELICANTH,16,19
RELICANTH,16,19
RELICANTH,16,19
RELICANTH,16,19
[070] # Underwater
Land,25
20,CHINCHOU,17,21
20,CLAMPERL,18,20
20,SHELLDER,18,20
10,CLAMPERL,18,19
10,CORSOLA,17,20
10,RELICANTH,16,19
10,SHELLDER,18,19
#-------------------------------
075 # Tiall Region
25,10,10
Land
RATTATA_1,11,14
GEODUDE_1,11,14
SANDSHREW_1,11,14
VULPIX_1,11,14
DIGLETT_1,11,14
MEOWTH_1,11,14
PIKACHU,11,14
PIKACHU,11,14
CUBONE,11,14
CUBONE,11,14
CUBONE,11,14
CUBONE,11,14
[075] # Tiall Region
Land,25
20,GEODUDE_1,11,14
20,RATTATA_1,11,14
10,CUBONE,11,14
10,DIGLETT_1,11,14
10,MEOWTH_1,11,14
10,PIKACHU,11,14
10,SANDSHREW_1,11,14
10,VULPIX_1,11,14