This commit is contained in:
infinitefusion
2024-12-21 10:42:12 -05:00
5763 changed files with 430767 additions and 269470 deletions
+61 -28
View File
@@ -5,8 +5,9 @@
#==============================================================================#
module Settings
# The version of your game. It has to adhere to the MAJOR.MINOR.PATCH format.
GAME_VERSION = '6.2.4'
GAME_VERSION_NUMBER = "6.2.4"
GAME_VERSION = '6.4.0'
GAME_VERSION_NUMBER = "6.4.0"
LATEST_GAME_RELEASE = "6.4"
POKERADAR_LIGHT_ANIMATION_RED_ID = 17
POKERADAR_LIGHT_ANIMATION_GREEN_ID = 18
@@ -20,17 +21,21 @@ module Settings
FUSION_ICON_SPRITE_OFFSET = 10
#Infinite fusion settings
NB_POKEMON = 470
CUSTOM_BASE_SPRITES_FOLDER = "Graphics/CustomBattlers/customBaseSprites/"
NB_POKEMON = 501
CUSTOM_BASE_SPRITES_FOLDER = "Graphics/CustomBattlers/local_spritesBaseSprites/"
CUSTOM_BATTLERS_FOLDER = "Graphics/CustomBattlers/"
CUSTOM_BATTLERS_FOLDER_INDEXED = "Graphics/CustomBattlers/indexed/"
BATTLERS_FOLDER = "Graphics/Battlers/"
CUSTOM_SPRITES_TO_IMPORT_FOLDER = "Graphics/CustomBattlers/Sprites to import/"
CUSTOM_BATTLERS_FOLDER_INDEXED = "Graphics/CustomBattlers/local_sprites/indexed/"
BATTLERS_FOLDER = "Graphics/Battlers/Autogens/"
DOWNLOADED_SPRITES_FOLDER = "Graphics/temp/"
DEFAULT_SPRITE_PATH = "Graphics/Battlers/Special/000.png"
CREDITS_FILE_PATH = "Data/SPRITE_CREDS"
CREDITS_FILE_PATH = "Data/sprites/Sprite Credits.csv"
VERSION_FILE_PATH = "Data/VERSION"
CUSTOM_SPRITES_FILE_PATH = "Data/CUSTOM_SPRITES"
CUSTOM_DEX_ENTRIES_PATH = "Data/dex.json"
CUSTOM_SPRITES_FILE_PATH = "Data/sprites/CUSTOM_SPRITES"
BASE_SPRITES_FILE_PATH = "Data/sprites/BASE_SPRITES"
CUSTOM_DEX_ENTRIES_PATH = "Data/pokedex/dex.json"
AI_DEX_ENTRIES_PATH = "Data/pokedex/generated_entries.json"
UPDATED_SPRITESHEETS_CACHE = "Data/sprites/updated_spritesheets_cache"
BACK_ITEM_ICON_PATH = "Graphics/Items/back.png"
@@ -42,9 +47,9 @@ module Settings
PLAYER_TEMP_OUTFIT_FALLBACK = 'temp'
HATS_DATA_PATH = "Data/hats_data.json"
HAIRSTYLE_DATA_PATH = "Data/hairstyles_data.json"
CLOTHES_DATA_PATH = "Data/clothes_data.json"
HATS_DATA_PATH = "Data/outfits/hats_data.json"
HAIRSTYLE_DATA_PATH = "Data/outfits/hairstyles_data.json"
CLOTHES_DATA_PATH = "Data/outfits/clothes_data.json"
PLAYER_SURFBASE_FOLDER = 'surf_base/'
OW_SHINE_ANIMATION_ID=25
@@ -52,9 +57,12 @@ module Settings
HTTP_CONFIGS_FILE_URL = "https://raw.githubusercontent.com/infinitefusion/pif-downloadables/refs/heads/master/Settings.rb"
HTTP_CONFIGS_FILE_PATH = "Data/Scripts/DownloadedSettings.rb"
BASE_POKEMON_SPRITES_REPO_URL = ""
SPRITES_FILE_URL = "https://raw.githubusercontent.com/infinitefusion/infinitefusion-e18/main/Data/CUSTOM_SPRITES"
BASE_SPRITES_FILE_URL = "https://raw.githubusercontent.com/infinitefusion/infinitefusion-e18/main/Data/BASE_SPRITES"
STARTUP_MESSAGES = ""
LEVEL_CAPS=[12,22,26,35,38,45,51,54,62,62,63,64,64,65,67,68]
CUSTOM_ENTRIES_NAME_PLACEHOLDER = "POKENAME"
@@ -70,20 +78,35 @@ module Settings
NO_LEVEL_MODE_LEVEL_INCR = 5.8
NO_LEVEL_MODE_LEVEL_BASE = 6
SAVEFILE_NB_BACKUPS=10
DISCORD_URL = "https://discord.com/invite/infinitefusion"
WIKI_URL = "https://infinitefusion.fandom.com/"
AI_ENTRIES_URL = "https://ai-entries.pkmninfinitefusion.workers.dev/"
AI_ENTRIES_RATE_MAX_NB_REQUESTS = 10 #Nb. requests allowed in each time window
AI_ENTRIES_RATE_TIME_WINDOW = 120 # In seconds
AI_ENTRIES_RATE_LOG_FILE = 'Data/pokedex/dex_rate_limit.log' # Path to the log file
CUSTOMSPRITES_RATE_MAX_NB_REQUESTS = 15 #Nb. requests allowed in each time window
CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW = 120 # In seconds
CUSTOMSPRITES_RATE_LOG_FILE = 'Data/sprites/sprites_rate_limit.log' # Path to the log file
MAX_NB_SPRITES_TO_DOWNLOAD_AT_ONCE=5
CUSTOM_SPRITES_REPO_URL = "https://bitbucket.org/infinitefusionsprites/customsprites/raw/main/CustomBattlers/"
CUSTOM_SPRITES_NEW_URL = "https://infinitefusion.net/CustomBattlers/"
BASE_POKEMON_ALT_SPRITES_REPO_URL = "https://bitbucket.org/infinitefusionsprites/customsprites/raw/main/Other/BaseSprites/"
BASE_POKEMON_ALT_SPRITES_NEW_URL = "https://infinitefusion.net/Other/BaseSprites/"
BASE_POKEMON_SPRITESHEET_URL = "https://infinitefusion.net/spritesheets/spritesheets_base/"
CUSTOM_FUSIONS_SPRITESHEET_URL = "https://infinitefusion.net/spritesheets/spritesheets_custom/"
RIVAL_STARTER_PLACEHOLDER_SPECIES = :MEW #(MEW)
VAR_1_PLACEHOLDER_SPECIES = :DIALGA
VAR_2_PLACEHOLDER_SPECIES = :PALKIA
VAR_3_PLACEHOLDER_SPECIES = :GIRATINA
CUSTOMSPRITES_RATE_MAX_NB_REQUESTS = 5 #Nb. requests allowed in each time window
CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW = 120 # In seconds
CUSTOMSPRITES_RATE_LOG_FILE = 'Data/sprites/sprites_rate_limit.log' # Path to the log file
RIVAL_STARTER_PLACEHOLDER_VARIABLE = 250
OVERRIDE_BATTLE_LEVEL_SWITCH = 785
@@ -97,12 +120,11 @@ module Settings
WONDERTRADE_PUBLIC_KEY = "http://localhost:8080"
MAX_NB_OUTFITS=99
DEFAULT_OUTFIT_MALE = "red"
DEFAULT_OUTFIT_FEMALE = "leaf"
STARTING_OUTFIT = "pikajamas"
OUTFIT_PREVIEW_PICTURE_ID=20
DEFAULT_TRAINER_CARD_BG="BLUE"
# The generation that the battle system follows. Used throughout the battle
# scripts, and also by some other settings which are used in and out of battle
# (you can of course change those settings to suit your game).
@@ -146,6 +168,7 @@ module Settings
JOHTO_STARTERS = [:CHIKORITA, :CYNDAQUIL, :TOTODILE]
HOENN_STARTERS = [:TREECKO, :TORCHIC, :MUDKIP]
SINNOH_STARTERS = [:TURTWIG, :CHIMCHAR, :PIPLUP]
KALOS_STARTERS = [:CHESPIN, :FENNEKIN, :FROAKIE]
#=============================================================================
@@ -237,7 +260,7 @@ module Settings
BADGE_FOR_FLY = 3
BADGE_FOR_STRENGTH = 5
BADGE_FOR_DIVE = 9
BADGE_FOR_WATERFALL = 8
BADGE_FOR_WATERFALL = 9
BADGE_FOR_TELEPORT = 3
BADGE_FOR_BOUNCE = 8
BADGE_FOR_ROCKCLIMB = 16
@@ -337,10 +360,13 @@ module Settings
# * Name of the graphic, found in the Graphics/Pictures folder.
# * The graphic will always (true) or never (false) be shown on a wall map.
REGION_MAP_EXTRAS = [
[0, 51, 16, 15, "mapHiddenBerth", false],
[0, 52, 20, 14, "mapHiddenFaraday", false]
#[0, 51, 16, 15, "mapHiddenBerth", false],
#[0, 52, 20, 14, "mapHiddenFaraday", false]
]
TRIPLE_TYPES = [:QMARKS,:ICEFIREELECTRIC,:FIREWATERELECTRIC,:WATERGROUNDFLYING,:GHOSTSTEELWATER,
:FIREWATERGRASS,:GRASSSTEEL,:BUGSTEELPSYCHIC,:ICEROCKSTEEL]
#=============================================================================
# A list of maps used by roaming Pokémon. Each map has an array of other maps
@@ -385,11 +411,13 @@ module Settings
ROAMING_SPECIES = [
[:ENTEI, 50, 350, 1, "Legendary Birds",ROAMING_AREAS,:Sunny],
[:B245H243, 50, 341, 1, "Legendary Birds",ROAMING_AREAS,:Storm],
[:LATIOS, 50, 602, 0, "Legendary Birds",SEVII_ROAMING,:StrongWinds],
[:LATIAS, 50, 602, 0, "Legendary Birds",SEVII_ROAMING,:StrongWinds],
[:B379H378, 50, 602, 0, "Legendary Birds",SEVII_ROAMING,:StrongWinds],
[:B378H379, 50, 602, 0, "Legendary Birds",SEVII_ROAMING,:StrongWinds],
[:FEEBAS, 15, 4, 3, "Pokemon HeartGold and SoulSilver - Wild Pokemon Battle (Kanto)",SEVII_ROAMING,:Rain]
]
PINKAN_ISLAND_MAPS=[51,46,428,531]
#=============================================================================
# A set of arrays, each containing the details of a wild encounter that can
@@ -427,7 +455,7 @@ module Settings
[484, 50, :AXEW,20,20], #Safari zone 2
[485, 50, :DEINO,20,20], #Safari zone 3
[486, 50, :LARVITAR,20,20], #Safari zone 4
[487, 50, :BELDUM,20,20], #Safari zone 5
[487, 50, :JANGMOO,20,20], #Safari zone 5
[59, 50, :DUNSPARCE,25,30], #Rt. 21
[171, 50, :BIDOOF,2,5], #Rt. 22
[143, 50, :RIOLU,25,25], #Rt. 23
@@ -443,7 +471,7 @@ module Settings
[265, 50, :KIRLIA,25,30], #Rt. 34
[254, 50, :SMEARGLE,25,30], #Rt. 35
[267, 50, :SUDOWOODO,25,30], #Rt. 36
[500, 50, :ROSELIA,30,30], #National Park
[500, 50, :FOMANTIS,30,30], #National Park
[266, 50, :BRELOOM,30,30], #Ilex Forest
[670, 50, :WEAVILE,50,50], #Ice mountains
[528, 50, :PYUKUMUKU,20,20], #Treasure Beach
@@ -504,6 +532,11 @@ module Settings
# ["Deutsch", "deutsch.dat"]
]
#Technical
SPRITE_CACHE_MAX_NB=100
NEWEST_SPRITEPACK_MONTH = 12
NEWEST_SPRITEPACK_YEAR = 2020
#=============================================================================
# Available speech frames. These are graphic files in "Graphics/Windowskins/".
@@ -3,6 +3,8 @@
# HTTP utility functions
#
#############################
#
def pbPostData(url, postdata, filename=nil, depth=0)
if url[/^http:\/\/([^\/]+)(.*)$/]
host = $1
@@ -38,6 +40,8 @@ def pbPostData(url, postdata, filename=nil, depth=0)
end
def pbDownloadData(url, filename = nil, authorization = nil, depth = 0, &block)
return nil if !downloadAllowed?()
echoln "downloading data from #{url}"
headers = {
"Proxy-Connection" => "Close",
"Pragma" => "no-cache",
@@ -55,7 +59,8 @@ end
def pbDownloadToString(url)
begin
data = pbDownloadData(url)
return data
return data if data
return ""
rescue
return ""
end
@@ -83,3 +88,61 @@ def pbPostToFile(url, postdata, file)
rescue
end
end
def serialize_value(value)
if value.is_a?(Hash)
serialize_json(value)
elsif value.is_a?(String)
escaped_value = value.gsub(/\\/, '\\\\\\').gsub(/"/, '\\"').gsub(/\n/, '\\n').gsub(/\r/, '\\r')
"\"#{escaped_value}\""
else
value.to_s
end
end
def serialize_json(data)
#echoln data
# Manually serialize the JSON data into a string
parts = ["{"]
data.each_with_index do |(key, value), index|
parts << "\"#{key}\":#{serialize_value(value)}"
parts << "," unless index == data.size - 1
end
parts << "}"
return parts.join
end
def downloadAllowed?()
return $PokemonSystem.download_sprites==0
end
def clean_json_string(str)
# Remove non-UTF-8 characters and unexpected control characters
cleaned_str = str.encode('UTF-8', 'binary', invalid: :replace, undef: :replace, replace: '')
# Remove literal \n, \r, \t, etc.
cleaned_str = cleaned_str.gsub(/\\n|\\r|\\t/, '')
# Remove actual newlines and carriage returns
cleaned_str = cleaned_str.gsub(/[\n\r]/, '')
# Remove leading and trailing quotes
cleaned_str = cleaned_str.gsub(/\A"|"\Z/, '')
# Replace Unicode escape sequences with corresponding characters
cleaned_str = cleaned_str.gsub(/\\u([\da-fA-F]{4})/) { |match|
[$1.to_i(16)].pack("U")
}
return cleaned_str
end
@@ -1,6 +1,8 @@
# The Game module contains methods for saving and loading the game.
module Game
# Initializes various global variables and loads the game data.
def self.initialize
$PokemonTemp = PokemonTemp.new
$game_temp = Game_Temp.new
@@ -10,6 +12,8 @@ module Game
$data_common_events = load_data('Data/CommonEvents.rxdata')
$data_system = load_data('Data/System.rxdata')
pbLoadBattleAnimations
load_sprites_list_caches()
$updated_spritesheets = load_updated_spritesheets()
GameData.load_all
map_file = format('Data/Map%03d.rxdata', $data_system.start_map_id)
if $data_system.start_map_id == 0 || !pbRgssExists?(map_file)
@@ -17,8 +21,79 @@ module Game
end
end
# Loads bootup data from save file (if it exists) or creates bootup data (if
# it doesn't).
def self.load_updated_spritesheets
updated_spritesheets_file = Settings::UPDATED_SPRITESHEETS_CACHE
updated_spritesheets = []
if File.exist?(updated_spritesheets_file)
File.open(updated_spritesheets_file, "r") do |file|
file.each_line { |line| updated_spritesheets << line.chomp }
end
end
return updated_spritesheets
end
def self.load_sprites_list_caches()
self.load_custom_sprites_list_cache() if File.exists?(Settings::CUSTOM_SPRITES_FILE_PATH)
self.load_base_sprites_list_cache() if File.exists?(Settings::BASE_SPRITES_FILE_PATH)
end
def self.load_custom_sprites_list_cache()
return if !$game_temp.custom_sprites_list.keys.empty? #only load once at loadup
echoln "loading custom sprites cache"
sprite_index = {}
File.foreach(Settings::CUSTOM_SPRITES_FILE_PATH) do |line|
filename = line.strip
next unless filename =~ /^(\d+)\.(\d+)([a-zA-Z]*)\.png$/ # Regex: Captures the numbers and any trailing letters
# Match groups
head_number = $1.to_i # Head (e.g., "1" in "1.2.png")
body_number = $2.to_i # Body (e.g., "2" in "1.2.png")
letters = $3 # Letters after the second number (e.g., "a", "b", etc.)
key = "B#{body_number}H#{head_number}".to_sym
sprite_index[key] ||= []
if letters.empty?
sprite_index[key] << ""
else
sprite_index[key] << letters
end
end
$game_temp.custom_sprites_list = sprite_index
echoln "custom sprites loaded"
end
#
# {1 => ["","a","b"]
#etc.
#
def self.load_base_sprites_list_cache()
return if !$game_temp.base_sprites_list.keys.empty? #only load once at loadup
echoln "loading base sprites cache"
sprite_index = {}
File.foreach(Settings::BASE_SPRITES_FILE_PATH) do |line|
filename = line.strip
next unless filename =~ /^(\d+)([a-zA-Z]*)\.png$/ # Regex: Captures the numbers and any trailing letters
# Match groups
dex_number = $1.to_i # Head (e.g., "1" in "1.2.png")
letters = $2 # Letters after the second number (e.g., "a", "b", etc.)
key = dex_number
sprite_index[key] ||= []
if letters.empty?
sprite_index[key] << ""
else
sprite_index[key] << letters
end
end
$game_temp.base_sprites_list = sprite_index
echoln "custom sprites loaded"
end
#
# {:B10H10 => ["","a","b"]
#etc.
#
def self.set_up_system
SaveData.move_old_windows_save if System.platform[/Windows/]
save_data = (SaveData.exists?) ? SaveData.read_from_file(SaveData::FILE_PATH) : {}
@@ -51,11 +126,17 @@ module Game
pokemon.exp_when_fused_body=nil
pokemon.exp_gained_since_fused=nil
pokemon.level = 5
echoln pokemon.owner.id
pokemon.owner.id = $Trainer.id
pokemon.ot=$Trainer.name
pokemon.obtain_method = 0
pokemon.species = GameData::Species.get(pokemon.species).get_baby_species(false)
$Trainer.pokedex.set_seen(pokemon.species)
$Trainer.pokedex.set_owned(pokemon.species)
pokemon.reset_moves
pokemon.calc_stats
end
end
end
@@ -77,7 +77,12 @@ class Scene_Map
return RPG::Cache.size >= 100
end
def reset_switches_for_map_transfer
$game_switches[SWITCH_ILEX_FOREST_SPOOKED_POKEMON] = false
end
def transfer_player(cancelVehicles = true)
reset_switches_for_map_transfer()
$game_temp.player_transferring = false
pbCancelVehicles($game_temp.player_new_map_id) if cancelVehicles
autofade($game_temp.player_new_map_id)
@@ -242,7 +247,7 @@ class Scene_Map
@spritesetGlobal.playersprite.updateBitmap
end
def reset_map(fadeout = false)
def reset_map(fadeout = false,reset_music=true)
$MapFactory.setup($game_map.map_id)
$game_player.moveto($game_player.x, $game_player.y)
$game_player.straighten
@@ -254,7 +259,7 @@ class Scene_Map
$game_temp.transition_processing = false
Graphics.transition(20)
end
$game_map.autoplay
$game_map.autoplay if reset_music
Graphics.frame_reset
Input.update
end
@@ -393,8 +393,8 @@ class Interpreter
old_y = event.y
# Apply strict version of passable, which treats tiles that are passable
# only from certain directions as fully impassible
return if !event.can_move_in_direction?($game_player.direction, true)
# ^why?? - no
return if !event.can_move_in_direction?($game_player.direction, false)
case $game_player.direction
when 2 then event.move_down
when 4 then event.move_left
@@ -28,6 +28,8 @@ class Game_Temp
attr_accessor :unimportedSprites
attr_accessor :nb_imported_sprites
attr_accessor :loading_screen
attr_accessor :custom_sprites_list
attr_accessor :base_sprites_list
#-----------------------------------------------------------------------------
# * Object Initialization
@@ -55,6 +57,9 @@ class Game_Temp
@message_window_showing = false
@transition_processing = false
@mart_prices = {}
@custom_sprites_list ={}
@base_sprites_list ={}
end
def clear_mart_prices
@@ -9,6 +9,7 @@ class Game_Switches
# * Object Initialization
#-----------------------------------------------------------------------------
def initialize
echoln caller
@data = []
end
#-----------------------------------------------------------------------------
@@ -57,7 +57,7 @@ class Game_Picture
# opacity : opacity level
# blend_type : blend method
#-----------------------------------------------------------------------------
def show(name, origin, x, y, zoom_x, zoom_y, opacity, blend_type)
def show(name, origin, x, y, zoom_x=100, zoom_y=100, opacity=255, blend_type=0)
@name = name
@origin = origin
@x = x.to_f
@@ -9,7 +9,6 @@ class Game_Player < Game_Character
attr_accessor :bump_se
attr_accessor :charsetData
attr_accessor :encounter_count
attr_accessor :outfit_changed
attr_accessor :x
attr_accessor :y
@@ -11,6 +11,7 @@ class Game_CommonEvent
#-----------------------------------------------------------------------------
def initialize(common_event_id)
@common_event_id = common_event_id
@interpreter = nil
refresh
end
@@ -141,6 +141,7 @@ end
class DependentEvents
attr_reader :lastUpdate
attr_reader :realEvents
attr_writer :follows_player
def createEvent(eventData)
@@ -60,6 +60,9 @@ end
class Sprite_Character < RPG::Sprite
attr_accessor :character
attr_accessor :pending_bitmap
attr_accessor :bitmap_override
attr_accessor :charbitmap
def initialize(viewport, character = nil)
super(viewport)
@@ -76,9 +79,33 @@ class Sprite_Character < RPG::Sprite
@reflection = Sprite_Reflection.new(self, character, viewport)
end
@surfbase = Sprite_SurfBase.new(self, character, viewport) if character == $game_player
checkModifySpriteGraphics(@character) if @character
update
end
def checkModifySpriteGraphics(character)
return if character == $game_player || !character.name
if TYPE_EXPERTS_APPEARANCES.keys.include?(character.name.to_sym)
typeExpert = character.name.to_sym
setSpriteToAppearance(TYPE_EXPERTS_APPEARANCES[typeExpert])
end
end
def setSpriteToAppearance(trainerAppearance)
#return if !@charbitmap || !@charbitmap.bitmap
new_bitmap = AnimatedBitmap.new(getBaseOverworldSpriteFilename())#@charbitmap
new_bitmap.bitmap = generateNPCClothedBitmapStatic(trainerAppearance)
@bitmap_override = new_bitmap
updateBitmap
end
def clearBitmapOverride()
@bitmap_override = nil
updateBitmap
end
def setSurfingPokemon(pokemonSpecies)
@surfingPokemon = pokemonSpecies
@surfbase.setPokemon(pokemonSpecies) if @surfbase
@@ -148,10 +175,14 @@ class Sprite_Character < RPG::Sprite
end
def refreshOutfit()
self.bitmap = getClothedPlayerSprite(true)
self.pending_bitmap = getClothedPlayerSprite(true)
end
def update
if self.pending_bitmap
self.bitmap = self.pending_bitmap
self.pending_bitmap = nil
end
return if @character.is_a?(Game_Event) && !@character.should_update?
super
if should_update?
@@ -178,6 +209,7 @@ class Sprite_Character < RPG::Sprite
@charbitmap.dispose if @charbitmap
@charbitmap = updateCharacterBitmap()
@charbitmap= @bitmap_override.clone if @bitmap_override
RPG::Cache.retain('Graphics/Characters/', @character_name, @character_hue) if @charbitmapAnimated = true
@bushbitmap.dispose if @bushbitmap
@@ -9,13 +9,14 @@ module Outfit_Offsets
RUN_OFFSETS_DOWN = [[0, 2], [0, 6], [0, 2], [0, 6]]
RUN_OFFSETS_LEFT = [[-2, -2], [-2, -2], [-2, -2], [-2, -2]]
RUN_OFFSETS_RIGHT = [[4, -2], [4, -2], [4, -2], [4, -2]]
RUN_OFFSETS_RIGHT = [[2, -2], [2, -2], [2, -2], [2, -2]]
RUN_OFFSETS_UP = [[0, -2], [0, -2], [0, -2], [0, -2]]
SURF_OFFSETS_DOWN = [[0, -6], [0, -4], [0, -6], [0, -4]]
SURF_OFFSETS_LEFT = [[-2, -10], [-2, -8], [-2, -10], [-2, -8]]
SURF_OFFSETS_RIGHT = [[4, -10], [4, -8], [4, -10], [4, -8]]
SURF_OFFSETS_UP = [[0, -6], [0, -4], [0, -6], [0, -4]]
#SURF_OFFSETS_UP = [[0, -6], [0, -4], [0, -6], [0, -4]]
SURF_OFFSETS_UP = [[0, -10], [0, -8], [0, -10], [0, -8]]
DIVE_OFFSETS_DOWN = [[0, -6], [0, -4], [0, -6], [0, -4]]
DIVE_OFFSETS_LEFT = [[6, -8], [6, -6], [6, -8], [6, -6]]
@@ -101,7 +101,7 @@ module MessageConfig
def self.pbSettingToTextSpeed(speed)
case speed
when 0 then return 1
when 1 then return -2
when 1 then return -3
when 2 then return -999
end
return TEXT_SPEED || 1
@@ -1,6 +1,7 @@
#===============================================================================
#
#===============================================================================
class AnimatedBitmap
attr_reader :path
attr_reader :filename
@@ -23,6 +24,19 @@ class AnimatedBitmap
end
end
def setup_from_bitmap(bitmap,hue=0)
@path = ""
@filename = ""
@bitmap = GifBitmap.new("", '', hue)
@bitmap.bitmap = bitmap;
end
def self.from_bitmap(bitmap, hue=0)
obj = allocate
obj.send(:setup_from_bitmap, bitmap, hue)
obj
end
def pbSetColor(r = 0, g = 0, b = 0, a = 255)
color = Color.new(r, g, b, a)
pbSetColorValue(color)
@@ -40,7 +54,7 @@ class AnimatedBitmap
def shiftColors(offset = 0)
@bitmap = GifBitmap.new(@path, @filename, offset)
@bitmap.bitmap.hue_change(offset)
end
def [](index)
@@ -133,6 +147,7 @@ class AnimatedBitmap
end
#===============================================================================
#
#===============================================================================
@@ -734,8 +734,10 @@ def pbMessageDisplay(msgwindow, message, letterbyletter = true, commandProc = ni
head = getBasePokemonID(param.to_i, false)
body = getBasePokemonID(param.to_i, true)
facewindow.dispose if facewindow
path = obtainPokemonSpritePath(body, head, true)
facewindow = isFusion ? PictureWindow.new(path) : PictureWindow.new("Graphics/Battlers/#{head}/#{head}.png")
#path = obtainPokemonSpritePath(body, head, true) if isFusion
spriteLoader = BattleSpriteLoader.new
facewindow = isFusion ? PictureWindow.new(spriteLoader.load_fusion_sprite(head,body)) : PictureWindow.new(spriteLoader.load_base_sprite(head))
pbPositionNearMsgWindow(facewindow, msgwindow, :left)
facewindow.viewport = msgwindow.viewport
facewindow.z = msgwindow.z
@@ -906,8 +908,10 @@ def pbMessageChooseNumber(message, params, &block)
return ret
end
def pbShowCommands(msgwindow, commands = nil, cmdIfCancel = 0, defaultCmd = 0)
return 0 if !commands
$PokemonTemp.speechbubble_arrow.visible =false if $PokemonTemp.speechbubble_arrow && !$PokemonTemp.speechbubble_arrow.disposed?
if defaultCmd == 0 && ($game_variables && $game_variables[VAR_COMMAND_WINDOW_INDEX] != 0)
defaultCmd = $game_variables[VAR_COMMAND_WINDOW_INDEX]
end
@@ -262,4 +262,28 @@ GameData::TerrainTag.register({
:id => :SharpedoObstacle,
:id_number => 23,
:sharpedoObstacle => true
})
GameData::TerrainTag.register({
:id => :Grass_alt1,
:id_number => 24,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
})
GameData::TerrainTag.register({
:id => :Grass_alt2,
:id_number => 25,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
})
GameData::TerrainTag.register({
:id => :Grass_alt3,
:id_number => 26,
:shows_grass_rustle => true,
:land_wild_encounters => true,
:battle_environment => :Grass
})
@@ -33,6 +33,27 @@ GameData::EncounterType.register({
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :Land1,
:type => :land,
:trigger_chance => 21,
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :Land2,
:type => :land,
:trigger_chance => 21,
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :Land3,
:type => :land,
:trigger_chance => 21,
:old_slots => [1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
})
GameData::EncounterType.register({
:id => :LandDay,
:type => :land,
@@ -118,8 +118,10 @@ module GameData
def is_mulch?; return @type == 11; end
def is_mega_stone?; return @type == 12; end # Does NOT include Red Orb/Blue Orb
UNTOSSABLE_ITEMS =[:PINKANBERRY,:DYNAMITE, :TM00]
def is_important?
return true if is_key_item? || is_HM? || is_TM?
return true if UNTOSSABLE_ITEMS.include?(@id)
return false
end
@@ -103,7 +103,7 @@ module GameData
def self.sprite_bitmap(species, form = 0, gender = 0, shiny = false, shadow = false, back = false, egg = false)
return self.egg_sprite_bitmap(species, form) if egg
return self.back_sprite_bitmap(species, form, gender, shiny, shadow) if back
return self.front_sprite_bitmap(species, form, gender, shiny, shadow)
return self.front_sprite_bitmap(species, shiny,)
end
def self.sprite_bitmap_from_pokemon(pkmn, back = false, species = nil)
@@ -7,7 +7,7 @@ module GameData
attr_reader :types
DATA = {}
DATA_FILENAME = "encounters_modern.dat"
DATA_FILENAME = "encounters_remix.dat"
extend ClassMethodsSymbols
include InstanceMethods
@@ -149,11 +149,14 @@ module GameData
end
def replace_species_to_randomized_gym(species, trainerId, pokemonIndex)
return if !pokemonIndex
return if !trainerId
return if !species
if $PokemonGlobal.randomGymTrainersHash == nil
$PokemonGlobal.randomGymTrainersHash = {}
end
if $game_switches[SWITCH_RANDOM_GYM_PERSIST_TEAMS] && $PokemonGlobal.randomGymTrainersHash != nil
if $PokemonGlobal.randomGymTrainersHash[trainerId] != nil && $PokemonGlobal.randomGymTrainersHash[trainerId].length >= $PokemonGlobal.randomTrainersHash[trainerId].length
if $PokemonGlobal.randomGymTrainersHash[trainerId] && $PokemonGlobal.randomGymTrainersHash[trainerId].length >= $PokemonGlobal.randomTrainersHash[trainerId].length
newSpecies = getSpecies($PokemonGlobal.randomGymTrainersHash[trainerId][pokemonIndex])
return newSpecies if newSpecies
return species
@@ -199,6 +202,7 @@ module GameData
end
def replace_species_to_randomized(species, trainerId, pokemonIndex)
return species if $game_switches[SWITCH_DONT_RANDOMIZE]
return species if $game_switches[SWITCH_FIRST_RIVAL_BATTLE]
return species if getDexNumberForSpecies(species) >= Settings::ZAPMOLCUNO_NB
if isGymBattle() && $game_switches[SWITCH_RANDOMIZE_GYMS_SEPARATELY]
@@ -10,7 +10,7 @@ module GameData
attr_reader :pokemon
DATA = {}
DATA_FILENAME = "trainers_modern.dat"
DATA_FILENAME = "trainers_remix.dat"
SCHEMA = {
"Items" => [:items, "*e", :Item],
@@ -194,6 +194,7 @@ module GameData
def replace_species_to_randomized(species, trainerId, pokemonIndex)
return species if $game_switches[SWITCH_FIRST_RIVAL_BATTLE]
return species if $game_switches[SWITCH_DONT_RANDOMIZE]
if isGymBattle() && $game_switches[SWITCH_RANDOMIZE_GYMS_SEPARATELY]
return replace_species_to_randomized_gym(species, trainerId, pokemonIndex)
end
@@ -1,9 +1,9 @@
class PokeBattle_Battler
# Fundamental to this object
attr_reader :battle
attr_reader :battle
attr_accessor :index
# The Pokémon and its properties
attr_reader :pokemon
attr_reader :pokemon
attr_accessor :pokemonIndex
attr_accessor :species
attr_accessor :type1
@@ -17,10 +17,10 @@ class PokeBattle_Battler
attr_accessor :spatk
attr_accessor :speed
attr_accessor :stages
attr_reader :totalhp
attr_reader :fainted # Boolean to mark whether self has fainted properly
attr_accessor :captured # Boolean to mark whether self was captured
attr_reader :dummy
attr_reader :totalhp
attr_reader :fainted # Boolean to mark whether self has fainted properly
attr_accessor :captured # Boolean to mark whether self was captured
attr_reader :dummy
attr_accessor :effects
# Things the battler has done in battle
attr_accessor :turnCount
@@ -32,16 +32,16 @@ class PokeBattle_Battler
attr_accessor :lastMoveUsed
attr_accessor :lastMoveUsedType
attr_accessor :lastRegularMoveUsed
attr_accessor :lastRegularMoveTarget # For Instruct
attr_accessor :lastRegularMoveTarget # For Instruct
attr_accessor :lastRoundMoved
attr_accessor :lastMoveFailed # For Stomping Tantrum
attr_accessor :lastRoundMoveFailed # For Stomping Tantrum
attr_accessor :lastMoveFailed # For Stomping Tantrum
attr_accessor :lastRoundMoveFailed # For Stomping Tantrum
attr_accessor :movesUsed
attr_accessor :currentMove # ID of multi-turn move currently being used
attr_accessor :tookDamage # Boolean for whether self took damage this round
attr_accessor :currentMove # ID of multi-turn move currently being used
attr_accessor :tookDamage # Boolean for whether self took damage this round
attr_accessor :tookPhysicalHit
attr_accessor :damageState
attr_accessor :initialHP # Set at the start of each move's usage
attr_accessor :initialHP # Set at the start of each move's usage
#=============================================================================
# Complex accessors
@@ -68,7 +68,6 @@ class PokeBattle_Battler
return @pokemon.ability_index >= 2
end
def ability=(value)
new_ability = GameData::Ability.try_get(value)
@ability_id = (new_ability) ? new_ability.id : nil
@@ -85,14 +84,14 @@ class PokeBattle_Battler
end
def defense
return @spdef if @battle.field.effects[PBEffects::WonderRoom]>0
return @spdef if @battle.field.effects[PBEffects::WonderRoom] > 0
return @defense
end
attr_writer :defense
def spdef
return @defense if @battle.field.effects[PBEffects::WonderRoom]>0
return @defense if @battle.field.effects[PBEffects::WonderRoom] > 0
return @spdef
end
@@ -101,18 +100,22 @@ class PokeBattle_Battler
attr_reader :hp
def hp=(value)
checkHPRelatedFormChange(value) #careful, setting @pokemon.hp also calls a method for changing the form on hp change so we should not change the form here, just update the graphics
@hp = value.to_i
@pokemon.hp = value.to_i if @pokemon
end
def fainted?; return @hp<=0; end
def fainted?
return @hp <= 0;
end
alias isFainted? fainted?
attr_reader :status
def status=(value)
@effects[PBEffects::Truant] = false if @status == :SLEEP && value != :SLEEP
@effects[PBEffects::Toxic] = 0 if value != :POISON
@effects[PBEffects::Toxic] = 0 if value != :POISON
@status = value
@pokemon.status = value if @pokemon
self.statusCount = 0 if value != :POISON && value != :SLEEP
@@ -130,9 +133,17 @@ class PokeBattle_Battler
#=============================================================================
# Properties from Pokémon
#=============================================================================
def happiness; return @pokemon ? @pokemon.happiness : 0; end
def nature; return @pokemon ? @pokemon.nature : 0; end
def pokerusStage; return @pokemon ? @pokemon.pokerusStage : 0; end
def happiness
return @pokemon ? @pokemon.happiness : 0;
end
def nature
return @pokemon ? @pokemon.nature : 0;
end
def pokerusStage
return @pokemon ? @pokemon.pokerusStage : 0;
end
#=============================================================================
# Mega Evolution, Primal Reversion, Shadow Pokémon
@@ -142,7 +153,10 @@ class PokeBattle_Battler
return @pokemon && @pokemon.hasMegaForm?
end
def mega?; return @pokemon && @pokemon.mega?; end
def mega?
return @pokemon && @pokemon.mega?;
end
alias isMega? mega?
def hasPrimal?
@@ -150,13 +164,21 @@ class PokeBattle_Battler
return @pokemon && @pokemon.hasPrimalForm?
end
def primal?; return @pokemon && @pokemon.primal?; end
def primal?
return @pokemon && @pokemon.primal?;
end
alias isPrimal? primal?
def shadowPokemon?; return false; end
def shadowPokemon?
return false;
end
alias isShadow? shadowPokemon?
def inHyperMode?; return false; end
def inHyperMode?
return false;
end
#=============================================================================
# Display-only properties
@@ -192,6 +214,7 @@ class PokeBattle_Battler
return @effects[PBEffects::Illusion].shiny? if @effects[PBEffects::Illusion]
return @pokemon && @pokemon.shiny?
end
alias isShiny? shiny?
def glitter?
@@ -202,6 +225,7 @@ class PokeBattle_Battler
return false if !@battle.wildBattle?
return $Trainer.owned?(displaySpecies)
end
alias owned owned?
def abilityName
@@ -214,27 +238,27 @@ class PokeBattle_Battler
return (itm) ? itm.name : ""
end
def pbThis(lowerCase=false)
def pbThis(lowerCase = false)
if opposes?
if @battle.trainerBattle?
return lowerCase ? _INTL("the opposing {1}",name) : _INTL("The opposing {1}",name)
return lowerCase ? _INTL("the opposing {1}", name) : _INTL("The opposing {1}", name)
else
return lowerCase ? _INTL("the wild {1}",name) : _INTL("The wild {1}",name)
return lowerCase ? _INTL("the wild {1}", name) : _INTL("The wild {1}", name)
end
elsif !pbOwnedByPlayer?
return lowerCase ? _INTL("the ally {1}",name) : _INTL("The ally {1}",name)
return lowerCase ? _INTL("the ally {1}", name) : _INTL("The ally {1}", name)
end
return name
end
def pbTeam(lowerCase=false)
def pbTeam(lowerCase = false)
if opposes?
return lowerCase ? _INTL("the opposing team") : _INTL("The opposing team")
end
return lowerCase ? _INTL("your team") : _INTL("Your team")
end
def pbOpposingTeam(lowerCase=false)
def pbOpposingTeam(lowerCase = false)
if opposes?
return lowerCase ? _INTL("your team") : _INTL("Your team")
end
@@ -246,46 +270,46 @@ class PokeBattle_Battler
#=============================================================================
def pbSpeed
return 1 if fainted?
stageMul = [2,2,2,2,2,2, 2, 3,4,5,6,7,8]
stageDiv = [8,7,6,5,4,3, 2, 2,2,2,2,2,2]
stageMul = [2, 2, 2, 2, 2, 2, 2, 3, 4, 5, 6, 7, 8]
stageDiv = [8, 7, 6, 5, 4, 3, 2, 2, 2, 2, 2, 2, 2]
stage = @stages[:SPEED] + 6
speed = @speed*stageMul[stage]/stageDiv[stage]
speed = @speed * stageMul[stage] / stageDiv[stage]
speedMult = 1.0
# Ability effects that alter calculated Speed
if abilityActive?
speedMult = BattleHandlers.triggerSpeedCalcAbility(self.ability,self,speedMult)
speedMult = BattleHandlers.triggerSpeedCalcAbility(self.ability, self, speedMult)
end
# Item effects that alter calculated Speed
if itemActive?
speedMult = BattleHandlers.triggerSpeedCalcItem(self.item,self,speedMult)
speedMult = BattleHandlers.triggerSpeedCalcItem(self.item, self, speedMult)
end
# Other effects
speedMult *= 2 if pbOwnSide.effects[PBEffects::Tailwind]>0
speedMult /= 2 if pbOwnSide.effects[PBEffects::Swamp]>0
speedMult *= 2 if pbOwnSide.effects[PBEffects::Tailwind] > 0
speedMult /= 2 if pbOwnSide.effects[PBEffects::Swamp] > 0
# Paralysis
if status == :PARALYSIS && !hasActiveAbility?(:QUICKFEET)
speedMult /= (Settings::MECHANICS_GENERATION >= 7) ? 2 : 4
end
# Badge multiplier
if @battle.internalBattle && pbOwnedByPlayer? &&
@battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPEED
@battle.pbPlayer.badge_count >= Settings::NUM_BADGES_BOOST_SPEED
speedMult *= 1.1
end
# Calculation
return [(speed*speedMult).round,1].max
return [(speed * speedMult).round, 1].max
end
def pbWeight
ret = (@pokemon) ? @pokemon.weight : 500
ret += @effects[PBEffects::WeightChange]
ret = 1 if ret<1
ret = 1 if ret < 1
if abilityActive? && !@battle.moldBreaker
ret = BattleHandlers.triggerWeightCalcAbility(self.ability,self,ret)
ret = BattleHandlers.triggerWeightCalcAbility(self.ability, self, ret)
end
if itemActive?
ret = BattleHandlers.triggerWeightCalcItem(self.item,self,ret)
ret = BattleHandlers.triggerWeightCalcItem(self.item, self, ret)
end
return [ret,1].max
return [ret, 1].max
end
#=============================================================================
@@ -293,11 +317,11 @@ class PokeBattle_Battler
#=============================================================================
def plainStats
ret = {}
ret[:ATTACK] = self.attack
ret[:DEFENSE] = self.defense
ret[:SPECIAL_ATTACK] = self.spatk
ret[:ATTACK] = self.attack
ret[:DEFENSE] = self.defense
ret[:SPECIAL_ATTACK] = self.spatk
ret[:SPECIAL_DEFENSE] = self.spdef
ret[:SPEED] = self.speed
ret[:SPEED] = self.speed
return ret
end
@@ -313,7 +337,6 @@ class PokeBattle_Battler
return @pokemon.hasHeadOf?(check_species)
end
def isFusionOf(check_species)
return @pokemon.isFusionOf(check_species)
end
@@ -322,13 +345,12 @@ class PokeBattle_Battler
return @pokemon.isFusion?()
end
# Returns the active types of this Pokémon. The array should not include the
# same type more than once, and should not include any invalid type numbers
# (e.g. -1).
def pbTypes(withType3=false)
def pbTypes(withType3 = false)
ret = [@type1]
ret.push(@type2) if @type2!=@type1
ret.push(@type2) if @type2 != @type1
# Burn Up erases the Fire-type.
ret.delete(:FIRE) if @effects[PBEffects::BurnUp]
# Roost erases the Flying-type. If there are no types left, adds the Normal-
@@ -373,6 +395,7 @@ class PokeBattle_Battler
return check_ability.include?(@ability_id) if check_ability.is_a?(Array)
return self.ability == check_ability
end
alias hasWorkingAbility hasActiveAbility?
# Applies to both losing self's ability (i.e. being replaced by another) and
@@ -385,8 +408,8 @@ class PokeBattle_Battler
# Form-changing abilities
:BATTLEBOND,
:DISGUISE,
# :FLOWERGIFT, # This can be stopped
# :FORECAST, # This can be stopped
# :FLOWERGIFT, # This can be stopped
# :FORECAST, # This can be stopped
:MULTITYPE,
:POWERCONSTRUCT,
:SCHOOLING,
@@ -427,11 +450,11 @@ class PokeBattle_Battler
return ability_blacklist.include?(abil.id)
end
def itemActive?(ignoreFainted=false)
def itemActive?(ignoreFainted = false)
return false if fainted? && !ignoreFainted
return false if @effects[PBEffects::Embargo]>0
return false if @battle.field.effects[PBEffects::MagicRoom]>0
return false if hasActiveAbility?(:KLUTZ,ignoreFainted)
return false if @effects[PBEffects::Embargo] > 0
return false if @battle.field.effects[PBEffects::MagicRoom] > 0
return false if hasActiveAbility?(:KLUTZ, ignoreFainted)
return true
end
@@ -440,6 +463,7 @@ class PokeBattle_Battler
return check_item.include?(@item_id) if check_item.is_a?(Array)
return self.item == check_item
end
alias hasWorkingItem hasActiveItem?
# Returns whether the specified item will be unlosable for this Pokémon.
@@ -448,9 +472,10 @@ class PokeBattle_Battler
return true if GameData::Item.get(check_item).is_mail?
return false if @effects[PBEffects::Transform]
# Items that change a Pokémon's form
if mega? # Check if item was needed for this Mega Evolution
if mega? # Check if item was needed for this Mega Evolution
return true if @pokemon.species_data.mega_stone == check_item
else # Check if item could cause a Mega Evolution
else
# Check if item could cause a Mega Evolution
GameData::Species.each do |data|
next if data.species != @species || data.unmega_form != @form
return true if data.mega_stone == check_item
@@ -516,15 +541,15 @@ class PokeBattle_Battler
return true
end
def takesIndirectDamage?(showMsg=false)
def takesIndirectDamage?(showMsg = false)
return false if fainted?
if hasActiveAbility?(:MAGICGUARD)
if showMsg
@battle.pbShowAbilitySplash(self)
if PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} is unaffected!",pbThis))
@battle.pbDisplay(_INTL("{1} is unaffected!", pbThis))
else
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!",pbThis,abilityName))
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!", pbThis, abilityName))
end
@battle.pbHideAbilitySplash(self)
end
@@ -536,8 +561,8 @@ class PokeBattle_Battler
def takesSandstormDamage?
return false if !takesIndirectDamage?
return false if pbHasType?(:GROUND) || pbHasType?(:ROCK) || pbHasType?(:STEEL)
return false if inTwoTurnAttack?("0CA","0CB") # Dig, Dive
return false if hasActiveAbility?([:OVERCOAT,:SANDFORCE,:SANDRUSH,:SANDVEIL])
return false if inTwoTurnAttack?("0CA", "0CB") # Dig, Dive
return false if hasActiveAbility?([:OVERCOAT, :SANDFORCE, :SANDRUSH, :SANDVEIL])
return false if hasActiveItem?(:SAFETYGOGGLES)
return true
end
@@ -545,8 +570,8 @@ class PokeBattle_Battler
def takesHailDamage?
return false if !takesIndirectDamage?
return false if pbHasType?(:ICE)
return false if inTwoTurnAttack?("0CA","0CB") # Dig, Dive
return false if hasActiveAbility?([:OVERCOAT,:ICEBODY,:SNOWCLOAK])
return false if inTwoTurnAttack?("0CA", "0CB") # Dig, Dive
return false if hasActiveAbility?([:OVERCOAT, :ICEBODY, :SNOWCLOAK])
return false if hasActiveItem?(:SAFETYGOGGLES)
return true
end
@@ -557,10 +582,10 @@ class PokeBattle_Battler
return true
end
def affectedByPowder?(showMsg=false)
def affectedByPowder?(showMsg = false)
return false if fainted?
if pbHasType?(:GRASS) && Settings::MORE_TYPE_EFFECTS
@battle.pbDisplay(_INTL("{1} is unaffected!",pbThis)) if showMsg
@battle.pbDisplay(_INTL("{1} is unaffected!", pbThis)) if showMsg
return false
end
if Settings::MECHANICS_GENERATION >= 6
@@ -568,9 +593,9 @@ class PokeBattle_Battler
if showMsg
@battle.pbShowAbilitySplash(self)
if PokeBattle_SceneConstants::USE_ABILITY_SPLASH
@battle.pbDisplay(_INTL("{1} is unaffected!",pbThis))
@battle.pbDisplay(_INTL("{1} is unaffected!", pbThis))
else
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!",pbThis,abilityName))
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!", pbThis, abilityName))
end
@battle.pbHideAbilitySplash(self)
end
@@ -578,7 +603,7 @@ class PokeBattle_Battler
end
if hasActiveItem?(:SAFETYGOGGLES)
if showMsg
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!",pbThis,itemName))
@battle.pbDisplay(_INTL("{1} is unaffected because of its {2}!", pbThis, itemName))
end
return false
end
@@ -587,50 +612,50 @@ class PokeBattle_Battler
end
def canHeal?
return false if fainted? || @hp>=@totalhp
return false if @effects[PBEffects::HealBlock]>0
return false if fainted? || @hp >= @totalhp
return false if @effects[PBEffects::HealBlock] > 0
return true
end
def affectedByContactEffect?(showMsg=false)
def affectedByContactEffect?(showMsg = false)
return false if fainted?
if hasActiveItem?(:PROTECTIVEPADS)
@battle.pbDisplay(_INTL("{1} protected itself with the {2}!",pbThis,itemName)) if showMsg
@battle.pbDisplay(_INTL("{1} protected itself with the {2}!", pbThis, itemName)) if showMsg
return false
end
return true
end
def movedThisRound?
return @lastRoundMoved && @lastRoundMoved==@battle.turnCount
return @lastRoundMoved && @lastRoundMoved == @battle.turnCount
end
def usingMultiTurnAttack?
return true if @effects[PBEffects::TwoTurnAttack]
return true if @effects[PBEffects::HyperBeam]>0
return true if @effects[PBEffects::Rollout]>0
return true if @effects[PBEffects::Outrage]>0
return true if @effects[PBEffects::Uproar]>0
return true if @effects[PBEffects::Bide]>0
return true if @effects[PBEffects::HyperBeam] > 0
return true if @effects[PBEffects::Rollout] > 0
return true if @effects[PBEffects::Outrage] > 0
return true if @effects[PBEffects::Uproar] > 0
return true if @effects[PBEffects::Bide] > 0
return false
end
def inTwoTurnAttack?(*arg)
return false if !@effects[PBEffects::TwoTurnAttack]
ttaFunction = GameData::Move.get(@effects[PBEffects::TwoTurnAttack]).function_code
arg.each { |a| return true if a==ttaFunction }
arg.each { |a| return true if a == ttaFunction }
return false
end
def semiInvulnerable?
return inTwoTurnAttack?("0C9","0CA","0CB","0CC","0CD","0CE","14D")
return inTwoTurnAttack?("0C9", "0CA", "0CB", "0CC", "0CD", "0CE", "14D")
end
def pbEncoredMoveIndex
return -1 if @effects[PBEffects::Encore]==0 || !@effects[PBEffects::EncoreMove]
return -1 if @effects[PBEffects::Encore] == 0 || !@effects[PBEffects::EncoreMove]
ret = -1
eachMoveWithIndex do |m,i|
next if m.id!=@effects[PBEffects::EncoreMove]
eachMoveWithIndex do |m, i|
next if m.id != @effects[PBEffects::EncoreMove]
ret = i
break
end
@@ -638,42 +663,42 @@ class PokeBattle_Battler
end
def initialItem
return @battle.initialItems[@index&1][@pokemonIndex]
return @battle.initialItems[@index & 1][@pokemonIndex]
end
def setInitialItem(newItem)
@battle.initialItems[@index&1][@pokemonIndex] = newItem
@battle.initialItems[@index & 1][@pokemonIndex] = newItem
end
def recycleItem
return @battle.recycleItems[@index&1][@pokemonIndex]
return @battle.recycleItems[@index & 1][@pokemonIndex]
end
def setRecycleItem(newItem)
@battle.recycleItems[@index&1][@pokemonIndex] = newItem
@battle.recycleItems[@index & 1][@pokemonIndex] = newItem
end
def belched?
return @battle.belch[@index&1][@pokemonIndex]
return @battle.belch[@index & 1][@pokemonIndex]
end
def setBelched
@battle.belch[@index&1][@pokemonIndex] = true
@battle.belch[@index & 1][@pokemonIndex] = true
end
#=============================================================================
# Methods relating to this battler's position on the battlefield
#=============================================================================
# Returns whether the given position belongs to the opposing Pokémon's side.
def opposes?(i=0)
def opposes?(i = 0)
i = i.index if i.respond_to?("index")
return (@index&1)!=(i&1)
return (@index & 1) != (i & 1)
end
# Returns whether the given position/battler is near to self.
def near?(i)
i = i.index if i.respond_to?("index")
return @battle.nearBattlers?(@index,i)
return @battle.nearBattlers?(@index, i)
end
# Returns whether self is owned by the player.
@@ -684,13 +709,13 @@ class PokeBattle_Battler
# Returns 0 if self is on the player's side, or 1 if self is on the opposing
# side.
def idxOwnSide
return @index&1
return @index & 1
end
# Returns 1 if self is on the player's side, or 0 if self is on the opposing
# side.
def idxOpposingSide
return (@index&1)^1
return (@index & 1) ^ 1
end
# Returns the data structure for this battler's side.
@@ -706,7 +731,7 @@ class PokeBattle_Battler
# Yields each unfainted ally Pokémon.
def eachAlly
@battle.battlers.each do |b|
yield b if b && !b.fainted? && !b.opposes?(@index) && b.index!=@index
yield b if b && !b.fainted? && !b.opposes?(@index) && b.index != @index
end
end
@@ -717,7 +742,7 @@ class PokeBattle_Battler
# Returns the battler that is most directly opposite to self. unfaintedOnly is
# whether it should prefer to return a non-fainted battler.
def pbDirectOpposing(unfaintedOnly=false)
def pbDirectOpposing(unfaintedOnly = false)
@battle.pbGetOpposingIndicesInOrder(@index).each do |i|
next if !@battle.battlers[i]
break if unfaintedOnly && @battle.battlers[i].fainted?
@@ -728,6 +753,49 @@ class PokeBattle_Battler
@battle.pbGetOpposingIndicesInOrder(@index).each do |i|
return @battle.battlers[i] if @battle.battlers[i]
end
return @battle.battlers[(@index^1)]
return @battle.battlers[(@index ^ 1)]
end
#Changes the form VISUALLY in battles. The species is changed in the equivalent method in Pokemon class
def checkHPRelatedFormChange(new_hp)
if @ability_id == :SHIELDSDOWN
if @pokemon.isFusionOf(:MINIOR_M)
if new_hp <= (@totalhp / 2)
changeBattlerForm(:MINIOR_M, :MINIOR_C,nil, :SHELLSMASH)
@battle.pbDisplay(_INTL("{1} changed to the Core Form!", pbThis))
end
end
if @pokemon.isFusionOf(:MINIOR_C)
if new_hp > (@totalhp / 2)
changeBattlerForm(:MINIOR_C, :MINIOR_M,nil, :SHELLSMASH)
@battle.pbDisplay(_INTL("{1} changed to the Meteor Form!", pbThis))
end
end
end
end
def changeBattlerForm(oldForm, newForm,commonAnimation=nil,moveAnimation=nil)
@pokemon.changeFormSpecies(oldForm, newForm)
if moveAnimation
changeFormSpeciesMoveAnimation(oldForm, newForm,moveAnimation)
else
changeFormSpeciesCommonAnimation(oldForm, newForm, commonAnimation)
end
end
#These methods only play the animation and change the graphics.
# To also change the species, call changeFormSpecies() instead
def changeFormSpeciesCommonAnimation(oldForm, newForm, animation = "UltraBurst2")
@battle.scene.pbChangePokemon(self, @pokemon)
@battle.scene.pbCommonAnimation(animation, self)
@battle.scene.pbRefreshOne(@index)
end
def changeFormSpeciesMoveAnimation(oldForm, newForm, moveID=:REFRESH)
@battle.scene.pbChangePokemon(self, @pokemon)
@battle.scene.pbAnimation(moveID, self,self)
@battle.scene.pbRefreshOne(@index)
end
end
@@ -595,8 +595,8 @@ class PokeBattle_Battler
end
end
def ensure_form_has_sprite(pokemon,spriteform_body,spriteform_head)
GameData::Species.sprite_filename(pokemon.dexNum, spriteform_body,spriteform_head)
def ensure_form_has_sprite(pokemon)
GameData::Species.sprite_filename(pokemon.dexNum)
end
@@ -624,6 +624,7 @@ class PokeBattle_Battler
#For meloetta form change
def changeFormSpecies(oldForm, newForm,animation = "UltraBurst2")
@pokemon.changeFormSpecies(oldForm,newForm)
playChangeFormAnimation(animation)
@@ -651,10 +652,10 @@ class PokeBattle_Battler
spriteform_body = newForm if @pokemon.hasBodyOf?(formChangingSpecies)
spriteform_head = newForm if @pokemon.hasHeadOf?(formChangingSpecies)
ensure_form_has_sprite(@pokemon,spriteform_body,spriteform_head)
#ensure_form_has_sprite(@pokemon)
if self.isFusion?
current_form_has_custom = customSpriteExists(@pokemon.species)
current_form_has_custom = customSpriteExistsSpecies(@pokemon.species)
new_form_has_custom = customSpriteExistsForm(@pokemon.species, spriteform_head, spriteform_body)
should_change_sprite = (current_form_has_custom && new_form_has_custom) || !current_form_has_custom
else
@@ -111,7 +111,7 @@ class PokeBattle_Battler
# Pokémon may be disobedient; calculate if it is
badgeLevel = 10 * (@battle.pbPlayer.badge_count + 1)
badgeLevel = GameData::GrowthRate.max_level if @battle.pbPlayer.badge_count >= 8
if @pokemon.foreign?(@battle.pbPlayer) && @level>badgeLevel
if (@pokemon.foreign?(@battle.pbPlayer) && @level>badgeLevel) || @pokemon.force_disobey
a = ((@level+badgeLevel)*@battle.pbRandom(256)/256).floor
disobedient |= (a>=badgeLevel)
end
@@ -1753,7 +1753,7 @@ class PokeBattle_Move_060 < PokeBattle_Move
end
if !checkedTerrain
case @battle.environment
when :Grass, :TallGrass
when :Grass, :TallGrass, :Grass_alt1,:Grass_alt2,:Grass_alt3,
@newType = :GRASS
when :MovingWater, :StillWater, :Puddle, :Underwater
@newType = :WATER
@@ -1659,7 +1659,8 @@ class PokeBattle_Move_0B6 < PokeBattle_Move
:TECHNOBLAST, # Genesect (Gen 5)
:THOUSANDARROWS, # Zygarde (Gen 6)
:THOUSANDWAVES, # Zygarde (Gen 6)
:VCREATE # Victini (Gen 5)
:VCREATE, # Victini (Gen 5)
:FAKEMOVE #not a real move
]
end
@@ -2086,9 +2086,7 @@ end
Events.onEndBattle += proc { |_sender,_e|
$Trainer.party.each_with_index do |value, i|
pokemon = $Trainer.party[i]
if pokemon.isFusionOf(:U_NECROZMA)
pokemon.changeFormSpecies(:U_NECROZMA,:NECROZMA)
end
pokemon.changeFormSpecies(:U_NECROZMA,:NECROZMA) if pokemon.isFusionOf(:U_NECROZMA)
end
}
@@ -222,6 +222,9 @@ module PokeBattle_BattleCommon
else
catch_rate /= 10
end
# First half of the shakes calculation
a = battler.totalhp
b = battler.hp
@@ -238,8 +241,12 @@ module PokeBattle_BattleCommon
return 4 if x >= 255 || BallHandlers.isUnconditional?(ball, self, battler)
# Second half of the shakes calculation
y = (65536 / ((255.0 / x) ** 0.1875)).floor
#Increased chances of catching if is on last ball
isOnLastBall = !$PokemonBag.pbHasItem?(ball)
echoln isOnLastBall
# Critical capture check
if Settings::ENABLE_CRITICAL_CAPTURES
if isOnLastBall
c = 0
numOwned = $Trainer.pokedex.owned_count
if numOwned > 600;
@@ -248,11 +255,14 @@ module PokeBattle_BattleCommon
c = x * 4 / 12
elsif numOwned > 300;
c = x * 3 / 12
elsif numOwned > 150;
else
c = x * 2 / 12
elsif numOwned > 30;
c = x / 12
end
# elsif numOwned > 150;
# c = x * 2 / 12
# elsif numOwned > 30;
# c = x / 12
# end
# Calculate the number of shakes
if c > 0 && pbRandom(256) < c
@criticalCapture = true
@@ -282,7 +282,7 @@ class PokeBattle_Battle
pbStartBattleSendOut(sendOuts)
# Weather announcement
weather_data = GameData::BattleWeather.try_get(@field.weather)
echoln @field.weather
echoln "Current weather: #{@field.weather}"
pbCommonAnimation(weather_data.animation) if weather_data
case @field.weather
@@ -183,7 +183,7 @@ BattleHandlers::StatusImmunityAbilityNonIgnorable.add(:COMATOSE,
BattleHandlers::StatusImmunityAbilityNonIgnorable.add(:SHIELDSDOWN,
proc { |ability,battler,status|
next true if battler.isSpecies?(:MINIOR) && battler.form<7
next true if battler.isFusionOf(:MINIOR_C) && battler.form<7
}
)
@@ -110,7 +110,7 @@ class PokemonDataBox < SpriteWrapper
@expBar.bitmap = @expBarBitmap.bitmap
@sprites["expBar"] = @expBar
# Create sprite wrapper that displays everything except the above
@contents = BitmapWrapper.new(@databoxBitmap.width,@databoxBitmap.height)
@contents = BitmapWrapper.new(@databoxBitmap.width+14,@databoxBitmap.height)
self.bitmap = @contents
self.visible = false
self.z = 150+((@battler.index)/2)*5
@@ -274,11 +274,51 @@ class PokemonDataBox < SpriteWrapper
imagePos.push(["Graphics/Pictures/Battle/icon_statuses",@spriteBaseX+24,56,
0,(s-1)*STATUS_ICON_HEIGHT,-1,STATUS_ICON_HEIGHT])
end
#Draw type icons (foe Pokémon only)
if @battler.opposes?(0) && $PokemonSystem.type_icons
drawEnemyTypeIcons(imagePos)
end
pbDrawImagePositions(self.bitmap,imagePos)
refreshHP
refreshExp
end
def drawEnemyTypeIcons(imagePos)
type1_number = GameData::Type.get(@battler.type1).id_number
type2_number = GameData::Type.get(@battler.type2).id_number
echoln type1_number
vertical_margin = 2
iconHeight=19
type_icons_x_position = @spriteBaseX + 210
type1_icon_y_position = 16
type2_icon_y_position = type1_icon_y_position+vertical_margin+iconHeight
type1_y_offset = type1_number*iconHeight
type2_y_offset = type2_number*iconHeight
x_offset=0
types_icon_path = "Graphics/Pictures/Battle/typesSmall"
if type1_number == type2_number
imagePos.push([types_icon_path,type_icons_x_position,type1_icon_y_position,
x_offset,type1_y_offset,-1,iconHeight])
else
imagePos.push([types_icon_path,type_icons_x_position,
type1_icon_y_position,
x_offset,
type1_y_offset,-1,iconHeight]
)
imagePos.push([types_icon_path,type_icons_x_position,type2_icon_y_position,
x_offset,
type2_y_offset,-1,iconHeight])
end
end
def refreshHP
@hpNumbers.bitmap.clear
return if !@battler.pokemon
@@ -174,7 +174,9 @@ class PokeBattle_Scene
y = 410
sprite = IconSprite.new(x,y,@viewport)
sprite.setBitmapDirectly(generate_front_trainer_sprite_bitmap())
allowEasterEggPokeball = pbInSafari? #Never allow except in Safari Zone - add more conditions if needed
sprite.setBitmapDirectly(generate_front_trainer_sprite_bitmap(allowEasterEggPokeball))
sprite.zoom_x=2
sprite.zoom_y=2
sprite.z=100 + idxTrainer
@@ -211,6 +213,9 @@ class PokeBattle_Scene
spriteX, spriteY = PokeBattle_SceneConstants.pbTrainerPosition(1, idxTrainer, numTrainers)
trainer = pbAddSprite("trainer_#{idxTrainer + 1}", spriteX, spriteY, trainerFile, @viewport)
spriteOverrideBitmap = setTrainerSpriteOverrides(trainerType)
trainer.bitmap = spriteOverrideBitmap if spriteOverrideBitmap
return if !trainer.bitmap
# Alter position of sprite
trainer.z = 7 + idxTrainer
@@ -218,6 +223,12 @@ class PokeBattle_Scene
trainer.oy = trainer.bitmap.height
end
def setTrainerSpriteOverrides(trainer_type)
if TYPE_EXPERTS_APPEARANCES.keys.include?(trainer_type)
return generate_front_trainer_sprite_bitmap_from_appearance(TYPE_EXPERTS_APPEARANCES[trainer_type]).bitmap
end
end
def pbCreatePokemonSprite(idxBattler)
sideSize = @battle.pbSideSize(idxBattler)
batSprite = PokemonBattlerSprite.new(@viewport, sideSize, idxBattler, @animations)
@@ -283,7 +283,7 @@ module RPG
weather_type = (is_new_sprite) ? @target_type : @type
# Update visibility/position/opacity of sprite
if @weatherTypes[weather_type][0].category == :Rain && (index % 2) != 0 # Splash
sprite.opacity = (lifetimes[index] < 0.2) ? 255 : 0 # 0.2 seconds
sprite.opacity = (lifetimes[index] < 0.4) ? 255 : 0 # 0.2 seconds
else
dist_x = @weatherTypes[weather_type][0].particle_delta_x * delta_t
dist_y = @weatherTypes[weather_type][0].particle_delta_y * delta_t
@@ -321,6 +321,7 @@ module RPG
end
def update_tile_position(sprite, index)
return if $PokemonSystem.on_mobile
return if !sprite || !sprite.bitmap || !sprite.visible
sprite.x = (@ox + @tile_x + (index % @tiles_wide) * sprite.bitmap.width).round
sprite.y = (@oy + @tile_y + (index / @tiles_wide) * sprite.bitmap.height).round
@@ -84,14 +84,26 @@ end
def pbStartOver(gameover=false)
$game_variables[VAR_CURRENT_GYM_TYPE]=-1
$game_switches[SWITCH_LOCK_PLAYER_MOVEMENT]=false
$game_switches[SWITCH_TEAMED_WITH_ERIKA_SEWERS]=false
clear_all_images()
$game_player.set_opacity(255)
$game_system.menu_disabled=false
if pbInBugContest?
pbBugContestStartOver
return
end
$Trainer.heal_party
if isOnPinkanIsland()
if $game_switches[SWITCH_PINKAN_SIDE_POLICE]
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]Hey, are you okay over there? Let me take you back to the dock."))
else
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]Hey, are you okay over there? Let me take you back to the beach."))
end
pinkanIslandWarpToStart()
return
end
if $PokemonGlobal.pokecenterMapId && $PokemonGlobal.pokecenterMapId>=0
if gameover
pbMessage(_INTL("\\w[]\\wm\\c[8]\\l[3]After the unfortunate defeat, you scurry back to a Pokémon Center."))
+30 -9
View File
@@ -303,7 +303,10 @@ Events.onMapChange += proc { |_sender, e|
$game_screen.weather(:None, 0, 0)
next
end
$game_screen.weather(new_weather[0], 9, 0) if rand(100) < new_weather[1]
echoln new_weather
$game_screen.weather(new_weather[0], 3, 0) if rand(100) < new_weather[1]
}
# Events.onMapChange += proc { |_sender, e|
@@ -596,7 +599,8 @@ def pbMoveRoute(event, commands, waitComplete = false)
return route
end
def pbWait(numFrames)
def
pbWait(numFrames)
numFrames.times do
Graphics.update
Input.update
@@ -816,19 +820,24 @@ def pbItemBall(item, quantity = 1, item_name = "", canRandom = true)
move = item.move
if $PokemonBag.pbStoreItem(item, quantity) # If item can be picked up
meName = (item.is_key_item?) ? "Key item get" : "Item get"
text_color = item.is_key_item? ? "\\c[3]" : "\\c[1]"
if item == :LEFTOVERS
pbMessage(_INTL("\\me[{1}]You found some \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
elsif item.is_machine? # TM or HM
pbMessage(_INTL("\\me[{1}]You found \\c[1]{2} {3}\\c[0]!\\wtnp[30]", meName, itemname, GameData::Move.get(move).name))
elsif quantity > 1
pbMessage(_INTL("\\me[{1}]You found {2} \\c[1]{3}\\c[0]!\\wtnp[30]", meName, quantity, itemname))
pbMessage(_INTL("\\me[{1}]You found {2} #{text_color}{3}\\c[0]!\\wtnp[30]", meName, quantity, itemname))
elsif itemname.starts_with_vowel?
pbMessage(_INTL("\\me[{1}]You found an \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
pbMessage(_INTL("\\me[{1}]You found an #{text_color}{2}\\c[0]!\\wtnp[30]", meName, itemname))
else
pbMessage(_INTL("\\me[{1}]You found a \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
pbMessage(_INTL("\\me[{1}]You found a #{text_color}{2}\\c[0]!\\wtnp[30]", meName, itemname))
end
pbMessage(_INTL("You put the {1} away\\nin the <icon=bagPocket{2}>\\c[1]{3} Pocket\\c[0].",
itemname, pocket, PokemonBag.pocketNames()[pocket]))
promptRegisterItem(item)
updatePinkanBerryDisplay()
return true
end
# Can't add the item
@@ -874,28 +883,40 @@ def pbReceiveItem(item, quantity = 1, item_name = "", music = nil, canRandom = t
pocket = item.pocket
move = item.move
meName = (item.is_key_item?) ? "Key item get" : "Item get"
text_color = item.is_key_item? ? "\\c[3]" : "\\c[1]"
if item == :LEFTOVERS
pbMessage(_INTL("\\me[{1}]You obtained some \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
elsif item.is_machine? # TM or HM
if $game_switches[SWITCH_RANDOMIZE_GYMS_SEPARATELY] && $game_switches[SWITCH_RANDOMIZED_GYM_TYPES] && $game_variables[VAR_CURRENT_GYM_TYPE] > -1
item = randomizeGymTM(item)
item = GameData::Item.get(randomizeGymTM(item))
end
pbMessage(_INTL("\\me[{1}]You obtained \\c[1]{2} {3}\\c[0]!\\wtnp[30]", meName, itemname, GameData::Move.get(move).name))
elsif quantity > 1
pbMessage(_INTL("\\me[{1}]You obtained {2} \\c[1]{3}\\c[0]!\\wtnp[30]", meName, quantity, itemname))
pbMessage(_INTL("\\me[{1}]You obtained {2} #{text_color}{3}\\c[0]!\\wtnp[30]", meName, quantity, itemname))
elsif itemname.starts_with_vowel?
pbMessage(_INTL("\\me[{1}]You obtained an \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
pbMessage(_INTL("\\me[{1}]You obtained an #{text_color}{2}\\c[0]!\\wtnp[30]", meName, itemname))
else
pbMessage(_INTL("\\me[{1}]You obtained a \\c[1]{2}\\c[0]!\\wtnp[30]", meName, itemname))
pbMessage(_INTL("\\me[{1}]You obtained a #{text_color}{2}\\c[0]!\\wtnp[30]", meName, itemname))
end
promptRegisterItem(item)
if $PokemonBag.pbStoreItem(item, quantity) # If item can be added
pbMessage(_INTL("You put the {1} away\\nin the <icon=bagPocket{2}>\\c[1]{3} Pocket\\c[0].",
itemname, pocket, PokemonBag.pocketNames()[pocket]))
updatePinkanBerryDisplay()
return true
end
return false # Can't add the item
end
def promptRegisterItem(item)
if item.is_key_item? && pbCanRegisterItem?(item)
if pbConfirmMessage(_INTL("Would you like to register the \\c[3]{1}\\c[0] in the quick actions menu?",item.name))
$PokemonBag.pbRegisterItem(item)
pbMessage(_INTL("\\se[{1}]The \\c[3]{2}\\c[0] was registered!", "GUI trainer card open", item.name))
end
end
end
def randomizeGymTM(old_item)
gym_index = pbGet(VAR_CURRENT_GYM_TYPE)
type_id = pbGet(VAR_GYM_TYPES_ARRAY)[gym_index]
@@ -749,6 +749,7 @@ Events.onEndBattle += proc { |_sender,e|
pbPickup(pkmn)
pbHoneyGather(pkmn)
end
pickUpTypeItemSetBonus()
when 2, 5 # Lose, draw
if !canLose
$game_system.bgm_unpause
@@ -15,6 +15,7 @@ class PokemonEncounters
@step_chances = {}
@encounter_tables = {}
encounter_data = getEncounterMode().get(map_ID, $PokemonGlobal.encounter_version)
encounter_data = GameData::Encounter.get(map_ID, $PokemonGlobal.encounter_version) if !encounter_data
if encounter_data
encounter_data.step_chances.each { |type, value| @step_chances[type] = value }
@encounter_tables = Marshal.load(Marshal.dump(encounter_data.types))
@@ -22,6 +23,7 @@ class PokemonEncounters
end
def getEncounterMode()
mode = GameData::Encounter
if $game_switches && $game_switches[SWITCH_MODERN_MODE]
mode = GameData::EncounterModern
@@ -29,6 +31,7 @@ class PokemonEncounters
if $game_switches && $game_switches[SWITCH_RANDOM_WILD] && $game_switches[SWITCH_RANDOM_WILD_AREA]
mode= GameData::EncounterRandom
end
echoln mode
return mode
end
@@ -253,12 +256,17 @@ class PokemonEncounters
def encounter_type
time = pbGetTimeNow
ret = nil
terrain_tag = $game_map.terrain_tag($game_player.x, $game_player.y)
if $PokemonGlobal.surfing
ret = find_valid_encounter_type_for_time(:Water, time)
else # Land/Cave (can have both in the same map)
if has_land_encounters? && $game_map.terrain_tag($game_player.x, $game_player.y).land_wild_encounters
ret = :BugContest if pbInBugContest? && has_encounter_type?(:BugContest)
ret = find_valid_encounter_type_for_time(:Land, time) if !ret
baseType = :Land #default grass
baseType = :Land1 if terrain_tag == :Grass_alt1
baseType = :Land2 if terrain_tag == :Grass_alt2
baseType = :Land3 if terrain_tag == :Grass_alt3
ret = find_valid_encounter_type_for_time(baseType, time) if !ret
end
if !ret && has_cave_encounters?
ret = find_valid_encounter_type_for_time(:Cave, time)
@@ -14,20 +14,20 @@ Events.onWildPokemonCreate += proc { |_sender, e|
end
}
# Used in the random dungeon map. Makes the levels of all wild Pokémon in that
# map depend on the levels of Pokémon in the player's party.
# This is a simple method, and can/should be modified to account for evolutions
# and other such details. Of course, you don't HAVE to use this code.
Events.onWildPokemonCreate += proc { |_sender, e|
pokemon = e[0]
if $game_map.map_id == 51
new_level = pbBalancedLevel($Trainer.party) - 4 + rand(5) # For variety
new_level = new_level.clamp(1, GameData::GrowthRate.max_level)
pokemon.level = new_level
pokemon.calc_stats
pokemon.reset_moves
end
}
# # Used in the random dungeon map. Makes the levels of all wild Pokémon in that
# # map depend on the levels of Pokémon in the player's party.
# # This is a simple method, and can/should be modified to account for evolutions
# # and other such details. Of course, you don't HAVE to use this code.
# Events.onWildPokemonCreate += proc { |_sender, e|
# pokemon = e[0]
# if $game_map.map_id == 0
# new_level = pbBalancedLevel($Trainer.party) - 4 + rand(5) # For variety
# new_level = new_level.clamp(1, GameData::GrowthRate.max_level)
# pokemon.level = new_level
# pokemon.calc_stats
# pokemon.reset_moves
# end
# }
# This is the basis of a trainer modifier. It works both for trainers loaded
# when you battle them, and for partner trainers when they are registered.
@@ -57,6 +57,7 @@ class PokemonGlobalMetadata
attr_accessor :safesave
#Trainers rematch
attr_accessor :rematchedTrainers
attr_accessor :questRewardsObtained
def initialize
# Movement
@@ -114,6 +115,7 @@ class PokemonGlobalMetadata
@pokerusTime = nil
# Save file
@safesave = false
@questRewardsObtained = []
end
# @deprecated Use {Player#character_ID} instead. This alias is slated to be removed in v20.
@@ -59,7 +59,7 @@ def pbHiddenMoveEvent
end
def pbCheckHiddenMoveBadge(badge = -1, showmsg = true)
return true if badge < 0 # No badge requirement
return true if badge < 0 || isOnPinkanIsland() # No badge requirement
return true if $DEBUG
if (Settings::FIELD_MOVES_COUNT_BADGES) ? $Trainer.badge_count >= badge : $Trainer.badges[badge]
return true
@@ -931,9 +931,14 @@ Events.onAction += proc { |_sender, _e|
Events.onAction += proc { |_sender, _e|
next if !$game_player.pbFacingTerrainTag.trashcan
if $PokemonGlobal.stepcount % 25 == 0
pbMessage(_INTL("Woah! A Pokémon jumped out of the trashcan!"))
pbWildBattle(:TRUBBISH, 10)
$PokemonGlobal.stepcount += 1
if !hatUnlocked?(HAT_CARDBOARD_BOX) && rand(2) == 0
obtainHat(HAT_CARDBOARD_BOX)
$PokemonGlobal.stepcount += 1
else
pbMessage(_INTL("Woah! A Pokémon jumped out of the trashcan!"))
pbWildBattle(:TRUBBISH, 10)
$PokemonGlobal.stepcount += 1
end
end
}
@@ -72,7 +72,7 @@ def pbFishing(hasEncounter,rodType=1)
break
end
itemChance = rand((rodType)*4)
itemChance = rand((rodType)*5)
if itemChance<=1
#ITEM
items = [:PEARL,
@@ -84,7 +84,20 @@ def pbFishing(hasEncounter,rodType=1)
:PEARL,
:WATERGEM
]
Kernel.pbItemBall(items[rand(items.size)],1,nil,false)
hats = [
HAT_SLOWKING_SHELL,
]
hatChance = rand(5)
if true#hatChance == 0
hat = hats.sample
if !hasHat?(hat)
obtainHat(hat)
else
Kernel.pbItemBall(items[rand(items.size)],1,nil,false)
end
else
Kernel.pbItemBall(items[rand(items.size)],1,nil,false)
end
Kernel.pbDisposeMessageWindow(msgWindow)
pbFishingEnd
$game_player.setDefaultCharName(nil,oldpattern)
+18
View File
@@ -3,6 +3,7 @@
#===============================================================================
class PokemonBag
attr_accessor :lastpocket
attr_accessor :pockets
def self.pocketNames
return Settings.bag_pocket_names
@@ -176,6 +177,7 @@ class PokemonBag
item = GameData::Item.get(item)
pocket = item.pocket
ret = ItemStorageHelper.pbDeleteItem(@pockets[pocket], item.id, qty)
updatePinkanBerryDisplay()
return ret
end
@@ -213,6 +215,18 @@ class PokemonBag
@registeredIndex = [0, 0, 1] if !@registeredIndex
return @registeredIndex
end
def saveBagAndClear()
$PokemonGlobal.pokemonSelectionOriginalBag= @pockets.map(&:dup)
echoln $PokemonGlobal.pokemonSelectionOriginalBag
clear()
end
def restoreBag()
return if !$PokemonGlobal.pokemonSelectionOriginalBag
echoln $PokemonGlobal.pokemonSelectionOriginalBag
@pockets = $PokemonGlobal.pokemonSelectionOriginalBag
end
end
@@ -354,6 +368,10 @@ module ItemStorageHelper
end
return false
end
end
@@ -51,22 +51,29 @@ class PokemonSprite < SpriteWrapper
end
def setPokemonBitmap(pokemon, back = false)
# Dispose of existing icon bitmap if it exists
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = (pokemon) ? GameData::Species.sprite_bitmap_from_pokemon(pokemon, back) : nil
if @_iconbitmap
if pokemon.hat
add_hat_to_bitmap(@_iconbitmap.bitmap,pokemon.hat,pokemon.hat_x,pokemon.hat_y)
else
end
self.bitmap = @_iconbitmap.bitmap
@_iconbitmap = nil
return if !pokemon
base_bitmap = (pokemon) ? GameData::Species.sprite_bitmap_from_pokemon(pokemon, back) : nil
if pokemon.hat
new_bitmap = Bitmap.new(base_bitmap.width, base_bitmap.height)
new_bitmap.blt(0, 0, base_bitmap.bitmap, base_bitmap.bitmap.rect)
add_hat_to_bitmap(new_bitmap, pokemon.hat, pokemon.hat_x, pokemon.hat_y)
@_iconbitmap = SpriteWrapper.new
@_iconbitmap.bitmap = new_bitmap
else
@_iconbitmap.bitmap=nil
# No hat, just use the base bitmap
@_iconbitmap = base_bitmap
end
# Assign the bitmap to the sprite
self.bitmap = (@_iconbitmap) ? @_iconbitmap.bitmap : nil
self.color = Color.new(0, 0, 0, 0)
changeOrigin
end
def setPokemonBitmapFromId(id, back = false, shiny = false, bodyShiny = false, headShiny = false,spriteform_body=nil,spriteform_head=nil)
@_iconbitmap.dispose if @_iconbitmap
@_iconbitmap = GameData::Species.sprite_bitmap_from_pokemon_id(id, back, shiny, bodyShiny, headShiny)
+135 -8
View File
@@ -104,6 +104,11 @@ class Pokemon
attr_accessor :hiddenPowerType
attr_accessor :sprite_scale #the size attribute for scaling the sprite (used only for gourgeist/pumpkaboo)
attr_accessor :size_category #the size attribute for scaling the sprite (used only for gourgeist/pumpkaboo)
attr_accessor :force_disobey
# Max total IVs
IV_STAT_LIMIT = 31
# Max total EVs
@@ -175,6 +180,8 @@ class Pokemon
echoln("Fused: #{@fused}")
echoln("Personal ID: #{@personalID}")
echoln("Hidden Power Type: #{@hiddenPowerType}")
echoln("Scale: #{sprite_scale}")
# Add other attribute print statements here
end
@@ -197,6 +204,10 @@ class Pokemon
return @species_data
end
def id_number
return species_data.id_number
end
#=============================================================================
# Species and form
#=============================================================================
@@ -217,6 +228,24 @@ class Pokemon
calc_stats
end
def sprite_scale()
@sprite_scale = 1 if !@sprite_scale
return @sprite_scale
end
def sprite_scale=(scale)
@sprite_scale = scale
end
def size_category()
@size_category = :AVERAGE if !@size_category
return @size_category
end
def size_category=(category)
@size_category = category
end
# @param check_species [Integer, Symbol, String] id of the species to check for
# @return [Boolean] whether this Pokémon is of the specified species
def isSpecies?(check_species)
@@ -224,6 +253,7 @@ class Pokemon
@species == GameData::Species.get(check_species).species)
end
def hasBodyOf?(check_species)
if !self.isFusion?
return isSpecies?(check_species)
@@ -242,6 +272,14 @@ class Pokemon
return headSpecies == checkSpeciesId
end
def head_id()
return get_head_id_from_symbol(@species)
end
def body_id()
return get_body_id_from_symbol(@species)
end
def shiny=(value)
@shiny = value
if value && Settings::SHINY_POKEMON_CHANCE != S_CHANCE_VALIDATOR
@@ -296,6 +334,7 @@ class Pokemon
end
def changeFormSpecies(oldForm, newForm)
is_already_old_form = self.isFusionOf(oldForm) #A 466
is_already_new_form = self.isFusionOf(newForm) #P
@@ -308,6 +347,7 @@ class Pokemon
changeSpeciesSpecific(self, getFusedPokemonIdFromSymbols(oldForm, newForm))
end
else
echoln "changing species...."
changeSpecies(self, oldForm, newForm) if is_already_old_form
changeSpecies(self, newForm, oldForm) if is_already_new_form
end
@@ -419,6 +459,7 @@ class Pokemon
def hp=(value)
@hp = value.clamp(0, @totalhp)
heal_status if @hp == 0
checkHPRelatedFormChange()
end
# Sets this Pokémon's status. See {GameData::Status} for all possible status effects.
@@ -446,6 +487,7 @@ class Pokemon
def heal_HP
return if egg?
@hp = @totalhp
checkHPRelatedFormChange()
end
# Heals the status problem of this Pokémon.
@@ -1047,7 +1089,11 @@ class Pokemon
# @param trainer [Player, NPCTrainer] the trainer to compare to the original trainer
# @return [Boolean] whether the given trainer is not this Pokémon's original trainer
def foreign?(trainer)
return @owner.id != trainer.id || @owner.name != trainer.name
return @owner.id != trainer.id# || @owner.name != trainer.name
end
def always_disobey(value)
@force_disobey = value
end
# @return [Time] the time when this Pokémon was obtained
@@ -1097,14 +1143,14 @@ class Pokemon
return species_data.name
end
# @return [Integer] the height of this Pokémon in decimetres (0.1 metres)
# @return [Integer] the height of this Pokémon in metres
def height
return species_data.height
return species_data.height/10
end
# @return [Integer] the weight of this Pokémon in hectograms (0.1 kilograms)
# @return [Integer] the weight of this Pokémon in kilograms
def weight
return species_data.weight
return species_data.weight/10
end
# @return [Hash<Integer>] the EV yield of this Pokémon (a hash with six key/value pairs)
@@ -1262,10 +1308,40 @@ class Pokemon
#=============================================================================
# Stat calculations
#=============================================================================
def getBaseStatsFormException()
if @species == :PUMPKABOO
case @size_category
when :SMALL
return { :HP => 44, :ATTACK => 66, :DEFENSE => 70, :SPECIAL_ATTACK => 44, :SPECIAL_DEFENSE => 55, :SPEED => 56}
when :AVERAGE
return nil
when :LARGE
return { :HP => 54, :ATTACK => 66, :DEFENSE => 70, :SPECIAL_ATTACK => 44, :SPECIAL_DEFENSE => 55, :SPEED => 46}
when :SUPER
return { :HP => 59, :ATTACK => 66, :DEFENSE => 70, :SPECIAL_ATTACK => 44, :SPECIAL_DEFENSE => 55, :SPEED => 41}
end
end
if @species == :GOURGEIST
case @size_category
when :SMALL
return { :HP => 55, :ATTACK => 85, :DEFENSE => 122, :SPECIAL_ATTACK => 58, :SPECIAL_DEFENSE => 75, :SPEED => 99}
when :AVERAGE
return nil
when :LARGE
return { :HP => 75, :ATTACK => 95, :DEFENSE => 122, :SPECIAL_ATTACK => 58, :SPECIAL_DEFENSE => 75, :SPEED => 69}
when :SUPER
return { :HP => 85, :ATTACK => 10, :DEFENSE => 122, :SPECIAL_ATTACK => 58, :SPECIAL_DEFENSE => 75, :SPEED => 54}
end
end
return nil
end
# @return [Hash<Integer>] this Pokémon's base stats, a hash with six key/value pairs
def baseStats
this_base_stats = species_data.base_stats
base_stats_exception = getBaseStatsFormException()
this_base_stats = base_stats_exception if base_stats_exception
ret = {}
GameData::Stat.each_main { |s| ret[s.id] = this_base_stats[s.id] }
return ret
@@ -1307,10 +1383,26 @@ class Pokemon
return self.ability == :WONDERGUARD ? 1 : stats[:HP]
end
def checkHPRelatedFormChange()
if @ability == :SHIELDSDOWN
return if $game_temp.in_battle #handled in battlers class in-battle
if isFusionOf(:MINIOR_M)
if @hp <= (@totalhp / 2)
changeFormSpecies(:MINIOR_M, :MINIOR_C)
end
end
if isFusionOf(:MINIOR_C)
if @hp > (@totalhp / 2)
changeFormSpecies(:MINIOR_C, :MINIOR_M)
end
end
end
end
# Recalculates this Pokémon's stats.
def calc_stats
base_stats = self.baseStats
this_level = self.level
this_level = self.level
this_IV = self.calcIV
if $game_switches[SWITCH_NO_LEVELS_MODE]
@@ -1375,6 +1467,35 @@ class Pokemon
# @param owner [Owner, Player, NPCTrainer] Pokémon owner (the player by default)
# @param withMoves [TrueClass, FalseClass] whether the Pokémon should have moves
# @param rechech_form [TrueClass, FalseClass] whether to auto-check the form
def determine_scale
return :AVERAGE if !@size_category
size_roll = rand(100) # Random number between 0-99
if @size_category == :SMALL
return 0.75
elsif @size_category == :AVERAGE
return 1
elsif @size_category == :LARGE
return 1 + (1.0 /3) #"Large Size"
elsif @size_category == :SUPER
return 1 + (2.0 /3) #"Super Size"
end
return 1
end
def determine_size_category
return :AVERAGE if !(Kernel.isPartPokemon(self,:PUMPKABOO) || Kernel.isPartPokemon(self,:GOURGEIST))
size_roll = rand(100) # Random number between 0-99
if size_roll < 10
return :SMALL
elsif size_roll < 50
return :AVERAGE
elsif size_roll < 90
return :LARGE
else
return :SUPER
end
end
def initialize(species, level, owner = $Trainer, withMoves = true, recheck_form = true)
@species_data = GameData::Species.get(species)
@species = @species_data.species
@@ -1433,7 +1554,7 @@ class Pokemon
@obtain_text = nil
@obtain_level = level
@hatched_map = 0
@timeReceived = pbGetTimeNow.to_i
@timeReceived = Time.new.to_i
@timeEggHatched = nil
@fused = nil
@personalID = rand(2 ** 16) | rand(2 ** 16) << 16
@@ -1445,7 +1566,9 @@ class Pokemon
@hat = nil
@hat_x = 0
@hat_y = 0
@size_category = determine_size_category()
@sprite_scale=determine_scale()
echoln @sprite_scale
calc_stats
if @form == 0 && recheck_form
f = MultipleForms.call("getFormOnCreation", self)
@@ -1455,4 +1578,8 @@ class Pokemon
end
end
end
def totalIv()
end
end
@@ -17,10 +17,18 @@ class Player < Trainer
attr_accessor :unlocked_clothes
attr_accessor :unlocked_hats
attr_accessor :unlocked_hairstyles
attr_accessor :unlocked_card_backgrounds
attr_accessor :last_worn_outfit
attr_accessor :last_worn_hat
attr_accessor :surfing_pokemon
attr_accessor :card_background
attr_accessor :unlocked_card_backgrounds
# @return [Array<Boolean>] the player's Gym Badges (true if owned)
attr_accessor :badges
# @return [Integer] the player's money
@@ -62,6 +70,22 @@ class Player < Trainer
@money = value.clamp(0, Settings::MAX_MONEY)
end
def last_worn_outfit
if !@last_worn_outfit
if pbGet(VAR_TRAINER_GENDER) == GENDER_MALE
@last_worn_outfit = DEFAULT_OUTFIT_MALE
else
@last_worn_outfit = DEFAULT_OUTFIT_FEMALE
end
end
return @last_worn_outfit
end
def last_worn_hat
return @last_worn_hat
end
# Sets the player's coins amount. It can not exceed {Settings::MAX_COINS}.
# @param value [Integer] new coins value
def coins=(value)
@@ -71,7 +95,6 @@ class Player < Trainer
def outfit=(value)
@outfit=value
$game_player.outfit_changed=true
end
def hat=(value)
@@ -80,7 +103,6 @@ class Player < Trainer
end
@hat=value
refreshPlayerOutfit()
$game_player.outfit_changed=true
end
def hair=(value)
@@ -89,7 +111,6 @@ class Player < Trainer
end
@hair=value
refreshPlayerOutfit()
$game_player.outfit_changed=true
end
def clothes=(value)
@@ -98,7 +119,6 @@ class Player < Trainer
end
@clothes=value
refreshPlayerOutfit()
$game_player.outfit_changed=true
end
@@ -210,6 +230,11 @@ class Player < Trainer
return @pokedex.owned?(species)
end
def can_change_outfit()
return false if isOnPinkanIsland()
return true
end
#=============================================================================
def initialize(name, trainer_type)
@@ -237,5 +262,10 @@ class Player < Trainer
@new_game_plus_unlocked = false
@new_game_plus = false
@surfing_pokemon = nil
@last_worn_outfit = nil
@last_worn_hat = nil
@card_background = Settings::DEFAULT_TRAINER_CARD_BG
@unlocked_card_backgrounds = [@card_background]
end
end
@@ -120,7 +120,8 @@ class PokemonEggHatch_Scene
pbMessage(_INTL("{1}'s data was added to the Pokédex", @pokemon.name))
pbShowPokedex(@pokemon.species)
end
nb_eggs_hatched = pbGet(VAR_NB_EGGS_HATCHED)
pbSet(VAR_NB_EGGS_HATCHED,nb_eggs_hatched+1)
end
def pbEndScene
@@ -233,6 +234,7 @@ Events.onStepTaken += proc { |_sender,_e|
for egg in $Trainer.party
next if egg.steps_to_hatch <= 0
egg.steps_to_hatch -= 1
egg.steps_to_hatch -= 1 if isWearingClothes(CLOTHES_BREEDER)
for i in $Trainer.pokemon_party
next if !i.hasAbility?(:FLAMEBODY) && !i.hasAbility?(:MAGMAARMOR)
egg.steps_to_hatch -= 1
@@ -589,7 +589,8 @@ class PokemonEvolutionScene
# Success jingle/message
pbMEPlay("Evolution success")
sprite_bitmap=@sprites["rsprite2"].getBitmap
drawSpriteCredits(sprite_bitmap.filename,sprite_bitmap.path, @viewport)
#drawSpriteCredits(sprite_bitmap.filename,sprite_bitmap.path, @viewport)
newspeciesname = GameData::Species.get(@newspecies).name
if !reversing
@@ -608,13 +609,10 @@ class PokemonEvolutionScene
pbEvolutionMethodAfterEvolution if !reversing
@pokemon
@pokemon.ability
oldAbility = @pokemon.ability.id
#oldAbility = @pokemon.ability.id if @pokemon.ability
newSpecies = GameData::Species.get(@newspecies)
allNewPossibleAbilities = newSpecies.abilities + newSpecies.hidden_abilities
#allNewPossibleAbilities = newSpecies.abilities + newSpecies.hidden_abilities
# Modify Pokémon to make it evolved
@pokemon.species = @newspecies
@@ -17,7 +17,7 @@
class HallOfFame_Scene
# When true, all pokémon will be in one line
# When false, all pokémon will be in two lines
SINGLEROW = false
@singlerow = true
# Make the pokémon movement ON in hall entry
ANIMATION = true
# Speed in pokémon movement in hall entry. Don't use less than 2!
@@ -34,7 +34,7 @@ class HallOfFame_Scene
# Allow eggs to be show and saved in hall
ALLOWEGGS = true
# Remove the hallbars when the trainer sprite appears
REMOVEBARS = true
REMOVEBARS = false
# The final fade speed on entry
FINALFADESPEED = 16
# Sprites opacity value when them aren't selected
@@ -48,7 +48,8 @@ class HallOfFame_Scene
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
# Comment the below line to doesn't use a background
addBackgroundPlane(@sprites, "bg", "hallfamebg", @viewport)
bgFile = @singlerow ? "hallfamebg" : "hallfamebg_multiline"
addBackgroundPlane(@sprites, "bg", bgFile, @viewport)
@sprites["hallbars"] = IconSprite.new(@viewport)
@sprites["hallbars"].setBitmap("Graphics/Pictures/hallfamebars")
@sprites["overlay"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport)
@@ -61,6 +62,7 @@ class HallOfFame_Scene
end
def pbStartSceneEntry
@singlerow = true
pbStartScene
@useMusic = (ENTRYMUSIC && ENTRYMUSIC != "")
pbBGMPlay(ENTRYMUSIC) if @useMusic
@@ -72,9 +74,12 @@ class HallOfFame_Scene
end
def pbStartScenePC
@singlerow = false
pbStartScene
@hallIndex = $PokemonGlobal.hallOfFame.size - 1
@hallEntry = $PokemonGlobal.hallOfFame[-1]
echoln $PokemonGlobal.hallOfFame[-1]
@hallEntry = $PokemonGlobal.hallOfFame[-1][:TEAM]
createBattlers(false)
pbFadeInAndShow(@sprites) { pbUpdate }
pbUpdatePC
@@ -126,32 +131,61 @@ class HallOfFame_Scene
# Clones every pokémon object
@hallEntry.push($Trainer.party[i].clone) if !$Trainer.party[i].egg? || ALLOWEGGS
end
entryData = {}
entryData[:TEAM] = @hallEntry
entryData[:DIFFICULTY] = getDifficulty
entryData[:MODE] = getCurrentGameMode()
entryData[:DATE] = getCurrentDate()
#Save trainer data (unused for now)
entryData[:TRAINER_HAT] = $Trainer.hat
entryData[:TRAINER_HAT_COLOR] = $Trainer.hat_color
entryData[:TRAINER_HAIR] = $Trainer.hair
entryData[:TRAINER_HAIR_COLOR] = $Trainer.hair_color
entryData[:TRAINER_CLOTHES] = $Trainer.clothes
entryData[:TRAINER_CLOTHES_COLOR] = $Trainer.clothes_color
entryData[:TRAINER_SKIN] = $Trainer.skin_tone
# Update the global variables
$PokemonGlobal.hallOfFame.push(@hallEntry)
$PokemonGlobal.hallOfFame.push(entryData)
$PokemonGlobal.hallOfFameLastNumber += 1
$PokemonGlobal.hallOfFame.delete_at(0) if HALLLIMIT > -1 &&
$PokemonGlobal.hallOfFame.size > HALLLIMIT
$PokemonGlobal.hallOfFame.size > HALLLIMIT
end
# Return the x/y point position in screen for battler index number
# Don't use odd numbers!
def xpointformula(battlernumber)
ret = 0
if !SINGLEROW
if !@singlerow
ret = 92 + 160 * xpositionformula(battlernumber) #32
else
ret = (60 * (battlernumber / 2) + 48) * (xpositionformula(battlernumber) - 1)
ret += Graphics.width / 2 - 56
start_position = -16 #-56
spacing = 70 # spacing between mons
ret = (spacing * (battlernumber / 2) + 48) * (xpositionformula(battlernumber) - 1)
gap_size = 40 #gap for the trainer sprite in the middle
if battlernumber % 2 == 0 #left side
ret -= gap_size / 2
else
ret += gap_size / 2
end
ret += Graphics.width / 2 + start_position
end
return ret
end
def ypointformula(battlernumber)
ret = 0
if !SINGLEROW
if !@singlerow
ret = 92 + 128 * ypositionformula(battlernumber) / 2
else
ret = 96 - 8 * (battlernumber / 2)
y_position_base = 125
height_increase = 20
# Calculate the decrement based on the battlernumber:
# Each pair (1-2, 3-4, etc.) will decrease y by 20
y_decrement = 40 - height_increase * (battlernumber / 2)
ret = y_position_base + y_decrement
end
return ret
end
@@ -159,7 +193,7 @@ class HallOfFame_Scene
# Returns 0, 1 or 2 as the x/y column value
def xpositionformula(battlernumber)
ret = 0
if !SINGLEROW
if !@singlerow
ret = (battlernumber / 3 % 2 == 0) ? (19 - battlernumber) % 3 : (19 + battlernumber) % 3
else
ret = battlernumber % 2 * 2
@@ -169,7 +203,7 @@ class HallOfFame_Scene
def ypositionformula(battlernumber)
ret = 0
if !SINGLEROW
if !@singlerow
ret = (battlernumber / 3) % 2 * 2
else
ret = 1
@@ -221,7 +255,7 @@ class HallOfFame_Scene
@sprites["pokemon#{i}"].x += (128 - @sprites["pokemon#{i}"].bitmap.width) / 2
@sprites["pokemon#{i}"].y += (128 - @sprites["pokemon#{i}"].bitmap.height) / 2
end
@sprites["pokemon#{i}"].z = 7 - i if SINGLEROW
@sprites["pokemon#{i}"].z = 7 - i if @singlerow
next if !hide
# Animation distance calculation
horizontal = 1 - xpositionformula(i)
@@ -246,13 +280,14 @@ class HallOfFame_Scene
def createTrainerBattler
@sprites["trainer"] = IconSprite.new(@viewport)
@sprites["trainer"].setBitmapDirectly(generate_front_trainer_sprite_bitmap())
if !SINGLEROW
if !@singlerow
@sprites["trainer"].x = Graphics.width - 96
@sprites["trainer"].y = 160
else
@sprites["trainer"].x = Graphics.width / 2
@sprites["trainer"].x = Graphics.width / 2 # - 96
@sprites["trainer"].y = 178
end
@sprites["trainer"].opacity = 255
@sprites["trainer"].z = 9
@sprites["trainer"].ox = @sprites["trainer"].bitmap.width / 2
@sprites["trainer"].oy = @sprites["trainer"].bitmap.height / 2
@@ -262,18 +297,18 @@ class HallOfFame_Scene
end
@xmovement[@battlerIndex] = 0
@ymovement[@battlerIndex] = 0
if (ANIMATION && !SINGLEROW) # Trainer Animation
startpoint = Graphics.width / 2
# 2 is the trainer speed
@xmovement[@battlerIndex] = (startpoint - @sprites["trainer"].x) / 2
@sprites["trainer"].x = startpoint
else
ENTRYWAITTIME.times do
Graphics.update
Input.update
pbUpdate
end
end
#if (ANIMATION)#) && !@singlerow) # Trainer Animation
startpoint = (Graphics.width / 2) - 200
# 2 is the trainer speed
@xmovement[@battlerIndex] = (startpoint - @sprites["trainer"].x) / 2
@sprites["trainer"].x = startpoint
# else
# ENTRYWAITTIME.times do
# Graphics.update
# Input.update
# pbUpdate
# end
# end
end
#Get difficulty for displaying in-game
@@ -339,17 +374,35 @@ class HallOfFame_Scene
pbDrawTextPositions(overlay, [[_INTL("Welcome to the Hall of Fame!"),
Graphics.width / 2, Graphics.height - 80, 2, BASECOLOR, SHADOWCOLOR]])
writeCurrentDate(overlay, 120, Graphics.height - 50)
writeDate(overlay, 120, Graphics.height - 50)
writeGameMode(overlay, (Graphics.width / 2) + 100, Graphics.height - 50)
end
def writeCurrentDate(overlay, x, y)
currentTime = Time.new
timeString = currentTime.year.to_s + "-" + ("%02d" % currentTime.month) + "-" + ("%02d" % currentTime.day)
def writeWelcomePC
overlay = @sprites["overlay"].bitmap
overlay.clear
pbDrawTextPositions(overlay, [[_INTL("Entered the Hall of Fame!"),
Graphics.width / 2, Graphics.height - 80, 2, BASECOLOR, SHADOWCOLOR]])
date = $PokemonGlobal.hallOfFame[@hallIndex][:DATE]
mode = $PokemonGlobal.hallOfFame[@hallIndex][:MODE]
difficulty = $PokemonGlobal.hallOfFame[@hallIndex][:DIFFICULTY]
writeDate(overlay, 120, Graphics.height - 50,date) if date
writeGameMode(overlay, (Graphics.width / 2) + 100, Graphics.height - 50, mode, difficulty) if mode && difficulty
end
def writeDate(overlay, x, y, timeString = nil)
timeString = getCurrentDate() if !timeString
pbDrawTextPositions(overlay, [[_INTL("{1}", timeString), x, y, 2, BASECOLOR, SHADOWCOLOR]])
end
def writeGameMode(overlay, x, y)
def getCurrentDate()
currentTime = Time.new
return currentTime.year.to_s + "-" + ("%02d" % currentTime.month) + "-" + ("%02d" % currentTime.day)
end
def getCurrentGameMode()
gameMode = "Classic mode"
if $game_switches[SWITCH_MODERN_MODE]
gameMode = "Remix mode"
@@ -372,8 +425,13 @@ class HallOfFame_Scene
if $game_switches[ENABLED_DEBUG_MODE_AT_LEAST_ONCE] || $DEBUG
gameMode = "Debug mode"
end
return gameMode
end
pbDrawTextPositions(overlay, [[_INTL("{1} ({2})", gameMode, getDifficulty), x, y, 2, BASECOLOR, SHADOWCOLOR]])
def writeGameMode(overlay, x, y, gameMode = nil, difficulty = nil)
gameMode = getCurrentGameMode() if !gameMode
difficulty = getDifficulty() if !difficulty
pbDrawTextPositions(overlay, [[_INTL("{1} ({2})", gameMode, difficulty), x, y, 2, BASECOLOR, SHADOWCOLOR]])
end
def pbAnimationLoop
@@ -437,18 +495,20 @@ class HallOfFame_Scene
# Show the welcome message and preparates the trainer
setPokemonSpritesOpacity(-1)
writeWelcome
createTrainerBattler
(ENTRYWAITTIME * 2 * Graphics.frame_rate / 20).times do
moveSprite(-1)
Graphics.update
Input.update
pbUpdate
end
while !(waitForInput)
Graphics.update
Input.update
pbUpdate
end
setPokemonSpritesOpacity(-1, OPACITY) if !SINGLEROW
createTrainerBattler
setPokemonSpritesOpacity(-1, OPACITY) # if !@singlerow
end
end
end
@@ -477,16 +537,23 @@ class HallOfFame_Scene
def pbUpdatePC
# Change the team
if @battlerIndex >= @hallEntry.size
if @battlerIndex >= @hallEntry.size + 1
@hallIndex -= 1
return false if @hallIndex == -1
@hallEntry = $PokemonGlobal.hallOfFame[@hallIndex]
@hallEntry = $PokemonGlobal.hallOfFame[@hallIndex][:TEAM]
@battlerIndex = 0
createBattlers(false)
elsif @battlerIndex == @hallEntry.size
for n in 0...@hallEntry.size
@sprites["pokemon#{n}"].opacity = 255
end
echoln @hallEntry
writeWelcomePC
return true
elsif @battlerIndex < 0
@hallIndex += 1
return false if @hallIndex >= $PokemonGlobal.hallOfFame.size
@hallEntry = $PokemonGlobal.hallOfFame[@hallIndex]
@hallEntry = $PokemonGlobal.hallOfFame[@hallIndex][:TEAM]
@battlerIndex = @hallEntry.size - 1
createBattlers(false)
end
@@ -552,9 +619,37 @@ class PokemonGlobalMetadata
# Number necessary if hallOfFame array reach in its size limit
attr_writer :hallOfFameLastNumber
#
# [{:TEAM:[], :DATE:string, :MODE:string, :DIFFICULTY:string}]
#
def hallOfFame
@hallOfFame = [] if !@hallOfFame
if @hallOfFame.size > 0 && @hallOfFame[0].is_a?(Array)
echoln "converting hall of fame"
convertedHallOfFame = []
@hallOfFame.each do |team|
hallOfFame = {}
hallOfFame[:TEAM] = team
hallOfFame[:DATE] = nil
hallOfFame[:MODE] = nil
hallOfFame[:DIFFICULTY] = nil
hallOfFame[:TRAINER_HAT] = nil
hallOfFame[:TRAINER_HAT_COLOR] = nil
hallOfFame[:TRAINER_HAIR] = nil
hallOfFame[:TRAINER_HAIR_COLOR] = nil
hallOfFame[:TRAINER_CLOTHES] = nil
hallOfFame[:TRAINER_CLOTHES_COLOR] = nil
hallOfFame[:TRAINER_SKIN] = nil
convertedHallOfFame << hallOfFame
end
@hallOfFame = convertedHallOfFame
echoln @hallOfFame
end
return @hallOfFame
# @hallOfFame = [] if !@hallOfFame
# return @hallOfFame
end
def hallOfFameLastNumber
@@ -37,33 +37,36 @@ class Scene_Credits
# Backgrounds to show in credits. Found in Graphics/Titles/ folder
BACKGROUNDS_LIST = ["credits1", "credits2", "credits3", "credits4", "credits5"]
BGM = "Credits"
SCROLL_SPEED = 60 # Pixels per second
SECONDS_PER_BACKGROUND = 11
SCROLL_SPEED = 62 # Pixels per second , ajuster pour fitter avec la musique
SECONDS_PER_BACKGROUND = 4
TEXT_OUTLINE_COLOR = Color.new(0, 0, 128, 255)
TEXT_BASE_COLOR = Color.new(255, 255, 255, 255)
TEXT_SHADOW_COLOR = Color.new(0, 0, 0, 100)
NB_SPRITES_TO_PRELOAD = 30
TOTAL_NB_FRAMES = 4000 #set manually, depends on music length
FUSION_SPRITES_MAX_OPACITY=200
NB_FRAMES_AT_MAX_OPACITY=30
# This next piece of code is the credits.
# Start Editing
CREDIT = <<_END_
Pokémon Infinite Fusion
By Chardub (Frogman)
By Chardub (Frogzilla)
General graphics / Music / Intellectual property
Nintendo
GameFreak
Programming / Eventing:
Programming / Game design:
Chardub
Fused Pokemon Sprites :
Fused Pokemon Sprites :
Japeal - Pokefusion 2
http://japeal.com/pkm
Special thanks to Aegide and Reizod for helping to
download the autogenerated sprites and to the owners of Japeal
for accepting to share their sprites.
Special thanks to Aegide and Reizod for
helping to download the autogenerated sprites
and to the owners of Japeal for accepting to
share their sprites.
Maps:
Chardub
@@ -75,12 +78,6 @@ Gameplay / Story :
Chardub
Kiwikelly
Most of the story and dialogues were based
off Pokémon Red and Blue, as well as
Pokémon Gold and Silver.
Both games are made by Game Freak.
Custom sprites collecting and handling
Kiwikelly, Payapon, Thornsoflight
@@ -94,36 +91,22 @@ Milchik the Miltank<s>Payapon
Pix<s>Rosemagwin
Thornsoflight
All of the custom fused Pokémon sprites
were made by various members of the sp
were made by various members of the
Pokémon Infinite Fusion Discord
Including massive contributions from these users:
Including significant contributions from:
{SPRITER_CREDITS}
Other custom graphics:
Kiwikelly
Knuckles
UnworthyPie
Doctor Miawoo
Chardub
TCGrunler#4583
Kiwikelly<s>Knuckles
UnworthyPie<s>Doctor Miawoo
Chardub<s>TCGrunler#4583
The following free ressources were also used
with their respective authors' consent:
Pokémon Sprites:
The Smogon XY Sprite Project:
Smogon Sun/Moon Sprite Project:
Other sprites:
Hankiro, luckygirl88, Nalty,
OceansLugiaSpirit,Pokemon-Diamond,
rekman, Rick1234, SailorVicious,WolfPP
Public use tileset graphics:
Alucus BoOmxBiG<s>chimcharsfireworkd
EpicDay<s>EternalTakai
@@ -143,24 +126,8 @@ Pokeli, TailDoll666100
Kazune Sawatari, sentsinkantéun,
Nanashima, CharizardTheMaster, The Zame Jack
Public use RPG Maker scripts:
Luka S.J, shiney570, Erasus, Umbreon
FL, KleinStudio, carmaniac, Wootius,
andracass
{INSERTS_PLUGIN_CREDITS_DO_NOT_REMOVE}
Data sources:
Bulbapedia
PBS files:
Generation 6 for Pokémon Essentials
WorldSlayer
mej71,karstictrainer, WorldSlayer,
TheDeKay, viperk1, SunakazeKun,
Radical Raptr, RPD490,
Takyon!, Pokegod7020, Drakath569,
Florio, MrDeepDarkMind, snooper117
"Pokémon Essentials" was created by:
Flameguru
Poccil (Peter O.)
@@ -195,12 +162,6 @@ All generated fusion sprites in this game
come from the Pokémon Fusion Generator:
https://japeal.com/pkm/
Playtesting and Custom Sprites were made by
various members of the Discord channel.
Special thanks to all of you and to
everyone who has been involved in the
development of the game!
Pokémon is owned by:
The Pokémon Company
Nintendo
@@ -212,7 +173,7 @@ _END_
# Stop Editing
def main
endCredits() if $PokemonSystem.on_mobile
#endCredits() if $PokemonSystem.on_mobile
#-------------------------------
# Animated Background Setup
#-------------------------------
@@ -222,6 +183,7 @@ _END_
@trim = Graphics.height / 10
# Number of game frames per background frame
@realOY = -(Graphics.height - @trim)
@customSpritesList = getSpritesList()
#-------------------------------
# Credits text Setup
#-------------------------------
@@ -325,6 +287,22 @@ _END_
pbBGMPlay(previousBGM)
end
def getSpritesList()
spritesList = []
$PokemonGlobal.alt_sprite_substitutions.each_value do |value|
if value.is_a?(PIFSprite)
spritesList << value
end
end
selected_spritesList = spritesList.sample(NB_SPRITES_TO_PRELOAD)
spriteLoader = BattleSpriteLoader.new
for sprite in selected_spritesList
spriteLoader.preload(sprite)
end
return selected_spritesList
end
# Check if the credits should be cancelled
def cancel?
if Input.trigger?(Input::USE) && $PokemonGlobal.creditsPlayed
@@ -352,15 +330,42 @@ _END_
def update
delta = Graphics.delta_s
@counter += delta
@background_sprite.setBitmap("Graphics/Titles/" + BACKGROUNDS_LIST[@bg_index])
@sprites_counter = 0 if !@sprites_counter
#@background_sprite.setBitmap("Graphics/Titles/" + BACKGROUNDS_LIST[@bg_index])
# # Go to next slide
# if @counter >= SECONDS_PER_BACKGROUND
# @counter -= SECONDS_PER_BACKGROUND
# @bg_index += 1
# @bg_index = 0 if @bg_index >= BACKGROUNDS_LIST.length
# @background_sprite.setBitmap("Graphics/Titles/" + BACKGROUNDS_LIST[@bg_index])
# end
@frames_counter = 0 if !@frames_counter
@frames_counter+=1
stopShowingSprites = @frames_counter >= (TOTAL_NB_FRAMES-300)
pbBGSStop if @frames_counter > TOTAL_NB_FRAMES
spriteLoader = BattleSpriteLoader.new
if @counter >= SECONDS_PER_BACKGROUND && @customSpritesList.length > 0 && !stopShowingSprites
@sprites_counter=0
randomSprite = @customSpritesList.sample
@customSpritesList.delete(randomSprite)
@background_sprite.setBitmapDirectly(spriteLoader.load_pif_sprite(randomSprite))
@background_sprite.x = rand(0..300)
@background_sprite.y = rand(0..200)
@counter -= SECONDS_PER_BACKGROUND
@background_sprite.opacity = 50
@fadingIn=true
end
if @fadingIn
if @background_sprite.opacity < FUSION_SPRITES_MAX_OPACITY
@background_sprite.opacity +=5
else
@fadingIn=false
end
else
@sprites_counter += 1
if @sprites_counter >= NB_FRAMES_AT_MAX_OPACITY
@background_sprite.opacity-=3
end
end
return if cancel?
return if last?
@realOY += SCROLL_SPEED * delta
+5
View File
@@ -120,6 +120,7 @@ class PokemonPauseMenu
commands[cmdBag = commands.length] = _INTL("Bag") if !pbInBugContest?
commands[cmdPokegear = commands.length] = _INTL("Pokégear") if $Trainer.has_pokegear
commands[cmdTrainer = commands.length] = $Trainer.name
commands[cmdOutfit = commands.length] = _INTL("Outfit") if $Trainer.can_change_outfit
if pbInSafari?
if Settings::SAFARI_STEPS <= 0
@scene.pbShowInfo(_INTL("Balls: {1}", pbSafariState.ballcount))
@@ -217,6 +218,10 @@ class PokemonPauseMenu
screen.pbStartScreen
@scene.pbRefresh
}
elsif cmdOutfit && cmdOutfit >= 0 && command == cmdOutfit
@scene.pbHideMenu
pbCommonEvent(COMMON_EVENT_OUTFIT)
elsif cmdQuit >= 0 && command == cmdQuit
@scene.pbHideMenu
if pbInSafari?
+143 -42
View File
@@ -10,6 +10,7 @@ class PokemonPokedexInfo_Scene
@index = index
@region = region
@page = 1
@entry_page = 0
@typebitmap = AnimatedBitmap.new(_INTL("Graphics/Pictures/Pokedex/icon_types"))
@sprites = {}
@sprites["background"] = IconSprite.new(0, 0, @viewport)
@@ -19,6 +20,7 @@ class PokemonPokedexInfo_Scene
@sprites["infosprite"].y = 136
@sprites["infosprite"].zoom_x = Settings::FRONTSPRITE_SCALE
@sprites["infosprite"].zoom_y = Settings::FRONTSPRITE_SCALE
@spritesLoader = BattleSpriteLoader.new
# @mapdata = pbLoadTownMapData
# map_metadata = GameData::MapMetadata.try_get($game_map.map_id)
@@ -93,7 +95,7 @@ class PokemonPokedexInfo_Scene
@sprites["downarrow"].visible = false
end
def pbStartSpritesSelectSceneBrief(species,alts_list)
def pbStartSpritesSelectSceneBrief(species, alts_list)
@available = alts_list
@species = species
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@@ -105,7 +107,7 @@ class PokemonPokedexInfo_Scene
@sprites["background"] = IconSprite.new(0, 0, @viewport)
@sprites["overlay"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport)
@sprites["infosprite"] = PokemonSprite.new(@viewport)
@spritesLoader = BattleSpriteLoader.new
@page = 3
initializeSpritesPageGraphics
initializeSpritesPage(@available)
@@ -188,9 +190,11 @@ class PokemonPokedexInfo_Scene
if @sprites["previousSprite"]
@sprites["previousSprite"].visible = false
end
# species_data = pbGetSpeciesData(@species)
species_data = GameData::Species.get_species_form(@species, @form)
@sprites["infosprite"].setSpeciesBitmap(@species)#, @gender, @form)
@sprites["infosprite"].setSpeciesBitmap(@species) #, @gender, @form)
# if @sprites["formfront"]
# @sprites["formfront"].setSpeciesBitmap(@species,@gender,@form)
@@ -279,7 +283,6 @@ class PokemonPokedexInfo_Scene
overlay = @sprites["overlay"].bitmap
base = Color.new(88, 88, 80)
shadow = Color.new(168, 184, 184)
shadowCustom = Color.new(160, 200, 150)
imagepos = []
if @brief
@@ -320,12 +323,9 @@ class PokemonPokedexInfo_Scene
# species_data.pokedex_entry, base, shadow)
#
#
customEntry = getCustomEntryText(species_data)
entryText = customEntry ? customEntry : species_data.pokedex_entry
shadowColor = customEntry ? shadowCustom : shadow
drawTextEx(overlay, 40, 244, Graphics.width - (40 * 2), 4, # overlay, x, y, width, num lines
entryText, base, shadowColor)
drawEntryText(overlay, species_data)
# Draw the footprint
footprintfile = GameData::Species.footprint_filename(@species, @form)
if footprintfile
@@ -362,30 +362,95 @@ class PokemonPokedexInfo_Scene
pbDrawImagePositions(overlay, imagepos)
end
def drawEntryText(overlay, species_data)
baseColor = Color.new(88, 88, 80)
shadow = Color.new(168, 184, 184)
shadowCustom = Color.new(160, 200, 150)
shadowAI = Color.new(168, 184, 220)
def reloadDexEntry()
overlay = @sprites["overlay"].bitmap
overlay.clear
drawPageInfo
end
if species_data.is_fusion
customEntry = getCustomEntryText(species_data)
if customEntry
entryText = customEntry
shadowColor = shadowCustom
else
aiEntry = getAIDexEntry(species_data.species, species_data.name)
if aiEntry
entryText = aiEntry
shadowColor = shadowAI
else
entryText = species_data.pokedex_entry
shadowColor = shadow
end
end
else
entryText = species_data.pokedex_entry
shadowColor = shadow
end
max_chars_per_page = 150
pages = splitTextIntoPages(entryText, max_chars_per_page)
@entry_page = 0 if !@entry_page || pages.length == 1
displayedText = pages[@entry_page]
if pages.length > 1
page_indicator_text = "#{@entry_page + 1}/#{pages.length}"
drawTextEx(overlay, 425, 340, Graphics.width - (40 * 2), 4, # overlay, x, y, width, num lines
page_indicator_text, baseColor, shadow)
end
drawTextEx(overlay, 40, 244, Graphics.width - (40 * 2), 4, # overlay, x, y, width, num lines
displayedText, baseColor, shadowColor)
end
def splitTextIntoPages(text, max_chars_per_page)
words = text.split
pages = []
current_page = ""
words.each do |word|
if current_page.length + word.length + 1 > max_chars_per_page
pages << current_page.strip
current_page = word
else
current_page += " " unless current_page.empty?
current_page += word
end
end
pages << current_page.strip unless current_page.empty?
pages
end
def reloadDexEntry()
overlay = @sprites["overlay"].bitmap
overlay.clear
drawPageInfo
end
def changeEntryPage()
pbSEPlay("GUI sel cursor")
@entry_page = @entry_page == 1 ? 0 : 1
reloadDexEntry
end
def isAutogenSprite(sprite_path)
return !sprite_path.include?(Settings::CUSTOM_BATTLERS_FOLDER)
end
def getCustomEntryText(species_data)
sprite_bitmap= GameData::Species.sprite_bitmap(species_data.species)
return nil if isAutogenSprite(sprite_bitmap.path)
spritename = sprite_bitmap.filename
possibleCustomEntries = getCustomDexEntry(spritename)
spriteLoader = BattleSpriteLoader.new
pif_sprite=spriteLoader.get_pif_sprite_from_species(species_data)
return nil if pif_sprite.type != :CUSTOM
possibleCustomEntries = getCustomDexEntry(pif_sprite)
if possibleCustomEntries && possibleCustomEntries.length > 0
customEntry = possibleCustomEntries.sample
customEntry = customEntry.gsub(Settings::CUSTOM_ENTRIES_NAME_PLACEHOLDER,species_data.name)
customEntry = customEntry.gsub(Settings::CUSTOM_ENTRIES_NAME_PLACEHOLDER, species_data.name)
end
return customEntry
end
def getCustomDexEntry(sprite)
def getCustomDexEntry(pif_sprite)
sprite = pif_sprite.to_filename()
json_data = File.read(Settings::CUSTOM_DEX_ENTRIES_PATH)
parsed_data = HTTPLite::JSON.parse(json_data)
@@ -398,6 +463,52 @@ end
end
end
def getAIDexEntry(pokemonID, name)
begin
head_number = get_head_number_from_symbol(pokemonID).to_s
body_number = get_body_number_from_symbol(pokemonID).to_s
# Ensure the file exists, if not, create it
unless File.exist?(Settings::AI_DEX_ENTRIES_PATH)
File.write(Settings::AI_DEX_ENTRIES_PATH, '{}')
end
json_data = File.read(Settings::AI_DEX_ENTRIES_PATH)
data = HTTPLite::JSON.parse(json_data)
# Check if the entry exists
unless data[head_number] && data[head_number][body_number]
# If not, fetch it from the API
url = Settings::AI_ENTRIES_URL + "?head=#{head_number}&body=#{body_number}"
if !requestRateExceeded?(Settings::AI_ENTRIES_RATE_LOG_FILE, Settings::AI_ENTRIES_RATE_TIME_WINDOW, Settings::AI_ENTRIES_RATE_MAX_NB_REQUESTS)
fetched_entry = clean_json_string(pbDownloadToString(url))
else
echoln "API rate exceeded for AI entries"
end
return nil if !fetched_entry || fetched_entry.empty?
# If the fetched entry is valid, update the JSON and save it
unless fetched_entry.empty?
data[head_number] ||= {}
data[head_number][body_number] = fetched_entry
serialized_data = serialize_json(data)
File.write(Settings::AI_DEX_ENTRIES_PATH, serialized_data)
else
echoln "No AI entry found for Pokemon " + pokemonID.to_s
return nil
end
end
entry = data[head_number][body_number]
entry = entry.gsub(Settings::CUSTOM_ENTRIES_NAME_PLACEHOLDER, name)
entry = entry.gsub("\n", "")
# Unescape any escaped quotes before returning the entry
entry = entry.gsub('\\"', '"')
return clean_json_string(entry)
rescue MKXPError
return nil
end
end
def pbFindEncounter(enc_types, species)
return false if !enc_types
@@ -505,6 +616,7 @@ end
end
def pbGoToPrevious
@entry_page = 0
newindex = @index
while newindex > 0
newindex -= 1
@@ -516,6 +628,7 @@ end
end
def pbGoToNext
@entry_page = 0
newindex = @index
while newindex < @dexlist.length - 1
newindex += 1
@@ -526,7 +639,7 @@ end
end
end
def pbChooseAlt(brief=false)
def pbChooseAlt(brief = false)
index = 0
for i in 0...@available.length
if @available[i][1] == @gender && @available[i][2] == @form
@@ -573,15 +686,13 @@ end
pbUpdate
dorefresh = false
if Input.trigger?(Input::ACTION)
pbSEStop
#reloadDexEntry()
Pokemon.play_cry(@species, @form) if @page == 1
changeEntryPage()
elsif Input.trigger?(Input::BACK)
pbPlayCloseMenuSE
break
elsif Input.trigger?(Input::USE)
if @page == 2 # Area
# dorefresh = true
if @page == 1 # entry
changeEntryPage()
elsif @page == 3 # Forms
#if @available.length > 1
pbPlayDecisionSE
@@ -593,7 +704,7 @@ end
oldindex = @index
pbGoToPrevious
if @index != oldindex
@selected_index=0
@selected_index = 0
pbUpdateDummyPokemon
@available = pbGetAvailableForms
pbSEStop
@@ -604,7 +715,7 @@ end
oldindex = @index
pbGoToNext
if @index != oldindex
@selected_index=0
@selected_index = 0
pbUpdateDummyPokemon
@available = pbGetAvailableForms
pbSEStop
@@ -644,7 +755,7 @@ end
Input.update
pbUpdate
if Input.trigger?(Input::ACTION)
pbSEStop
changeEntryPage()
Pokemon.play_cry(@species, @form)
elsif Input.trigger?(Input::BACK)
pbPlayCloseMenuSE
@@ -652,24 +763,14 @@ end
elsif Input.trigger?(Input::USE)
pbPlayDecisionSE
break
elsif Input.trigger?(Input::RIGHT) || Input.trigger?(Input::LEFT)
changeEntryPage()
end
end
end
def pbSelectSpritesSceneBrief
pbChooseAlt(true)
# loop do
# Graphics.update
# Input.update
# pbUpdate
# if Input.trigger?(Input::ACTION)
# pbPlayDecisionSE
# elsif Input.trigger?(Input::BACK)
# pbPlayCloseMenuSE
# break
# end
# end
end
end
@@ -711,7 +812,7 @@ class PokemonPokedexInfoScreen
nb_sprites_for_alts_page = isSpeciesFusion(species) ? 2 : 1
alts_list = @scene.pbGetAvailableForms(species)
if alts_list.length > nb_sprites_for_alts_page
@scene.pbStartSpritesSelectSceneBrief(species,alts_list)
@scene.pbStartSpritesSelectSceneBrief(species, alts_list)
@scene.pbSelectSpritesSceneBrief
@scene.pbEndScene
end
+5 -2
View File
@@ -1015,7 +1015,7 @@ class PokemonPartyScreen
@scene.pbAnnotate(nil)
end
def pbPokemonMultipleEntryScreenEx(ruleset)
def pbPokemonMultipleEntryScreenEx(ruleset,ableProc=nil)
annot = []
statuses = []
ordinals = [_INTL("INELIGIBLE"), _INTL("NOT ENTERED"), _INTL("BANNED")]
@@ -1033,8 +1033,11 @@ class PokemonPartyScreen
ret = nil
addedEntry = false
for i in 0...@party.length
statuses[i] = (ruleset.isPokemonValid?(@party[i])) ? 1 : 2
statuses[i] = (ruleset.isPokemonValid?(@party[i],ableProc)) ? 1 : 2
end
for i in 0...@party.length
annot[i] = ordinals[statuses[i]]
end
+1 -1
View File
@@ -1331,6 +1331,7 @@ class PokemonSummary_Scene
end
def pbPokemonHatFromSummary(pokemon)
echoln pokemon.hat
cmd = 0
msg = "What should you do?"
loop do
@@ -1338,7 +1339,6 @@ class PokemonSummary_Scene
_INTL("Put on hat"),
_INTL("Remove hat"),
_INTL("Back")])
echoln cmd
break if cmd == -1
if cmd == 0 #Put on hat
@sprites["pokemon"].visible=false
+74 -55
View File
@@ -7,98 +7,114 @@ class PokemonTrainerCard_Scene
end
def pbStartScene
@viewport = Viewport.new(0,0,Graphics.width,Graphics.height)
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@sprites = {}
background = pbResolveBitmap(sprintf("Graphics/Pictures/Trainer Card/bg_f"))
if $Trainer.female? && background
addBackgroundPlane(@sprites,"bg","Trainer Card/bg_f",@viewport)
else
addBackgroundPlane(@sprites,"bg","Trainer Card/bg",@viewport)
end
cardexists = pbResolveBitmap(sprintf("Graphics/Pictures/Trainer Card/card_f"))
@sprites["card"] = IconSprite.new(0,0,@viewport)
setCardBackground()
is_postgame = $game_switches[SWITCH_BEAT_THE_LEAGUE]
if $Trainer.female? && cardexists
path = "Graphics/Pictures/Trainer Card/card_f"
if is_postgame
path+="_postgame"
end
@sprites["card"].setBitmap(path)
else
path = "Graphics/Pictures/Trainer Card/card"
if is_postgame
path+="_postgame"
end
@sprites["card"].setBitmap(path)
end
@sprites["overlay"] = BitmapSprite.new(Graphics.width,Graphics.height,@viewport)
overlay_version = is_postgame ? "overlay_postgame" : "overlay"
addBackgroundPlane(@sprites, "highlights", "Trainer Card/#{overlay_version}", @viewport)
@sprites["overlay"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport)
pbSetSystemFont(@sprites["overlay"].bitmap)
@sprites["trainer"] = IconSprite.new(336,112,@viewport)
@sprites["trainer"] = IconSprite.new(336, 112, @viewport)
@sprites["trainer"].setBitmapDirectly(generate_front_trainer_sprite_bitmap())
@sprites["trainer"].x -= (@sprites["trainer"].bitmap.width-128)/2
@sprites["trainer"].y -= (@sprites["trainer"].bitmap.height-128)
@sprites["trainer"].x -= (@sprites["trainer"].bitmap.width - 128) / 2
@sprites["trainer"].y -= (@sprites["trainer"].bitmap.height - 128)
@sprites["trainer"].z = 2
pbDrawTrainerCardFront
pbFadeInAndShow(@sprites) { pbUpdate }
end
def setCardBackground()
background_img = $Trainer.card_background ? $Trainer.card_background : "BLUE"
background_img_path = "Graphics/Pictures/Trainer Card/backgrounds/#{background_img}"
cardexists = pbResolveBitmap(sprintf(background_img_path))
@sprites["card"] = IconSprite.new(0, 0, @viewport)
if cardexists
@sprites["card"].setBitmap(background_img_path) if cardexists
else
@sprites["card"].setBitmap("Graphics/Pictures/Trainer Card/card")
end
@sprites["card"].z=-100
end
def promptSwapBackground()
$Trainer.unlocked_card_backgrounds = [] if !$Trainer.unlocked_card_backgrounds
if $Trainer.unlocked_card_backgrounds.length >= 1
if pbConfirmMessage("Swap your current Trainer Card background")
chosen = pbListScreen("Trainer card", TrainerCardBackgroundLister.new($Trainer.unlocked_card_backgrounds))
echoln chosen
if chosen
$Trainer.card_background = chosen
pbSEPlay("GUI trainer card open")
setCardBackground()
end
end
else
pbMessage("You can purchase new Trainer Card backgrounds at PokéMarts!")
end
end
def pbDrawTrainerCardFront
overlay = @sprites["overlay"].bitmap
overlay.clear
baseColor = Color.new(72,72,72)
shadowColor = Color.new(160,160,160)
baseColor = Color.new(72, 72, 72)
shadowColor = Color.new(160, 160, 160)
totalsec = Graphics.frame_count / Graphics.frame_rate
hour = totalsec / 60 / 60
min = totalsec / 60 % 60
time = (hour>0) ? _INTL("{1}h {2}m",hour,min) : _INTL("{1}m",min)
time = (hour > 0) ? _INTL("{1}h {2}m", hour, min) : _INTL("{1}m", min)
$PokemonGlobal.startTime = pbGetTimeNow if !$PokemonGlobal.startTime
starttime = _INTL("{1} {2}, {3}",
pbGetAbbrevMonthName($PokemonGlobal.startTime.mon),
$PokemonGlobal.startTime.day,
$PokemonGlobal.startTime.year)
pbGetAbbrevMonthName($PokemonGlobal.startTime.mon),
$PokemonGlobal.startTime.day,
$PokemonGlobal.startTime.year)
textPositions = [
[_INTL("Name"),34,58,0,baseColor,shadowColor],
[$Trainer.name,302,58,1,baseColor,shadowColor],
[_INTL("ID No."),332,58,0,baseColor,shadowColor],
[sprintf("%05d",$Trainer.public_ID),468,58,1,baseColor,shadowColor],
[_INTL("Money"),34,106,0,baseColor,shadowColor],
[_INTL("${1}",$Trainer.money.to_s_formatted),302,106,1,baseColor,shadowColor],
[_INTL("Pokédex"),34,154,0,baseColor,shadowColor],
[sprintf("%d/%d",$Trainer.pokedex.owned_count,$Trainer.pokedex.seen_count),302,154,1,baseColor,shadowColor],
[_INTL("Time"),34,202,0,baseColor,shadowColor],
[time,302,202,1,baseColor,shadowColor],
[_INTL("Started"),34,250,0,baseColor,shadowColor],
[starttime,302,250,1,baseColor,shadowColor]
[_INTL("Name"), 34, 58, 0, baseColor, shadowColor],
[$Trainer.name, 302, 58, 1, baseColor, shadowColor],
[_INTL("ID No."), 332, 58, 0, baseColor, shadowColor],
[sprintf("%05d", $Trainer.public_ID), 468, 58, 1, baseColor, shadowColor],
[_INTL("Money"), 34, 106, 0, baseColor, shadowColor],
[_INTL("${1}", $Trainer.money.to_s_formatted), 302, 106, 1, baseColor, shadowColor],
[_INTL("Pokédex"), 34, 154, 0, baseColor, shadowColor],
[sprintf("%d/%d", $Trainer.pokedex.owned_count, $Trainer.pokedex.seen_count), 302, 154, 1, baseColor, shadowColor],
[_INTL("Time"), 34, 202, 0, baseColor, shadowColor],
[time, 302, 202, 1, baseColor, shadowColor],
[_INTL("Started"), 34, 250, 0, baseColor, shadowColor],
[starttime, 302, 250, 1, baseColor, shadowColor]
]
pbDrawTextPositions(overlay,textPositions)
pbDrawTextPositions(overlay, textPositions)
x = 72
imagePositions = []
postgame = $game_switches[SWITCH_BEAT_THE_LEAGUE]
numberOfBadgesDisplayed = postgame ? 16 : 8
for i in 0...numberOfBadgesDisplayed
badgeRow= i<8 ? 0 : 1
badgeRow = i < 8 ? 0 : 1
if $Trainer.badges[i]
if i == 8
x =72
x = 72
end
badge_graphic_x = badgeRow == 0 ? i*32 : (i-8)*32
badge_graphic_y =badgeRow*32
y = getBadgeDisplayHeight(postgame,i)
imagePositions.push(["Graphics/Pictures/Trainer Card/icon_badges",x,y,badge_graphic_x,badge_graphic_y,32,32])
badge_graphic_x = badgeRow == 0 ? i * 32 : (i - 8) * 32
badge_graphic_y = badgeRow * 32
y = getBadgeDisplayHeight(postgame, i)
imagePositions.push(["Graphics/Pictures/Trainer Card/icon_badges", x, y, badge_graphic_x, badge_graphic_y, 32, 32])
end
x += 48
end
pbDrawImagePositions(overlay,imagePositions)
pbDrawImagePositions(overlay, imagePositions)
end
def getBadgeDisplayHeight(postgame,i)
def getBadgeDisplayHeight(postgame, i)
if postgame
if i < 8
y=310
y = 310
else
y=344
y = 344
end
else
y = 312
@@ -112,6 +128,9 @@ class PokemonTrainerCard_Scene
Graphics.update
Input.update
pbUpdate
if Input.trigger?(Input::USE)
promptSwapBackground()
end
if Input.trigger?(Input::BACK)
pbPlayCloseMenuSE
break
+3 -1
View File
@@ -21,6 +21,7 @@ class PokemonSystem
attr_accessor :speedup_speed
attr_accessor :max_nb_sprites_download
attr_accessor :on_mobile
attr_accessor :type_icons
def initialize
@textspeed = 1 # Text speed (0=slow, 1=normal, 2=fast)
@@ -40,7 +41,8 @@ class PokemonSystem
@speedup_speed = 3 #for hold only
@download_sprites = 0
@max_nb_sprites_download = 5
@on_mobile = false
@type_icons = true
end
end
@@ -2,6 +2,7 @@
# Pokémon icons
#===============================================================================
class PokemonBoxIcon < IconSprite
attr_accessor :pokemon
def initialize(pokemon, viewport = nil)
super(0, 0, viewport)
@pokemon = pokemon
@@ -516,10 +517,12 @@ class PokemonBoxSprite < SpriteWrapper
end
def refreshAllBoxSprites
# spriteLoader = BattleSpriteLoader.new
for i in 0...PokemonBox::BOX_SIZE
if @pokemonsprites[i] && !@pokemonsprites[i].disposed?
@pokemonsprites[i].refresh(@fusions_enabled)
end
#spriteLoader.preload_sprite_from_pokemon(@pokemonsprites[i].pokemon) if @pokemonsprites[i].pokemon
end
end
@@ -2040,6 +2043,11 @@ class PokemonStorageScreen
end
command = pbShowCommands(_INTL("Release this Pokémon?"), [_INTL("No"), _INTL("Yes")])
if command == 1
if pokemon.owner.name == "RENTAL"
pbDisplay(_INTL("This Pokémon cannot be released"))
return
end
pkmnname = pokemon.name
@scene.pbRelease(selected, heldpoke)
if heldpoke
+15
View File
@@ -235,8 +235,23 @@ def pbTrainerPC
pbSEPlay("PC close")
end
def checkPorygonEncounter
porygon_chance = 200
if $PokemonGlobal.stepcount % porygon_chance == 0
pbSEPlay("Paralyze3")
pbWait(12)
pbMessage(_INTL("Huh? The PC glitched for a second while it booted."))
pbMessage(_INTL("Did something make its way into the PC?"))
pbWait(8)
pbAddPokemonSilent(:PORYGON,1)
$PokemonGlobal.stepcount += 1
end
# code here
end
def pbPokeCenterPC
pbMessage(_INTL("\\se[PC open]{1} booted up the PC.",$Trainer.name))
checkPorygonEncounter()
command = 0
loop do
commands = PokemonPCList.getCommandList
+123 -78
View File
@@ -11,7 +11,7 @@ class PokemonMartAdapter
end
def setMoney(value)
$Trainer.money=value
$Trainer.money = value
end
def getInventory
@@ -87,6 +87,29 @@ class PokemonMartAdapter
def getShadowColorOverride(item)
return nil
end
#specialType is a symbol
def getSpecialItemCaption(specialType)
return nil
end
def getSpecialItemDescription(specialType)
return nil
end
def doSpecialItemAction(specialType)
return nil
end
def getSpecialItemBaseColor(specialType)
return nil
end
def getSpecialItemShadowColor(specialType)
return nil
end
end
#===============================================================================
@@ -116,6 +139,22 @@ class BuyAdapter
def isSelling?
return false
end
def getSpecialItemCaption(specialType)
return @adapter.getSpecialItemCaption(specialType)
end
def getSpecialItemBaseColor(specialType)
return @adapter.getSpecialItemBaseColor(specialType)
end
def getSpecialItemShadowColor(specialType)
return @adapter.getSpecialItemShadowColor(specialType)
end
def getAdapter()
return @adapter
end
end
#===============================================================================
@@ -157,12 +196,12 @@ end
#===============================================================================
class Window_PokemonMart < Window_DrawableCommand
def initialize(stock, adapter, x, y, width, height, viewport = nil)
@stock = stock
@adapter = adapter
@stock = stock
@adapter = adapter
super(x, y, width, height, viewport)
@selarrow = AnimatedBitmap.new("Graphics/Pictures/martSel")
@baseColor = Color.new(88,88,80)
@shadowColor = Color.new(168,184,184)
@selarrow = AnimatedBitmap.new("Graphics/Pictures/martSel")
@baseColor = Color.new(88, 88, 80)
@shadowColor = Color.new(168, 184, 184)
self.windowskin = nil
end
@@ -178,23 +217,29 @@ class Window_PokemonMart < Window_DrawableCommand
textpos = []
rect = drawCursor(index, rect)
ypos = rect.y
if index == count-1
if index == count - 1
textpos.push([_INTL("CANCEL"), rect.x, ypos - 4, false, self.baseColor, self.shadowColor])
else
item = @stock[index]
itemname = @adapter.getDisplayName(item)
if item.is_a?(Symbol) && @adapter.getAdapter().is_a?(OutfitsMartAdapter)
itemname = @adapter.getSpecialItemCaption(item)
baseColor = @adapter.getSpecialItemBaseColor(item) ? @adapter.getSpecialItemBaseColor(item) : baseColor
shadowColor = @adapter.getSpecialItemShadowColor(item) ? @adapter.getSpecialItemShadowColor(item) : shadowColor
textpos.push([itemname, rect.x, ypos - 4, false, baseColor, shadowColor])
else
itemname = @adapter.getDisplayName(item)
baseColorOverride = @adapter.getBaseColorOverride(item)
shadowColorOverride = @adapter.getShadowColorOverride(item)
baseColorOverride = @adapter.getBaseColorOverride(item)
shadowColorOverride = @adapter.getShadowColorOverride(item)
baseColor = baseColorOverride ? baseColorOverride : self.baseColor
shadowColor = shadowColorOverride ? shadowColorOverride : self.shadowColor
baseColor = baseColorOverride ? baseColorOverride : self.baseColor
shadowColor = shadowColorOverride ? shadowColorOverride : self.shadowColor
qty = @adapter.getDisplayPrice(item)
sizeQty = self.contents.text_size(qty).width
xQty = rect.x + rect.width - sizeQty - 2 - 16
textpos.push([itemname, rect.x, ypos - 4, false, baseColor, shadowColor])
textpos.push([qty, xQty, ypos - 4, false, baseColor, shadowColor])
qty = @adapter.getDisplayPrice(item)
sizeQty = self.contents.text_size(qty).width
xQty = rect.x + rect.width - sizeQty - 2 - 16
textpos.push([itemname, rect.x, ypos - 4, false, baseColor, shadowColor])
textpos.push([qty, xQty, ypos - 4, false, baseColor, shadowColor])
end
end
pbDrawTextPositions(self.contents, textpos)
end
@@ -204,7 +249,7 @@ end
#
#===============================================================================
class PokemonMart_Scene
def initialize(currency_name="Money")
def initialize(currency_name = "Money")
@currency_name = currency_name
end
@@ -223,7 +268,7 @@ class PokemonMart_Scene
(itemwindow.item) ? @adapter.getDescription(itemwindow.item) : _INTL("Quit shopping.")
itemwindow.refresh
end
@sprites["moneywindow"].text = _INTL("{2}:\r\n<r>{1}", @adapter.getMoneyString,@currency_name)
@sprites["moneywindow"].text = _INTL("{2}:\r\n<r>{1}", @adapter.getMoneyString, @currency_name)
end
def scroll_map()
@@ -408,7 +453,7 @@ class PokemonMart_Scene
wasbusy = cw.busy?
self.update
if !cw.busy? && !yielded
yield if block_given? # For playing SE as soon as the message is all shown
yield if block_given? # For playing SE as soon as the message is all shown
yielded = true
end
pbRefresh if !cw.busy? && wasbusy
@@ -451,16 +496,16 @@ class PokemonMart_Scene
end
end
def pbChooseNumber(helptext,item,maximum)
def pbChooseNumber(helptext, item, maximum)
curnumber = 1
ret = 0
helpwindow = @sprites["helpwindow"]
itemprice = @adapter.getPrice(item, !@buying)
itemprice /= 2 if !@buying
pbDisplay(helptext, true)
using(numwindow = Window_AdvancedTextPokemon.new("")) { # Showing number of items
using(numwindow = Window_AdvancedTextPokemon.new("")) { # Showing number of items
qty = @adapter.getQuantity(item)
using(inbagwindow = Window_AdvancedTextPokemon.new("")) { # Showing quantity in bag
using(inbagwindow = Window_AdvancedTextPokemon.new("")) { # Showing quantity in bag
pbPrepareWindow(numwindow)
pbPrepareWindow(inbagwindow)
numwindow.viewport = @viewport
@@ -565,10 +610,10 @@ end
#
#===============================================================================
class PokemonMartScreen
def initialize(scene,stock,adapter=PokemonMartAdapter.new)
@scene=scene
@stock=stock
@adapter=adapter
def initialize(scene, stock, adapter = PokemonMartAdapter.new)
@scene = scene
@stock = stock
@adapter = adapter
end
def pbConfirm(msg)
@@ -579,52 +624,52 @@ class PokemonMartScreen
return @scene.pbDisplay(msg)
end
def pbDisplayPaused(msg,&block)
return @scene.pbDisplayPaused(msg,&block)
def pbDisplayPaused(msg, &block)
return @scene.pbDisplayPaused(msg, &block)
end
def pbBuyScreen
@scene.pbStartBuyScene(@stock,@adapter)
item=nil
@scene.pbStartBuyScene(@stock, @adapter)
item = nil
loop do
pbWait(4)
item=@scene.pbChooseBuyItem
item = @scene.pbChooseBuyItem
break if !item
quantity=0
itemname=@adapter.getDisplayName(item)
price=@adapter.getPrice(item)
if @adapter.getMoney<price
quantity = 0
itemname = @adapter.getDisplayName(item)
price = @adapter.getPrice(item)
if @adapter.getMoney < price
pbDisplayPaused(_INTL("You don't have enough money."))
next
end
if GameData::Item.get(item).is_important?
if !pbConfirm(_INTL("Certainly. You want {1}. That will be ${2}. OK?",
itemname,price.to_s_formatted))
itemname, price.to_s_formatted))
next
end
quantity=1
quantity = 1
else
maxafford = (price <= 0) ? Settings::BAG_MAX_PER_SLOT : @adapter.getMoney / price
maxafford = Settings::BAG_MAX_PER_SLOT if maxafford > Settings::BAG_MAX_PER_SLOT
quantity=@scene.pbChooseNumber(
_INTL("{1}? Certainly. How many would you like?",itemname),item,maxafford)
next if quantity==0
price*=quantity
quantity = @scene.pbChooseNumber(
_INTL("{1}? Certainly. How many would you like?", itemname), item, maxafford)
next if quantity == 0
price *= quantity
if !pbConfirm(_INTL("{1}, and you want {2}. That will be ${3}. OK?",
itemname,quantity,price.to_s_formatted))
itemname, quantity, price.to_s_formatted))
next
end
end
if @adapter.getMoney<price
if @adapter.getMoney < price
pbDisplayPaused(_INTL("You don't have enough money."))
next
end
added=0
added = 0
quantity.times do
break if !@adapter.addItem(item)
added+=1
added += 1
end
if added!=quantity
if added != quantity
added.times do
if !@adapter.removeItem(item)
raise _INTL("Failed to delete stored items")
@@ -632,16 +677,16 @@ class PokemonMartScreen
end
pbDisplayPaused(_INTL("You have no more room in the Bag."))
else
@adapter.setMoney(@adapter.getMoney-price)
@adapter.setMoney(@adapter.getMoney - price)
for i in 0...@stock.length
if GameData::Item.get(@stock[i]).is_important? && $PokemonBag.pbHasItem?(@stock[i])
@stock[i]=nil
@stock[i] = nil
end
end
@stock.compact!
pbDisplayPaused(_INTL("Here you are! Thank you!")) { pbSEPlay("Mart buy item") }
if $PokemonBag
if quantity>=10 && GameData::Item.get(item).is_poke_ball? && GameData::Item.exists?(:PREMIERBALL)
if quantity >= 10 && GameData::Item.get(item).is_poke_ball? && GameData::Item.exists?(:PREMIERBALL)
if @adapter.addItem(GameData::Item.get(:PREMIERBALL))
pbDisplayPaused(_INTL("I'll throw in a Premier Ball, too."))
end
@@ -653,35 +698,35 @@ class PokemonMartScreen
end
def pbSellScreen
item=@scene.pbStartSellScene(@adapter.getInventory,@adapter)
item = @scene.pbStartSellScene(@adapter.getInventory, @adapter)
loop do
item=@scene.pbChooseSellItem
item = @scene.pbChooseSellItem
break if !item
itemname=@adapter.getDisplayName(item)
price=@adapter.getPrice(item,true)
itemname = @adapter.getDisplayName(item)
price = @adapter.getPrice(item, true)
if !@adapter.canSell?(item)
pbDisplayPaused(_INTL("{1}? Oh, no. I can't buy that.",itemname))
pbDisplayPaused(_INTL("{1}? Oh, no. I can't buy that.", itemname))
next
end
qty=@adapter.getQuantity(item)
next if qty==0
qty = @adapter.getQuantity(item)
next if qty == 0
@scene.pbShowMoney
if qty>1
qty=@scene.pbChooseNumber(
_INTL("{1}? How many would you like to sell?",itemname),item,qty)
if qty > 1
qty = @scene.pbChooseNumber(
_INTL("{1}? How many would you like to sell?", itemname), item, qty)
end
if qty==0
if qty == 0
@scene.pbHideMoney
next
end
price/=2
price*=qty
if pbConfirm(_INTL("I can pay ${1}. Would that be OK?",price.to_s_formatted))
@adapter.setMoney(@adapter.getMoney+price)
price /= 2
price *= qty
if pbConfirm(_INTL("I can pay ${1}. Would that be OK?", price.to_s_formatted))
@adapter.setMoney(@adapter.getMoney + price)
qty.times do
@adapter.removeItem(item)
end
pbDisplayPaused(_INTL("Turned over the {1} and received ${2}.",itemname,price.to_s_formatted)) { pbSEPlay("Mart buy item") }
pbDisplayPaused(_INTL("Turned over the {1} and received ${2}.", itemname, price.to_s_formatted)) { pbSEPlay("Mart buy item") }
@scene.pbRefresh
end
@scene.pbHideMoney
@@ -694,8 +739,8 @@ def replaceShopStockWithRandomized(stock)
if $PokemonGlobal.randomItemsHash != nil
newStock = []
for item in stock
newItem =$PokemonGlobal.randomItemsHash[item]
if newItem != nil && GameData::Item.get(newItem).price >0 && !Settings::EXCLUDE_FROM_RANDOM_SHOPS.include?(newItem)
newItem = $PokemonGlobal.randomItemsHash[item]
if newItem != nil && GameData::Item.get(newItem).price > 0 && !Settings::EXCLUDE_FROM_RANDOM_SHOPS.include?(newItem)
newStock << newItem
else
newStock << item
@@ -709,7 +754,7 @@ end
#===============================================================================
#
#===============================================================================
def pbPokemonMart(stock,speech=nil,cantsell=false)
def pbPokemonMart(stock, speech = nil, cantsell = false)
if $game_switches[SWITCH_RANDOM_ITEMS_GENERAL] && $game_switches[SWITCH_RANDOM_SHOP_ITEMS]
stock = replaceShopStockWithRandomized(stock)
end
@@ -720,30 +765,30 @@ def pbPokemonMart(stock,speech=nil,cantsell=false)
end
stock.compact!
commands = []
cmdBuy = -1
cmdBuy = -1
cmdSell = -1
cmdQuit = -1
commands[cmdBuy = commands.length] = _INTL("Buy")
commands[cmdBuy = commands.length] = _INTL("Buy")
commands[cmdSell = commands.length] = _INTL("Sell") if !cantsell
commands[cmdQuit = commands.length] = _INTL("Quit")
cmd = pbMessage(
speech ? speech : _INTL("Welcome! How may I serve you?"),
commands,cmdQuit+1)
commands, cmdQuit + 1)
loop do
if cmdBuy>=0 && cmd==cmdBuy
if cmdBuy >= 0 && cmd == cmdBuy
scene = PokemonMart_Scene.new
screen = PokemonMartScreen.new(scene,stock)
screen = PokemonMartScreen.new(scene, stock)
screen.pbBuyScreen
elsif cmdSell>=0 && cmd==cmdSell
elsif cmdSell >= 0 && cmd == cmdSell
scene = PokemonMart_Scene.new
screen = PokemonMartScreen.new(scene,stock)
screen = PokemonMartScreen.new(scene, stock)
screen.pbSellScreen
else
pbMessage(_INTL("Please come again!"))
break
end
cmd = pbMessage(_INTL("Is there anything else I can help you with?"),
commands,cmdQuit+1)
commands, cmdQuit + 1)
end
$game_temp.clear_mart_prices
end
@@ -67,7 +67,21 @@ end
#===============================================================================
#
#===============================================================================
def pbEntryScreen(*arg)
def pbEntryScreen(ableproc=nil)
retval = false
pbFadeOutIn {
scene = PokemonParty_Scene.new
screen = PokemonPartyScreen.new(scene, $Trainer.party)
ret = screen.pbPokemonMultipleEntryScreenEx(pbBattleChallenge.rules.ruleset,ableproc)
# Set party
pbBattleChallenge.setParty(ret) if ret
# Continue (return true) if Pokémon were chosen
retval = (ret != nil && ret.length > 0)
}
return retval
end
def pbEntryScreenArgs(*arg)
retval = false
pbFadeOutIn {
scene = PokemonParty_Scene.new
@@ -103,15 +117,62 @@ class Game_Event
end
end
def getTrainerTypeGraphic(trainerType)
case trainerType
when :YOUNGSTER then return "BW (19)"
when :LASS then return "BW (23)"
when :POKEMANIAC then return "BW (30)"
when :PSYCHIC_F then return "BW (30)"
when :GENTLEMAN then return "BW (55)"
when :LADY then return "BW (28)"
when :CAMPER then return "BW (59)"
when :PICNICKER then return "BW (60)"
when :TUBER_M then return "BWTuber_male"
when :TUBER_F then return "BWTuber_female"
when :SWIMMER_M then return "BWSwimmerLand"
when :SWIMMER_F then return "BWSwimmer_female2"
when :COOLTRAINER_F then return "BW024"
when :JUGGLER then return "BWHarlequin"
when :POKEMONBREEDER then return "BW028"
when :BUGCATCHER then return "BWBugCatcher_male"
when :BLACKBELT then return "BWBlackbelt"
when :FISHERMAN then return "BW (71)"
when :RUINMANIAC then return "BW (72)"
when :TAMER then return "BW (69)"
when :BEAUTY then return "BW015"
when :AROMALADY then return "BWAomalady"
when :ROCKER then return "BWPunkGuy"
when :BIRDKEEPER then return "BW (29)"
when :SAILOR then return "BWSailor"
when :HIKER then return "BWHiker"
when :ENGINEER then return "BW (75)"
when :COOLTRAINER_M then return "BW023"
when :BIKER then return "BW055"
when :CRUSHGIRL then return "BWBattleGirl"
when :POKEMONRANGER_M then return "BW (47)"
when :POKEMONRANGER_F then return "BW (48)"
when :PSYCHIC_M then return "BW (30)"
when :CHANNELER then return "BW (40)"
when :GAMBLER then return "BW (111)"
when :SCIENTIST then return "BW (81)"
when :SUPERNERD then return "BW (81)"
when :CUEBALL then return "BWRoughneck"
end
end
#===============================================================================
#
#===============================================================================
def pbBattleChallengeGraphic(event)
nextTrainer = pbBattleChallenge.nextTrainer
bttrainers = pbGetBTTrainers(pbBattleChallenge.currentChallenge)
filename = GameData::TrainerType.charset_filename_brief((bttrainers[nextTrainer][0] rescue nil))
trainerType = (bttrainers[nextTrainer][0] rescue nil)
filename = getTrainerTypeGraphic(trainerType)
begin
filename = "NPCpbAddForeignPokemon 01" if nil_or_empty?(filename)
filename = "" if nil_or_empty?(filename)
bitmap = AnimatedBitmap.new("Graphics/Characters/" + filename)
bitmap.dispose
event.character_name = filename
@@ -123,8 +123,12 @@ class PokemonRuleSet
return self
end
def isPokemonValid?(pkmn)
def isPokemonValid?(pkmn,ableProc=nil)
return false if !pkmn
if ableProc
return false if !ableProc.call(pkmn)
end
for rule in @pokemonRules
return false if !rule.isValid?(pkmn)
end
@@ -64,7 +64,7 @@ end
#===============================================================================
# Giving Pokémon to the player (will send to storage if party is full)
#===============================================================================
def pbAddPokemon(pkmn, level = 1, see_form = true, dontRandomize=false)
def pbAddPokemon(pkmn, level = 1, see_form = true, dontRandomize=false, variableToSave=nil)
return false if !pkmn
if pbBoxesFull?
pbMessage(_INTL("There's no more room for Pokémon!\1"))
@@ -74,12 +74,15 @@ def pbAddPokemon(pkmn, level = 1, see_form = true, dontRandomize=false)
pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
tryRandomizeGiftPokemon(pkmn,dontRandomize)
species_name = pkmn.speciesName
pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, species_name))
pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[20]\1", $Trainer.name, species_name))
pbNicknameAndStore(pkmn)
$Trainer.pokedex.register(pkmn) if see_form
pbSet(variableToSave,pkmn) if variableToSave
return true
end
def pbAddPokemonSilent(pkmn, level = 1, see_form = true)
return false if !pkmn || pbBoxesFull?
pkmn = Pokemon.new(pkmn, level) if !pkmn.is_a?(Pokemon)
@@ -9,16 +9,14 @@ end
def pbWarpToMapId
params = ChooseNumberParams.new
params.setRange(1,pbMapTree().length)
params.setRange(1,999) #pbMapTree().length)
params.setDefaultValue($game_map.map_id)
map_id = pbMessageChooseNumber("map id?",params)
return [map_id,0,0]
end
def pbWarpToMapFly
pbBetterRegionMap(0,true,true,false,nil,true)
$game_screen.weather(:None,0,0)
$game_map.refresh
return pbBetterRegionMap(-1, true, true,false,nil,true)
end
def pbWarpToMap
@@ -253,13 +253,26 @@ class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
"Only legendaries can be randomized into legendaries"]
)
options << EnumOption.new(_INTL("Starters"), [_INTL("1st Stage"), _INTL("Any"), _INTL("Off")],
proc { $game_switches[SWITCH_RANDOM_STARTERS] ? 0 : 2 },
proc {
getStarterRandomizerSelectedOption() },
proc { |value|
$game_switches[SWITCH_RANDOM_STARTERS] = (value == 0 || value == 1)
if value == 0
case value
when 0
$game_switches[SWITCH_RANDOM_STARTERS] = true
$game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE] = true
when 1
$game_switches[SWITCH_RANDOM_STARTERS] = true
$game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE] = false
else
$game_switches[SWITCH_RANDOM_STARTERS] = false
$game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE] = false
end
echoln "random starters: #{$game_switches[SWITCH_RANDOM_STARTERS]}"
echoln "random 1st stage: #{$game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE]}"
}, ["The starters will always be a first evolution Pokémon",
"The starters can be any Pokémon",
"The starters are not randomized"]
@@ -283,12 +296,21 @@ class RandomizerWildPokemonOptionsScene < PokemonOption_Scene
proc { $game_switches[REGULAR_TO_FUSIONS] ? 0 : 1 },
proc { |value|
$game_switches[REGULAR_TO_FUSIONS] = value == 0
}, "Include fused Pokémon in the randomize pool for wild Pokémon"
}, "All wild Pokémon will already be pre-fused"
)
return options
end
def getStarterRandomizerSelectedOption()
return 0 if $game_switches[SWITCH_RANDOM_STARTERS] && $game_switches[SWITCH_RANDOM_STARTER_FIRST_STAGE]
return 1 if $game_switches[SWITCH_RANDOM_STARTERS]
return 2
end
end
class RandomizerGymOptionsScene < PokemonOption_Scene
RANDOM_GYM_TYPES = 921
@@ -329,7 +351,8 @@ class RandomizerGymOptionsScene < PokemonOption_Scene
proc { $game_switches[SWITCH_RANDOM_GYM_CUSTOMS] ? 0 : 1 },
proc { |value|
$game_switches[SWITCH_RANDOM_GYM_CUSTOMS] = value == 0
}, "Use only Pokémon that have custom sprites in gym trainers or gym leader teams"
}, ["Use only Pokémon that have custom sprites in gym trainers or gym leader teams",
"Pick any possible fusion, including auto-generated sprites."]
)
options << EnumOption.new(_INTL("Gym types"), [_INTL("On"), _INTL("Off")],
proc { $game_switches[RANDOM_GYM_TYPES] ? 0 : 1 },
@@ -21,8 +21,8 @@ HELD_ITEMS = [:AIRBALLOON, :BRIGHTPOWDER, :EVIOLITE, :FLOATSTONE, :DESTINYKNOT,
:JABOCABERRY, :ROWAPBERRY, :FAIRYGEM]
INVALID_ITEMS = [:COVERFOSSIL, :PLUMEFOSSIL, :ACCURACYUP, :DAMAGEUP, :ANCIENTSTONE, :ODDKEYSTONE_FULL,
:TM00,:DEVOLUTIONSPRAY, :INVISIBALL]
RANDOM_ITEM_EXCEPTIONS = [:DNASPLICERS, :DYNAMITE]
:DEVOLUTIONSPRAY, :INVISIBALL]
RANDOM_ITEM_EXCEPTIONS = [:DNASPLICERS,:POKEBALL, :DYNAMITE]
def getRandomGivenTM(item)
return item if item == nil
@@ -182,30 +182,30 @@ end
#summarize random options
def Kernel.sumRandomOptions()
answer = $game_switches[954] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_STARTERS] ? "On" : "Off"
stringOptions = "\nStarters: " << answer
answer = $game_switches[778] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_WILD] ? "On" : "Off"
stringOptions << "\nWild Pokémon: " << answer << " "
if $game_switches[777]
if $game_switches[SWITCH_RANDOM_WILD_AREA]
stringOptions << "(Area)"
else
stringOptions << "(Global)"
end
answer = $game_switches[987] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_TRAINERS] ? "On" : "Off"
stringOptions << "\nTrainers: " << answer
answer = $game_switches[955] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_STATIC_ENCOUNTERS] ? "On" : "Off"
stringOptions << "\nStatic encounters: " << answer
answer = $game_switches[780] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_GIFT_POKEMON] ? "On" : "Off"
stringOptions << "\nGift Pokémon: " << answer
answer = $game_switches[958] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_ITEMS] ? "On" : "Off"
stringOptions << "\nItems: " << answer
answer = $game_switches[959] ? "On" : "Off"
answer = $game_switches[SWITCH_RANDOM_TMS] ? "On" : "Off"
stringOptions << "\nTMs: " << answer
return stringOptions
@@ -225,14 +225,13 @@ def Kernel.sumGameStats()
stringStats << "Seen " << $Trainer.pokedexSeen.to_s << " Pokémon"
stringStats << "\nCaught " << $Trainer.pokedexOwned.to_s << " Pokémon"
stringStats << "\nBeaten the Elite Four " << $game_variables[VAR_STAT_NB_ELITE_FOUR].to_s << " times"
stringStats << "\nBeat the Elite Four " << $game_variables[VAR_STAT_NB_ELITE_FOUR].to_s << " times"
stringStats << "\nFused " << $game_variables[VAR_STAT_NB_FUSIONS].to_s << " Pokémon"
nbGymRematches = $game_variables[VAR_STAT_LEADER_REMATCH]
stringStats << "\nRematched " << nbGymRematches.to_s << " Gym Leaders" if nbGymRematches > 0
stringStats << "\nRematched " << $game_variables[VAR_STAT_LEADER_REMATCH].to_s << " Gym Leaders"
stringStats << "\nTook " << $PokemonGlobal.stepcount.to_s << " steps"
stringStats << "\nVisited " << countVisitedMaps.to_s << " different areas"
stringStats << "\nUsed " << $game_variables[VAR_STAT_RARE_CANDY].to_s << " Rare Candies"
stringStats << "\nUsed " << $game_variables[VAR_STAT_RARE_CANDY] << " Rare Candies"
if $game_switches[910]
stringStats << "\nMade " << $game_variables[VAR_STAT_NB_WONDERTRADES].to_s << " Wonder Trades"
@@ -240,6 +239,8 @@ def Kernel.sumGameStats()
stringStats << "\nTipped $" << $game_variables[VAR_STAT_CLOWN_TIP_TOTAL].to_s << " to clowns"
stringStats << "\nDestroyed " << $game_variables[VAR_STAT_NB_SANDCASTLES].to_s << " sandcastles"
stringStats << "\nReported " << $game_variables[VAR_NB_CRIMES_REPORTED].to_s << " crimes" if $game_variables[VAR_NB_CRIMES_REPORTED] > 0
if $game_variables[VAR_STAT_GAMBLER_WINS] > 0 || $game_variables[VAR_STAT_GAMBLER_LOSSES] > 0
stringStats << "\nWon $" << $game_variables[VAR_STAT_GAMBLER_WINS].to_s << " against gamblers"
@@ -445,10 +446,10 @@ def getCustomSpeciesList(allowOnline = true, redownload_file = false)
end
end
if speciesList.length <= 20000 && allowOnline
if redownload_file && Kernel.pbConfirmMessage(_INTL("Not enough local sprites found. Attempt to fetch list from the internet?"))
updateOnlineCustomSpritesFile
end
# if speciesList.length <= 20000 && allowOnline
# if redownload_file && Kernel.pbConfirmMessage(_INTL("Not enough local sprites found. Attempt to fetch list from the internet?"))
# updateOnlineCustomSpritesFile
# end
#try to get list from github
online_list = list_online_custom_sprites(true)
return speciesList if !online_list
@@ -458,10 +459,12 @@ def getCustomSpeciesList(allowOnline = true, redownload_file = false)
species_id_list << dexnum if dexnum && dexnum <= maxDexNumber && dexnum > 0
end
return species_id_list
end
#end
return speciesList
end
def is_file_alt(file)
filename = file.split(".")[0]
return filename.match(/[a-zA-Z]/)
@@ -106,13 +106,15 @@ class DoublePreviewScreen
body_pokemon = getBodyID(dexNumber)
head_pokemon = getHeadID(dexNumber, body_pokemon)
picturePath = getPicturePath(head_pokemon, body_pokemon)
bitmap = AnimatedBitmap.new(picturePath)
# picturePath = getPicturePath(head_pokemon, body_pokemon)
# bitmap = AnimatedBitmap.new(picturePath)
spriteLoader = BattleSpriteLoader.new
bitmap = spriteLoader.load_fusion_sprite(head_pokemon,body_pokemon)
bitmap.scale_bitmap(Settings::FRONTSPRITE_SCALE)
#hasCustom = picturePath.include?("CustomBattlers")
hasCustom = customSpriteExistsBase(body_pokemon,head_pokemon)
#hasCustom = customSpriteExistsBase(body_pokemon,head_pokemon)
hasCustom = customSpriteExists(body_pokemon,head_pokemon)
previewwindow = PictureWindow.new(bitmap)
previewwindow.x = x
previewwindow.y = y
@@ -131,10 +133,6 @@ class DoublePreviewScreen
end
def getPicturePath(head_pokemon, body_pokemon)
return get_fusion_sprite_path(head_pokemon,body_pokemon)
end
def drawFusionInformation(fusedDexNum, level, x = 0)
viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@typewindows << drawPokemonType(fusedDexNum, viewport, x + 55, 220) if @draw_types
+3 -3
View File
@@ -97,11 +97,11 @@ module GameData
end
def get_body_species
return @body_pokemon
return @body_pokemon.id_number
end
def get_head_species
return @head_pokemon
return @head_pokemon.id_number
end
def adjust_stats_with_evs
@@ -309,7 +309,7 @@ module GameData
end
def calculate_growth_rate
growth_rate_priority = [:Slow, :Erratic, :Fluctuating, :Parabolic, :Medium, :Fast] #todo rearrange order for balance?
growth_rate_priority = [:Fast, :Medium, :Parabolic, :Fluctuating, :Erratic, :Slow] #todo rearrange order for balance?
body_growth_rate = @body_pokemon.growth_rate
head_growth_rate = @head_pokemon.growth_rate
base_growth_rates = [body_growth_rate, head_growth_rate]
+51 -22
View File
@@ -430,14 +430,14 @@ class PokemonFusionScene
dna_splicer.z = 0
duration = Graphics.frame_rate * nb_seconds
direction = 1
dna_splicer.bitmap = pbBitmap("Graphics/Items/POTION")
#dna_splicer.bitmap = pbBitmap("Graphics/Items/POTION")
for j in 0...Graphics.frame_rate * 50
if j % 2 ==0
dna_splicer.bitmap = pbBitmap("Graphics/Items/SUPERSPLICERS")
else
dna_splicer.bitmap = pbBitmap("Graphics/Items/DNASPLICERS")
end
# if j % 2 ==0
# dna_splicer.bitmap = pbBitmap("Graphics/Items/SUPERSPLICERS")
# else
# dna_splicer.bitmap = pbBitmap("Graphics/Items/DNASPLICERS")
# end
if j % 5 == 0
dna_splicer.y += direction
@@ -500,9 +500,16 @@ class PokemonFusionScene
#
# #sprite_body.mirror if sprite_body_angle == 0 || sprite_body_angle == Math::PI
#
# update_sprite_color(sprite_body,j)
# update_sprite_color(sprite_head,j)
#
#
# sprite_head.update
# sprite_fused.update
# sprite_body.update
#
#
#
# end
# sprite_head.opacity = 0
# sprite_body.opacity = 0
@@ -513,9 +520,22 @@ class PokemonFusionScene
# @metafile3 = sprite_body
# end
def update_sprite_color(sprite,current_frame)
start_tone_change = 100 #frame at which the tone starts to change
return if current_frame < start_tone_change
new_tone = current_frame-start_tone_change
sprite.tone=Tone.new(new_tone,new_tone,new_tone)
if current_frame %2 ==0
#sprite.opacity-= 1
end
end
# def pbGenerateMetafiles(nb_seconds,ellipse_center_x,ellipse_center_y,ellipse_major_axis_length,ellipse_minor_axis_length)
#def pbGenerateMetafiles(s1x, s1y, s2x, s2y, s3x, s3y, sxx, s3xx)
#OLD ANIMATION
def pbGenerateMetafiles(nb_seconds,ellipse_center_x,ellipse_center_y,ellipse_major_axis_length,ellipse_minor_axis_length)
@sprites["rsprite1"].ox = @sprites["rsprite1"].bitmap.width / 2
@@ -643,19 +663,19 @@ class PokemonFusionScene
# Starts the fusion screen
def pbStartScreen(pokemon1, pokemon2, newspecies,splicerItem)
def pbStartScreen(pokemon_body, pokemon_head, newspecies,splicerItem)
@sprites = {}
@viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
@viewport.z = 99999
@pokemon1 = pokemon1
@pokemon2 = pokemon2
@pokemon1 = pokemon_body
@pokemon2 = pokemon_head
@newspecies = newspecies
addBackgroundOrColoredPlane(@sprites, "background", "DNAbg",
Color.new(248, 248, 248), @viewport)
poke1_number = GameData::Species.get(@pokemon1.species).id_number
poke2_number = GameData::Species.get(@pokemon2.species).id_number
poke_body_number = GameData::Species.get(@pokemon1.species).id_number
poke_head_number = GameData::Species.get(@pokemon2.species).id_number
@sprites["rsprite1"] = PokemonSprite.new(@viewport)
@sprites["rsprite2"] = PokemonSprite.new(@viewport)
@@ -665,10 +685,15 @@ class PokemonFusionScene
@sprites["dnasplicer"].y=(Graphics.height/2)-50
@sprites["dnasplicer"].opacity=0
@sprites["rsprite1"].setPokemonBitmapFromId(poke1_number, false, pokemon1.shiny?)
@sprites["rsprite3"].setPokemonBitmapFromId(poke2_number, false, pokemon2.shiny?)
@sprites["rsprite1"].setPokemonBitmapFromId(poke_body_number, false, pokemon_head.shiny?)
@sprites["rsprite3"].setPokemonBitmapFromId(poke_head_number, false, pokemon_head.shiny?)
@sprites["rsprite2"].setPokemonBitmapFromId(@newspecies, false, pokemon1.shiny? || pokemon2.shiny?, pokemon1.shiny?, pokemon2.shiny?)
spriteLoader = BattleSpriteLoader.new
@fusion_pif_sprite = spriteLoader.obtain_fusion_pif_sprite(poke_head_number,poke_body_number)
#this will use the sprite that is set when we call obtain_fusion_pif_sprite, and apply the shiny effect
@sprites["rsprite2"].setPokemonBitmapFromId(@newspecies, false, pokemon_head.shiny? || pokemon_body.shiny?, pokemon_head.shiny?, pokemon_body.shiny?)
splicer_bitmap = _INTL("Graphics/Items/{1}",splicerItem)
@sprites["dnasplicer"].setBitmap(splicer_bitmap)
@@ -722,8 +747,8 @@ class PokemonFusionScene
####FUSION MULTIPLIER
#####LEVELS
level1 = pokemon1.level
level2 = pokemon2.level
level1 = pokemon_head.level
level2 = pokemon_body.level
####LEVEL DIFFERENCE
if (level1 >= level2) then
@@ -788,7 +813,7 @@ class PokemonFusionScene
metaplayer1.play
metaplayer2.play
metaplayer3.play
#metaplayer4.play
metaplayer4.play
pbBGMStop()
pbPlayCry(@pokemon)
Kernel.pbMessageDisplay(@sprites["msgwindow"],
@@ -839,7 +864,8 @@ class PokemonFusionScene
overlay = BitmapSprite.new(Graphics.width, Graphics.height, @viewport).bitmap
sprite_bitmap = @sprites["rsprite2"].getBitmap
drawSpriteCredits(sprite_bitmap.filename, sprite_bitmap.path, @viewport)
drawSpriteCredits(@fusion_pif_sprite, @viewport)
pbBGMPlay(pbGetWildVictoryME)
Kernel.pbMessageDisplay(@sprites["msgwindow"],
_INTL("\\se[]Congratulations! Your Pokémon were fused into {2}!\\wt[80]", @pokemon1.name, newspeciesname))
@@ -925,13 +951,13 @@ class PokemonFusionScene
end
end
def drawSpriteCredits(filename, path, viewport)
def drawSpriteCredits(pif_sprite, viewport)
overlay = BitmapSprite.new(Graphics.width, Graphics.height, @viewport).bitmap
return if path.start_with?(Settings::BATTLERS_FOLDER)
return if pif_sprite.type == :AUTOGEN
x = Graphics.width / 2
y = 240
spritename = File.basename(filename, '.*')
spritename = pif_sprite.to_filename()
spritename = File.basename(spritename, '.*')
discord_name = getSpriteCredits(spritename)
return if !discord_name
@@ -948,6 +974,9 @@ def drawSpriteCredits(filename, path, viewport)
pbDrawTextPositions(overlay, textpos)
end
def clearUIForMoves
addBackgroundOrColoredPlane(@sprites, "background", "DNAbg",
Color.new(248, 248, 248), @viewport)
+55 -24
View File
@@ -380,8 +380,8 @@ module GameData
["Regi", "rock"],
["Regi", "ice"],
["Regi", "steel"],
["Latia", "tias"],
["Latio", "tios"],
["La", "tias"],
["La", "tios"],
["Kyo", "ogre"],
["Grou", "don"],
["Ray", "quaza"],
@@ -559,11 +559,11 @@ module GameData
["Marac", "actus"],
["Dweb", "ebble"],
["Crust", "ustle"],
["Scrag", "aggy"],
["Scraft", "afty"],
["Scra", "ggy"],
["Scraf", "ty"],
["Sigi", "lyph"],
["Ya", "mask"],
["Cofag", "grigus"],
["Cofa", "grigus"],
["Tirt", "touga"],
["Carra", "costa"],
["Arch", "chen"],
@@ -650,15 +650,15 @@ module GameData
["Kel", "deo"],
["Melo", "etta"],
["Gene", "esect"],
["Chesp", "spin"],
["Quill", "ladin"],
["Chesn", "naught"],
["Ches", "pin"],
["Quil", "ladin"],
["Ches", "naught"],
["Fenne", "kin"],
["Braix", "xen"],
["Delph", "phox"],
["Brai", "xen"],
["Del", "phox"],
["Froa", "kie"],
["Froga", "dier"],
["Gren", "ninja"],
["Frog", "adier"],
["Gre", "ninja"],
["Bunnel", "elby"],
["Diggers", "ersby"],
["Fletch", "ling"],
@@ -684,8 +684,8 @@ module GameData
["Aegi", "slash"],
["Spritz", "itzee"],
["Aroma", "tisse"],
["Swirl", "irlix"],
["Slurp", "urpuff"],
["Swir", "lix"],
["Slur", "puff"],
["Ink", "kay"],
["Mala", "lamar"],
["Bin", "nacle"],
@@ -703,7 +703,7 @@ module GameData
["Syl", "veon"],
["Hawl", "lucha"],
["Deden", "denne"],
["Carb", "bink"],
["Car", "bink"],
["Goo", "my"],
["Sli", "goo"],
["Goo", "dra"],
@@ -711,7 +711,7 @@ module GameData
["Phant", "tump"],
["Tre", "venant"],
["Pump", "kaboo"],
["Gourg", "urgeist"],
["Gour", "geist"],
["Berg", "mite"],
["Ava", "lugg"],
["Noi", "bat"],
@@ -719,7 +719,7 @@ module GameData
["Xern", "neas"],
["Yvel", "veltal"],
["Zyga", "garde"],
["Dian", "ancie"],
["Dian", "cie"],
["Hoop", "oopa"],
["Volcan", "canion"],
["Rowl", "owlet"],
@@ -754,7 +754,7 @@ module GameData
["Dew", "pider"],
["Ara", "quanid"],
["Fo", "mantis"],
["Lur", "antis"],
["Lu", "rantis"],
["More", "lull"],
["Shii", "notic"],
["Salan", "dit"],
@@ -767,8 +767,8 @@ module GameData
["Com", "fey"],
["Oran", "guru"],
["Pass", "simian"],
["Wimp", "pod"],
["Goliso", "sopod"],
["Wim", "pod"],
["Goli", "sopod"],
["Sandy", "gast"],
["Palo", "sand"],
["Pyuku", "muku"],
@@ -781,10 +781,10 @@ module GameData
["Mimi", "kyu"],
["Brux", "ish"],
["Dram", "ampa"],
["Dhelm", "helmise"],
["Jang", "angmo-o"],
["Haka", "akamo-o"],
["Komm", "mo-o"],
["Dhel", "mise"],
["Jang", "mo-o"],
["Haka", "mo-o"],
["Kom", "mo-o"],
["Tapu Ko", " Koko"],
["Tapu Le", " Lele"],
["Tapu Bu", " Bulu"],
@@ -1129,6 +1129,37 @@ module GameData
468 => 488,
469 => 779,
470 => 800,
471 => 782,
472 => 783,
473 => 784,
474 => 767,
475 => 768,
476 => 753,
477 => 754,
478 => 703,
479 => 650,
480 => 651,
481 => 652,
482 => 653,
483 => 654,
484 => 655,
485 => 656,
486 => 657,
487 => 658,
488 => 324,
489 => 710,
490 => 711,
491 => 684,
492 => 685,
493 => 559,
494 => 560,
495 => 270,
496 => 271,
497 => 272,
498 => 774,
499 => 774,
500 => 719,
501 => 370,
}
end
@@ -0,0 +1,52 @@
class SpritesBitmapCache
@@cache = {} # Cache storage for individual sprites
@@usage_order = [] # Tracks usage order for LRU eviction
def getCache()
return @@cache
end
def get_bitmap(pif_sprite)
sprite_key = get_cache_key(pif_sprite)
if @@cache.key?(sprite_key)
mark_key_as_recently_used(sprite_key)
return @@cache[sprite_key].clone
end
return nil
end
def mark_key_as_recently_used(sprite_key)
@@usage_order.delete(sprite_key)
@@usage_order << sprite_key
end
#Keys format: [type]_B[body]H[head]_letter
# ex:
# AUTOGEN_B12H12_
# CUSTOM_B12H12_a
# BASE_BH12_a
# etc.
def get_cache_key(pif_sprite)
return "#{pif_sprite.type.to_s}_B#{pif_sprite.body_id}H#{pif_sprite.head_id}_#{pif_sprite.alt_letter}".to_sym
end
#Keys format: AUTOGEN_B12H12_a
def add(pif_sprite,bitmap)
sprite_key = get_cache_key(pif_sprite)
echoln "adding key #{sprite_key} to cache"
@@cache[sprite_key] = bitmap.clone
if @@cache.size >= Settings::SPRITE_CACHE_MAX_NB
# Evict least recently used (first in order)
oldest_key = @@usage_order.shift
@@cache.delete(oldest_key)
echoln "Evicted: #{oldest_key} from sprite cache"
end
@@usage_order << sprite_key
end
def clear
@@cache = {}
@@usage_order = []
end
end
@@ -0,0 +1,125 @@
class PIFSpriteExtracter
COLUMNS = 20 # Number of columns in the spritesheet
@@spritesheet_cache = SpritesBitmapCache.new
def load_sprite(pif_sprite,download_allowed=true)
begin
start_time = Time.now
bitmap = @@spritesheet_cache.get_bitmap(pif_sprite)
loaded_from_spritesheet=false
if !bitmap
download_new_spritesheet(pif_sprite) if should_update_spritesheet?(pif_sprite) && download_allowed
if pbResolveBitmap(getSpritesheetPath(pif_sprite))
bitmap = load_bitmap_from_spritesheet(pif_sprite)
loaded_from_spritesheet=true
@@spritesheet_cache.add(pif_sprite, bitmap)
else
return nil
end
end
sprite_bitmap = AnimatedBitmap.from_bitmap(bitmap)
end_time = Time.now
source = loaded_from_spritesheet ? :"spritesheet" : "cache"
echoln "Loaded sprite for <head:#{pif_sprite.head_id}, body: #{pif_sprite.body_id}, variant: #{pif_sprite.alt_letter}> from #{source} in #{end_time - start_time} seconds"
return sprite_bitmap
rescue Exception
e = $!
echoln "Error loading sprite: #{e}" if bitmap
end
end
def download_new_spritesheet(pif_sprite)
spritesheet_file = getSpritesheetPath(pif_sprite)
if download_spritesheet(pif_sprite,spritesheet_file)
$updated_spritesheets << spritesheet_file
update_downloaded_spritesheets_list()
return true
end
return false
end
def update_downloaded_spritesheets_list()
File.open(Settings::UPDATED_SPRITESHEETS_CACHE, "w") do |file|
$updated_spritesheets.each { |line| file.puts(line) }
end
end
def get_sprite_position_on_spritesheet(body_id,sprite_size,nb_column)
row = body_id / nb_column
col = body_id % nb_column
# echoln "(#{col},#{row})"
# Define the area of the sprite on the spritesheet
sprite_x_position = col * sprite_size
sprite_y_position = row * sprite_size
return sprite_x_position, sprite_y_position
end
def extract_bitmap_to_file(pif_sprite, dest_folder)
# Create the directory if it doesn't exist
Dir.mkdir(dest_folder) unless Dir.exist?(dest_folder)
single_sprite_bitmap=load_sprite(pif_sprite)
# Save the single sprite bitmap to a file
file_path = "#{dest_folder}/#{head_id}.#{body_id}.png"
single_sprite_bitmap.save_to_png(file_path)
# Dispose of the single sprite bitmap
single_sprite_bitmap.dispose
# Return the path to the saved PNG file
return file_path
end
#Implemented for base and custom, not autogen
def should_update_spritesheet?(spritesheet_file)
return false
end
def getSpritesheetPath(pif_sprite)
return nil #implement in subclasses
end
def clear_cache()
@@spritesheet_cache.clear
end
end
class PokemonGlobalMetadata
attr_accessor :current_spritepack_date
end
# class SpritesBitmapCache
# @@cache = {} # Cache storage for spritesheets
# @@usage_order = [] # Tracks usage order for LRU eviction
#
# def self.fetch(key)
# if @@cache.key?(key)
# # Move key to the end to mark it as recently used
# @@usage_order.delete(key)
# @@usage_order << key
# return @@cache[key]
# end
#
# # Load spritesheet via block if not found in cache
# spritesheet = yield
#
# if @@cache.size >= Settings::SPRITE_CACHE_MAX_NB
# # Evict least recently used (first in order)
# oldest_key = @@usage_order.shift
# @@cache.delete(oldest_key)
# echoln "Evicted: #{oldest_key} from spritesheet cache"
# end
#
# # Add new spritesheet to cache and track its usage
# @@cache[key] = spritesheet
# @@usage_order << key
# spritesheet
# end
# end
@@ -0,0 +1,157 @@
class AutogenExtracter < PIFSpriteExtracter
SPRITESHEET_FOLDER_PATH = "Graphics\\Battlers\\spritesheets_autogen\\"
SPRITE_SIZE = 288 # Each sprite is 288x288 pixels
COLUMNS = 10 # Number of columns in the spritesheet
SHEET_WIDTH = SPRITE_SIZE * COLUMNS # 2880 pixels wide spritesheet
@instance = new
def self.instance
@@instance ||= new # If @@instance is nil, create a new instance
@@instance # Return the existing or new instance
end
def load_bitmap_from_spritesheet(pif_sprite)
body_id = pif_sprite.body_id
spritesheet_file = getSpritesheetPath(pif_sprite)
spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
# Extract individual sprite
sprite_x_position, sprite_y_position = get_sprite_position_on_spritesheet(body_id, SPRITE_SIZE, COLUMNS)
src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
bitmap.blt(0, 0, spritesheet_bitmap, src_rect)
# Dispose of spritesheet if it's no longer needed
spritesheet_bitmap.dispose
return bitmap
end
def getSpritesheetPath(pif_sprite)
head_id = pif_sprite.head_id
return "#{SPRITESHEET_FOLDER_PATH}#{head_id}.png"
end
#
# # Check cache before loading from disk
# sprite_bitmap = @@spritesheet_cache.fetch(pif_sprite) do
# # Load spritesheet from disk if necessary
# echoln "Loading spritesheet from disk: #{spritesheet_file}"
# spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
#
# # Extract individual sprite
# sprite_x_position, sprite_y_position = get_sprite_position_on_spritesheet(body_id, SPRITE_SIZE, COLUMNS)
# src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
#
# sprite = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
# sprite.blt(0, 0, spritesheet_bitmap, src_rect)
#
# # Dispose of spritesheet if it's no longer needed
# spritesheet_bitmap.dispose
#
# sprite
# end
# animatedBitmap = AnimatedBitmap.from_bitmap(sprite_bitmap)
#
# end_time = Time.now
# echoln "finished load sprite in #{end_time - start_time} seconds"
# echoln animatedBitmap
# return animatedBitmap
# end
def load_sprite_with_spritesheet_cache(pif_sprite)
start_time = Time.now
head_id = pif_sprite.head_id
body_id = pif_sprite.body_id
spritesheet_file = "#{SPRITESHEET_FOLDER_PATH}#{head_id}.png"
# Check cache before loading from disk
spritesheet_bitmap = @@spritesheet_cache.fetch(spritesheet_file) do
echoln "Loading spritesheet from disk: #{spritesheet_file}"
AnimatedBitmap.new(spritesheet_file).bitmap
end
sprite_x_position, sprite_y_position = get_sprite_position_on_spritesheet(body_id, SPRITE_SIZE, COLUMNS)
src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap.blt(0, 0, spritesheet_bitmap, src_rect)
#spritesheet_bitmap.dispose # Dispose since not needed
animatedBitmap = AnimatedBitmap.from_bitmap(sprite_bitmap)
end_time = Time.now
echoln "finished load sprite in #{end_time - start_time} seconds"
return animatedBitmap
end
end
# def extract_bitmap_to_file(head_id, body_id, folder)
# # Create the directory if it doesn't exist
# Dir.mkdir(folder) unless Dir.exist?(folder)
#
# # Load the entire spritesheet
# spritesheet_file = "#{SPRITESHEET_FOLDER_PATH}#{head_id}.png"
# spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
#
# # Calculate the 0-based row and column from the sprite index
# zero_index = body_id - 1
# row = zero_index / COLUMNS
# col = zero_index % COLUMNS
#
# # Define the area of the sprite on the spritesheet
# sprite_x_position = col * SPRITE_SIZE
# sprite_y_position = row * SPRITE_SIZE
#
# # Create a new bitmap for the single sprite
# single_sprite_bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
# single_sprite_bitmap.blt(0, 0, spritesheet_bitmap, Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE))
#
# # Dispose of the spritesheet bitmap if its no longer needed
# spritesheet_bitmap.dispose
#
# # Save the single sprite bitmap to a file
# file_path = "#{folder}/#{head_id}.#{body_id}.png"
# single_sprite_bitmap.save_to_png(file_path)
#
# # Dispose of the single sprite bitmap
# single_sprite_bitmap.dispose
#
# # Return the path to the saved PNG file
# return file_path
# end
#end
#
#
# class SpritesBitmapCache
# @@cache = {} # Cache storage for individual sprites
# @@usage_order = [] # Tracks usage order for LRU eviction
#
# def self.fetch(pif_sprite)
# sprite_key = "B#{pif_sprite.body_id}H#{pif_sprite.head_id}".to_sym
# if @@cache.key?(sprite_key)
# # Move key to the end to mark it as recently used
# @@usage_order.delete(sprite_key)
# @@usage_order << sprite_key
# return @@cache[sprite_key]
# end
#
# # Load sprite via block if not found in cache
# sprite_bitmap = yield
#
# if @@cache.size >= Settings::SPRITE_CACHE_MAX_NB
# # Evict least recently used (first in order)
# oldest_key = @@usage_order.shift
# @@cache.delete(oldest_key)
# echoln "Evicted: #{oldest_key} from sprite cache"
# end
#
# # Add new sprite to cache and track its usage
# @@cache[sprite_key] = sprite_bitmap
# @@usage_order << sprite_key
# sprite_bitmap
# echoln @@cache
# end
# end
@@ -0,0 +1,58 @@
class BaseSpriteExtracter < PIFSpriteExtracter
@instance = new
def self.instance
@@instance ||= new # If @@instance is nil, create a new instance
@@instance # Return the existing or new instance
end
SPRITESHEET_FOLDER_PATH = "Graphics/CustomBattlers/spritesheets/spritesheets_base/"
SPRITE_SIZE = 288 # Original sprite size
SCALED_SIZE = 288 # Scaled sprite size
NB_COLUMNS_BASESPRITES = 10
SHEET_WIDTH = SPRITE_SIZE * NB_COLUMNS_BASESPRITES # 2880 pixels wide spritesheet
def load_bitmap_from_spritesheet(pif_sprite)
alt_letter = pif_sprite.alt_letter
spritesheet_file = getSpritesheetPath(pif_sprite)
spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
letter_index = letters_to_index(alt_letter)
sprite_x_position, sprite_y_position = get_sprite_position_on_spritesheet(letter_index, SPRITE_SIZE, NB_COLUMNS_BASESPRITES)
src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap.blt(0, 0, spritesheet_bitmap, src_rect)
spritesheet_bitmap.dispose # Dispose since not needed
return sprite_bitmap
end
def letters_to_index(letters)
letters = letters.downcase # Ensure input is case-insensitive
index = 0
letters.each_char do |char|
index = index * 26 + (char.ord - 'a'.ord + 1)
end
#echoln "index: #{index}"
return index
end
def load_sprite_directly(head_id, body_id, alt_letter = "")
load_sprite(PIFSprite.new(:CUSTOM, head_id, body_id, alt_letter))
end
def getSpritesheetPath(pif_sprite)
dex_number = getDexNumberForSpecies(pif_sprite.head_id)
return "#{SPRITESHEET_FOLDER_PATH}#{dex_number}.png"
end
def should_update_spritesheet?(pif_sprite)
return false if !$updated_spritesheets
return false if !downloadAllowed?()
return false if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE,Settings::CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW,Settings::CUSTOMSPRITES_RATE_MAX_NB_REQUESTS,false)
spritesheet_file = getSpritesheetPath(pif_sprite)
return true if !pbResolveBitmap(spritesheet_file)
return !$updated_spritesheets.include?(spritesheet_file)
end
end
@@ -0,0 +1,266 @@
class BattleSpriteLoader
def initialize
@download_allowed = true
end
def load_pif_sprite_directly(pif_sprite)
extractor = get_sprite_extractor_instance(pif_sprite.type)
return extractor.load_sprite(pif_sprite)
end
#random alt
def load_pif_sprite(pif_sprite)
case pif_sprite.type
when :CUSTOM, :AUTOGEN
load_fusion_sprite(pif_sprite.head_id, pif_sprite.body_id)
when :BASE
load_base_sprite(pif_sprite.head_id)
end
end
# Only preloads if the pokemon's sprite has been assigned an alt letter
def preload_sprite_from_pokemon(pokemon)
return if !pokemon
substitution_id = get_sprite_substitution_id_from_dex_number(pokemon.species)
echoln substitution_id
echoln $PokemonGlobal.alt_sprite_substitutions
pif_sprite = $PokemonGlobal.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
if !pif_sprite
pif_sprite = get_pif_sprite_from_species(pokemon.species)
end
preload(pif_sprite)
end
#loads a sprite into cache without actually returning it
# Does not download spritesheet
def preload(pif_sprite)
echoln "preloading"
previous_download_allowed = @download_allowed
@download_allowed = false
load_pif_sprite(pif_sprite)
@download_allowed = previous_download_allowed
end
def clear_sprites_cache(type)
extractor = get_sprite_extractor_instance(type)
extractor.clear_cache
end
def load_from_dex_number(dex_number)
if dex_number > NB_POKEMON
if dex_number > ZAPMOLCUNO_NB #Triple Fusion
return load_triple_fusion_sprite(dex_number)
else
#Regular fusion
body_id = getBodyID(dex_number)
head_id = getHeadID(dex_number, body_id)
return load_fusion_sprite(head_id, body_id)
end
else
#base pokemon
return load_base_sprite(dex_number)
end
end
def obtain_fusion_pif_sprite(head_id,body_id)
substitution_id = get_sprite_substitution_id_for_fusion(head_id, body_id)
pif_sprite = $PokemonGlobal.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
if !pif_sprite
pif_sprite = select_new_pif_fusion_sprite(head_id, body_id)
substitution_id = get_sprite_substitution_id_for_fusion(head_id, body_id)
$PokemonGlobal.alt_sprite_substitutions[substitution_id] = pif_sprite if $PokemonGlobal
end
return pif_sprite
end
def load_fusion_sprite(head_id, body_id)
pif_sprite = obtain_fusion_pif_sprite(head_id,body_id)
local_path = check_for_local_sprite(pif_sprite)
if local_path
return AnimatedBitmap.new(local_path)
end
extractor = get_sprite_extractor_instance(pif_sprite.type)
loaded_sprite = extractor.load_sprite(pif_sprite, @download_allowed)
if !loaded_sprite
loaded_sprite = handle_unloaded_sprites(extractor,pif_sprite)
end
return loaded_sprite
end
def load_base_sprite(dex_number)
substitution_id = get_sprite_substitution_id_from_dex_number(dex_number)
pif_sprite = $PokemonGlobal.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
if !pif_sprite
pif_sprite = select_new_pif_base_sprite(dex_number)
$PokemonGlobal.alt_sprite_substitutions[substitution_id] = pif_sprite if $PokemonGlobal
end
local_path = check_for_local_sprite(pif_sprite)
if local_path
return AnimatedBitmap.new(local_path)
end
extractor = get_sprite_extractor_instance(pif_sprite.type)
loaded_sprite = extractor.load_sprite(pif_sprite)
if !loaded_sprite
loaded_sprite = handle_unloaded_sprites(extractor,pif_sprite)
end
return loaded_sprite
end
def handle_unloaded_sprites(extractor,pif_sprite)
if(extractor.is_a?(CustomSpriteExtracter)) #Custom failed to load, load an autogen (which should always be there)
new_extractor = get_sprite_extractor_instance(:AUTOGEN)
return new_extractor.load_sprite(pif_sprite)
else
#If autogen or base sprite aren't able to load a sprite then we have nothing else to load -> show a ? instead.
return AnimatedBitmap.new(Settings::DEFAULT_SPRITE_PATH)
end
end
#Always loaded from local individual sprites
def load_triple_fusion_sprite(dex_number)
sprite_path = getSpecialSpriteName(dex_number)
return AnimatedBitmap.new(sprite_path)
end
def get_sprite_extractor_instance(type)
case type
when :AUTOGEN
return AutogenExtracter.instance
when :CUSTOM
return CustomSpriteExtracter.instance
when :BASE
return BaseSpriteExtracter.instance
else
raise ArgumentError, "Unknown sprite type: #{type}"
end
end
def check_for_local_sprite(pif_sprite)
if pif_sprite.type == :BASE
sprite_path = "#{Settings::CUSTOM_BASE_SPRITES_FOLDER}#{pif_sprite.head_id}#{pif_sprite.alt_letter}.png"
else
sprite_path = "#{Settings::CUSTOM_BATTLERS_FOLDER_INDEXED}#{pif_sprite.head_id}/#{pif_sprite.head_id}.#{pif_sprite.body_id}#{pif_sprite.alt_letter}.png"
end
return pbResolveBitmap(sprite_path)
end
def get_pif_sprite_from_species(species)
species = GameData::Species.get(species)
head_id = species.get_head_species
body_id = species.get_body_species
substitution_id = get_sprite_substitution_id_for_fusion(head_id, body_id)
pif_sprite = $PokemonGlobal.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
return pif_sprite if pif_sprite
if species.id_number <= NB_POKEMON #base pokemon
return select_new_pif_base_sprite(head_id)
else #isFusion
return select_new_pif_fusion_sprite(head_id, body_id)
end
end
#
# Flow:
# # if none found, look for custom sprite in custom spritesheet (download if can't find spritesheet or new spritepack released)
# if none found, load from autogen spritesheet
def select_new_pif_fusion_sprite(head_id, body_id)
species_symbol = "B#{body_id}H#{head_id}".to_sym
spritename = get_fusion_spritename(head_id,body_id)
customSpritesList = $game_temp.custom_sprites_list[species_symbol]
alt_letter = ""
if customSpritesList
alt_letter = get_random_alt_letter_for_custom(head_id,body_id,true)
type = :CUSTOM
type = :AUTOGEN if !alt_letter
else
type = :AUTOGEN
end
if $PokemonTemp.forced_alt_sprites && $PokemonTemp.forced_alt_sprites.include?(spritename)
alt_letter = $PokemonTemp.forced_alt_sprites[spritename]
end
return PIFSprite.new(type, head_id, body_id, alt_letter)
end
def select_new_pif_base_sprite(dex_number)
random_alt = get_random_alt_letter_for_unfused(dex_number, true) #nil if no main
random_alt = "" if !random_alt
return PIFSprite.new(:BASE, dex_number, nil, random_alt)
end
def getSpecialSpriteName(dexNum)
base_path = "Graphics/Battlers/special/"
case dexNum
when Settings::ZAPMOLCUNO_NB
return sprintf(base_path + "144.145.146")
when Settings::ZAPMOLCUNO_NB + 1
return sprintf(base_path + "144.145.146")
when Settings::ZAPMOLCUNO_NB + 2
return sprintf(base_path + "243.244.245")
when Settings::ZAPMOLCUNO_NB + 3
return sprintf(base_path +"340.341.342")
when Settings::ZAPMOLCUNO_NB + 4
return sprintf(base_path +"343.344.345")
when Settings::ZAPMOLCUNO_NB + 5
return sprintf(base_path +"349.350.351")
when Settings::ZAPMOLCUNO_NB + 6
return sprintf(base_path +"151.251.381")
when Settings::ZAPMOLCUNO_NB + 11
return sprintf(base_path +"150.348.380")
#starters
when Settings::ZAPMOLCUNO_NB + 7
return sprintf(base_path +"3.6.9")
when Settings::ZAPMOLCUNO_NB + 8
return sprintf(base_path +"154.157.160")
when Settings::ZAPMOLCUNO_NB + 9
return sprintf(base_path +"278.281.284")
when Settings::ZAPMOLCUNO_NB + 10
return sprintf(base_path +"318.321.324")
#starters prevos
when Settings::ZAPMOLCUNO_NB + 12
return sprintf(base_path +"1.4.7")
when Settings::ZAPMOLCUNO_NB + 13
return sprintf(base_path +"2.5.8")
when Settings::ZAPMOLCUNO_NB + 14
return sprintf(base_path +"152.155.158")
when Settings::ZAPMOLCUNO_NB + 15
return sprintf(base_path +"153.156.159")
when Settings::ZAPMOLCUNO_NB + 16
return sprintf(base_path +"276.279.282")
when Settings::ZAPMOLCUNO_NB + 17
return sprintf(base_path +"277.280.283")
when Settings::ZAPMOLCUNO_NB + 18
return sprintf(base_path +"316.319.322")
when Settings::ZAPMOLCUNO_NB + 19
return sprintf(base_path +"317.320.323")
when Settings::ZAPMOLCUNO_NB + 20 #birdBoss Left
return sprintf(base_path +"invisible")
when Settings::ZAPMOLCUNO_NB + 21 #birdBoss middle
return sprintf(base_path + "144.145.146")
when Settings::ZAPMOLCUNO_NB + 22 #birdBoss right
return sprintf(base_path +"invisible")
when Settings::ZAPMOLCUNO_NB + 23 #sinnohboss left
return sprintf(base_path +"invisible")
when Settings::ZAPMOLCUNO_NB + 24 #sinnohboss middle
return sprintf(base_path +"343.344.345")
when Settings::ZAPMOLCUNO_NB + 25 #sinnohboss right
return sprintf(base_path +"invisible")
when Settings::ZAPMOLCUNO_NB + 25 #cardboard
return sprintf(base_path +"invisible")
when Settings::ZAPMOLCUNO_NB + 26 #cardboard
return sprintf(base_path + "cardboard")
when Settings::ZAPMOLCUNO_NB + 27 #Triple regi
return sprintf(base_path + "447.448.449")
#Triple Kalos 1
when Settings::ZAPMOLCUNO_NB + 28
return sprintf(base_path + "479.482.485")
when Settings::ZAPMOLCUNO_NB + 29
return sprintf(base_path + "480.483.486")
when Settings::ZAPMOLCUNO_NB + 30
return sprintf(base_path + "481.484.487")
else
return sprintf(base_path + "000")
end
end
end
@@ -0,0 +1,102 @@
class CustomSpriteExtracter < PIFSpriteExtracter
@instance = new
def self.instance
@@instance ||= new # If @@instance is nil, create a new instance
@@instance # Return the existing or new instance
end
SPRITESHEET_FOLDER_PATH = "Graphics/CustomBattlers/spritesheets/spritesheets_custom/"
SPRITE_SIZE = 288 # Original sprite size
SCALED_SIZE = 288 # Scaled sprite size
SHEET_WIDTH = SPRITE_SIZE * COLUMNS # 2880 pixels wide spritesheet
def load_bitmap_from_spritesheet(pif_sprite)
body_id = pif_sprite.body_id
spritesheet_file = getSpritesheetPath(pif_sprite)
spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
sprite_x_position,sprite_y_position =get_sprite_position_on_spritesheet(body_id,SPRITE_SIZE,COLUMNS)
src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
sprite_bitmap.blt(0, 0, spritesheet_bitmap, src_rect)
spritesheet_bitmap.dispose # Dispose since not needed
return sprite_bitmap
end
def load_sprite_to_file(pif_sprite)
head_id = pif_sprite.head_id
body_id = pif_sprite.body_id
alt_letter = pif_sprite.alt_letter
base_folder = "#{Settings::CUSTOM_BATTLERS_FOLDER_INDEXED}#{head_id}/"
individualSpriteFile = "#{base_folder}#{head_id}.#{body_id}#{alt_letter}.png"
if !pbResolveBitmap(individualSpriteFile)
animatedBitmap = load_sprite_from_spritesheet(pif_sprite)
Dir.mkdir(base_folder) unless Dir.exist?(base_folder)
animatedBitmap.bitmap.save_to_png(individualSpriteFile)
end
return AnimatedBitmap.new(individualSpriteFile)
end
def getSpritesheetPath(pif_sprite)
alt_letter = pif_sprite.alt_letter
head_id = pif_sprite.head_id
return "#{SPRITESHEET_FOLDER_PATH}#{head_id}/#{head_id}#{alt_letter}.png"
end
def should_update_spritesheet?(pif_sprite)
return false if !$updated_spritesheets
return false if !downloadAllowed?()
return false if requestRateExceeded?(Settings::CUSTOMSPRITES_RATE_LOG_FILE,Settings::CUSTOMSPRITES_ENTRIES_RATE_TIME_WINDOW,Settings::CUSTOMSPRITES_RATE_MAX_NB_REQUESTS,false)
spritesheet_file = getSpritesheetPath(pif_sprite)
return true if !pbResolveBitmap(spritesheet_file)
return !$updated_spritesheets.include?(spritesheet_file)
end
def load_sprite_directly(head_id,body_id,alt_letter="")
load_sprite(PIFSprite.new(:CUSTOM,head_id,body_id,alt_letter))
end
#
# def extract_bitmap_to_file(head_id, body_id, alt_letter, folder)
# # Create the directory if it doesn't exist
# Dir.mkdir(folder) unless Dir.exist?(folder)
#
# # Load the entire spritesheet
# spritesheet_file = "#{SPRITESHEET_FOLDER_PATH}#{head_id}\\#{head_id}#{alt_letter}.png"
# spritesheet_bitmap = AnimatedBitmap.new(spritesheet_file).bitmap
#
# # Calculate the 0-based row and column from the sprite index
# index = body_id
# row = index / COLUMNS
# col = index % COLUMNS
#
# # Define the area of the sprite on the spritesheet
# sprite_x_position = col * SPRITE_SIZE
# sprite_y_position = row * SPRITE_SIZE
#
# # Create a new bitmap for the sprite at its original size
# sprite_bitmap = Bitmap.new(SPRITE_SIZE, SPRITE_SIZE)
#
# # Copy the sprite from the spritesheet to the new bitmap
# src_rect = Rect.new(sprite_x_position, sprite_y_position, SPRITE_SIZE, SPRITE_SIZE)
# sprite_bitmap.blt(0, 0, spritesheet_bitmap, src_rect)
#
# # Dispose of the spritesheet bitmap if its no longer needed
# spritesheet_bitmap.dispose
#
# # Save the sprite bitmap to a file
# file_path = "#{folder}/#{head_id}.#{body_id}.png"
# sprite_bitmap.save_to_png(file_path)
#
# # Dispose of the sprite bitmap
# sprite_bitmap.dispose
#
# # Return the path to the saved PNG file
# return file_path
# end
end
@@ -0,0 +1,78 @@
#object representing a sprite which saves its position in the tileset
class PIFSprite
attr_accessor :type
attr_accessor :head_id
attr_accessor :body_id
attr_accessor :alt_letter
#types:
# :AUTOGEN, :CUSTOM, :BASE
def initialize(type, head_id, body_id, alt_letter="")
@type = type
@head_id = head_id
@body_id = body_id
@alt_letter = alt_letter
end
#little hack for old methods that expect a filename for a sprite
def to_filename()
case @type
when :CUSTOM
return "#{@head_id}.#{@body_id}#{@alt_letter}.png"
when :AUTOGEN
return "#{@head_id}.#{@body_id}.png"
when :BASE
return "#{@head_id}#{@alt_letter}.png"
end
end
def setup_from_spritename(spritename,type)
@type = type
cleaned_name = spritename.gsub(".png","")
if cleaned_name =~ /(\d+)\.(\d+)([a-zA-Z]*)/
head_id = $1
body_id = $2
alt_letter = $3
end
@head_id = head_id
@body_id = body_id
@alt_letter = alt_letter
end
def self.from_spritename(spritename,type)
obj = allocate
obj.send(:setup_from_spritename, spritename,type)
obj
end
end
def new_pif_sprite_from_dex_num(type, dexNum,alt_letter)
body_id = getBodyID(dexNum)
head_id = getHeadID(dexNum,body_id)
return PIFSprite.new(type,head_id,body_id,alt_letter)
end
def pif_sprite_from_spritename(spritename, autogen = false)
spritename = spritename.split(".png")[0] #remove the extension
if spritename =~ /^(\d+)\.(\d+)([a-zA-Z]*)$/ # Two numbers with optional letters
type = :CUSTOM
head_id = $1.to_i # Head (e.g., "1" in "1.2.png")
body_id = $2.to_i # Body (e.g., "2" in "1.2.png")
alt_letter = $3 # Optional trailing letter (e.g., "a" in "1.2a.png")
elsif spritename =~ /^(\d+)([a-zA-Z]*)$/ # One number with optional letters
type = :BASE
head_id = $1.to_i # Head (e.g., "1" in "1.png")
alt_letter = $2 # Optional trailing letter (e.g., "a" in "1a.png")
else
echoln "Invalid sprite format: #{spritename}"
return nil
end
type = :AUTOGEN if autogen
return PIFSprite.new(type,head_id,body_id,alt_letter)
end
@@ -0,0 +1,89 @@
def setSpriteSubstitution(pif_sprite)
end
def getSpriteSubstitutionForDex(dex_num)
end
def setSpriteSubstitution(head,body)
end
def set_updated_spritesheets
echoln
end
def initialize_alt_sprite_substitutions()
$PokemonGlobal.alt_sprite_substitutions = {} if !$PokemonGlobal.alt_sprite_substitutions
migrate_sprites_substitutions()
end
def get_sprite_substitution_id_for_fusion(head_id, body_id)
species_symbol = "B#{body_id}H#{head_id}".to_sym
return get_sprite_substitution_id_from_dex_number(species_symbol)
end
def get_sprite_substitution_id_from_dex_number(species_symbol)
species = GameData::Species.get(species_symbol)
if species.is_fusion
substitution_id = [species.get_head_species,species.get_body_species]
else
substitution_id= species.id_number
end
return substitution_id
end
def migrate_sprites_substitutions
return if $game_switches[SWITCH_UPDATED_TO_SPRITESHEETS_SPRITES]
new_substitutions = {}
old_number_pokemon = 470
for dex_number_key in $PokemonGlobal.alt_sprite_substitutions.keys
if $PokemonGlobal.alt_sprite_substitutions[dex_number_key].is_a?(String) && can_convert_to_int?(dex_number_key)
old_dex_number = dex_number_key.to_i
if old_dex_number > old_number_pokemon #fusion
body_id = getBodyID(old_dex_number,old_number_pokemon)
head_id = getHeadID(old_dex_number,body_id,old_number_pokemon)
new_id = [head_id,body_id]
type = :CUSTOM
else
new_id = old_dex_number
head_id = old_dex_number
body_id= nil
type = :BASE
end
file_path = $PokemonGlobal.alt_sprite_substitutions[dex_number_key]
alt_letter =get_alt_letter_from_path(file_path)
pif_sprite = PIFSprite.new(type,head_id,body_id,alt_letter)
new_substitutions[new_id] = pif_sprite
end
end
$PokemonGlobal.alt_sprite_substitutions = new_substitutions
$game_switches[SWITCH_UPDATED_TO_SPRITESHEETS_SPRITES] = true
end
def can_convert_to_int?(str)
Integer(str)
true
rescue ArgumentError
false
end
def get_alt_letter_from_path(filename)
# Remove the extension
base_name = filename.sub(/\.png$/, '')
# Check the last character
last_char = base_name[-1]
if last_char.match?(/\d/) # Check if the last character is a number
alt_letter = ""
else
# Reverse the base name and capture all letters until the first number
alt_letter = base_name.reverse[/[a-zA-Z]+/].reverse
end
return alt_letter
end
+56 -4
View File
@@ -75,9 +75,15 @@ SWITCH_NIGHTMARE_EFFECT= 805
SWITCH_JOHTO_STARTERS=884
SWITCH_HOENN_STARTERS=885
SWITCH_SINNOH_STARTERS=886
SWITCH_KALOS_STARTERS=888
SWITCH_CUSTOM_STARTERS=883
SWITCH_JOINED_TEAM_ROCKET=1037
SWITCH_PINKAN_SIDE_ROCKET=1099
SWITCH_PINKAN_SIDE_POLICE=1100
SWITCH_LEAVING_PINKAN_ISLAND=1113
SWITCH_BLOCK_PINKAN_WHISTLE=1111
VAR_ORICORIO_FLOWERS = 276
#Randomizer Switches
@@ -121,7 +127,7 @@ SWITCH_RANDOMIZED_WILD_POKEMON_TO_FUSIONS=829
SWITCH_RANDOM_WILD_LEGENDARIES=1031
SWITCH_RANDOM_TRAINER_LEGENDARIES=1032
SWITCH_RANDOM_GYM_LEGENDARIES=1033
SWITCH_DONT_RANDOMIZE=890
#Other switches
SWITCH_RACE_BIKE = 984
@@ -141,9 +147,10 @@ SWITCH_SUPER_SLOW_SPEED=649
SWITCH_LOUNGE_BATTLE_LEVEL = 240
SWITCH_CANNOT_CATCH_POKEMON = 75
SWITCH_UNLOCKED_POKEMON_HATS = 770
SWITCH_ILEX_FOREST_SPOOKED_POKEMON = 1021
SWITCH_LOCK_PLAYER_MOVEMENT = 815
SWITCH_TEAMED_WITH_ERIKA_SEWERS=141
SWITCH_BAND_DRUMMER = 1004
SWITCH_BAND_ACOUSTIC_GUITAR = 1005
SWITCH_BAND_ELECTRIC_GUITAR = 1006
@@ -152,10 +159,29 @@ SWITCH_BAND_FLUTE = 1008
SWITCH_SELECTING_CLOTHES = 804
SWITCH_KANTO_HAIR_COLLECTION = 1059
SWITCH_JOHTO_HAIR_COLLECTION = 1060
SWITCH_HOENN_HAIR_COLLECTION = 1061
SWITCH_SINNOH_HAIR_COLLECTION = 1062
SWITCH_UNOVA_HAIR_COLLECTION = 1063
SWITCH_KALOS_HAIR_COLLECTION = 1064
SWITCH_ALOLA_HAIR_COLLECTION = 1065
SWITCH_GALAR_HAIR_COLLECTION = 1066
SWITCH_PALDEA_HAIR_COLLECTION = 1067
SWITCH_GEN10_HAIR_COLLECTION = 1068
SWITCH_UPDATED_TO_SPRITESHEETS_SPRITES=1117
#OUTFITS
#
WEARING_ROCKET_OUTFIT = 1038
#############
# VARIABLES #
#############
VAR_CURRENT_MART=291
VAR_CURRENT_CITY_NUMERICAL_ID=14 #for wondertrade/pokemarts
VAR_SINGLE_POKEMON_MODE=251
SINGLE_POKEMON_MODE_VAR=251 #c'est appellé comme ca en qqpart dans un event pis ca me tente pas de chercher ou
@@ -185,8 +211,18 @@ VAR_STAT_NB_SANDCASTLES=163
VAR_STAT_GAMBLER_WINS=43
VAR_STAT_GAMBLER_LOSSES=44
VAR_STAT_HOTELS_SPENT=225
VAR_NB_EGGS_HATCHED=298
VAR_STAT_QUESTS_ACCEPTED=96
VAR_STAT_QUESTS_COMPLETED=98
VAR_NB_ROCKET_MISSIONS = 286
VAR_BOUTIQUE_OUTFIT=290
VAR_FISHING_CONTEST_RECORD=294
VAR_STAT_NB_SECRETS=193
VAR_STAT_FUSION_QUIZ_HIGHEST_SCORE=267
VAR_STAT_FUSION_QUIZ_NB_TIMES=268
@@ -196,7 +232,10 @@ VAR_LUNAR_FEATHERS=282
VAR_FOSSIL=271
VAR_SSANNE_MENU=313
VAR_TEMP_SSANNE_ORDER=314
VAR_TEMP_SSANNE_PLATE=325
VAR_SSANNE_DISHES_HELD_ARRAY=316
VAR_BATTLE_TOWER_MIN_BST = 257
VAR_BATTLE_TOWER_MAX_BST = 258
@@ -210,6 +249,12 @@ VAR_NEXT_ARTIST_FORMATTED = 264
VAR_RADIO_POINTS=266
VAR_TRAINER_GENDER=52
VAR_TRAINER_AGE=99
VAR_ROCKET_NAME=25
VAR_NB_CRIMES_REPORTED=300
VAR_EXOTIC_POKEMON_ID=327
VAR_TYPE_EXPERTS_BEATEN=332
TOTAL_NB_TYPE_EXPERTS=331
#Randomizer
VAR_RANDOMIZER_WILD_POKE_BST=197
@@ -238,6 +283,8 @@ VAR_CONSTELLATION_SHARPEDO=317
VAR_CONSTELLATION_ARCEUS=318
VAR_LATEST_CONSTELLATION=319
VAR_TRAINER_CARD_BACKGROUND_PRICE=329
VAR_GALLERY_TEAM_FLAGS=330
##############
@@ -247,6 +294,11 @@ COMMON_EVENT_REGI_TABLET = 84
COMMON_EVENT_SILHOUETTE = 87
COMMON_EVENT_HOTEL = 12
COMMON_EVENT_SINGLESPECIES_MODE = 73
COMMON_EVENT_OUTFIT = 80
COMMON_EVENT_FIX_GAME = 16
COMMON_EVENT_IDLE_HAT = 100
COMMON_EVENT_PINKAN_WHISTLE = 106
COMMON_EVENT_PINKAN_BACK_TO_BEGIN = 103
##############
@@ -980,45 +980,45 @@ class SpriteHash
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.each { |item| write(item) }
# elsif e.is_a?(Numeric)
# @file.putc e
# else
# raise "Invalid data for writing."
# 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 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.each { |item| write(item) }
elsif e.is_a?(Numeric)
@file.putc e
else
raise "Invalid data for writing."
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)
@@ -1057,9 +1057,12 @@ class Bitmap
data << px.alpha
end
end
# Zlib deflation
smoldata = Zlib::Deflate.deflate(data.pack("C*")).bytes.map
# data chunk length
smoldata = Zlib::Deflate.deflate(data.pack("C*"))
smoldata = smoldata.bytes
# Data chunk length
f.write_int smoldata.size
# IDAT
f << [0x49, 0x44, 0x41, 0x54]
@@ -1074,9 +1077,11 @@ class Bitmap
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
@@ -62,7 +62,7 @@ def extract_custom_sprites_that_evolve_into_non_customs(includeOnlyNextEvos=true
next if nextEvolutions.empty?
for evolution in nextEvolutions
evoSpecies = evolution[0]
if !customSpriteExists(evoSpecies) && !alreadyWritten.include?(evoSpecies)
if !customSpriteExistsSpecies(evoSpecies) && !alreadyWritten.include?(evoSpecies)
body = getBodyID(evoSpecies)
head = getHeadID(evoSpecies,body)
f.write((evoSpecies.to_s) +";")
@@ -108,7 +108,7 @@ def extract_pokes_with_non_custom_final_evos(includeOnlyNextEvos=true)
for evolution in nextEvolutions
evoSpecies = evolution[0]
isFinalEvo = GameData::Species.get(evoSpecies).get_evolutions.empty?
if !customSpriteExists(evoSpecies) && !alreadyWritten.include?(evoSpecies) && isFinalEvo
if !customSpriteExistsSpecies(evoSpecies) && !alreadyWritten.include?(evoSpecies) && isFinalEvo
body = getBodyID(evoSpecies)
head = getHeadID(evoSpecies,body)
f.write((evoSpecies.to_s) +";")
@@ -158,7 +158,7 @@ def extract_incomplete_evolution_lines
non_customs = []
nbCustoms=0
for stage in evolutions
if !customSpriteExists(stage)
if !customSpriteExistsSpecies(stage)
non_customs << stage
else
nbCustoms+=1
@@ -63,21 +63,25 @@ end
def setHairColor(hue_shift)
$Trainer.hair_color = hue_shift
refreshPlayerOutfit()
end
def shiftHatColor(incr)
$Trainer.hat_color = 0 if !$Trainer.hat_color
$Trainer.hat_color += incr
refreshPlayerOutfit()
end
def shiftClothesColor(incr)
$Trainer.clothes_color = 0 if !$Trainer.clothes_color
$Trainer.clothes_color += incr
refreshPlayerOutfit()
end
def shiftHairColor(incr)
$Trainer.hair_color = 0 if !$Trainer.hair_color
$Trainer.hair_color += incr
refreshPlayerOutfit()
end
def pbLoadOutfitBitmap(outfitFileName)
@@ -99,25 +103,41 @@ end
def getEasterEggHeldItem()
map = $game_map.map_id
return "HOTDOG" if [141, 194].include?(map) #restaurant
return "SNOWBALL" if [670, 693, 698, 694].include?(map)
return "WALLET" if [432, 433, 434, 435, 436, 292].include?(map) #dept. store
return "ALARMCLOCK" if [43, 48, 67, 68, 69, 70, 71, 73].include?(map) #Player room
return "secrets/HOTDOG" if [141, 194].include?(map) #restaurant
return "secrets/SNOWBALL" if [670, 693, 698, 694].include?(map)
return "secrets/WALLET" if [432, 433, 434, 435, 436, 292].include?(map) #dept. store
return "secrets/ALARMCLOCK" if [43, 48, 67, 68, 69, 70, 71, 73].include?(map) #Player room
return "SAFARIBALL" if [445, 484, 485, 486, 107, 487, 488, 717, 82, 75, 74].include?(map) #Safari Zone
return "secrets/WISP" if [401,402,403,467,468,469].include?(map) #Pokemon Tower
return "secrets/SKULL" if [400].include?(map) #Pokemon Tower ground floor
return "secrets/ROCK" if [349,350,800,].include?(map) #Rock Tunnel
return "secrets/MAGIKARP" if [394,471,189,].include?(map) #Fishing huts
return "secrets/AZUREFLUTE" if [694,].include?(map) && $PokemonBag.pbQuantity(:AZUREFLUTE)>=1 #Ice Mountain peak
return "secrets/BIGSODA" if [436,].include?(map) && $PokemonBag.pbQuantity(:SODAPOP)>=1 #Celadon dept. store top
return "secrets/EGG" if [13,406,214,].include?(map) #Celadon Café
return "secrets/STICK" if [266,].include?(map) #Ilex forest
return nil
end
def getCurrentPokeball()
otherItem = getEasterEggHeldItem()
def getCurrentPokeball(allowEasterEgg=true)
otherItem = getEasterEggHeldItem() if allowEasterEgg
return otherItem if otherItem
firstPokemon = $Trainer.party[0]
return firstPokemon.poke_ball if firstPokemon
return nil
end
def generate_front_trainer_sprite_bitmap(pokeball = nil, clothes_id = nil, hat_id = nil, hair_id = nil,
def generate_front_trainer_sprite_bitmap_from_appearance(trainerAppearance)
echoln caller
echoln trainerAppearance.hat
return generate_front_trainer_sprite_bitmap(false,nil,trainerAppearance.clothes,trainerAppearance.hat,
trainerAppearance.hair,trainerAppearance.skin_color,
trainerAppearance.hair_color,trainerAppearance.hat_color,trainerAppearance.clothes_color)
end
def generate_front_trainer_sprite_bitmap(allowEasterEgg=true, pokeball = nil, clothes_id = nil, hat_id = nil, hair_id = nil,
skin_tone_id = nil, hair_color = nil, hat_color = nil, clothes_color = nil)
echoln hat_id
clothes_id = $Trainer.clothes if !clothes_id
hat_id = $Trainer.hat if !hat_id
hair_id = $Trainer.hair if !hair_id
@@ -130,7 +150,7 @@ def generate_front_trainer_sprite_bitmap(pokeball = nil, clothes_id = nil, hat_i
outfitFilename = getTrainerSpriteOutfitFilename(clothes_id) #_INTL(Settings::PLAYER_GRAPHICS_FOLDER + Settings::PLAYER_CLOTHES_FOLDER + "/clothes_trainer_{1}", $Trainer.clothes)
hatFilename = getTrainerSpriteHatFilename(hat_id) # _INTL(Settings::PLAYER_GRAPHICS_FOLDER + Settings::PLAYER_HAT_FOLDER + "/hat_trainer_{1}", $Trainer.hat)
pokeball = getCurrentPokeball if !pokeball
pokeball = getCurrentPokeball(allowEasterEgg) if !pokeball
ballFilename = getTrainerSpriteBallFilename(pokeball) if pokeball
baseFilePath = getBaseTrainerSpriteFilename(skin_tone_id)
@@ -158,6 +178,7 @@ def generate_front_trainer_sprite_bitmap(pokeball = nil, clothes_id = nil, hat_i
hatBitmap = AnimatedBitmap.new(hatFilename, hat_color_shift) if pbResolveBitmap(hatFilename) #pbLoadOutfitBitmap(hatFilename) if pbResolveBitmap(hatFilename)
baseBitmap.bitmap = baseBitmap.bitmap.clone
baseBitmap.bitmap.blt(0, 0, outfitBitmap.bitmap, outfitBitmap.bitmap.rect) if outfitBitmap
baseBitmap.bitmap.blt(0, 0, hairBitmapWrapper.bitmap, hairBitmapWrapper.bitmap.rect) if hairBitmapWrapper
@@ -167,6 +188,48 @@ def generate_front_trainer_sprite_bitmap(pokeball = nil, clothes_id = nil, hat_i
return baseBitmap
end
def generateNPCClothedBitmapStatic(trainerAppearance,action = "walk")
baseBitmapFilename = getBaseOverworldSpriteFilename(action, trainerAppearance.skin_color)
baseSprite = AnimatedBitmap.new(baseBitmapFilename)
baseBitmap = baseSprite.bitmap.clone # nekkid sprite
outfitFilename = getOverworldOutfitFilename(trainerAppearance.clothes, action)
hairFilename = getOverworldHairFilename(trainerAppearance.hair)
#Clothes
clothes_color_shift = trainerAppearance.clothes_color || 0
clothesBitmap = AnimatedBitmap.new(outfitFilename, clothes_color_shift).bitmap if pbResolveBitmap(outfitFilename)
baseBitmap.blt(0, 0, clothesBitmap, clothesBitmap.rect)
#clothesBitmap.dispose
#Hair
hair_color_shift = trainerAppearance.hair_color || 0
hairBitmap = AnimatedBitmap.new(hairFilename, hair_color_shift).bitmap if pbResolveBitmap(hairFilename)
baseBitmap.blt(0, 0, hairBitmap, hairBitmap.rect)
hat_color_shift = trainerAppearance.hat_color || 0
hatFilename = getOverworldHatFilename(trainerAppearance.hat)
hatBitmapWrapper = AnimatedBitmap.new(hatFilename, hat_color_shift) if pbResolveBitmap(hatFilename)
if hatBitmapWrapper
frame_count = 4 # Assuming 4 frames for hair animation; adjust as needed
hat_frame_bitmap = duplicateHatForFrames(hatBitmapWrapper.bitmap, frame_count)
frame_width = baseSprite.bitmap.width / frame_count # Calculate frame width
frame_count.times do |i|
# Calculate offset for each frame
frame_offset = [i * frame_width, 0]
# Adjust Y offset if frame index is odd
frame_offset[1] -= 2 if i.odd?
positionHat(baseBitmap, hat_frame_bitmap, frame_offset, i, frame_width)
end
end
return baseBitmap
end
def generateClothedBitmapStatic(trainer, action = "walk")
baseBitmapFilename = getBaseOverworldSpriteFilename(action, trainer.skin_tone)
if !pbResolveBitmap(baseBitmapFilename)
@@ -174,39 +237,77 @@ def generateClothedBitmapStatic(trainer, action = "walk")
end
baseSprite = AnimatedBitmap.new(baseBitmapFilename)
baseBitmap = baseSprite.bitmap.clone #nekkid sprite
outfitFilename = getOverworldOutfitFilename(trainer.clothes, action) #
# Clone the base sprite bitmap to create the base for the player's sprite
baseBitmap = baseSprite.bitmap.clone # nekkid sprite
outfitFilename = getOverworldOutfitFilename(trainer.clothes, action)
outfitFilename = getOverworldOutfitFilename(Settings::PLAYER_TEMP_OUTFIT_FALLBACK) if !pbResolveBitmap(outfitFilename)
hairFilename = getOverworldHairFilename(trainer.hair)
hatFilename = getOverworldHatFilename(trainer.hat)
hair_color_shift = trainer.hair_color
hat_color_shift = trainer.hat_color
clothes_color_shift = trainer.clothes_color
# Use default values if color shifts are not set
hair_color_shift = trainer.hair_color || 0
hat_color_shift = trainer.hat_color || 0
clothes_color_shift = trainer.clothes_color || 0
hair_color_shift = 0 if !hair_color_shift
hat_color_shift = 0 if !hat_color_shift
clothes_color_shift = 0 if !clothes_color_shift
#@hat.update(@character_name, hatFilename,hat_color_shift) if @hat
# Use fallback outfit if the specified outfit cannot be resolved
if !pbResolveBitmap(outfitFilename)
outfitFilename = Settings::PLAYER_TEMP_OUTFIT_FALLBACK
end
outfitBitmap = AnimatedBitmap.new(outfitFilename, clothes_color_shift) # if pbResolveBitmap(outfitFilename) #pbLoadOutfitBitmap(outfitFilename) if pbResolveBitmap(outfitFilename)
# Load the outfit and hair bitmaps
outfitBitmap = AnimatedBitmap.new(outfitFilename, clothes_color_shift)
hairBitmapWrapper = AnimatedBitmap.new(hairFilename, hair_color_shift) if pbResolveBitmap(hairFilename)
hatBitmapWrapper = AnimatedBitmap.new(hatFilename, hat_color_shift) if pbResolveBitmap(hatFilename)
# Blit the outfit onto the base sprite
baseBitmap.blt(0, 0, outfitBitmap.bitmap, outfitBitmap.bitmap.rect) if outfitBitmap
#baseBitmap.blt(0, 0, hairBitmapWrapper.bitmap, hairBitmapWrapper.bitmap.rect)
current_offset = 0 #getCurrentSpriteOffset()
current_offset = [0, 0] # Replace this with getCurrentSpriteOffset() if needed
positionHair(baseBitmap, hairBitmapWrapper.bitmap, current_offset) if hairBitmapWrapper
#baseBitmap.blt(0, 0, hatBitmap, hatBitmap.rect) if hatBitmap
# Handle the hat - duplicate it for each frame if necessary
if hatBitmapWrapper
frame_count = 4 # Assuming 4 frames for hair animation; adjust as needed
hat_frame_bitmap = duplicateHatForFrames(hatBitmapWrapper.bitmap, frame_count)
frame_width = baseSprite.bitmap.width / frame_count # Calculate frame width
frame_count.times do |i|
# Calculate offset for each frame
frame_offset = [i * frame_width, 0]
# Adjust Y offset if frame index is odd
frame_offset[1] -= 2 if i.odd?
positionHat(baseBitmap, hat_frame_bitmap, frame_offset, i, frame_width)
end
end
return baseBitmap
end
def positionHair(baseBitmap, hairBirmap, offset)
baseBitmap.blt(offset[0], offset[1], hairBirmap, hairBirmap.rect)
def positionHair(baseBitmap, hairBitmap, offset)
baseBitmap.blt(offset[0], offset[1], hairBitmap, hairBitmap.rect)
end
def positionHat(baseBitmap, hatBitmap, offset, frame_index, frame_width)
# Define a rect for each frame
frame_rect = Rect.new(frame_index * frame_width, 0, frame_width, hatBitmap.height)
# Blit only the part of the hat corresponding to the current frame
baseBitmap.blt(offset[0], offset[1], hatBitmap, frame_rect)
end
def duplicateHatForFrames(hatBitmap, frame_count)
# Create a new bitmap for the duplicated hat frames
frame_width = hatBitmap.width
total_width = frame_width * frame_count
duplicatedBitmap = Bitmap.new(total_width, hatBitmap.height)
# Copy the single hat frame across each required frame
frame_count.times do |i|
duplicatedBitmap.blt(i * frame_width, 0, hatBitmap, hatBitmap.rect)
end
return duplicatedBitmap
end
def add_hat_to_bitmap(bitmap, hat_id, x_pos, y_pos, scale = 1, mirrored = false)
@@ -240,3 +341,4 @@ end
@@ -22,6 +22,66 @@ class OutfitSelector
return list_folders(get_hair_sets_list_path())
end
def generate_hats_choice(baseOptions=true,additionalIds=[],additionalTags=[],filterOutTags=[])
list = []
list += additionalIds
list += search_hats(additionalTags)
if baseOptions
list += get_hats_base_options()
list += search_hats(get_regional_sets_tags())
end
return list
end
def generate_clothes_choice(baseOptions=true,additionalIds=[],additionalTags=[],filterOutTags=[])
list = []
list += additionalIds
list += search_clothes(additionalTags)
if baseOptions
list += get_clothes_base_options()
list += search_clothes(get_regional_sets_tags())
end
return list
end
def generate_hairstyle_choice(baseOptions=true,additionalIds=[],additionalTags=[],filterOutTags=[])
list = []
list += additionalIds
list += search_hairstyles(additionalTags)
if baseOptions
list += get_hairstyle_salon_base_options()
list += search_hairstyles(get_regional_sets_tags())
end
list << HAIR_BALD
return list
end
def get_regional_sets_tags()
regional_tags = []
regional_tags << "kanto" if $game_switches[SWITCH_KANTO_HAIR_COLLECTION]
regional_tags << "johto" if $game_switches[SWITCH_JOHTO_HAIR_COLLECTION]
regional_tags << "hoenn" if $game_switches[SWITCH_HOENN_HAIR_COLLECTION]
regional_tags << "sinnoh" if $game_switches[SWITCH_SINNOH_HAIR_COLLECTION]
regional_tags << "unova" if $game_switches[SWITCH_UNOVA_HAIR_COLLECTION]
regional_tags << "kalos" if $game_switches[SWITCH_KALOS_HAIR_COLLECTION]
regional_tags << "alola" if $game_switches[SWITCH_ALOLA_HAIR_COLLECTION]
regional_tags << "galar" if $game_switches[SWITCH_GALAR_HAIR_COLLECTION]
regional_tags << "paldea" if $game_switches[SWITCH_PALDEA_HAIR_COLLECTION]
return regional_tags
end
def get_hairstyle_salon_base_options()
return search_hairstyles(["default"])
end
def get_clothes_base_options()
return search_clothes(["default"])
end
def get_hats_base_options()
return search_hats(["default"])
end
def parse_hairstyles_folder
hairstyle_types= list_folders(get_hair_sets_list_path())
max_versions_number = 10
@@ -13,7 +13,7 @@ def update_global_hats_list()
# Iterate through the JSON data and create Hat objects
hat_data.each do |data|
tags = data['tags'] ? data['tags'].split(',') : []
tags = data['tags'] ? data['tags'].split(',').map(&:strip) : []
hat = Hat.new(
data['id'],
data['name'],
@@ -34,7 +34,7 @@ def update_global_hairstyles_list()
# Iterate through the JSON data and create Hat objects
hair_data.each do |data|
tags = data['tags'] ? data['tags'].split(',') : []
tags = data['tags'] ? data['tags'].split(',').map(&:strip) : []
hair = Hairstyle.new(
data['id'],
data['name'],
@@ -55,7 +55,7 @@ def update_global_clothes_list()
# Iterate through the JSON data and create Hat objects
outfits_data.each do |data|
tags = data['tags'] ? data['tags'].split(',') : []
tags = data['tags'] ? data['tags'].split(',').map(&:strip) : []
outfit = Clothes.new(
data['id'],
data['name'],
@@ -20,16 +20,33 @@ def filter_clothes(filter_tags = [], only_unlocked = false)
return filter_outfits_by_tag(full_data_list, filter_tags, existing_files_list, unlocked_list, only_unlocked)
end
def filter_clothes_only_not_owned(clothes_ids_list)
filtered_list = []
clothes_ids_list.each do|clothe_id|
filtered_list << clothe_id if !$Trainer.unlocked_clothes.include?(clothe_id)
end
return filtered_list
end
def filter_clothes_only_owned(clothes_ids_list)
filtered_list = []
clothes_ids_list.each do|clothe_id|
filtered_list << clothe_id if $Trainer.unlocked_clothes.include?(clothe_id)
end
return filtered_list
end
#HATS
def search_hats(matching_tags = [], only_unlocked = false)
def search_hats(matching_tags = [],excluding_tags=[], only_unlocked = false)
update_global_outfit_lists()
selector = OutfitSelector.new
full_data_list = $PokemonGlobal.hats_data
existing_files_list = selector.parse_hats_folder()
unlocked_list = $Trainer.unlocked_hats
return search_outfits_by_tag(full_data_list, matching_tags, existing_files_list, unlocked_list, only_unlocked)
return search_outfits_by_tag(full_data_list, matching_tags, existing_files_list, unlocked_list, only_unlocked,excluding_tags)
end
def filter_hats(filter_tags = [], only_unlocked = false)
@@ -38,18 +55,58 @@ def filter_hats(filter_tags = [], only_unlocked = false)
full_data_list = $PokemonGlobal.hats_data
existing_files_list = selector.parse_hats_folder()
echoln existing_files_list
unlocked_list = $Trainer.unlocked_hats
return filter_outfits_by_tag(full_data_list, filter_tags, existing_files_list, unlocked_list, only_unlocked)
end
def filter_hats_only_not_owned(hats_ids_list)
filtered_list = []
hats_ids_list.each do|hat_id|
filtered_list << hat_id if !$Trainer.unlocked_hats.include?(hat_id)
end
return filtered_list
end
def filter_hats_only_owned(hats_ids_list)
filtered_list = []
hats_ids_list.each do|hat_id|
filtered_list << hat_id if $Trainer.unlocked_hats.include?(hat_id)
end
return filtered_list
end
#HAIRSTYLES
def search_hairstyles(matching_tags = [], only_unlocked = false)
update_global_outfit_lists()
selector = OutfitSelector.new
full_data_list = $PokemonGlobal.hairstyles_data
existing_files_list = selector.parse_hairstyle_types_folder()
return search_outfits_by_tag(full_data_list, matching_tags, existing_files_list, [], false)
end
def filter_out_hairstyles(filter_tags = [],base_list = [],require_unlocked=false)
update_global_outfit_lists()
selector = OutfitSelector.new
data_list = $PokemonGlobal.hairstyles_data
existing_files_list = selector.parse_hairstyle_types_folder()
return exclude_outfits_by_tag(data_list, filter_tags, existing_files_list, base_list, false)
end
# Generic searching methods
#Get outfits that have ANY of the tags
def search_outfits_by_tag(outfits_map, matching_tags = [], physical_files_list = [], unlocked_list = [], require_unlocked = false)
def search_outfits_by_tag(outfits_map, matching_tags = [], physical_files_list = [], unlocked_list = [], require_unlocked = false, excluding_tags=[])
filtered_list = []
outfits_map.each do |outfit_id, outfit|
next if outfit.tags.any? { |tag| excluding_tags.include?(tag) }
if outfit.tags.any? { |tag| matching_tags.include?(tag) }
filtered_list << outfit_id if outfit_is_valid?(outfit_id, physical_files_list, unlocked_list, require_unlocked)
end
@@ -70,6 +127,19 @@ def filter_outfits_by_tag(outfits_map, filter_tags = [], physical_files_list = [
return filtered_list
end
#Get all outfits from list that DON'T have a tag
def exclude_outfits_by_tag(outfits_map, filter_tags = [], physical_files_list = [], unlocked_list = [], require_unlocked = false)
update_global_outfit_lists()
filtered_list = []
outfits_map.each do |outfit_id, outfit|
if filter_tags.any? { |tag| !outfit.tags.include?(tag) }
filtered_list << outfit_id if outfit_is_valid?(outfit_id, physical_files_list, unlocked_list, require_unlocked)
end
end
return filtered_list
end
def outfit_is_valid?(outfit_id, physical_files_list, unlocked_list, require_unlocked)
return false if require_unlocked && !unlocked_list.include?(outfit_id)
@@ -85,6 +155,7 @@ end
def get_clothes_by_id(id)
update_global_outfit_lists()
echoln $PokemonGlobal.clothes_data
return $PokemonGlobal.clothes_data.has_key?(id) ? $PokemonGlobal.clothes_data[id] : nil
end
+185
View File
@@ -0,0 +1,185 @@
#set outfit ids,
#
CLOTHES_NORMAL = "normal"
CLOTHES_FIGHTING = "fighting"
CLOTHES_FLYING = "temp"
CLOTHES_POISON = "deadlypoisondanger"
CLOTHES_GROUND = "groundcowboy"
CLOTHES_ROCK = "temp"
CLOTHES_BUG_1 = "bughakama"
CLOTHES_BUG_2 = "bughakamapants"
CLOTHES_GHOST = "temp"
CLOTHES_STEEL_M = "steelworkerM"
CLOTHES_STEEL_F = "steelworkerF"
CLOTHES_FIRE = "firefigther"
CLOTHES_WATER = "waterdress"
CLOTHES_GRASS = "temp"
CLOTHES_ELECTRIC = "urbanelectric"
CLOTHES_PSYCHIC = "temp"
CLOTHES_ICE = "temp"
CLOTHES_DRAGON = "dragonconqueror"
CLOTHES_DARK = "temp"
CLOTHES_FAIRY_M = "mikufairym"
CLOTHES_FAIRY_F = "mikufairyf"
NORMAL_ITEMS = [:NORMALGEM,:MOOMOOMILK,:POTION,:FULLHEAL,:CHILANBERRY,]
FIGHTING_ITEMS = [:FIGHTINGGEM,:PROTEIN,:CHOPLEBERRY,]
FLYING_ITEMS = [:FLYINGGEM,:HEALTHWING,:MUSCLEWING,:RESISTWING,:GENIUSWING,:CLEVERWING,:SWIFTWING,:AIRBALLOON,:PRETTYWING,:COBABERRY, ]
POISON_ITEMS = [:POISONGEM,:ANTIDOTE, :KEBIABERRY, ]
GROUND_ITEMS = [:GROUNDGEM,:SHUCABERRY, ]
ROCK_ITEMS = [:ROCKGEM, :STARDUST,:CHARTIBERRY, ]
BUG_ITEMS = [:BUGGEM,:HONEY,:TANGABERRY, ]
GHOST_ITEMS = [:GHOSTGEM,:KASIBBERRY,]
STEEL_ITEMS = [:STEELGEM,:BABIRIBERRY,:METALPOWDER,]
FIRE_ITEMS = [:FIREGEM,:LAVACOOKIE,:BURNHEAL,:OCCABERRY, ]
WATER_ITEMS = [:WATERGEM,:HEARTSCALE,:PEARL,:PASSHOBERRY ]
GRASS_ITEMS = [:GRASSGEM,:LUMBERRY,:ORANBERRY,:SITRUSBERRY,:GRASSYSEED,:ABSORBBULB,:TINYMUSHROOM, :RINDOBERRY, ]
ELECTRIC_ITEMS = [:ELECTRICGEM,:ELECTRICSEED,:PARLYZHEAL,:CELLBATTERY,:WACANBERRY, ]
PSYCHIC_ITEMS = [:PSYCHICGEM,:PSYCHICSEED, :MENTALHERB, :PAYAPABERRY,]
ICE_ITEMS = [:ICEGEM,:SNOWBALL,:ICEHEAL,:YACHEBERRY, ]
DRAGON_ITEMS = [:DRAGONGEM,:HABANBERRY, ]
DARK_ITEMS = [:DARKGEM,:COLBURBERRY, ]
FAIRY_ITEMS = [:FAIRYGEM,:MISTYSEED, ]
def isWearingElectricOutfit()
return (isWearingClothes(CLOTHES_ELECTRIC))
end
def isWearingNormalOutfit()
return (isWearingClothes(CLOTHES_NORMAL))
end
def isWearingFightingOutfit()
return (isWearingClothes(CLOTHES_FIGHTING))
end
def isWearingFlyingOutfit()
return (isWearingClothes(CLOTHES_FLYING))
end
def isWearingPoisonOutfit()
return (isWearingClothes(CLOTHES_POISON))
end
def isWearingGroundOutfit()
return (isWearingClothes(CLOTHES_GROUND))
end
def isWearingRockOutfit()
return (isWearingClothes(CLOTHES_ROCK))
end
def isWearingBugOutfit()
return ((isWearingClothes(CLOTHES_BUG_1) || isWearingClothes(CLOTHES_BUG_2)))
end
def isWearingGhostOutfit()
return (isWearingClothes(CLOTHES_GHOST))
end
def isWearingSteelOutfit()
return ((isWearingClothes(CLOTHES_STEEL_M) || isWearingClothes(CLOTHES_STEEL_F)))
end
def isWearingFireOutfit()
return (isWearingClothes(CLOTHES_FIRE))
end
def isWearingWaterOutfit()
return (isWearingClothes(CLOTHES_WATER))
end
def isWearingGrassOutfit()
return (isWearingClothes(CLOTHES_GRASS))
end
def isWearingPsychicOutfit()
return (isWearingClothes(CLOTHES_PSYCHIC))
end
def isWearingIceOutfit()
return (isWearingClothes(CLOTHES_ICE))
end
def isWearingDragonOutfit()
return (isWearingClothes(CLOTHES_DRAGON))
end
def isWearingDarkOutfit()
return (isWearingClothes(CLOTHES_DARK))
end
def isWearingFairyOutfit()
return ((isWearingClothes(CLOTHES_FAIRY_M) || isWearingClothes(CLOTHES_FAIRY_F)))
end
def pickUpTypeItemSetBonus()
return if rand(10) != 0
items_list = if isWearingElectricOutfit()
ELECTRIC_ITEMS
elsif isWearingNormalOutfit()
NORMAL_ITEMS
elsif isWearingFightingOutfit()
FIGHTING_ITEMS
elsif isWearingFlyingOutfit()
FLYING_ITEMS
elsif isWearingPoisonOutfit()
POISON_ITEMS
elsif isWearingGroundOutfit()
GROUND_ITEMS
elsif isWearingRockOutfit()
ROCK_ITEMS
elsif isWearingBugOutfit()
BUG_ITEMS
elsif isWearingGhostOutfit()
GHOST_ITEMS
elsif isWearingSteelOutfit()
STEEL_ITEMS
elsif isWearingFireOutfit()
FIRE_ITEMS
elsif isWearingWaterOutfit()
WATER_ITEMS
elsif isWearingGrassOutfit()
GRASS_ITEMS
elsif isWearingPsychicOutfit()
PSYCHIC_ITEMS
elsif isWearingIceOutfit()
ICE_ITEMS
elsif isWearingDragonOutfit()
DRAGON_ITEMS
elsif isWearingDarkOutfit()
DARK_ITEMS
elsif isWearingFairyOutfit()
FAIRY_ITEMS
else
[]
end
if !items_list.empty?
Kernel.pbItemBall(items_list.sample)
end
end
+118
View File
@@ -0,0 +1,118 @@
#Clothes
CLOTHES_TEAM_ROCKET_MALE = "rocketm"
CLOTHES_TEAM_ROCKET_FEMALE = "rocketf"
CLOTHES_OFFICE_WORKER_F = "officeworkerf"
CLOTHES_OFFICE_WORKER_M = "officeworkerm"
CLOTHES_BUSINESS_SUIT = "BusinessSuit"
CLOTHES_ADVENTURER = "fantasyadventurersoutfit"
CLOTHES_EMERALD = "emeraldSPE"
CLOTHES_PIKACHU_ONESIE = "pikaonesie"
CLOTHES_BREEDER="PKMBreeder"
CLOTHES_LASS_YELLOW ="lass"
CLOTHES_LASS_BLUE ="lass2"
DEFAULT_OUTFIT_MALE = "red"
DEFAULT_OUTFIT_FEMALE = "leaf"
STARTING_OUTFIT = "pikajamas"
#Hats
HAT_TEAM_ROCKET = "rocketcap"
HAT_POSTMAN = "postman"
HAT_PIDGEY_NEST = "pidgey"
HAT_SWABLU_NEST = "swablu"
HAT_PIKACHUM_NEST = "pikhatchum"
HAT_PIKACHUF_NEST = "pikhatchuf"
HAT_PARAS_NEST = "headparas"
HAT_EEVEE_NEST = "eevee"
HAT_PARASHROOM = "parashroom"
HAT_AERODACTYL = "aerodactylSkull"
HAT_DUSKULL_MASK = "duskullmask"
HAT_SLEEPMASK = "sleepmask"
HAT_DITTO_MASK = "creepydittomask"
HAT_EGG = "egg"
HAT_DRIFLOON_CAP = "drifloon"
HAT_EMERALD = "emeraldSPEgem"
HAT_SQUIRTLE_SHADES = "squirtlesquadshades"
HAT_WOOPER = "wooperclips"
HAT_PIKACHU_HOOD = "pikaonesie"
HAT_FEZ = "fez"
HAT_HALO = "halo"
HAT_MAGIKARP = "magicap"
HAT_SLOWKING_SHELL = "slowking"
HAT_ZOROARK = "banefulfoxmask"
HAT_FROG = "froghat"
HAT_SANTA = "santa"
HAT_BREEDER_1="breedervisor"
HAT_BREEDER_2="breederbandana"
HAT_BREEDER_2_2="PKMBreeder"
HAT_BREEDER_3="egg"
HAT_BREEDEROUTFIT="PKMBreeder"
FUSION_HAT = "fusionnerd"
FUSION_OUTFIT = "fusionnerd"
HAT_ASH = "ash"
HAT_BIANCA = "bianca"
HAT_CLEFAIRY = "clefairyearheadband"
HAT_FLOWER = "mikufairy"
HAT_CARDBOARD_BOX = "box"
HAT_CAPTAIN = "seacaptain"
HAT_GYM_REWARD_1 = "brockpan"
HAT_GYM_REWARD_2 = "starmieclip"
HAT_GYM_REWARD_3 = "surgeglasses"
HAT_GYM_REWARD_4 = "erikaHeadband"
HAT_GYM_REWARD_5 = "kogascarf"
HAT_GYM_REWARD_6 = "sabrinasballs"
HAT_GYM_REWARD_7 = "blaineGlasses"
HAT_GYM_REWARD_8 = "giovannifedora"
HAT_GYM_REWARD_9 = "luluribbon"
HAT_GYM_REWARD_10 = "kurtsentaihelmet"
HAT_GYM_REWARD_11 = "falknerscage"
HAT_GYM_REWARD_12 = "clairbow"
HAT_GYM_REWARD_13 = "chuckmoustache"
HAT_GYM_REWARD_14 = "prycemask"
HAT_GYM_REWARD_15 = "mortyHeadband"
HAT_GYM_REWARD_16 = "magnemitepin"
#Hairstyles
HAIR_RED = "red"
HAIR_LEAF = "leaf"
HAIR_HEXMANIAC = "HexManiac"
HAIR_LASS = "lass"
HAIR_BALD = "bald"
HAIR_RIVAL = "gary"
HAIR_BROCK = "brock"
HAIR_MISTY1 = "mistyRBY"
HAIR_MISTY2 = "mistyGSC"
HAIR_SURGE = "surge" #does not exist yet
HAIR_ERIKA = "erika"
HAIR_KOGA = "koga" #does not exist yet
HAIR_JANINE = "janine"
HAIR_SABRINA = "sabrina" #does not exist yet
HAIR_BLAINE = "blaine" #does not exist yet
HAIR_GIOVANNI = "giovanni" #does not exist yet
HAIR_WHITNEY = "whitney"
HAIR_KURT = "kurt"
HAIR_FALKNER = "falkner"
HAIR_CLAIR = "clair"
HAIR_CHUCK = "chuck" #does not exist yet
HAIR_PRYCE = "pryce" #does not exist yet
HAIR_MORTY = "morty" #does not exist yet
HAIR_JASMINE = "jasmine" #does not exist yet
@@ -79,6 +79,7 @@ class CharacterSelectMenuPresenter
@name = getDefaultName() if @name == ''
pbSEPlay("GUI trainer card open", 80, 100)
updateDisplayedName(current_index)
applyHair() #for easter egg lol
when OPTION_CONFIRM
pbSEPlay("GUI save choice", 80, 100)
@current_index = @options.length - 1
@@ -111,7 +112,8 @@ class CharacterSelectMenuPresenter
def applyAllSelectedValues
applyGender(@gender)
pbSet(VAR_TRAINER_AGE, @gender)
echoln @age
pbSet(VAR_TRAINER_AGE, @age)
$Trainer.skin_tone = @skinTone
$Trainer.name = @name
end
@@ -214,11 +216,19 @@ class CharacterSelectMenuPresenter
end
def applyHair()
applyHairEasterEggs()
hairColorId = HAIR_COLOR_IDS[@hairColor]
hairId = hairColorId.to_s + "_" + @hairstyle.to_s
$Trainer.hair = hairId
end
def applyHairEasterEggs()
@hairstyle = HAIR_RIVAL if @name == "Gary" && @gender == 1
@hairstyle = HAIR_BROCK if @name == "Brock" && @gender == 1
@hairstyle = HAIR_MISTY if @name == "Misty" && @gender == 0
end
def applyGender(gender_index)
# outfitId = gender + 1
pbSet(VAR_TRAINER_GENDER, gender_index)
@@ -1,4 +1,3 @@
def playOutfitRemovedAnimation()
pbSEPlay("shiny", 80, 60)
$scene.spriteset.addUserAnimation(Settings::OW_SHINE_ANIMATION_ID, $game_player.x, $game_player.y, true)
@@ -9,7 +8,7 @@ def playOutfitChangeAnimation()
$scene.spriteset.addUserAnimation(Settings::OW_SHINE_ANIMATION_ID, $game_player.x, $game_player.y, true)
end
def selectHairstyle(all_unlocked=false)
def selectHairstyle(all_unlocked = false)
selector = OutfitSelector.new
display_outfit_preview()
hat = $Trainer.hat
@@ -22,11 +21,11 @@ def selectHairstyle(all_unlocked=false)
case choice
when 0 #NEXT
playOutfitChangeAnimation()
selector.changeToNextHairstyle(1,all_unlocked)
selector.changeToNextHairstyle(1, all_unlocked)
display_outfit_preview()
when 1 #PREVIOUS
playOutfitChangeAnimation()
selector.changeToNextHairstyle(-1,all_unlocked)
selector.changeToNextHairstyle(-1, all_unlocked)
display_outfit_preview()
when 2 #Toggle hat
pbSEPlay("GUI storage put down", 80, 100)
@@ -44,11 +43,16 @@ def selectHairstyle(all_unlocked=false)
$Trainer.hat = hat
end
def selectHairColor
original_color = $Trainer.hair_color
$game_switches[SWITCH_SELECTING_CLOTHES]=true
$game_map.update
display_outfit_preview()
hat = $Trainer.hat
commands = ["Shift up", "Shift down", "Toggle hat", "Reset", "Back"]
commands = ["Shift up", "Shift down", "Toggle hat", "Reset", "Confirm", "Never Mind"]
previous_input = 0
while (true)
choice = pbShowCommands(nil, commands, commands.length, previous_input)
previous_input = choice
@@ -58,10 +62,12 @@ def selectHairColor
pbSEPlay("GUI storage pick up", 80, 100)
shiftHairColor(10)
display_outfit_preview()
ret = true
when 1 #PREVIOUS
pbSEPlay("GUI storage pick up", 80, 100)
shiftHairColor(-10)
display_outfit_preview()
ret = true
when 2 #Toggle hat
pbSEPlay("GUI storage put down", 80, 100)
if hat == $Trainer.hat
@@ -74,17 +80,27 @@ def selectHairColor
pbSEPlay("GUI storage put down", 80, 100)
$Trainer.hair_color = 0
display_outfit_preview()
ret = false
when 4 #Confirm
break
else
$Trainer.hair_color = original_color
ret = false
break
end
end
hide_outfit_preview()
$Trainer.hat = hat
$game_switches[SWITCH_SELECTING_CLOTHES]=false
$game_map.update
return ret
end
def selectHatColor
original_color = $Trainer.hat_color
display_outfit_preview()
commands = ["Shift up", "Shift down", "Reset", "Back"]
commands = ["Shift up", "Shift down", "Reset", "Confirm", "Never Mind"]
previous_input = 0
while (true)
choice = pbShowCommands(nil, commands, commands.length, previous_input)
@@ -94,25 +110,37 @@ def selectHatColor
pbSEPlay("GUI storage pick up", 80, 100)
shiftHatColor(10)
display_outfit_preview()
ret = true
when 1 #PREVIOUS
pbSEPlay("GUI storage pick up", 80, 100)
shiftHatColor(-10)
display_outfit_preview()
ret = true
when 2 #Reset
pbSEPlay("GUI storage put down", 80, 100)
$Trainer.hat_color = 0
display_outfit_preview()
refreshPlayerOutfit()
ret = false
when 3 #Confirm
break
else
$Trainer.hat_color = original_color
ret = false
break
end
end
refreshPlayerOutfit()
hide_outfit_preview()
return ret
end
def selectClothesColor
original_color = $Trainer.clothes_color
display_outfit_preview()
commands = ["Shift up", "Shift down", "Reset", "Back"]
commands = ["Shift up", "Shift down", "Reset", "Confirm", "Never Mind"]
previous_input = 0
ret = false
while (true)
choice = pbShowCommands(nil, commands, commands.length, previous_input)
previous_input = choice
@@ -121,22 +149,32 @@ def selectClothesColor
pbSEPlay("GUI storage pick up", 80, 100)
shiftClothesColor(10)
display_outfit_preview()
ret = true
when 1 #PREVIOUS
pbSEPlay("GUI storage pick up", 80, 100)
shiftClothesColor(-10)
display_outfit_preview()
ret = true
when 2 #Reset
pbSEPlay("GUI storage pick up", 80, 100)
$Trainer.clothes_color = 0
display_outfit_preview()
refreshPlayerOutfit()
ret = false
when 3 #Confirm
break
else
$Trainer.clothes_color = original_color
ret = false
break
end
end
refreshPlayerOutfit()
hide_outfit_preview()
return ret
end
def selectHat(all_unlocked=false)
def selectHat(all_unlocked = false)
selector = OutfitSelector.new
display_outfit_preview()
commands = ["Next hat", "Previous hat", "Remove hat", "Back"]
@@ -147,11 +185,11 @@ def selectHat(all_unlocked=false)
case choice
when 0 #NEXT
playOutfitChangeAnimation()
selector.changeToNextHat(1,all_unlocked)
selector.changeToNextHat(1, all_unlocked)
display_outfit_preview()
when 1 #PREVIOUS
playOutfitChangeAnimation()
selector.changeToNextHat(-1,all_unlocked)
selector.changeToNextHat(-1, all_unlocked)
display_outfit_preview()
when 2 #REMOVE HAT
playOutfitRemovedAnimation()
@@ -169,7 +207,7 @@ def spinCharacter
end
def selectClothes(all_unlocked=false)
def selectClothes(all_unlocked = false)
selector = OutfitSelector.new
display_outfit_preview()
commands = ["Next", "Previous"]
@@ -183,11 +221,11 @@ def selectClothes(all_unlocked=false)
case choice
when 0 #NEXT
playOutfitChangeAnimation()
selector.changeToNextClothes(1,all_unlocked)
selector.changeToNextClothes(1, all_unlocked)
display_outfit_preview()
when 1 #PREVIOUS
playOutfitChangeAnimation()
selector.changeToNextClothes(-1,all_unlocked)
selector.changeToNextClothes(-1, all_unlocked)
display_outfit_preview()
when 2 #REMOVE CLOTHES
break if !$DEBUG
@@ -201,8 +239,6 @@ def selectClothes(all_unlocked=false)
hide_outfit_preview()
end
def place_hat_on_pokemon(pokemon)
hatscreen = PokemonHatPresenter.new(nil, pokemon)
hatscreen.pbStartScreen()
@@ -16,16 +16,17 @@ class PokemonHatPresenter
@original_pokemon_bitmap = nil
end
def getPicturePath()
if @pokemon.isTripleFusion?
picturePath = GameData::Species::getSpecialSpriteName(@pokemon.species_data.id_number)
elsif @pokemon.isFusion?
picturePath = get_fusion_sprite_path(@pokemon.species_data.head_pokemon.id_number, @pokemon.species_data.body_pokemon.id_number)
else
picturePath = get_unfused_sprite_path(@pokemon.species_data.id_number, @pokemon.spriteform_body)
end
return picturePath
end
# def getPicturePath()
# if @pokemon.isTripleFusion?
# picturePath = GameData::Species::getSpecialSpriteName(@pokemon.species_data.id_number)
# elsif @pokemon.isFusion?
# picturePath = get_fusion_sprite_path(@pokemon.species_data.head_pokemon.id_number, @pokemon.species_data.body_pokemon.id_number)
# else
# picturePath = get_unfused_sprite_path(@pokemon.species_data.id_number)
# end
# echoln picturePath
# return picturePath
# end
def pbStartScreen
@view.init_window(self)
@@ -71,13 +72,15 @@ class PokemonHatPresenter
def position_hat
@view.display_move_arrows
min_x, max_x = -64, 88
min_y, max_y = -20, 140
loop do
Graphics.update
Input.update
@x_pos += PIXELS_PER_MOVEMENT if Input.repeat?(Input::RIGHT)
@x_pos -= PIXELS_PER_MOVEMENT if Input.repeat?(Input::LEFT)
@y_pos += PIXELS_PER_MOVEMENT if Input.repeat?(Input::DOWN)
@y_pos -= PIXELS_PER_MOVEMENT if Input.repeat?(Input::UP)
@x_pos += PIXELS_PER_MOVEMENT if Input.repeat?(Input::RIGHT) && @x_pos < max_x
@x_pos -= PIXELS_PER_MOVEMENT if Input.repeat?(Input::LEFT) && @x_pos > min_x
@y_pos += PIXELS_PER_MOVEMENT if Input.repeat?(Input::DOWN) && @y_pos < max_y
@y_pos -= PIXELS_PER_MOVEMENT if Input.repeat?(Input::UP) && @y_pos > min_y
break if Input.trigger?(Input::USE)
return false if Input.trigger?(Input::BACK)
@view.update()
@@ -87,8 +90,25 @@ class PokemonHatPresenter
end
def initialize_bitmap()
picturePath = getPicturePath()
@original_pokemon_bitmap = AnimatedBitmap.new(picturePath)
spriteLoader = BattleSpriteLoader.new
if @pokemon.isTripleFusion?
#todo
elsif @pokemon.isFusion?
@original_pokemon_bitmap = spriteLoader.load_fusion_sprite(@pokemon.head_id(),@pokemon.body_id())
else
echoln @pokemon
echoln @pokemon.species_data
@original_pokemon_bitmap = spriteLoader.load_base_sprite(@pokemon.id_number)
end
# picturePath = getPicturePath()
# if picturePath
# @original_pokemon_bitmap = AnimatedBitmap.new(picturePath)
# else
# @original_pokemon_bitmap = GameData::Species.setAutogenSprite(@pokemon)
# #autogen
# end
@original_pokemon_bitmap.scale_bitmap(Settings::FRONTSPRITE_SCALE)
end
@@ -32,6 +32,10 @@ class PokemonHatView
end
def getWindowWidth()
return @previewwindow.width/2
end
def initialize_arrows()
middle_horizontal = 100
width_horizontal = 90
@@ -23,7 +23,8 @@ class TrainerClothesPreview
end
def show()
@playerBitmap = generate_front_trainer_sprite_bitmap(@pokeball,
@playerBitmap = generate_front_trainer_sprite_bitmap(false,
@pokeball,
@clothes, @hat, @hair,
@skin_tone,
@hair_color, @hat_color, @clothes_color)
@@ -35,7 +35,7 @@ class ClothesMartAdapter < OutfitsMartAdapter
def addItem(item)
changed_clothes = obtainNewClothes(item.id)
changed_clothes = obtainClothes(item.id)
if changed_clothes
@worn_clothes = item.id
end
@@ -1,11 +1,12 @@
def genericOutfitsShopMenu(stock = [], itemType = nil, versions = false)
def genericOutfitsShopMenu(stock = [], itemType = nil, versions = false, isShop=true, message=nil)
commands = []
commands[cmdBuy = commands.length] = _INTL("Buy")
commands[cmdQuit = commands.length] = _INTL("Quit")
cmd = pbMessage(_INTL("Welcome! How may I serve you?"), commands, cmdQuit + 1)
message = _INTL("Welcome! How may I serve you?") if !message
cmd = pbMessage(message, commands, cmdQuit + 1)
loop do
if cmdBuy >= 0 && cmd == cmdBuy
adapter = getAdapter(itemType, stock, true)
adapter = getAdapter(itemType, stock, isShop)
view = ClothesShopView.new()
presenter = getPresenter(itemType, view, stock, adapter, versions)
presenter.pbBuyScreen
@@ -14,8 +15,6 @@ def genericOutfitsShopMenu(stock = [], itemType = nil, versions = false)
pbMessage(_INTL("Please come again!"))
break
end
cmd = pbMessage(_INTL("Is there anything else I can help you with?"),
commands, cmdQuit + 1)
end
end
@@ -41,32 +40,35 @@ end
def list_all_possible_outfits() end
def clothesShop(outfits_list = [])
def clothesShop(outfits_list = [], free=false,customMessage=nil)
stock = []
outfits_list.each { |outfit_id|
outfit = get_clothes_by_id(outfit_id)
stock << outfit if outfit
}
genericOutfitsShopMenu(stock, :CLOTHES)
genericOutfitsShopMenu(stock, :CLOTHES,false,!free,customMessage)
end
def hatShop(outfits_list = [])
def hatShop(outfits_list = [], free=false, customMessage=nil)
stock = []
outfits_list.each { |outfit_id|
outfit = get_hat_by_id(outfit_id)
stock << outfit if outfit
}
genericOutfitsShopMenu(stock, :HAT)
genericOutfitsShopMenu(stock, :HAT,false,!free,customMessage)
end
def hairShop(outfits_list = [])
stock = []
def hairShop(outfits_list = [],free=false, customMessage=nil)
currentHair = getSimplifiedHairIdFromFullID($Trainer.hair)
stock = [:SWAP_COLOR]
#always add current hairstyle as first option (in case the player just wants to swap the color)
stock << get_hair_by_id(currentHair) if $Trainer.hair
outfits_list.each { |outfit_id|
echoln outfit_id
next if outfit_id == currentHair
outfit = get_hair_by_id(outfit_id)
stock << outfit if outfit
}
genericOutfitsShopMenu(stock, :HAIR, true)
genericOutfitsShopMenu(stock, :HAIR, true,!free,customMessage)
end
def openSelectOutfitMenu(stock = [], itemType)
@@ -91,13 +93,14 @@ def changeHatMenu()
outfit = get_hat_by_id(outfit_id)
stock << outfit if outfit
}
stock << :REMOVE_HAT
openSelectOutfitMenu(stock, :HAT)
end
def changeOutfit()
commands = []
commands[cmdClothes = commands.length] = _INTL("Change clothes")
commands[cmdHat = commands.length] = _INTL("Change hat")
commands[cmdClothes = commands.length] = _INTL("Change clothes")
commands[cmdQuit = commands.length] = _INTL("Quit")
cmd = pbMessage(_INTL("What would you like to do?"), commands, cmdQuit + 1)
@@ -112,4 +115,7 @@ def changeOutfit()
break
end
end
end
@@ -44,14 +44,10 @@ class ClothesShopPresenter < PokemonMartScreen
itemname, price.to_s_formatted))
next
end
quantity = 1
if @adapter.getMoney < price
pbDisplayPaused(_INTL("You don't have enough money."))
next
end
added = 0
@adapter.setMoney(@adapter.getMoney - price)
@stock.compact!
pbDisplayPaused(_INTL("Here you are! Thank you!")) { pbSEPlay("Mart buy item") }
@@ -1,14 +1,12 @@
class ClothesShopView < PokemonMart_Scene
def initialize(currency_name="Money")
def initialize(currency_name = "Money")
@currency_name = currency_name
end
def pbStartBuyOrSellScene(buying, stock, adapter)
super(buying, stock, adapter)
@initial_direction = $game_player.direction
@sprites["icon"].visible=false
@sprites["icon"].visible = false
if @adapter.isShop?
@sprites["background"].setBitmap("Graphics/Pictures/martScreenOutfit")
else
@@ -16,7 +14,7 @@ class ClothesShopView < PokemonMart_Scene
end
preview_y = @adapter.isShop? ? 80 : 0
@sprites["trainerPreview"] = TrainerClothesPreview.new(0, preview_y, true,"WALLET")
@sprites["trainerPreview"] = TrainerClothesPreview.new(0, preview_y, true, "WALLET")
@sprites["trainerPreview"].show()
@sprites["moneywindow"].visible = false if !@adapter.isShop?
@@ -26,18 +24,21 @@ class ClothesShopView < PokemonMart_Scene
end
def scroll_map
pbScrollMap(DIRECTION_UP, 5, 5)
pbScrollMap(DIRECTION_RIGHT, 7, 5)
pbScrollMap(DIRECTION_UP, 5, 6)
pbScrollMap(DIRECTION_RIGHT, 7, 6)
@initial_direction = $game_player.direction
$game_player.turn_down
pbRefreshSceneMap
end
def scroll_back_map
@adapter.reset_player_clothes()
pbScrollMap(DIRECTION_LEFT, 7, 5)
pbScrollMap(DIRECTION_DOWN, 5, 5)
pbScrollMap(DIRECTION_LEFT, 7, 6)
pbScrollMap(DIRECTION_DOWN, 5, 6)
$game_player.turn_generic(@initial_direction)
pbRefreshSceneMap
#$scene.reset_map(true)
#pbRefreshSceneMap
# $scene.reset_map(false)
end
def refreshStock(adapter)
@@ -54,11 +55,21 @@ class ClothesShopView < PokemonMart_Scene
itemwindow = @sprites["itemwindow"]
#@sprites["icon"].item = itemwindow.item
#@sprites["icon"].item = itemwindow.item
@sprites["itemtextwindow"].text =
(itemwindow.item) ? @adapter.getDescription(itemwindow.item) : _INTL("Quit.")
item = itemwindow.item
if itemwindow.item
if itemwindow.item.is_a?(Symbol)
text = @adapter.getSpecialItemCaption(item)
else
text = @adapter.getDescription(item)
end
else
text = _INTL("Quit.")
end
@sprites["itemtextwindow"].text = text
itemwindow.refresh
end
@sprites["moneywindow"].text = _INTL("{2}:\r\n<r>{1}", @adapter.getMoneyString,@currency_name)
@sprites["moneywindow"].text = _INTL("{2}:\r\n<r>{1}", @adapter.getMoneyString, @currency_name)
end
def updateTrainerPreview()
@@ -66,13 +77,20 @@ class ClothesShopView < PokemonMart_Scene
end
def displayNewItem(itemwindow)
@adapter.updateTrainerPreview(itemwindow.item,@sprites["trainerPreview"])
@sprites["itemtextwindow"].text =
(itemwindow.item) ? @adapter.getDescription(itemwindow.item) : _INTL("Quit.")
item = itemwindow.item
if item
if item.is_a?(Symbol)
description = @adapter.getSpecialItemDescription(itemwindow.item)
else
description = @adapter.getDescription(itemwindow.item)
end
@adapter.updateTrainerPreview(itemwindow.item, @sprites["trainerPreview"])
else
description = _INTL("Quit.")
end
@sprites["itemtextwindow"].text = description
end
def pbChooseBuyItem
itemwindow = @sprites["itemwindow"]
displayNewItem(itemwindow)
@@ -87,25 +105,27 @@ class ClothesShopView < PokemonMart_Scene
if itemwindow.item != olditem
displayNewItem(itemwindow)
end
if Input.trigger?(Input::AUX1)#L button
@adapter.switchVersion(itemwindow.item,-1)
if Input.trigger?(Input::AUX1) #L button - disabled because same key as speed up...
#@adapter.switchVersion(itemwindow.item, -1)
#updateTrainerPreview()
end
if Input.trigger?(Input::AUX2) #R button
@adapter.switchVersion(itemwindow.item, 1)
updateTrainerPreview()
end
if Input.trigger?(Input::AUX2)#R button
@adapter.switchVersion(itemwindow.item,1)
updateTrainerPreview()
end
if Input.trigger?(Input::SPECIAL)#R button
if Input.trigger?(Input::SPECIAL) #R button
@adapter.toggleEvent(itemwindow.item)
updateTrainerPreview()
end
if Input.trigger?(Input::BACK)
pbPlayCloseMenuSE
return nil
elsif Input.trigger?(Input::USE)
if itemwindow.index < @stock.length
if itemwindow.item.is_a?(Symbol)
@adapter.doSpecialItemAction(itemwindow.item)
updateTrainerPreview()
elsif itemwindow.index < @stock.length
pbRefresh
return @stock[itemwindow.index]
else
@@ -130,10 +150,9 @@ class ClothesShopView < PokemonMart_Scene
super
end
def pbEndBuyScene
@sprites["trainerPreview"].erase()
@sprites["trainerPreview"]=nil
@sprites["trainerPreview"] = nil
pbDisposeSpriteHash(@sprites)
@viewport.dispose
Kernel.pbClearText()
@@ -6,21 +6,37 @@ class HairMartAdapter < OutfitsMartAdapter
def initialize(stock = nil, isShop = nil)
super
@version = getCurrentHairVersion().to_i
@worn_hair = $Trainer.hair
@worn_hat = $Trainer.hat
@hat_visible=false
@hat_visible = false
@removable = true
@previous_item= find_first_item()
end
def switchVersion(item, delta=1)
def find_first_item()
return @items.find { |item| item.is_a?(Outfit) }
end
def switchVersion(item, delta = 1)
if !item.is_a?(Outfit)
item = @previous_item
end
pbSEPlay("GUI party switch", 80, 100)
newVersion = @version+ delta
newVersion = @version + delta
lastVersion = findLastHairVersion(item.id)
newVersion = lastVersion if newVersion <= 0
newVersion = 1 if newVersion > lastVersion
@version = newVersion
end
#player can't "own" hairstyles
# if you want to go back one you had before, you have to pay again
def itemOwned(item)
return false
end
def toggleEvent(item)
pbSEPlay("GUI storage put down", 80, 100)
toggleHatVisibility()
@@ -28,8 +44,8 @@ class HairMartAdapter < OutfitsMartAdapter
def toggleText()
text = ""
text << "Color: L / R\n"
text << "Hat: D\n"
#text << "Color: R, \n"
text << "Toggle Hat: D\n"
end
@@ -39,15 +55,16 @@ class HairMartAdapter < OutfitsMartAdapter
def getPrice(item, selling = nil)
return 0 if !@isShop
trainerStyleID = getSplitHairFilenameAndVersionFromID($Trainer.hair)[0]
return 0 if item == trainerStyleID
return nil if itemOwned(item)
trainer_hair_id = getSplitHairFilenameAndVersionFromID(@worn_hair)[1]
return nil if item.id == trainer_hair_id
return item.price.to_i
end
def getDisplayPrice(item, selling = nil)
trainerStyleID = getSplitHairFilenameAndVersionFromID($Trainer.hair)[0]
return "-" if item == trainerStyleID
trainerStyleID = getSplitHairFilenameAndVersionFromID(@worn_hair)[1]
return "-" if item.id == trainerStyleID
super
end
@@ -64,6 +81,7 @@ class HairMartAdapter < OutfitsMartAdapter
end
def getName(item)
echoln $Trainer.hair
return item.id
end
@@ -84,12 +102,13 @@ class HairMartAdapter < OutfitsMartAdapter
end
def updateTrainerPreview(item, previewWindow)
return if !item
item = @previous_item if !item
item = @previous_item if item.is_a?(Symbol)
@previous_item = find_first_item() if !item.is_a?(Symbol)
displayed_hat = @hat_visible ? @worn_hat : nil
previewWindow.hat=displayed_hat
previewWindow.hat = displayed_hat
$Trainer.hat = displayed_hat
itemId = getCurrentHairId(item.id)
echoln itemId
previewWindow.hair = itemId
$Trainer.hair = itemId
pbRefreshSceneMap
@@ -99,10 +118,8 @@ class HairMartAdapter < OutfitsMartAdapter
def addItem(item)
itemId = getCurrentHairId(item.id)
changed_clothes = obtainNewHairstyle(itemId)
if changed_clothes
@worn_clothes = itemId
end
obtainNewHairstyle(itemId)
@worn_hair = itemId
end
def get_current_clothes()
@@ -112,15 +129,57 @@ class HairMartAdapter < OutfitsMartAdapter
def putOnOutfit(item)
itemFullId = getCurrentHairId(item.id)
putOnHair(item.id, @version)
@worn_clothes = itemFullId
@worn_hair = itemFullId
end
def reset_player_clothes()
$Trainer.hair = @worn_clothes
# can change hair color for free if not changing the style
if getVersionFromFullID(@worn_hair) != @version
worn_id = getSimplifiedHairIdFromFullID(@worn_hair)
if getSimplifiedHairIdFromFullID($Trainer.hair) == worn_id
@worn_hair = getFullHairId(worn_id,@version)
end
end
$Trainer.hair = @worn_hair
$Trainer.hat = @worn_hat
end
def get_unlocked_items_list()
return $Trainer.unlocked_hairstyles
end
def getSpecialItemCaption(specialType)
case specialType
when :SWAP_COLOR
return "Swap Color"
end
return nil
end
def getSpecialItemBaseColor(specialType)
case specialType
when :SWAP_COLOR
return MessageConfig::BLUE_TEXT_MAIN_COLOR
end
return nil
end
def getSpecialItemShadowColor(specialType)
case specialType
when :SWAP_COLOR
return MessageConfig::BLUE_TEXT_SHADOW_COLOR
end
return nil
end
def getSpecialItemDescription(specialType)
return "Swap to the next base hair color."
end
def doSpecialItemAction(specialType)
switchVersion(nil,1)
end
end
@@ -28,9 +28,11 @@ class HairShopPresenter < PokemonMartScreen
itemname = @adapter.getDisplayName(item)
price = @adapter.getPrice(item)
echoln price
if !price.is_a?(Integer)
#@adapter.switchVersion(item,1)
pbDisplayPaused(_INTL("This is your current hairstyle!"))
@adapter.putOnOutfit(item)
next
end
if @adapter.getMoney < price
@@ -8,6 +8,9 @@ class HatsMartAdapter < OutfitsMartAdapter
def toggleEvent(item)
if !@isShop
$Trainer.hat = nil
@worn_clothes = nil
if pbConfirmMessage(_INTL("Do you want to take off your hat?"))
$Trainer.hat = nil
@worn_clothes = nil
@@ -17,9 +20,10 @@ class HatsMartAdapter < OutfitsMartAdapter
end
def toggleText()
return if @isShop
toggleKey = "D"#getMappedKeyFor(Input::SPECIAL)
return "Remove hat: #{toggleKey}"
return
# return if @isShop
# toggleKey = "D"#getMappedKeyFor(Input::SPECIAL)
# return "Remove hat: #{toggleKey}"
end
def getName(item)
@@ -42,15 +46,20 @@ class HatsMartAdapter < OutfitsMartAdapter
end
def updateTrainerPreview(item, previewWindow)
return if !item
previewWindow.hat = item.id
$Trainer.hat = item.id unless $Trainer.hat==nil
if item.is_a?(Outfit)
previewWindow.hat = item.id
$Trainer.hat = item.id# unless $Trainer.hat==nil
else
$Trainer.hat=nil
previewWindow.hat= nil
end
pbRefreshSceneMap
previewWindow.updatePreview()
end
def addItem(item)
changed_clothes = obtainNewHat(item.id)
return unless item.is_a?(Outfit)
changed_clothes = obtainHat(item.id)
if changed_clothes
@worn_clothes = item.id
end
@@ -61,6 +70,7 @@ class HatsMartAdapter < OutfitsMartAdapter
end
def putOnOutfit(item)
return unless item.is_a?(Outfit)
putOnHat(item.id)
@worn_clothes = item.id
end
@@ -72,4 +82,38 @@ class HatsMartAdapter < OutfitsMartAdapter
def get_unlocked_items_list()
return $Trainer.unlocked_hats
end
def getSpecialItemCaption(specialType)
case specialType
when :REMOVE_HAT
return "Remove hat"
end
return nil
end
def getSpecialItemBaseColor(specialType)
case specialType
when :REMOVE_HAT
return MessageConfig::BLUE_TEXT_MAIN_COLOR
end
return nil
end
def getSpecialItemShadowColor(specialType)
case specialType
when :REMOVE_HAT
return MessageConfig::BLUE_TEXT_SHADOW_COLOR
end
return nil
end
def getSpecialItemDescription(specialType)
echoln $Trainer.hair
hair_situation = !$Trainer.hair || getSimplifiedHairIdFromFullID($Trainer.hair) == HAIR_BALD ? "bald head" : "fabulous hair"
return "Go without a hat and show off your #{hair_situation}!"
end
def doSpecialItemAction(specialType)
toggleEvent(nil)
end
end

Some files were not shown because too many files have changed in this diff Show More