diff --git a/Data/Map001.rxdata b/Data/Map001.rxdata index e24d326..6b91d88 100644 Binary files a/Data/Map001.rxdata and b/Data/Map001.rxdata differ diff --git a/Data/Map012.rxdata b/Data/Map012.rxdata index 15929c2..ba2f0f2 100644 Binary files a/Data/Map012.rxdata and b/Data/Map012.rxdata differ diff --git a/Data/Map015.rxdata b/Data/Map015.rxdata index daf1078..64741c2 100644 Binary files a/Data/Map015.rxdata and b/Data/Map015.rxdata differ diff --git a/Data/Map022.rxdata b/Data/Map022.rxdata index f75afe2..574f053 100644 Binary files a/Data/Map022.rxdata and b/Data/Map022.rxdata differ diff --git a/Data/Map025.rxdata b/Data/Map025.rxdata index a05c23f..7b05805 100644 Binary files a/Data/Map025.rxdata and b/Data/Map025.rxdata differ diff --git a/Data/Map026.rxdata b/Data/Map026.rxdata index bc960ca..0c54074 100644 Binary files a/Data/Map026.rxdata and b/Data/Map026.rxdata differ diff --git a/Data/Map027.rxdata b/Data/Map027.rxdata index afaa74c..1d977c6 100644 Binary files a/Data/Map027.rxdata and b/Data/Map027.rxdata differ diff --git a/Data/Map028.rxdata b/Data/Map028.rxdata new file mode 100644 index 0000000..88f056b Binary files /dev/null and b/Data/Map028.rxdata differ diff --git a/Data/Map029.rxdata b/Data/Map029.rxdata new file mode 100644 index 0000000..e7fc325 Binary files /dev/null and b/Data/Map029.rxdata differ diff --git a/Data/Map030.rxdata b/Data/Map030.rxdata new file mode 100644 index 0000000..e06755b Binary files /dev/null and b/Data/Map030.rxdata differ diff --git a/Data/Map031.rxdata b/Data/Map031.rxdata new file mode 100644 index 0000000..5051117 Binary files /dev/null and b/Data/Map031.rxdata differ diff --git a/Data/Map032.rxdata b/Data/Map032.rxdata new file mode 100644 index 0000000..3291b2c Binary files /dev/null and b/Data/Map032.rxdata differ diff --git a/Data/Map033.rxdata b/Data/Map033.rxdata new file mode 100644 index 0000000..4792c83 Binary files /dev/null and b/Data/Map033.rxdata differ diff --git a/Data/Map034.rxdata b/Data/Map034.rxdata new file mode 100644 index 0000000..4a1249e Binary files /dev/null and b/Data/Map034.rxdata differ diff --git a/Data/Map035.rxdata b/Data/Map035.rxdata new file mode 100644 index 0000000..7f16709 Binary files /dev/null and b/Data/Map035.rxdata differ diff --git a/Data/Map036.rxdata b/Data/Map036.rxdata new file mode 100644 index 0000000..d115607 Binary files /dev/null and b/Data/Map036.rxdata differ diff --git a/Data/Map037.rxdata b/Data/Map037.rxdata new file mode 100644 index 0000000..fbe5e97 Binary files /dev/null and b/Data/Map037.rxdata differ diff --git a/Data/Map038.rxdata b/Data/Map038.rxdata new file mode 100644 index 0000000..c1c6603 Binary files /dev/null and b/Data/Map038.rxdata differ diff --git a/Data/Map039.rxdata b/Data/Map039.rxdata new file mode 100644 index 0000000..232437c Binary files /dev/null and b/Data/Map039.rxdata differ diff --git a/Data/MapInfos.rxdata b/Data/MapInfos.rxdata index ee38fca..b73f44f 100644 Binary files a/Data/MapInfos.rxdata and b/Data/MapInfos.rxdata differ diff --git a/Data/PluginScripts.rxdata b/Data/PluginScripts.rxdata index d4a1a9b..1f57805 100644 Binary files a/Data/PluginScripts.rxdata and b/Data/PluginScripts.rxdata differ diff --git a/Data/System.rxdata b/Data/System.rxdata index 4001123..3d1b3c9 100644 Binary files a/Data/System.rxdata and b/Data/System.rxdata differ diff --git a/Data/Tilesets.rxdata b/Data/Tilesets.rxdata index 7cbb84d..4385d7d 100644 Binary files a/Data/Tilesets.rxdata and b/Data/Tilesets.rxdata differ diff --git a/Data/map_connections.dat b/Data/map_connections.dat index 227afa3..23a1add 100644 Binary files a/Data/map_connections.dat and b/Data/map_connections.dat differ diff --git a/Data/map_metadata.dat b/Data/map_metadata.dat index a83236d..cce3d96 100644 Binary files a/Data/map_metadata.dat and b/Data/map_metadata.dat differ diff --git a/Data/messages_game.dat b/Data/messages_game.dat index 4f6bd50..cdef912 100644 Binary files a/Data/messages_game.dat and b/Data/messages_game.dat differ diff --git a/Data/town_map.dat b/Data/town_map.dat index c785e4e..ee378d8 100644 Binary files a/Data/town_map.dat and b/Data/town_map.dat differ diff --git a/Graphics/Autotiles/HoennSand shore1.png b/Graphics/Autotiles/HoennSand shore1.png new file mode 100644 index 0000000..95b1098 Binary files /dev/null and b/Graphics/Autotiles/HoennSand shore1.png differ diff --git a/Graphics/Autotiles/Sand Water Edge-test.png b/Graphics/Autotiles/Sand Water Edge-test.png new file mode 100644 index 0000000..feab4b5 Binary files /dev/null and b/Graphics/Autotiles/Sand Water Edge-test.png differ diff --git a/Graphics/Characters/Hoenn Object Fountain.png b/Graphics/Characters/Hoenn Object Fountain.png new file mode 100644 index 0000000..3cd4448 Binary files /dev/null and b/Graphics/Characters/Hoenn Object Fountain.png differ diff --git a/Graphics/Characters/HoennObjectTree.png b/Graphics/Characters/HoennObjectTree.png new file mode 100644 index 0000000..61c17d9 Binary files /dev/null and b/Graphics/Characters/HoennObjectTree.png differ diff --git a/Graphics/Characters/MSteps/stepsDown.png b/Graphics/Characters/MSteps/stepsDown.png new file mode 100644 index 0000000..4416fb4 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsDown.png differ diff --git a/Graphics/Characters/MSteps/stepsDownBike.png b/Graphics/Characters/MSteps/stepsDownBike.png new file mode 100644 index 0000000..b5bf0a8 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsDownBike.png differ diff --git a/Graphics/Characters/MSteps/stepsLeft.png b/Graphics/Characters/MSteps/stepsLeft.png new file mode 100644 index 0000000..4a2dc2c Binary files /dev/null and b/Graphics/Characters/MSteps/stepsLeft.png differ diff --git a/Graphics/Characters/MSteps/stepsLeftBike.png b/Graphics/Characters/MSteps/stepsLeftBike.png new file mode 100644 index 0000000..73399d5 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsLeftBike.png differ diff --git a/Graphics/Characters/MSteps/stepsRight.png b/Graphics/Characters/MSteps/stepsRight.png new file mode 100644 index 0000000..1c24d9a Binary files /dev/null and b/Graphics/Characters/MSteps/stepsRight.png differ diff --git a/Graphics/Characters/MSteps/stepsRightBike.png b/Graphics/Characters/MSteps/stepsRightBike.png new file mode 100644 index 0000000..73399d5 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsRightBike.png differ diff --git a/Graphics/Characters/MSteps/stepsUp.png b/Graphics/Characters/MSteps/stepsUp.png new file mode 100644 index 0000000..ca92509 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsUp.png differ diff --git a/Graphics/Characters/MSteps/stepsUpBike.png b/Graphics/Characters/MSteps/stepsUpBike.png new file mode 100644 index 0000000..b5bf0a8 Binary files /dev/null and b/Graphics/Characters/MSteps/stepsUpBike.png differ diff --git a/Graphics/Tilesets/Hoenn_Inside.png b/Graphics/Tilesets/Hoenn_Inside.png index bfdeca4..ccf4ff4 100644 Binary files a/Graphics/Tilesets/Hoenn_Inside.png and b/Graphics/Tilesets/Hoenn_Inside.png differ diff --git a/Graphics/Tilesets/Hoenn_Outside.png b/Graphics/Tilesets/Hoenn_Outside.png index 8cc2881..1fcf378 100644 Binary files a/Graphics/Tilesets/Hoenn_Outside.png and b/Graphics/Tilesets/Hoenn_Outside.png differ diff --git a/PBS/map_connections.txt b/PBS/map_connections.txt index 0a16102..7239b29 100644 --- a/PBS/map_connections.txt +++ b/PBS/map_connections.txt @@ -1,29 +1,47 @@ # See the documentation on the wiki to learn how to edit this file. #------------------------------- +# Route 101 (6) - Route 104 (33) +6,North,0,33,South,112 +# Rt101-102Tree (14) - Route 104 (33) +14,North,0,33,South,70 +# Petalburg City (15) - Route 104 (33) +15,West,0,33,East,50 +# Rt101-102Tree3 (17) - Route 104 (33) +17,West,0,33,East,80 +# Rt101-102Tree4 (18) - Route 104 (33) +18,West,0,33,East,34 +# Rustboro City (37) - Route 104 (33) +37,South,0,33,North,0 # Littleroot Town (2) - Route 101 (6) 2,North,0,6,South,0 -# Rt101-102Tree (14) - Littleroot Town (2) -14,East,20,2,West,0 -# Rt101-102Tree2 (16) - Littleroot Town (2) -16,East,60,2,West,0 -# Route 101 (6) - Route 102 (12) -6,North,0,12,South,42 # Rt101-102Tree (14) - Route 101 (6) 14,East,0,6,West,0 # Oldale Town (7) - Route 101 (6) 7,South,0,6,North,8 +# Route 102 (12) - Route 101 (6) +12,South,42,6,North,0 # Petalburg City (15) - Route 101 (6) 15,South,72,6,North,0 # Rt101-102Tree2 (16) - Route 101 (6) 16,East,40,6,West,0 -# Oldale Town (7) - Route 102 (12) -7,West,0,12,East,5 +# Rt101-102Tree (14) - Littleroot Town (2) +14,East,20,2,West,0 +# Rt101-102Tree2 (16) - Littleroot Town (2) +16,East,60,2,West,0 # Oldale Town (7) - Rt101-102Tree (14) 7,South,0,14,North,50 +# Route 102 (12) - Rt101-102Tree (14) +12,South,0,14,North,0 +# Petalburg City (15) - Rt101-102Tree (14) +15,East,30,14,West,0 +# Rt101-102Tree3 (17) - Rt101-102Tree (14) +17,East,0,14,West,0 +# Rt101-102Tree4 (18) - Rt101-102Tree (14) +18,East,46,14,West,0 +# Route 102 (12) - Oldale Town (7) +12,East,5,7,West,0 # Rt101-102Tree3 (17) - Oldale Town (7) 17,North,80,7,South,0 -# Rt101-102Tree (14) - Route 102 (12) -14,North,0,12,South,0 # Petalburg City (15) - Route 102 (12) 15,East,5,12,West,0 # Rt101-102Tree3 (17) - Route 102 (12) @@ -32,21 +50,21 @@ 16,South,0,12,North,0 # Rt101-102Tree4 (18) - Route 102 (12) 18,East,21,12,West,0 -# Route 102 (12) - Rt101-102Tree5 (19) -12,0,70,19,19,0 -# Petalburg City (15) - Rt101-102Tree (14) -15,East,30,14,West,0 -# Rt101-102Tree3 (17) - Rt101-102Tree (14) -17,East,0,14,West,0 -# Rt101-102Tree4 (18) - Rt101-102Tree (14) -18,East,46,14,West,0 # Rt101-102Tree3 (17) - Petalburg City (15) 17,North,0,15,South,0 # Rt101-102Tree2 (16) - Petalburg City (15) 16,West,10,15,East,0 # Rt101-102Tree4 (18) - Petalburg City (15) 18,South,0,15,North,0 +# Rustboro City (37) - Petalburg City (15) +37,East,110,15,West,0 # Rt101-102Tree2 (16) - Rt101-102Tree3 (17) 16,West,40,17,East,0 +# Rustboro City (37) - Rt101-102Tree3 (17) +37,East,140,17,West,0 # Rt101-102Tree4 (18) - Rt101-102Tree2 (16) 18,East,6,16,West,0 +# Rustboro City (37) - Rt101-102Tree4 (18) +37,East,94,18,West,0 +# Route 104 (33) - Rt101-102Tree5 (19) +33,51,125,19,0,0 diff --git a/PBS/map_metadata.txt b/PBS/map_metadata.txt index 46912ac..f2713b1 100644 --- a/PBS/map_metadata.txt +++ b/PBS/map_metadata.txt @@ -64,4 +64,13 @@ HealingSpot = 15,20,16 MapPosition = 2,2,11 #------------------------------- [020] # Petalburg Poké Center +Name = Petalburg Poké Center MapPosition = 2,2,11 +#------------------------------- +[037] # Rustboro City +Name = Rustboro City +Outdoor = true +ShowArea = true +Bicycle = true +HealingSpot = 37,16,38 +MapPosition = 2,1,8 diff --git a/PBS/pokemon_uranium.txt b/PBS/pokemon_uranium.txt index a42e8a7..3ed4ea1 100644 --- a/PBS/pokemon_uranium.txt +++ b/PBS/pokemon_uranium.txt @@ -1,25 +1,25 @@ -[RAPTORCH] -Name = Raptorch -Types = FIRE,GROUND -BaseStats = 40,55,45,65,50,70 -GenderRatio = FemaleOneEighth -GrowthRate = Medium -BaseExp = 65 -EVs = SPEED,1 -CatchRate = 45 -Happiness = 70 -Abilities = FLAMEBODY -HiddenAbilities = BLAZE -Moves = 1,SCRATCH,1,GROWL,5,EMBER,13,MUDSLAP,19,FLAMEWHEEL -# TutorMoves = -# EggMoves = -EggGroups = Monster,Dragon -HatchSteps = 5120 -Height = 0.8 -Weight = 10.5 -Color = Black -Shape = Bipedal -Habitat = Rare -# Category = -Pokedex = Raptorch are energetic Pokémon that require constant attention, or they will start setting their surroundings on fire. -# Evolutions = IVYSAUR,Level,16 +[RAPTORCH] +Name = Raptorch +Types = FIRE,GROUND +BaseStats = 40,55,45,65,50,70 +GenderRatio = FemaleOneEighth +GrowthRate = Medium +BaseExp = 65 +EVs = SPEED,1 +CatchRate = 45 +Happiness = 70 +Abilities = FLAMEBODY +HiddenAbilities = BLAZE +Moves = 1,SCRATCH,1,GROWL,5,EMBER,13,MUDSLAP,19,FLAMEWHEEL +# TutorMoves = +# EggMoves = +EggGroups = Monster,Dragon +HatchSteps = 5120 +Height = 0.8 +Weight = 10.5 +Color = Black +Shape = Bipedal +Habitat = Rare +# Category = +Pokedex = Raptorch are energetic Pokémon that require constant attention, or they will start setting their surroundings on fire. +# Evolutions = IVYSAUR,Level,16 diff --git a/PBS/town_map.txt b/PBS/town_map.txt index fe8c426..4c6c1f0 100644 --- a/PBS/town_map.txt +++ b/PBS/town_map.txt @@ -44,3 +44,9 @@ Point = 5,11,Oldale Town,,7,6,17, Point = 4,11,Route 102,,,,, Point = 3,11,Route 102,,,,, Point = 2,11,Petalburg City,Petalburg Gym,15,20,17, +Point = 1,11,Route 104,,,,, +Point = 1,10,Route 104,,,,, +Point = 1,9,Route 104,,,,, +Point = 1,8,Rustboro City,Rustboro Gym,37,16,39, +Point = 1,7,Rustboro City,Rustboro Gym,37,16,39, + diff --git a/Plugins/Marin's Footprints/MFootprints.rb b/Plugins/Marin's Footprints/MFootprints.rb new file mode 100644 index 0000000..d11abb2 --- /dev/null +++ b/Plugins/Marin's Footprints/MFootprints.rb @@ -0,0 +1,181 @@ +#==============================================================================# +# Footprints # +# by Marin # +#==============================================================================# +# If an event walks on a tile with terrain tag 3 (Sand), it will produce # +# visual footprints. Works with Following Pokémon. # +#==============================================================================# +# Please give credit when using this. # +#==============================================================================# + +class Sprite_Character + # This is the amount the opacity is lowered per frame. It needs to go 256 -> 0, + # which means setting this to 4 would make each step pair last 64 frames (~1.5s) + FADE_OUT_SPEED = 2 + + # Set here the terrain tag for footprints, 3 is sand + TERRAIN_FOOT = 3 + + # A configurable X/Y offset for the step sprites, in case they don't align + # nicely with the player's graphic. + WALK_X_OFFSET = 0 + WALK_Y_OFFSET = 0 + + # A configurable X/Y offset for bike print sprites, in case they don't align + # nicely with the player's graphic. + BIKE_X_OFFSET = -8 + BIKE_Y_OFFSET = 0 + + # If true, both the player AND the follower will create footprints. + # If false, only the follower will create footprints. + DUPLICATE_FOOTSTEPS_WITH_FOLLOWER = false + + # If the event name includes any of these strings, it will not produce + # footprints. + EVENTNAME_MAY_NOT_INCLUDE = [ + "NoFootprint", + ".noprint", + ".nostep", + ".nofootprint", + ".nofootstep" + ] + + # If the filename (graphic) includes any of these strings, it will not produce + # footprints. Works on top of the event name list. + FILENAME_MAY_NOT_INCLUDE = [ + + ] + + attr_accessor :steps + attr_reader :follower + + alias footsteps_initialize initialize + def initialize(*args) + footsteps_initialize(*args) + if $PokemonGlobal && $PokemonGlobal.respond_to?(:dependentEvents) && + $PokemonGlobal.dependentEvents && $PokemonGlobal.dependentEvents.respond_to?(:realEvents) && + $PokemonGlobal.dependentEvents.realEvents.is_a?(Array) && + $PokemonGlobal.dependentEvents.realEvents.include?(@character) + @follower = true + end + @steps = [] + end + + alias footsteps_dispose dispose + def dispose + @steps.each { |e| e[0].dispose } + footsteps_dispose + end + + alias footsteps_update update + def update + footsteps_update + @old_x ||= @character.x + @old_y ||= @character.y + if (@character.x != @old_x || @character.y != @old_y) && !["", "nil"].include?(@character.character_name) + if @character == $game_player && $PokemonGlobal.dependentEvents && + $PokemonGlobal.dependentEvents.respond_to?(:realEvents) && + $PokemonGlobal.dependentEvents.realEvents.select { |e| !["", "nil"].include?(e.character_name) }.size > 0 && + !DUPLICATE_FOOTSTEPS_WITH_FOLLOWER + if !EVENTNAME_MAY_NOT_INCLUDE.include?($PokemonGlobal.dependentEvents.realEvents[0].name) && + !FILENAME_MAY_NOT_INCLUDE.include?($PokemonGlobal.dependentEvents.realEvents[0].character_name) + make_steps = false + else + make_steps = true + end + elsif (!@character.respond_to?(:name) || !EVENTNAME_MAY_NOT_INCLUDE.include?(@character.name)) && + !FILENAME_MAY_NOT_INCLUDE.include?(@character.character_name) + tilesetid = @character.map.instance_eval { @map.tileset_id } + make_steps = [2,1,0].any? do |e| + tile_id = @character.map.data[@old_x, @old_y, e] + next false if tile_id.nil? + next $data_tilesets[tilesetid].terrain_tags[tile_id] == TERRAIN_FOOT + end + end + if make_steps + fstep = Sprite.new(self.viewport) + fstep.z = 0 + dirs = [nil,"DownLeft","Down","DownRight","Left","Still","Right","UpLeft", + "Up", "UpRight"] + if @character == $game_player && $PokemonGlobal.bicycle + fstep.bmp("Graphics/Characters/MSteps/steps#{dirs[@character.direction]}Bike") + else + fstep.bmp("Graphics/Characters/MSteps/steps#{dirs[@character.direction]}") + end + @steps ||= [] + if @character == $game_player && $PokemonGlobal.bicycle + x = BIKE_X_OFFSET + y = BIKE_Y_OFFSET + else + x = WALK_X_OFFSET + y = WALK_Y_OFFSET + end + @steps << [fstep, @character.map, @old_x + x / Game_Map::TILE_WIDTH.to_f, @old_y + y / Game_Map::TILE_HEIGHT.to_f] + end + end + @old_x = @character.x + @old_y = @character.y + update_footsteps + end + + def update_footsteps + if @steps + for i in 0...@steps.size + next unless @steps[i] + sprite, map, x, y, ox = @steps[i] + sprite.x = -map.display_x / Game_Map::X_SUBPIXELS + x * Game_Map::TILE_WIDTH + sprite.y = -map.display_y / Game_Map::Y_SUBPIXELS + (y + 1) * Game_Map::TILE_HEIGHT + sprite.y -= Game_Map::TILE_HEIGHT + sprite.opacity -= FADE_OUT_SPEED + if sprite.opacity <= 0 + sprite.dispose + @steps[i] = nil + end + end + @steps.compact! + end + end +end + +class DependentEventSprites + attr_accessor :sprites + + def refresh + steps = [] + for sprite in @sprites + steps << sprite.steps + if sprite.follower + $FollowerSteps = sprite.steps + end + sprite.steps = [] + sprite.dispose + end + @sprites.clear + $PokemonGlobal.dependentEvents.eachEvent do |event, data| + if data[0] == @map.map_id # Check original map + #@map.events[data[1]].erase + end + if data[2] == @map.map_id # Check current map + spr = Sprite_Character.new(@viewport, event) + if spr.follower + spr.steps = $FollowerSteps + $FollowerSteps = nil + end + @sprites.push(spr) + end + end + end +end + +class Spriteset_Map + alias footsteps_update update + def update + footsteps_update + # Only update events that are on-screen + for sprite in @character_sprites + if sprite.character.is_a?(Game_Event) + sprite.update_footsteps + end + end + end +end \ No newline at end of file diff --git a/Plugins/Marin's Footprints/meta.txt b/Plugins/Marin's Footprints/meta.txt new file mode 100644 index 0000000..252ab4e --- /dev/null +++ b/Plugins/Marin's Footprints/meta.txt @@ -0,0 +1,5 @@ +Name = Marin's Footprints +Version = 2.0 +Essentials = 21.1 +Credits = Marin, Jony +Link = https://reliccastle.com/resources/165/ \ No newline at end of file diff --git a/Plugins/Marin's Scripting Utilities/meta.txt b/Plugins/Marin's Scripting Utilities/meta.txt new file mode 100644 index 0000000..414a751 --- /dev/null +++ b/Plugins/Marin's Scripting Utilities/meta.txt @@ -0,0 +1,5 @@ +Name = Marin's Scripting Utilities +Version = 2.0 +Essentials = 20 +Credits = Marin +Link = https://reliccastle.com/resources/165/ \ No newline at end of file diff --git a/Plugins/Marin's Scripting Utilities/script.rb b/Plugins/Marin's Scripting Utilities/script.rb new file mode 100644 index 0000000..902841a --- /dev/null +++ b/Plugins/Marin's Scripting Utilities/script.rb @@ -0,0 +1,925 @@ +class Object + def get_variables + return self.instance_variables.map { |v| [v,self.method(v.to_s.gsub(/@/, "").to_sym).call] } + end + + def set_variables(vars) + vars.each do |v| + self.method((v[0].to_s.gsub(/@/, "") + "=").to_sym).call(v[1]) + end + end +end + +# E.g. PokeBattle_Pokemon -> to_sym -> :PokeBattle_Pokemon +class Class + def to_sym + return self.to_s.to_sym + end +end + +class NilClass + def empty? + return true + end + + def numeric? + return false + end +end + +# Dir class extensions +class Dir + class << Dir + alias marin_delete delete + end + + # Returns all files in the targeted path + def self.get_files(path, recursive = true) + return Dir.get_all(path, recursive).select { |path| File.file?(path) } + end + + # Returns all directories in the targeted path + def self.get_dirs(path, recursive = true) + return Dir.get_all(path, recursive).select { |path| File.directory?(path) } + end + + # Returns all files and directories in the targeted path + def self.get_all(path, recursive = true) + files = [] + Dir.foreach(path) do |f| + next if f == "." || f == ".." + if File.directory?(path + "/" + f) && recursive + files.concat(Dir.get_files(path + "/" + f)) + end + files << path + "/" + f + end + return files + end +end + +class Numeric + # Formats the number nicely (e.g. 1234567890 -> format() -> 1,234,567,890) + def format(separator = ',') + a = self.to_s.split('').reverse.breakup(3) + return a.map { |e| e.join('') }.join(separator).reverse + end + + # Makes sure the returned string is at least n characters long + # (e.g. 4 -> to_digits -> "004") + # (e.g. 19 -> to_digits -> "019") + # (e.g. 123 -> to_digits -> "123") + def to_digits(n = 3) + str = self.to_s + return str if str.size >= n + ret = "" + (n - str.size).times { ret += "0" } + return ret + str + end + + # n root of self. Defaults to 2 => square root. + def root(n = 2) + return (self ** (1.0 / n)) + end + + # Factorial + # 4 -> fact -> (4 * 3 * 2 * 1) -> 24 + def fact + raise ArgumentError, "Cannot execute factorial on negative numerics" if self < 0 + tot = 1 + for i in 2..self + tot *= i + end + return tot + end + + # Combinations + def ncr(k) + return (self.fact / (k.fact * (self - k).fact)) + end + + # k permutations of n (self) + def npr(k) + return (self.fact / (self - k).fact) + end + + # Converts number to binary number (returns as string) + def to_b + return self.to_s(2) + end + + def empty? + return false + end + + def numeric? + return true + end +end + +class NilClass + def numeric? + return false + end +end + +# Calculates the total amount of elements in an Enumerable. Example: +# ["one","two","three"].fullsize #=> 11 +module Enumerable + def fullsize + n = 0 + for e in self + if e.is_a?(String) + n += e.size + elsif e.respond_to?(:fullsize) + n += e.fullsize + elsif e.respond_to?(:size) && !e.is_a?(Numeric) + n += e.size + else + n += 1 + end + end + return n + end +end + +class Array + # Returns a random element of the array + def random + return self[Object.method(:rand).call(self.size)] + end + + # Returns whether or not the array is empty. + def empty? + return self.size == 0 + end + + # Shuffles the order of the array + def shuffle + indexes = [] + new = [] + while new.size != self.size + # Weird way of calling rand for compatibility + # with Luka's scripting utilities + i = Object.method(:rand).call(self.size) + if !indexes.include?(i) + indexes << i + new << self[i] + end + end + return new + end + + # Shuffles the order of the array and replaces itself + def shuffle! + self.replace(shuffle) + end + + # Breaks the array up every n elements + def breakup(n) + ret = [] + for i in 0...self.size + ret[(i / n).floor] ||= [] + ret[(i / n).floor] << self[i] + end + return ret + end + + # Breaks the array up every n elements and replaces itself + def breakup!(n) + self.replace(breakup(n)) + end + + # Swaps two elements' indexes + def swap(index1, index2) + new = self.clone + tmp = new[index2].clone + new[index2] = new[index1] + new[index1] = tmp + return new + end + + # Swaps two elements' indexes and replaces itself + def swap!(index1, index2) + self.replace(swap(index1, index2)) + end + + # Returns whether or not the first element is equal to the passed argument + def starts_with?(e) + return self.first == e + end + + # Returns whether or not the last element is equal to the passed argument + def ends_with?(e) + return self.last == e + end + + # Converts itself to a hash where possible + def to_hash(delete_nil_entries = false) + ret = {} + for i in 0...self.size + next if self[i].nil? && delete_nil_entries + ret[i] = self[i] + end + return ret + end + + # If you have 8 elements, if true, grabs the 5th element, the 4th if false. + # If you have 7 elements, grabs the 4th. + def mid(round_up = true) + i = (self.size - 1) / 2.0 + i = i.ceil if round_up + return self[i].floor + end + + # Returns the average of all elements in the array. Will throw errors on non-numerics. + # Skips entries. + def average + total = 0 + self.each { |n| total += n unless n.nil? } + return total / self.compact.size.to_f + end + + # Adds some aliases for : , , + alias has? include? + alias includes? include? + alias contains? include? + + # Evaluates the block you pass it for every number between 0 and "slots". + # Example usage: + # Array.make_table { |i| i ** 2 } + # => [1, 4, 9, 16, 25, 36, 49, 64, 81, 100] + # Array.make_table(10..16) { |i| i.to_s(2) } + # => ["1010", "1011", "1100", "1101", "1110", "1111", "10000"] + # (you can also pass it an array of values to iterate over) + def self.make_table(range = 1..10, &proc) + return range.map { |n| next proc.call(n) } + end + + # If true: + # [0, 1, 3, 4, 5] -- etc + # If false: + # [0,1,2,3,4,5] -- etc + Json_Extra_Space_After_Entry = false + + # Converts _self_ to a JSON string with an indent of Json_Indent_Width per layer. + def to_json(indent = Hash::Json_Indent_Width, inline = false) + return "[]" unless self.size > 0 + full = "[" + for i in 0...self.size + nl = false + if self[i].is_a?(Hash) || self[i].is_a?(Array) + val = self[i].to_json(indent + Hash::Json_Indent_Width, i == 0) + nl = !(inline && i == 0) + else + val = self[i] + val = "\"#{val}\"" if val.is_a?(String) + nl = (self.fullsize > 24 || self.map { |e| e.class.to_sym }.include?(:Hash)) + end + full += "\n" + " " * indent if nl + full += val.to_s + "," + full += " " if Json_Extra_Space_After_Entry + end + i = 2 + Json_Extra_Space_After_Entry.to_i + full = full[0..(-i)] + full += "\n#{" " * (indent - Hash::Json_Indent_Width)}" if self.fullsize > 24 || + self.map { |e| e.class.to_sym }.include?(:Hash) + full += "]" + return full + end +end + +class Hash + # Converts itself to an array where possible + def to_array(delete_nil_entries = false) + ret = [] + keys = self.keys.sort + for key in keys + next if self[key].nil? && delete_nil_entries + ret[key] = self[key] + end + return ret + end + + def compact + new = {} + for key in self.keys + new[key] = self[key] unless self[key].nil? + end + return new + end + + def compact! + self.replace(compact) + end + + # Amount of spaces per "layer" in the JSON. + Json_Indent_Width = 4 + + # Converts _self_ to a JSON string with an indent of Json_Indent_Width per layer. + def to_json(indent = Json_Indent_Width, _ = nil) + return "{}" if self.size == 0 + full = "{" + keys = self.keys.sort do |a,b| + if $JSON_Sort_Order + if $JSON_Sort_Order.include?(a) + if $JSON_Sort_Order.include?(b) + next $JSON_Sort_Order.index(a) <=> $JSON_Sort_Order.index(b) + else + next -1 + end + else + if $JSON_Sort_Order.include?(b) + next 1 + end + # If neither are in the key, go alphabetical + end + end + if a.numeric? + if b.numeric? + next a <=> b + else + next -1 + end + else + if b.numeric? + next 1 + else + next a <=> b + end + end + end + for key in keys + if self[key].is_a?(Hash) || self[key].is_a?(Array) + val = self[key].to_json(indent + Json_Indent_Width, key == self.keys[0]) + else + val = self[key] + val = "\"#{val}\"" if val.is_a?(String) + end + full += "\n#{" " * indent}\"#{key}\": #{val}," + end + full = full[0..-2] + full += "\n#{" " * (indent - Json_Indent_Width)}}" + return full + end +end + +# String class extensions +class String + # Converts to bits + def to_b + return self.unpack('b*')[0] + end + + # Converts to bits and replaces itself + def to_b! + self.replace(to_b) + end + + # Converts from bits + def from_b + return [self].pack('b*') + end + + # Convert from bits and replaces itself + def from_b! + self.replace(from_b) + end + + # Returns a random character from the string + def random + return self[rand(self.size)] + end + + # Shuffles the order of the characters + def shuffle + return self.split("").shuffle.join("") + end + + # Breaks the string up every _n_ characters + def breakup(n) + new = [] + for i in 0...self.size + new[(i / n).floor] ||= "" + new[(i / n).floor] += self[i] + end + return new + end + + def empty? + return (self.size == 0) + end + + def numeric? + i = 0 + for e in self.split("") + next if i == 0 && e == "-" + return false unless [0,1,2,3,4,5,6,7,8,9].map { |n| n.to_s }.include?(e) + end + return true + end + + # Deflates itself and returns the result + def deflate + return Zlib::Deflate.deflate(self) + end + + # Deflates and replaces itself + def deflate! + self.replace(deflate) + end + + # Inflates itself and returns the result + def inflate + return Zlib::Inflate.inflate(self) + end + + # Inflates and replaces itself + def inflate! + self.replace(inflate) + end + + # Adds some aliases for : , , + alias has? include? + alias includes? include? + alias contains? include? +end + +# Sprite class extensions +class Sprite + # Shorthand for initializing a bitmap by path, bitmap, or width/height: + # -> bmp("Graphics/Pictures/bag") + # -> bmp(32, 32) + # -> bmp(some_other_bitmap) + def bmp(arg1 = nil, arg2 = nil) + if arg1 + if arg2 + arg1 = Graphics.width if arg1 == -1 + arg2 = Graphics.height if arg2 == -1 + self.bitmap = Bitmap.new(arg1, arg2) + elsif arg1.is_a?(Bitmap) + self.bitmap = arg1.clone + else + self.bitmap = Bitmap.new(arg1) + end + else + return self.bitmap + end + end + + # Alternative to bmp(path): + # -> bmp = "Graphics/Pictures/bag" + def bmp=(arg1) + bmp(arg1) + end + + # Usage: + # -> [x] # Sets sprite.x to x + # -> [x,y] # Sets sprite.x to x and sprite.y to y + # -> [x,y,z] # Sets sprite.x to x and sprite.y to y and sprite.z to z + # -> [nil,y] # Sets sprite.y to y + # -> [nil,nil,z] # Sets sprite.z to z + # -> [x,nil,z] # Sets sprite.x to x and sprite.z to z + # Etc. + def xyz=(args) + self.x = args[0] || self.x + self.y = args[1] || self.y + self.z = args[2] || self.z + end + + # Returns the x, y, and z coordinates in the xyz=(args) format, [x,y,z] + def xyz + return [self.x,self.y,self.z] + end + + # Centers the sprite by setting the origin points to half the width and height + def center_origins + return if !self.bitmap + self.ox = self.bitmap.width / 2 + self.oy = self.bitmap.height / 2 + end + + # Returns the sprite's full width, taking zoom_x into account + def fullwidth + return self.bitmap.width.to_f * self.zoom_x + end + + # Returns the sprite's full height, taking zoom_y into account + def fullheight + return self.bitmap.height.to_f * self.zoom_y + end +end + +class TextSprite < Sprite + # Sets up the sprite and bitmap. You can also pass text to draw + # either an array of arrays, or an array containing the normal "parameters" + # for drawing text: + # [text,x,y,align,basecolor,shadowcolor] + def initialize(viewport = nil, text = nil, width = -1, height = -1) + super(viewport) + @width = width + @height = height + self.bmp(@width, @height) + pbSetSystemFont(self.bmp) + if text.is_a?(Array) + if text[0].is_a?(Array) + pbDrawTextPositions(self.bmp,text) + else + pbDrawTextPositions(self.bmp,[text]) + end + end + end + + # Clears the bitmap (and thus all drawn text) + def clear + self.bmp.clear + pbSetSystemFont(self.bmp) + end + + # You can also pass text to draw either an array of arrays, or an array + # containing the normal "parameters" for drawing text: + # [text,x,y,align,basecolor,shadowcolor] + def draw(text, clear = false) + self.clear if clear + if text[0].is_a?(Array) + pbDrawTextPositions(self.bmp,text) + else + pbDrawTextPositions(self.bmp,[text]) + end + end + + # Draws text with outline + # [text,x,y,align,basecolor,shadowcolor] + def draw_outline(text, clear = false) + self.clear if clear + if text[0].is_a?(Array) + for e in text + e[2] -= 224 + pbDrawOutlineText(self.bmp,e[1],e[2],640,480,e[0],e[4],e[5],e[3]) + end + else + e = text + e[2] -= 224 + pbDrawOutlineText(self.bmp,e[1],e[2],640,480,e[0],e[4],e[5],e[3]) + end + end + + # Draws and breaks a line if the width is exceeded + # [text,x,y,width,numlines,basecolor,shadowcolor] + def draw_ex(text, clear = false) + self.clear if clear + if text[0].is_a?(Array) + for e in text + drawTextEx(self.bmp,e[1],e[2],e[3],e[4],e[0],e[5],e[6]) + end + else + e = text + drawTextEx(self.bmp,e[1],e[2],e[3],e[4],e[0],e[5],e[6]) + end + end + + # Clears and disposes the sprite + def dispose + clear + super + end +end + +# A better alternative to the typical @sprites = {} +class SpriteHash + attr_reader :x + attr_reader :y + attr_reader :z + attr_reader :visible + attr_reader :opacity + + def initialize + @hash = {} + @x = 0 + @y = 0 + @z = 0 + @visible = true + @opacity = 255 + end + + # Returns the object in the specified key + def [](key) + key = key.to_sym if key.respond_to?(:to_sym) && !key.is_a?(Numeric) + return @hash[key] + end + + # Sets an object in specified key to the specified value + def []=(key, value) + key = key.to_sym if key.respond_to?(:to_sym) && !key.is_a?(Numeric) + add(key, value) + end + + # Returns the raw hash + def raw + return @hash + end + + # Returns the keys in the hash + def keys + return @hash.keys + end + + def length; return self.size; end + def count; return self.size; end + + # Returns the amount of keys in the hash + def size + return @hash.keys.size + end + + # Clones the hash + def clone + return @hash.clone + end + + # Adds an object to the specified key + def add(key, value) + clear_disposed + key = key.to_sym if key.respond_to?(:to_sym) && !key.is_a?(Numeric) + @hash[key] if @hash[key] && @hash[key].respond_to?(:dispose) + @hash[key] = value + clear_disposed + end + + # Deletes an object in the specified key + def delete(key) + key = key.to_sym if key.respond_to?(:to_sym) && !key.is_a?(Numeric) + @hash[key] = nil + clear_disposed + end + + # Iterates over all sprites + def each + clear_disposed + @hash.each { |s| yield s[1] if block_given? } + end + + # Updates all sprites + def update + clear_disposed + for key in @hash.keys + @hash[key].update if @hash[key].respond_to?(:update) + end + end + + # Disposes all sprites + def dispose + clear_disposed + for key in @hash.keys + @hash[key].dispose if @hash[key].respond_to?(:dispose) + end + clear_disposed + end + + # Compatibility + def disposed? + return false + end + + # Changes x on all sprites + def x=(value) + clear_disposed + for key in @hash.keys + @hash[key].x += value - @x + end + @x = value + end + + # Changes y on all sprites + def y=(value) + clear_disposed + for key in @hash.keys + @hash[key].y += value - @y + end + @y = value + end + + # Changes z on all sprites + def z=(value) + clear_disposed + for key in @hash.keys + @hash[key].z += value - @z + end + @z = value + end + + # Changes visibility on all sprites + def visible=(value) + clear_disposed + for key in @hash.keys + @hash[key].visible = value + end + end + + # Changes opacity on all sprites + def opacity=(value) + clear_disposed + for key in @hash.keys + @hash[key].opacity += value - @opacity + end + @opacity = [0,value,255].sort[1] + end + + # Fades out all sprites + def hide(frames = 16) + clear_disposed + frames.times do + Graphics.update + Input.update + for key in @hash.keys + @hash[key].opacity -= 255 / frames.to_f + end + end + @opacity = 0 + end + + # Fades in all sprites + def show(frames = 16) + clear_disposed + frames.times do + Graphics.update + Input.update + for key in @hash.keys + @hash[key].opacity += 255 / frames.to_f + end + end + @opacity = 255 + end + + # Deletes all disposed sprites from the hash + def clear_disposed + for key in @hash.keys + if (@hash[key].disposed? rescue true) + @hash[key] = nil + @hash.delete(key) + end + end + end + + # Renames the old key to the new key + def rename(old, new) + self[new] = self[old] + delete(old) + end +end + +class ByteWriter + def initialize(filename) + @file = File.new(filename, "wb") + end + + def <<(*data) + write(*data) + end + + def write(*data) + data.each do |e| + if e.is_a?(Array) || e.is_a?(Enumerator) + e.each { |item| write(item) } + elsif e.is_a?(Numeric) + @file.putc e + else + raise "Invalid data for writing.\nData type: #{e.class}\nData: #{e.inspect[0..100]}" + end + end + end + + def write_int(int) + self << ByteWriter.to_bytes(int) + end + + def close + @file.close + @file = nil + end + + def self.to_bytes(int) + return [ + (int >> 24) & 0xFF, + (int >> 16) & 0xFF, + (int >> 8) & 0xFF, + int & 0xFF + ] + end +end + +class Bitmap + def save_to_png(filename) + f = ByteWriter.new(filename) + + #============================= Writing header ===============================# + # PNG signature + f << [0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A] + # Header length + f << [0x00, 0x00, 0x00, 0x0D] + # IHDR + headertype = [0x49, 0x48, 0x44, 0x52] + f << headertype + + # Width, height, compression, filter, interlacing + headerdata = ByteWriter.to_bytes(self.width). + concat(ByteWriter.to_bytes(self.height)). + concat([0x08, 0x06, 0x00, 0x00, 0x00]) + f << headerdata + + # CRC32 checksum + sum = headertype.concat(headerdata) + f.write_int Zlib::crc32(sum.pack("C*")) + + #============================== Writing data ================================# + data = [] + for y in 0...self.height + # Start scanline + data << 0x00 # Filter: None + for x in 0...self.width + px = self.get_pixel(x, y) + # Write raw RGBA pixels + data << px.red + data << px.green + data << px.blue + data << px.alpha + end + end + # Zlib deflation + smoldata = Zlib::Deflate.deflate(data.pack("C*")).bytes + # data chunk length + f.write_int smoldata.size + # IDAT + f << [0x49, 0x44, 0x41, 0x54] + f << smoldata + # CRC32 checksum + f.write_int Zlib::crc32([0x49, 0x44, 0x41, 0x54].concat(smoldata).pack("C*")) + + #============================== End Of File =================================# + # Empty chunk + f << [0x00, 0x00, 0x00, 0x00] + # IEND + f << [0x49, 0x45, 0x4E, 0x44] + # CRC32 checksum + f.write_int Zlib::crc32([0x49, 0x45, 0x4E, 0x44].pack("C*")) + f.close + return nil + end +end + + +# Stand-alone methods + +# Fades in a black overlay +def showBlk(n = 16) + return if $blkVp || $blk + $blkVp = Viewport.new(0,0,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT) + $blkVp.z = 9999999 + $blk = Sprite.new($blkVp) + $blk.bmp(-1,-1) + $blk.bitmap.fill_rect(0,0,Settings::SCREEN_WIDTH,Settings::SCREEN_HEIGHT,Color.new(0,0,0)) + $blk.opacity = 0 + for i in 0...(n + 1) + Graphics.update + Input.update + yield i if block_given? + $blk.opacity += 256 / n.to_f + end +end + +# Fades out and disposes a black overlay +def hideBlk(n = 16) + return if !$blk || !$blkVp + for i in 0...(n + 1) + Graphics.update + Input.update + yield i if block_given? + $blk.opacity -= 256 / n.to_f + end + $blk.dispose + $blk = nil + $blkVp.dispose + $blkVp = nil +end + +def pbGetActiveEventPage(event, mapid = nil) + mapid ||= event.map.map_id if event.respond_to?(:map) + pages = (event.is_a?(RPG::Event) ? event.pages : event.instance_eval { @event.pages }) + for i in 0...pages.size + c = pages[pages.size - 1 - i].condition + ss = !(c.self_switch_valid && !$game_self_switches[[mapid, + event.id,c.self_switch_ch]]) + sw1 = !(c.switch1_valid && !$game_switches[c.switch1_id]) + sw2 = !(c.switch2_valid && !$game_switches[c.switch2_id]) + var = true + if c.variable_valid + if !c.variable_value || !$game_variables[c.variable_id].is_a?(Numeric) || + $game_variables[c.variable_id] < c.variable_value + var = false + end + end + if ss && sw1 && sw2 && var # All conditions are met + return pages[pages.size - 1 - i] + end + end + return nil +end \ No newline at end of file diff --git a/Plugins/PokemonVault/001_Core.rb b/Plugins/PokemonVault/001_Core.rb index 8eed930..cb8afc7 100644 --- a/Plugins/PokemonVault/001_Core.rb +++ b/Plugins/PokemonVault/001_Core.rb @@ -1,119 +1,119 @@ -#=============================================================================== -# Pokémon Vault – Core Storage System -#=============================================================================== -# External, cross-save, cross-game Pokémon storage. -#=============================================================================== - -module PokemonVault - VAULT_FOLDER_NAME = "Pokemon Vault" - VAULT_FILE = "vault.dat" - MAX_BOXES = 400 - BOX_SIZE = 30 - - module_function - - #--------------------------------------------------------------------------- - # Vault Data - #--------------------------------------------------------------------------- - - def vault_directory - parent = File.dirname(System.data_directory) - dir = File.join(parent, VAULT_FOLDER_NAME) - Dir.mkdir(dir) unless Dir.exist?(dir) - return dir - end - - def vault_path - File.join(vault_directory, VAULT_FILE) - end - - def empty_vault - Array.new(MAX_BOXES) { Array.new(BOX_SIZE) } - end - - def valid_vault?(vault) - return false if !vault.is_a?(Array) - return false if vault.length != MAX_BOXES - vault.all? { |box| box.is_a?(Array) && box.length == BOX_SIZE } - end - - def load_vault - path = vault_path - return empty_vault if !File.exist?(path) - data = Marshal.load(File.binread(path)) - return valid_vault?(data) ? data : empty_vault - rescue - return empty_vault - end - - def save_vault(vault) - File.binwrite(vault_path, Marshal.dump(vault)) - end - - #--------------------------------------------------------------------------- - # Eligibility Rules - #--------------------------------------------------------------------------- - - def storable_pokemon?(pkmn) - return false if !pkmn - return false if pkmn.egg? - - species = pkmn.species_data - return false if species.has_flag?("NotTradeable") - return false if species.has_flag?("NotStorable") - - true - end - - #--------------------------------------------------------------------------- - # Vault Operations - #--------------------------------------------------------------------------- - - def first_empty_slot(vault) - vault.each_with_index do |box, b| - box.each_with_index do |slot, s| - return [b, s] if slot.nil? - end - end - nil - end - - def add_pokemon(pkmn) - return false if !storable_pokemon?(pkmn) - vault = load_vault - pos = first_empty_slot(vault) - return false if !pos - - b, s = pos - vault[b][s] = pkmn - save_vault(vault) - true - end - - def remove_pokemon(box, slot) - vault = load_vault - return nil if !vault.dig(box, slot) - - pkmn = vault[box][slot] - vault[box][slot] = nil - save_vault(vault) - pkmn - end - - #--------------------------------------------------------------------------- - # Remove/Add From PC - #--------------------------------------------------------------------------- - - def remove_from_pc(box, slot) - pkmn = $PokemonStorage[box, slot] - return nil if !storable_pokemon?(pkmn) - - $PokemonStorage[box, slot] = nil - pkmn - end - - def add_to_pc(pkmn) - return false if !pkmn - return !$PokemonStorage.pbStoreCaught(pkmn).nil? - end -end +#=============================================================================== +# Pokémon Vault – Core Storage System +#=============================================================================== +# External, cross-save, cross-game Pokémon storage. +#=============================================================================== + +module PokemonVault + VAULT_FOLDER_NAME = "Pokemon Vault" + VAULT_FILE = "vault.dat" + MAX_BOXES = 400 + BOX_SIZE = 30 + + module_function + + #--------------------------------------------------------------------------- + # Vault Data + #--------------------------------------------------------------------------- + + def vault_directory + parent = File.dirname(System.data_directory) + dir = File.join(parent, VAULT_FOLDER_NAME) + Dir.mkdir(dir) unless Dir.exist?(dir) + return dir + end + + def vault_path + File.join(vault_directory, VAULT_FILE) + end + + def empty_vault + Array.new(MAX_BOXES) { Array.new(BOX_SIZE) } + end + + def valid_vault?(vault) + return false if !vault.is_a?(Array) + return false if vault.length != MAX_BOXES + vault.all? { |box| box.is_a?(Array) && box.length == BOX_SIZE } + end + + def load_vault + path = vault_path + return empty_vault if !File.exist?(path) + data = Marshal.load(File.binread(path)) + return valid_vault?(data) ? data : empty_vault + rescue + return empty_vault + end + + def save_vault(vault) + File.binwrite(vault_path, Marshal.dump(vault)) + end + + #--------------------------------------------------------------------------- + # Eligibility Rules + #--------------------------------------------------------------------------- + + def storable_pokemon?(pkmn) + return false if !pkmn + return false if pkmn.egg? + + species = pkmn.species_data + return false if species.has_flag?("NotTradeable") + return false if species.has_flag?("NotStorable") + + true + end + + #--------------------------------------------------------------------------- + # Vault Operations + #--------------------------------------------------------------------------- + + def first_empty_slot(vault) + vault.each_with_index do |box, b| + box.each_with_index do |slot, s| + return [b, s] if slot.nil? + end + end + nil + end + + def add_pokemon(pkmn) + return false if !storable_pokemon?(pkmn) + vault = load_vault + pos = first_empty_slot(vault) + return false if !pos + + b, s = pos + vault[b][s] = pkmn + save_vault(vault) + true + end + + def remove_pokemon(box, slot) + vault = load_vault + return nil if !vault.dig(box, slot) + + pkmn = vault[box][slot] + vault[box][slot] = nil + save_vault(vault) + pkmn + end + + #--------------------------------------------------------------------------- + # Remove/Add From PC + #--------------------------------------------------------------------------- + + def remove_from_pc(box, slot) + pkmn = $PokemonStorage[box, slot] + return nil if !storable_pokemon?(pkmn) + + $PokemonStorage[box, slot] = nil + pkmn + end + + def add_to_pc(pkmn) + return false if !pkmn + return !$PokemonStorage.pbStoreCaught(pkmn).nil? + end +end diff --git a/Plugins/PokemonVault/002_UI.rb b/Plugins/PokemonVault/002_UI.rb index ac1d686..8ce9e76 100644 --- a/Plugins/PokemonVault/002_UI.rb +++ b/Plugins/PokemonVault/002_UI.rb @@ -1,301 +1,301 @@ -#=============================================================================== -# PC Shit -#=============================================================================== - -class PokemonStorageScreen - def pbChoosePokemonForVault(eligibility_proc = nil, helptext = nil) - $game_temp.in_storage = true - @scene.pbStartBox(self, 0) - chosen = nil - - loop do - selected = @scene.pbSelectBox(@storage.party) - - # Close PC - if selected && selected[0] == -3 - break if pbConfirmMessage(_INTL("Exit the PC?")) - next - end - - break if selected.nil? - - box, slot = selected - pkmn = @storage[box, slot] - next if !pkmn - - if eligibility_proc && !eligibility_proc.call(pkmn) - pbMessage(_INTL("That Pokémon can’t be stored in the Vault.")) - next - end - -if box < 0 - pbMessage(_INTL("You can only select Pokémon from PC Boxes.")) - next -end - - commands = [ - _INTL("Select"), - _INTL("Summary"), - _INTL("Cancel") - ] - - command = pbShowCommands(helptext || _INTL("{1} is selected.", pkmn.name), commands) - - case command - when 0 # Select - chosen = [pkmn, box, slot] - break - when 1 # Summary - pbSummary(selected, nil) - end - end - - @scene.pbCloseBox - $game_temp.in_storage = false - return chosen - end -end - - -#=============================================================================== -# Placeholder UI (Fuck This) -#=============================================================================== - -module PokemonVault - module_function - - def open_menu - loop do - choice = pbMessage( - _INTL("Pokémon Vault"), - [ - _INTL("Upload Pokémon"), - _INTL("Upload Box"), - _INTL("Download Pokémon"), - _INTL("Download Box"), - _INTL("Quit") - ] - ) - - case choice - when 0 - upload_single_pokemon - when 1 - upload_entire_box - when 2 - download_single_pokemon - when 3 - download_entire_box - else - break - end - end - end -end - - -module PokemonVault - module_function - - #--------------------------------------------------------------------------- - # Upload From PC - #--------------------------------------------------------------------------- - - def choose_pokemon_from_pc(eligibility_proc = nil, helptext = nil) - chosen = nil - pbFadeOutIn do - scene = PokemonStorageScene.new - screen = PokemonStorageScreen.new(scene, $PokemonStorage) - chosen = screen.pbChoosePokemonForVault(eligibility_proc, helptext) - end - return chosen - end - -def upload_single_pokemon - chosen = choose_pokemon_from_pc( - proc { |pkmn| storable_pokemon?(pkmn) }, - _INTL("Choose a Pokémon to upload.") - ) - - return if !chosen - - pkmn, box, slot = chosen - - return if !pbConfirmMessage( - _INTL("Upload {1} to the Pokémon Vault?", pkmn.name) - ) - - removed = remove_from_pc(box, slot) - - if add_pokemon(removed) - pbMessage(_INTL("{1} was uploaded to the Vault.", removed.name)) - Game.save - pbMEPlay("GUI save game") - else - pbMessage(_INTL("The Vault is full.")) - add_to_pc(removed) - end -end - - #--------------------------------------------------------------------------- - # Upload PC Box - #--------------------------------------------------------------------------- - - def upload_entire_box - box = pbMessage( - _INTL("Which box do you want to upload?"), - (1..Settings::NUM_STORAGE_BOXES).map { |i| _INTL("Box {1}", i) } - ) - return if box < 0 - - box_index = box - uploaded = 0 - skipped = 0 - - BOX_SIZE.times do |slot| - pkmn = $PokemonStorage[box_index, slot] - next if !storable_pokemon?(pkmn) - - if add_pokemon(pkmn) - $PokemonStorage[box_index, slot] = nil - uploaded += 1 - else - skipped += 1 - break - end - end - - pbMessage( - _INTL( - "Uploaded {1} Pokémon.\nSkipped {2}.", - uploaded, - skipped - ) - ) - - Game.save if uploaded > 0 - pbMEPlay("GUI save game") if uploaded > 0 - end -end - -module PokemonVault - module_function - - def choose_pokemon_from_vault - vault = load_vault - entries = [] - - vault.each_with_index do |box, b| - box.each_with_index do |pkmn, s| - next if !pkmn - entries << [pkmn, b, s] - end - end - - if entries.empty? - pbMessage(_INTL("The Pokémon Vault is empty.")) - return nil - end - - commands = entries.map.with_index do |(pkmn, b, s), i| - _INTL("{1}. {2} (Box {3}, Slot {4})", - i + 1, - pkmn.name, - b + 1, - s + 1 - ) - end - - commands << _INTL("Cancel") - - choice = pbMessage( - _INTL("Choose a Pokémon to download."), - commands - ) - - return nil if choice < 0 || choice >= entries.length - - return entries[choice] # [pkmn, box, slot] - end -end - -module PokemonVault - module_function - -def download_single_pokemon - chosen = choose_pokemon_from_vault - return if !chosen - - pkmn, box, slot = chosen - - return if !pbConfirmMessage( - _INTL("Download {1} from the Pokémon Vault?", pkmn.name) - ) - - removed = remove_pokemon(box, slot) - return if !removed - - # Attempt to store in PC - if add_to_pc(removed) - pbMessage(_INTL("{1} was downloaded to your PC.", removed.name)) - Game.save - pbMEPlay("GUI save game") - else - pbMessage(_INTL("Your PC Boxes are full.")) - add_pokemon(removed) # rollback safely into Vault - end -end -end - -def download_entire_box - vault = load_vault - box_choices = [] - - vault.each_with_index do |box, i| - count = box.compact.length - next if count == 0 - box_choices << [i, count] - end - - if box_choices.empty? - pbMessage(_INTL("The Pokémon Vault is empty.")) - return - end - - commands = box_choices.map do |(b, count)| - _INTL("Vault Box {1} ({2} Pokémon)", b + 1, count) - end - commands << _INTL("Cancel") - - choice = pbMessage(_INTL("Choose a Vault box to download."), commands) - return if choice < 0 || choice >= box_choices.length - - box_index, _ = box_choices[choice] - - downloaded = 0 - skipped = 0 - - vault[box_index].each_with_index do |pkmn, slot| - next if !pkmn - - # Attempt to store in PC - if add_to_pc(pkmn) - vault[box_index][slot] = nil - downloaded += 1 - else - skipped += 1 - break # PC is full; stop downloading this box - end - end - - save_vault(vault) - - pbMessage( - _INTL("Downloaded {1} Pokémon.\nSkipped {2}.", - downloaded, - skipped - ) - ) - Game.save if downloaded > 0 - pbMEPlay("GUI save game") if downloaded > 0 +#=============================================================================== +# PC Shit +#=============================================================================== + +class PokemonStorageScreen + def pbChoosePokemonForVault(eligibility_proc = nil, helptext = nil) + $game_temp.in_storage = true + @scene.pbStartBox(self, 0) + chosen = nil + + loop do + selected = @scene.pbSelectBox(@storage.party) + + # Close PC + if selected && selected[0] == -3 + break if pbConfirmMessage(_INTL("Exit the PC?")) + next + end + + break if selected.nil? + + box, slot = selected + pkmn = @storage[box, slot] + next if !pkmn + + if eligibility_proc && !eligibility_proc.call(pkmn) + pbMessage(_INTL("That Pokémon can’t be stored in the Vault.")) + next + end + +if box < 0 + pbMessage(_INTL("You can only select Pokémon from PC Boxes.")) + next +end + + commands = [ + _INTL("Select"), + _INTL("Summary"), + _INTL("Cancel") + ] + + command = pbShowCommands(helptext || _INTL("{1} is selected.", pkmn.name), commands) + + case command + when 0 # Select + chosen = [pkmn, box, slot] + break + when 1 # Summary + pbSummary(selected, nil) + end + end + + @scene.pbCloseBox + $game_temp.in_storage = false + return chosen + end +end + + +#=============================================================================== +# Placeholder UI (Fuck This) +#=============================================================================== + +module PokemonVault + module_function + + def open_menu + loop do + choice = pbMessage( + _INTL("Pokémon Vault"), + [ + _INTL("Upload Pokémon"), + _INTL("Upload Box"), + _INTL("Download Pokémon"), + _INTL("Download Box"), + _INTL("Quit") + ] + ) + + case choice + when 0 + upload_single_pokemon + when 1 + upload_entire_box + when 2 + download_single_pokemon + when 3 + download_entire_box + else + break + end + end + end +end + + +module PokemonVault + module_function + + #--------------------------------------------------------------------------- + # Upload From PC + #--------------------------------------------------------------------------- + + def choose_pokemon_from_pc(eligibility_proc = nil, helptext = nil) + chosen = nil + pbFadeOutIn do + scene = PokemonStorageScene.new + screen = PokemonStorageScreen.new(scene, $PokemonStorage) + chosen = screen.pbChoosePokemonForVault(eligibility_proc, helptext) + end + return chosen + end + +def upload_single_pokemon + chosen = choose_pokemon_from_pc( + proc { |pkmn| storable_pokemon?(pkmn) }, + _INTL("Choose a Pokémon to upload.") + ) + + return if !chosen + + pkmn, box, slot = chosen + + return if !pbConfirmMessage( + _INTL("Upload {1} to the Pokémon Vault?", pkmn.name) + ) + + removed = remove_from_pc(box, slot) + + if add_pokemon(removed) + pbMessage(_INTL("{1} was uploaded to the Vault.", removed.name)) + Game.save + pbMEPlay("GUI save game") + else + pbMessage(_INTL("The Vault is full.")) + add_to_pc(removed) + end +end + + #--------------------------------------------------------------------------- + # Upload PC Box + #--------------------------------------------------------------------------- + + def upload_entire_box + box = pbMessage( + _INTL("Which box do you want to upload?"), + (1..Settings::NUM_STORAGE_BOXES).map { |i| _INTL("Box {1}", i) } + ) + return if box < 0 + + box_index = box + uploaded = 0 + skipped = 0 + + BOX_SIZE.times do |slot| + pkmn = $PokemonStorage[box_index, slot] + next if !storable_pokemon?(pkmn) + + if add_pokemon(pkmn) + $PokemonStorage[box_index, slot] = nil + uploaded += 1 + else + skipped += 1 + break + end + end + + pbMessage( + _INTL( + "Uploaded {1} Pokémon.\nSkipped {2}.", + uploaded, + skipped + ) + ) + + Game.save if uploaded > 0 + pbMEPlay("GUI save game") if uploaded > 0 + end +end + +module PokemonVault + module_function + + def choose_pokemon_from_vault + vault = load_vault + entries = [] + + vault.each_with_index do |box, b| + box.each_with_index do |pkmn, s| + next if !pkmn + entries << [pkmn, b, s] + end + end + + if entries.empty? + pbMessage(_INTL("The Pokémon Vault is empty.")) + return nil + end + + commands = entries.map.with_index do |(pkmn, b, s), i| + _INTL("{1}. {2} (Box {3}, Slot {4})", + i + 1, + pkmn.name, + b + 1, + s + 1 + ) + end + + commands << _INTL("Cancel") + + choice = pbMessage( + _INTL("Choose a Pokémon to download."), + commands + ) + + return nil if choice < 0 || choice >= entries.length + + return entries[choice] # [pkmn, box, slot] + end +end + +module PokemonVault + module_function + +def download_single_pokemon + chosen = choose_pokemon_from_vault + return if !chosen + + pkmn, box, slot = chosen + + return if !pbConfirmMessage( + _INTL("Download {1} from the Pokémon Vault?", pkmn.name) + ) + + removed = remove_pokemon(box, slot) + return if !removed + + # Attempt to store in PC + if add_to_pc(removed) + pbMessage(_INTL("{1} was downloaded to your PC.", removed.name)) + Game.save + pbMEPlay("GUI save game") + else + pbMessage(_INTL("Your PC Boxes are full.")) + add_pokemon(removed) # rollback safely into Vault + end +end +end + +def download_entire_box + vault = load_vault + box_choices = [] + + vault.each_with_index do |box, i| + count = box.compact.length + next if count == 0 + box_choices << [i, count] + end + + if box_choices.empty? + pbMessage(_INTL("The Pokémon Vault is empty.")) + return + end + + commands = box_choices.map do |(b, count)| + _INTL("Vault Box {1} ({2} Pokémon)", b + 1, count) + end + commands << _INTL("Cancel") + + choice = pbMessage(_INTL("Choose a Vault box to download."), commands) + return if choice < 0 || choice >= box_choices.length + + box_index, _ = box_choices[choice] + + downloaded = 0 + skipped = 0 + + vault[box_index].each_with_index do |pkmn, slot| + next if !pkmn + + # Attempt to store in PC + if add_to_pc(pkmn) + vault[box_index][slot] = nil + downloaded += 1 + else + skipped += 1 + break # PC is full; stop downloading this box + end + end + + save_vault(vault) + + pbMessage( + _INTL("Downloaded {1} Pokémon.\nSkipped {2}.", + downloaded, + skipped + ) + ) + Game.save if downloaded > 0 + pbMEPlay("GUI save game") if downloaded > 0 end \ No newline at end of file diff --git a/Plugins/PokemonVault/meta.txt b/Plugins/PokemonVault/meta.txt index e12816f..edff952 100644 --- a/Plugins/PokemonVault/meta.txt +++ b/Plugins/PokemonVault/meta.txt @@ -1,6 +1,6 @@ -Name = Pokémon Vault -Version = 1.0.1 -Essentials = 21.1 -Requires = v21.1 Hotfixes,1.0.9 -Website = https://eeveeexpo.com/resources/1828/ +Name = Pokémon Vault +Version = 1.0.1 +Essentials = 21.1 +Requires = v21.1 Hotfixes,1.0.9 +Website = https://eeveeexpo.com/resources/1828/ Credits = ReallyBoredCoder \ No newline at end of file diff --git a/Town Map Generator.html b/Town Map Generator.html index f0877ba..1c53792 100644 --- a/Town Map Generator.html +++ b/Town Map Generator.html @@ -1,420 +1,420 @@ - -
- Town Map Generator -
-
- - - - - - - - - - - - - - - - - - - - - - - - - -
Filename:Name of the region graphic (in Graphics/UI/Town Map/)
Name:Name of the region
Square width:Width of each point in the Town Map (in pixels)
Square height:Height of each point in the Town Map (in pixels)
-
-
-
- Edit point properties
- Click on a point in the Town Map to edit its properties. -
-
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - -
Co-ordinates:X and Y co-ordinates of this point in the Town Map (click in the map above)
Name:Name of this location
Landmark:Name of a landmark found in this location
Fly destination:Map ID, X and Y tile co-ordinates the player will appear at when Flying to this location
Switch:Number of a Game Switch that needs to be ON to see this point's name/landmark and to Fly to this location
-
- -
-
- PBS file "town_map.txt" text for this region
-
-   - Apply the data in this box to the map above
- When you're done, copy this text into "town_map.txt". Remember that it needs a section line (a number in square brackets). -
-
- \ No newline at end of file