mirror of
https://github.com/infinitefusion/infinitefusion-e18.git
synced 2025-12-09 06:04:59 +00:00
update 6.7
This commit is contained in:
@@ -0,0 +1,499 @@
|
||||
def map_sprites_by_artist
|
||||
creditsMap = Hash.new
|
||||
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
|
||||
row = line.split(',')
|
||||
spritename = row[0]
|
||||
if row[1]
|
||||
artist = row[1].chomp
|
||||
sprites = creditsMap.key?(artist) ? creditsMap[artist] : []
|
||||
sprites << spritename
|
||||
creditsMap[artist] = sprites
|
||||
end
|
||||
end
|
||||
return creditsMap
|
||||
end
|
||||
|
||||
def get_top_artists(nb_names = 100)
|
||||
filename = Settings::CREDITS_FILE_PATH
|
||||
name_counts = Hash.new(0)
|
||||
|
||||
File.readlines(filename).each do |line|
|
||||
name = line.strip.split(',')[1]
|
||||
name_counts[name] += 1
|
||||
end
|
||||
|
||||
name_counts.sort_by { |name, count| -count }.to_h
|
||||
.first(nb_names)
|
||||
.to_h
|
||||
end
|
||||
|
||||
def analyzeSpritesList(spritesList, mostPopularCallbackVariable = 1)
|
||||
pokemon_map = Hash.new
|
||||
for spritename in spritesList
|
||||
splitName = spritename.split(".")
|
||||
headNum = splitName[0].to_i
|
||||
bodyNum = splitName[1].to_i
|
||||
|
||||
if pokemon_map.key?(headNum)
|
||||
pokemon_map[headNum] += 1
|
||||
else
|
||||
pokemon_map[headNum] = 1
|
||||
end
|
||||
|
||||
if pokemon_map.key?(bodyNum)
|
||||
pokemon_map[bodyNum] += 1
|
||||
else
|
||||
pokemon_map[bodyNum] = 1
|
||||
end
|
||||
end
|
||||
most_popular = pokemon_map.max_by { |key, value| value }
|
||||
most_popular_poke = most_popular[0]
|
||||
most_popular_nb = most_popular[1]
|
||||
|
||||
pbSet(mostPopularCallbackVariable, most_popular_nb)
|
||||
species = getSpecies(most_popular_poke)
|
||||
|
||||
return species
|
||||
end
|
||||
|
||||
def getPokemonSpeciesFromPifSprite(pif_sprite)
|
||||
if pif_sprite.type == :BASE
|
||||
return getSpecies(pif_sprite.head_id)
|
||||
else
|
||||
return getFusionSpecies(pif_sprite.body_id, pif_sprite.head_id)
|
||||
end
|
||||
end
|
||||
|
||||
# def getPokemonSpeciesFromSprite(spritename)
|
||||
# return nil if !spritename
|
||||
# spritename.gsub('.png', '')
|
||||
# splitName = spritename.split(".")
|
||||
# headNum = splitName[0].to_i
|
||||
# bodyNum = splitName[1].to_i
|
||||
#
|
||||
# #call this to make sure that the sprite is downloaded
|
||||
# get_fusion_sprite_path(headNum, bodyNum)
|
||||
#
|
||||
# species = getFusionSpecies(bodyNum, headNum)
|
||||
# return species
|
||||
# end
|
||||
|
||||
def doesCurrentExhibitionFeaturePokemon(displayedSprites, pokemon)
|
||||
for sprite in displayedSprites
|
||||
headNum = sprite.head_id
|
||||
bodyNum = sprite.body_id
|
||||
return true if headNum == pokemon.id_number || bodyNum == pokemon.id_number
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def select_spriter(minNbSprites = 10, save_in_var = 1)
|
||||
spriters_list = list_all_spriters_with_min_nb_of_sprites(minNbSprites)
|
||||
commands = []
|
||||
spriters_list.each do |name, i|
|
||||
if name
|
||||
commands.push([i, name, name])
|
||||
end
|
||||
end
|
||||
chosen = pbChooseList(commands, 0, nil, 1)
|
||||
return nil if !chosen
|
||||
return chosen
|
||||
end
|
||||
|
||||
def list_all_spriters_with_min_nb_of_sprites(minNbSprites)
|
||||
return list_all_spriters() if !minNbSprites
|
||||
filename = Settings::CREDITS_FILE_PATH
|
||||
spriters_hash = Hash.new(0)
|
||||
|
||||
File.readlines(filename).each do |line|
|
||||
name = line.strip.split(',')[1]
|
||||
if name
|
||||
spriters_hash[name] += 1
|
||||
end
|
||||
end
|
||||
|
||||
spriters_list = []
|
||||
for spriter_name in spriters_hash.keys
|
||||
if spriters_hash[spriter_name] >= minNbSprites
|
||||
spriters_list << spriter_name
|
||||
end
|
||||
end
|
||||
return spriters_list
|
||||
end
|
||||
|
||||
def list_all_spriters()
|
||||
filename = Settings::CREDITS_FILE_PATH
|
||||
names_list = []
|
||||
File.readlines(filename).each do |line|
|
||||
name = line.strip.split(',')[1]
|
||||
if !names_list.include?(name)
|
||||
names_list << name
|
||||
end
|
||||
end
|
||||
return names_list
|
||||
end
|
||||
|
||||
def generateCurrentGalleryBattle(level = nil, number_of_pokemon = 3)
|
||||
spriter_name = pbGet(259)
|
||||
#set highest level in party if nil
|
||||
if !level
|
||||
level = $Trainer.highest_level_pokemon_in_party
|
||||
end
|
||||
possible_battlers = []
|
||||
for i in 0..5
|
||||
pif_sprite = pbGet(VAR_GALLERY_FEATURED_SPRITES)[i]
|
||||
species = getPokemonSpeciesFromPifSprite(pif_sprite)
|
||||
possible_battlers << species if species
|
||||
end
|
||||
|
||||
selected_battlers_idx = possible_battlers.sample(number_of_pokemon)
|
||||
party = []
|
||||
selected_battlers_idx.each { |species| 00
|
||||
party << Pokemon.new(species, level)
|
||||
}
|
||||
|
||||
custom_appearance = generate_appearance_from_name(spriter_name)
|
||||
customTrainerBattle(spriter_name,
|
||||
:PAINTER,
|
||||
party,
|
||||
level,
|
||||
pick_spriter_losing_dialog(spriter_name),
|
||||
pick_trainer_sprite(spriter_name),
|
||||
custom_appearance
|
||||
|
||||
)
|
||||
|
||||
end
|
||||
|
||||
def generateArtGallery(nbSpritesDisplayed = 6, saveArtistNameInVariable = 1, saveSpritesInVariable = 2, saveAllArtistSpritesInVariable = 3, artistName = nil)
|
||||
artistName = nil if artistName == 0
|
||||
creditsMap = map_sprites_by_artist
|
||||
select_daily_team_flags()
|
||||
featuredArtist = artistName ? artistName : getRandomSpriteArtist(creditsMap, nbSpritesDisplayed)
|
||||
if featuredArtist
|
||||
if !creditsMap[featuredArtist] #try again if issue
|
||||
artistName = getRandomSpriteArtist(creditsMap, nbSpritesDisplayed)
|
||||
return generateArtGallery(nbSpritesDisplayed, saveSpritesInVariable, saveSpritesInVariable, saveSpritesInVariable, artistName)
|
||||
end
|
||||
featuredSprites_files = creditsMap[featuredArtist].shuffle.take(nbSpritesDisplayed)
|
||||
echoln featuredSprites_files
|
||||
featuredSprites = []
|
||||
for sprite_name in featuredSprites_files
|
||||
featuredSprites << pif_sprite_from_spritename(sprite_name)
|
||||
end
|
||||
echoln featuredSprites
|
||||
pbSet(saveArtistNameInVariable, File.basename(featuredArtist, '#*'))
|
||||
pbSet(saveSpritesInVariable, featuredSprites)
|
||||
pbSet(saveAllArtistSpritesInVariable, creditsMap[featuredArtist])
|
||||
return featuredSprites
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
FLAGS_PATH = "Graphics/Pictures/Trainer Card/backgrounds/flags/"
|
||||
|
||||
def select_daily_team_flags()
|
||||
eligible_flags = []
|
||||
all_flags = Dir.entries(FLAGS_PATH)
|
||||
.select { |file| file.end_with?('_FLAG.png') }
|
||||
.map { |file| file.sub('_FLAG.png', '') }
|
||||
for flag in all_flags
|
||||
if GameData::Species.get(flag.to_sym)
|
||||
eligible_flags << flag
|
||||
end
|
||||
end
|
||||
selectedFlags = eligible_flags.sample(4)
|
||||
echoln selectedFlags
|
||||
pbSet(VAR_GALLERY_TEAM_FLAGS, selectedFlags)
|
||||
end
|
||||
|
||||
def displayTeamFlag(frame)
|
||||
selected_flags = pbGet(VAR_GALLERY_TEAM_FLAGS)
|
||||
echoln pbGet(VAR_GALLERY_TEAM_FLAGS)
|
||||
flag_image_id = 10
|
||||
frame_image_id = 9
|
||||
flag = selected_flags[frame]
|
||||
species = GameData::Species.get(flag.to_sym)
|
||||
|
||||
flag_path = "Trainer Card/backgrounds/flags/#{flag}_FLAG"
|
||||
|
||||
x_position = 150
|
||||
y_position = 50
|
||||
$game_screen.pictures[flag_image_id].show(flag_path, 0, x_position, y_position, 50, 50)
|
||||
$game_screen.pictures[frame_image_id].show("teamFlagFrame", 0, x_position, y_position, 50, 50)
|
||||
name = species.real_name
|
||||
pbMessage("\"Team #{name} Flag\"")
|
||||
|
||||
display_team_flag_statistics(species)
|
||||
|
||||
# species_sprites = list_all_sprite_credits_for_pokemon(species)
|
||||
# unique_sprites = species_sprites.reject { |sprite_name, _| sprite_name.match(/[a-zA-Z]$/) }
|
||||
# percent = (unique_sprites.keys.length.to_f / (NB_POKEMON * 2)) * 100
|
||||
# pbMessage("Team #{name} completion: \\C[1]#{sprintf('%.2f', percent)}%")
|
||||
#
|
||||
# top_contributors = get_top_contributors_for_pokemon(species_sprites, 5)
|
||||
# echoln top_contributors
|
||||
#
|
||||
#
|
||||
# contributors_string = ""
|
||||
# top_contributors.keys.each_with_index do |spriter, index|
|
||||
# contributors_string += "\\C[1]#{spriter}\\C[0]"
|
||||
# contributors_string += " (#{top_contributors[spriter]} sprites)"
|
||||
# contributors_string += "<br>" unless index == top_contributors.length - 1
|
||||
# end
|
||||
# pbMessage("Top contributors:<br>#{contributors_string}")
|
||||
|
||||
flag_id = "flags/#{species.id.to_s}_FLAG"
|
||||
flag_name = "Team #{species.real_name}"
|
||||
prompt_flag_purchase(flag_id, flag_name, 5000)
|
||||
|
||||
$game_screen.pictures[flag_image_id].erase
|
||||
$game_screen.pictures[frame_image_id].erase
|
||||
end
|
||||
|
||||
def display_specific_pokemon_statistics()
|
||||
species_id = select_any_pokemon()
|
||||
return if !species_id
|
||||
species = GameData::Species.get(species_id)
|
||||
species_sprites = list_all_sprite_credits_for_pokemon(species)
|
||||
unique_sprites = filter_unique_sprites_nb_for_pokemon(species_sprites)
|
||||
percent = (unique_sprites.length.to_f / (NB_POKEMON * 2)) * 100
|
||||
pbMessage(_INTL("{1} completion: \\C[1]{2}%\\C[0]",species.real_name,sprintf('%.2f', percent)))
|
||||
|
||||
contributors_string = ""
|
||||
top_contributors = get_top_contributors_for_pokemon(species_sprites, 5)
|
||||
top_contributors.keys.each_with_index do |spriter, index|
|
||||
contributors_string += "\\C[1]#{spriter}\\C[0]"
|
||||
contributors_string += " (#{top_contributors[spriter]} sprites)"
|
||||
contributors_string += "<br>" unless index == top_contributors.length - 1
|
||||
end
|
||||
pbMessage(_INTL("{1} top contributors:<br>{2}",species.real_name,contributors_string))
|
||||
end
|
||||
|
||||
def display_team_flag_statistics(species)
|
||||
evolution_line = species.get_related_species
|
||||
flag_pokemon_name = species.name
|
||||
echoln evolution_line
|
||||
if evolution_line.length > 1
|
||||
pbMessage(_INTL("This flag stands as a tribute to the artists who have devoted their talents to portraying \\C[1]{1}\\C[0] and its evolution line in all its forms.",flag_pokemon_name))
|
||||
else
|
||||
pbMessage(_INTL("This flag stands as a tribute to the artists who have devoted their talents to portraying \\C[1]{1}\\C[0] in all its forms.",flag_pokemon_name))
|
||||
end
|
||||
all_sprites = []
|
||||
family_unique_sprites_nb = []
|
||||
for pokemon_id in evolution_line
|
||||
species = GameData::Species.get(pokemon_id)
|
||||
species_sprites = list_all_sprite_credits_for_pokemon(species)
|
||||
unique_sprites = filter_unique_sprites_nb_for_pokemon(species_sprites)
|
||||
all_sprites << species_sprites
|
||||
unique_sprites_nb = unique_sprites.length.to_f
|
||||
family_unique_sprites_nb << unique_sprites_nb
|
||||
percent = (unique_sprites.length.to_f / (NB_POKEMON * 2)) * 100
|
||||
pbMessage(_INTL("{1} completion: \\C[1]{2}%\\C[0]",species.real_name,sprintf('%.2f', percent))) if evolution_line.length > 1
|
||||
end
|
||||
overall_total = 0
|
||||
family_unique_sprites_nb.each { |nb|
|
||||
overall_total += nb
|
||||
}
|
||||
overall_percent = (overall_total / ((NB_POKEMON * 2)*family_unique_sprites_nb.length))*100
|
||||
pbMessage(_INTL("Team {1} overall completion: \\C[3]{2}%\\C[0]",flag_pokemon_name,sprintf('%.2f', overall_percent)))
|
||||
|
||||
family_line_sprites = {}
|
||||
for pokemon_sprites in all_sprites
|
||||
family_line_sprites = family_line_sprites.merge(pokemon_sprites)
|
||||
end
|
||||
|
||||
contributors_string = ""
|
||||
top_contributors = get_top_contributors_for_pokemon(family_line_sprites, 5)
|
||||
top_contributors.keys.each_with_index do |spriter, index|
|
||||
contributors_string += "\\C[1]#{spriter}\\C[0]"
|
||||
contributors_string += _INTL(" ({1} sprites)",top_contributors[spriter])
|
||||
contributors_string += "<br>" unless index == top_contributors.length - 1
|
||||
end
|
||||
pbMessage(_INTL("Team {1} top contributors:<br>{2}",flag_pokemon_name,contributors_string))
|
||||
|
||||
end
|
||||
|
||||
def filter_unique_sprites_nb_for_pokemon(species_sprites)
|
||||
unique_sprites = species_sprites.reject { |sprite_name, _| sprite_name.match(/[a-zA-Z]$/) }
|
||||
return unique_sprites
|
||||
end
|
||||
|
||||
def display_special_banner()
|
||||
flag_id = "500000"
|
||||
flag_name = _INTL("Team 500,000")
|
||||
price = 10000
|
||||
|
||||
banner_title = _INTL("Half-million Milestone Banner")
|
||||
flag_path = "Trainer Card/backgrounds/#{flag_id}"
|
||||
|
||||
flag_image_id = 10
|
||||
frame_image_id = 9
|
||||
|
||||
x_position = 150
|
||||
y_position = 50
|
||||
$game_screen.pictures[flag_image_id].show(flag_path, 0, x_position, y_position, 50, 50)
|
||||
$game_screen.pictures[frame_image_id].show("teamFlagFrame", 0, x_position, y_position, 50, 50)
|
||||
|
||||
pbMessage("\"#{banner_title}\"")
|
||||
pbMessage(_INTL("A banner honoring the 500,000 members of the community who have come together to inspire countless others."))
|
||||
pbWait(10)
|
||||
percent = get_total_completion_percent()
|
||||
pbMessage(_INTL("All Pokémon completion: \\C[1]{1}%",sprintf('%.2f', percent)))
|
||||
|
||||
prompt_flag_purchase(flag_id, flag_name, price)
|
||||
$game_screen.pictures[flag_image_id].erase
|
||||
$game_screen.pictures[frame_image_id].erase
|
||||
end
|
||||
|
||||
def prompt_flag_purchase(flag_id, flag_name, price)
|
||||
$Trainer.unlocked_card_backgrounds = [] if ! $Trainer.unlocked_card_backgrounds
|
||||
if !$Trainer.unlocked_card_backgrounds.include?(flag_id) && $Trainer.money >= price
|
||||
pbWait(20)
|
||||
if pbConfirmMessage(_INTL("\\GWould you to purchase the \\C[1]{1}\\C[0] flag as a background for your \\C[1]Trainer Card\\C[0] for ${2}?",flag_name,price))
|
||||
pbSEPlay("Mart buy item")
|
||||
$Trainer.money -= price
|
||||
unlock_card_background(flag_id)
|
||||
pbMessage(_INTL("\\GYou purchased the \\C[1]{1}\\C[0] Trainer Card background!",flag_name))
|
||||
if pbConfirmMessage(_INTL("Swap your current Trainer Card for the newly purchased one?"))
|
||||
pbSEPlay("GUI trainer card open")
|
||||
$Trainer.card_background = flag_id
|
||||
else
|
||||
pbMessage(_INTL("You can swap the background at anytime when viewing your Trainer Card."))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def get_total_completion_percent()
|
||||
customSpritesList = $game_temp.custom_sprites_list.keys
|
||||
total_nb_pokemon = (NB_POKEMON * NB_POKEMON) + NB_POKEMON
|
||||
sprited_pokemon = customSpritesList.length
|
||||
return (sprited_pokemon.to_f / total_nb_pokemon) * 100
|
||||
end
|
||||
|
||||
def get_top_contributors_for_pokemon(species_sprites, top_x)
|
||||
frequency = Hash.new(0)
|
||||
species_sprites.values.each { |str| frequency[str] += 1 }
|
||||
frequency.sort_by { |_, count| -count }.first(top_x).to_h
|
||||
end
|
||||
|
||||
def list_all_sprite_credits_for_pokemon(species)
|
||||
dex_num = species.id_number
|
||||
sprites = {}
|
||||
filename = Settings::CREDITS_FILE_PATH
|
||||
File.readlines(filename).each do |line|
|
||||
split_line = line.strip.split(',')
|
||||
sprite = split_line[0]
|
||||
match = sprite.match(/(\d+)\.(\d+)/)
|
||||
next unless match # Skip if no match is found
|
||||
head_id = match[1].to_i
|
||||
tail_id = match[2].to_i
|
||||
|
||||
artist = split_line[1]
|
||||
sprites[sprite] = artist if head_id == dex_num || tail_id == dex_num
|
||||
end
|
||||
return sprites
|
||||
end
|
||||
|
||||
def displayGalleryFrame(frame)
|
||||
frame_image_id = 10
|
||||
bg_image_id = 9
|
||||
|
||||
pif_sprite = pbGet(VAR_GALLERY_FEATURED_SPRITES)[frame]
|
||||
if !pif_sprite.is_a?(PIFSprite)
|
||||
pbMessage(_INTL("The frame is empty..."))
|
||||
return
|
||||
end
|
||||
species = getPokemonSpeciesFromPifSprite(pif_sprite)
|
||||
$game_screen.pictures[frame_image_id].show("pictureFrame_bg", 0, 0, 0)
|
||||
$game_screen.pictures[bg_image_id].show("pictureFrame", 0, 0, 0)
|
||||
name = species.real_name
|
||||
author = pbGet(259)
|
||||
message = "\"#{name}\"\nBy #{author}"
|
||||
displaySpriteWindowWithMessage(pif_sprite, message, 90, -10, 201)
|
||||
$game_screen.pictures[frame_image_id].erase
|
||||
$game_screen.pictures[bg_image_id].erase
|
||||
|
||||
end
|
||||
|
||||
def format_artist_name(full_name)
|
||||
return File.basename(full_name, '#*')
|
||||
end
|
||||
|
||||
def getRandomSpriteArtist(creditsMap = nil, minimumNumberOfSprites = 10, giveUpAfterX = 50)
|
||||
creditsMap = map_sprites_by_artist if !creditsMap
|
||||
i = 0
|
||||
while i < giveUpAfterX
|
||||
artist = creditsMap.keys.sample
|
||||
return artist if creditsMap[artist].length >= minimumNumberOfSprites
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def getSpriteCredits(spriteName)
|
||||
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
|
||||
row = line.split(',')
|
||||
if row[0] == (spriteName)
|
||||
return row[1]
|
||||
end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def formatList(list, separator)
|
||||
formatted = ""
|
||||
i = 0
|
||||
for element in list
|
||||
formatted << element
|
||||
formatted << separator if i < list.length
|
||||
i += 1
|
||||
end
|
||||
end
|
||||
|
||||
def format_names_for_game_credits()
|
||||
spriters_map = get_top_artists(100)
|
||||
formatted = ""
|
||||
i = 1
|
||||
for spriter in spriters_map.keys
|
||||
formatted << spriter
|
||||
if i % 2 == 0
|
||||
formatted << "\n"
|
||||
else
|
||||
formatted << "<s>"
|
||||
end
|
||||
i += 1
|
||||
end
|
||||
return formatted
|
||||
end
|
||||
|
||||
|
||||
def get_spritename_from_path(file_path, includeExtension = false)
|
||||
filename_with_extension = File.basename(file_path)
|
||||
filename_without_extension = File.basename(filename_with_extension, ".*")
|
||||
return filename_with_extension if includeExtension
|
||||
return filename_without_extension
|
||||
end
|
||||
|
||||
def getSpriterCreditForDexNumber(species_sym)
|
||||
#download sprite to make sure it's in the substitutions map
|
||||
body_id = getBodyID(species_sym)
|
||||
head_id = getHeadID(species_sym, body_id)
|
||||
spritename = "#{head_id}.#{body_id}"
|
||||
return getSpriteCredits(spritename)
|
||||
end
|
||||
|
||||
#
|
||||
# def getSpriterCreditForPokemon(species_sym)
|
||||
# p species_sym
|
||||
# #download sprite to make sure it's in the substitutions map
|
||||
# head_id = get_head_id_from_symbol(species_sym)
|
||||
# body_id = get_body_id_from_symbol(species_sym)
|
||||
#
|
||||
# echoln head_id
|
||||
# echoln body_id
|
||||
# spritename = get_fusion_sprite_path(head_id,body_id)
|
||||
# p spritename
|
||||
# p getSpriteCredits(spritename)
|
||||
# return getSpriteCredits(spritename)
|
||||
# end
|
||||
@@ -0,0 +1,259 @@
|
||||
class PokeBattle_Battler
|
||||
attr_accessor :ability_id
|
||||
attr_accessor :ability2_id
|
||||
|
||||
#Primary ability utility methods for battlers class
|
||||
def ability
|
||||
return GameData::Ability.try_get(@ability_id)
|
||||
end
|
||||
|
||||
def ability=(value)
|
||||
new_ability = GameData::Ability.try_get(value)
|
||||
@ability_id = (new_ability) ? new_ability.id : nil
|
||||
end
|
||||
|
||||
def abilityName
|
||||
abil = self.ability
|
||||
return (abil) ? abil.name : ""
|
||||
end
|
||||
|
||||
#Secondary ability utility methods for battlers class
|
||||
def ability2
|
||||
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
return GameData::Ability.try_get(@ability2_id)
|
||||
end
|
||||
|
||||
def ability2=(value)
|
||||
return if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
new_ability = GameData::Ability.try_get(value)
|
||||
@ability2_id = (new_ability) ? new_ability.id : nil
|
||||
end
|
||||
|
||||
def ability2Name
|
||||
abil = self.ability2
|
||||
return (abil) ? abil.name : ""
|
||||
end
|
||||
|
||||
#Ability logic overrides
|
||||
|
||||
def hasActiveAbility?(check_ability, ignore_fainted = false)
|
||||
return hasActiveAbilityDouble?(check_ability, ignore_fainted) if $game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
return false if !abilityActive?(ignore_fainted)
|
||||
return check_ability.include?(@ability_id) if check_ability.is_a?(Array)
|
||||
return self.ability == check_ability
|
||||
end
|
||||
|
||||
def hasActiveAbilityDouble?(check_ability, ignore_fainted = false)
|
||||
return false if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
return false if !abilityActive?(ignore_fainted)
|
||||
if check_ability.is_a?(Array)
|
||||
return check_ability.include?(@ability_id) || check_ability.include?(@ability2_id)
|
||||
end
|
||||
return self.ability == check_ability || self.ability2 == check_ability
|
||||
end
|
||||
|
||||
def triggerAbilityEffectsOnHit(move, user, target)
|
||||
# Target's ability
|
||||
if target.abilityActive?(true)
|
||||
oldHP = user.hp
|
||||
BattleHandlers.triggerTargetAbilityOnHit(target.ability, user, target, move, @battle)
|
||||
BattleHandlers.triggerTargetAbilityOnHit(target.ability2, user, target, move, @battle) if $game_switches[SWITCH_DOUBLE_ABILITIES] && target.ability2
|
||||
user.pbItemHPHealCheck if user.hp < oldHP
|
||||
end
|
||||
# User's ability
|
||||
if user.abilityActive?(true)
|
||||
BattleHandlers.triggerUserAbilityOnHit(user.ability, user, target, move, @battle)
|
||||
BattleHandlers.triggerUserAbilityOnHit(user.ability2, user, target, move, @battle) if $game_switches[SWITCH_DOUBLE_ABILITIES] && user.ability2
|
||||
user.pbItemHPHealCheck
|
||||
end
|
||||
end
|
||||
|
||||
def pbCheckDamageAbsorption(user, target)
|
||||
# Substitute will take the damage
|
||||
if target.effects[PBEffects::Substitute] > 0 && !ignoresSubstitute?(user) &&
|
||||
(!user || user.index != target.index)
|
||||
target.damageState.substitute = true
|
||||
return
|
||||
end
|
||||
# Disguise will take the damage
|
||||
if !@battle.moldBreaker && target.isFusionOf(:MIMIKYU) &&
|
||||
target.form == 0 && (target.ability == :DISGUISE || target.ability2 == :DISGUISE)
|
||||
target.damageState.disguise = true
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
# Called when a Pokémon (self) enters battle, at the end of each move used,
|
||||
# and at the end of each round.
|
||||
def pbContinualAbilityChecks(onSwitchIn = false)
|
||||
# Check for end of primordial weather
|
||||
@battle.pbEndPrimordialWeather
|
||||
# Trace
|
||||
if $game_switches[SWITCH_DOUBLE_ABILITIES] && onSwitchIn
|
||||
displayOpponentDoubleAbilities()
|
||||
else
|
||||
if hasActiveAbility?(:TRACE)
|
||||
# NOTE: In Gen 5 only, Trace only triggers upon the Trace bearer switching
|
||||
# in and not at any later times, even if a traceable ability turns
|
||||
# up later. Essentials ignores this, and allows Trace to trigger
|
||||
# whenever it can even in the old battle mechanics.
|
||||
choices = []
|
||||
@battle.eachOtherSideBattler(@index) do |b|
|
||||
next if b.ungainableAbility? ||
|
||||
[:POWEROFALCHEMY, :RECEIVER, :TRACE].include?(b.ability_id)
|
||||
choices.push(b)
|
||||
end
|
||||
if choices.length > 0
|
||||
choice = choices[@battle.pbRandom(choices.length)]
|
||||
@battle.pbShowAbilitySplash(self)
|
||||
self.ability = choice.ability
|
||||
@battle.pbDisplay(_INTL("{1} traced {2}'s {3}!", pbThis, choice.pbThis(true), choice.abilityName))
|
||||
@battle.pbHideAbilitySplash(self)
|
||||
if !onSwitchIn && (unstoppableAbility? || abilityActive?)
|
||||
BattleHandlers.triggerAbilityOnSwitchIn(self.ability, self, @battle)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def displayOpponentDoubleAbilities()
|
||||
@battle.eachOtherSideBattler(@index) do |battler|
|
||||
@battle.pbShowPrimaryAbilitySplash(battler,true)
|
||||
@battle.pbShowSecondaryAbilitySplash(battler,true) if battler.isFusion?()
|
||||
@battle.pbHideAbilitySplash(battler)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
class Pokemon
|
||||
attr_writer :ability_index
|
||||
attr_writer :ability2_index
|
||||
|
||||
#Primary ability utility methods for pokemon class
|
||||
def ability_index
|
||||
@ability_index = (@personalID & 1) if !@ability_index
|
||||
return @ability_index
|
||||
end
|
||||
|
||||
def ability
|
||||
return GameData::Ability.try_get(ability_id())
|
||||
end
|
||||
|
||||
def ability=(value)
|
||||
return if value && !GameData::Ability.exists?(value)
|
||||
@ability = (value) ? GameData::Ability.get(value).id : value
|
||||
end
|
||||
|
||||
#Secondary ability utility methods for pokemon class
|
||||
def ability2_index
|
||||
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
@ability2_index = (@personalID & 1) if !@ability2_index
|
||||
return @ability2_index
|
||||
end
|
||||
|
||||
def ability2
|
||||
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
return GameData::Ability.try_get(ability2_id())
|
||||
end
|
||||
|
||||
def ability2=(value)
|
||||
return if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
return if value && !GameData::Ability.exists?(value)
|
||||
@ability2 = (value) ? GameData::Ability.get(value).id : value
|
||||
end
|
||||
|
||||
|
||||
def ability_id
|
||||
if !@ability
|
||||
sp_data = species_data
|
||||
abil_index = ability_index
|
||||
#echoln abil_index
|
||||
if abil_index >= 2 # Hidden ability
|
||||
@ability = sp_data.hidden_abilities[abil_index - 2]
|
||||
abil_index = (@personalID & 1) if !@ability
|
||||
end
|
||||
if !@ability # Natural ability or no hidden ability defined
|
||||
if $game_switches[SWITCH_NO_LEVELS_MODE]
|
||||
@ability = sp_data.abilities[0] || sp_data.abilities[0]
|
||||
@ability2 = sp_data.abilities[1] || sp_data.abilities[0]
|
||||
else
|
||||
@ability = sp_data.abilities[abil_index] || sp_data.abilities[0]
|
||||
end
|
||||
end
|
||||
end
|
||||
return @ability
|
||||
end
|
||||
|
||||
def ability2_id
|
||||
return nil if !$game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
if !@ability2
|
||||
sp_data = species_data
|
||||
abil_index = ability_index
|
||||
if abil_index >= 2 # Hidden ability
|
||||
@ability2 = sp_data.hidden_abilities[abil_index - 2]
|
||||
abil_index = (@personalID & 1) if !@ability2
|
||||
end
|
||||
if !@ability2 # Natural ability or no hidden ability defined
|
||||
@ability2 = sp_data.abilities[abil_index] || sp_data.abilities[0]
|
||||
end
|
||||
end
|
||||
return @ability2
|
||||
end
|
||||
|
||||
def adjustHPForWonderGuard(stats)
|
||||
return self.ability == :WONDERGUARD ? 1 : stats[:HP] || ($game_switches[SWITCH_DOUBLE_ABILITIES] && self.ability2 == :WONDERGUARD)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class PokemonFusionScene
|
||||
|
||||
def pbChooseAbility(ability1Id,ability2Id)
|
||||
ability1 = GameData::Ability.get(ability1Id)
|
||||
ability2 = GameData::Ability.get(ability2Id)
|
||||
availableNatures = []
|
||||
availableNatures << @pokemon1.nature
|
||||
availableNatures << @pokemon2.nature
|
||||
|
||||
setAbilityAndNatureAndNickname([ability1,ability2], availableNatures)
|
||||
end
|
||||
|
||||
|
||||
def setAbilityAndNatureAndNickname(abilitiesList, naturesList)
|
||||
clearUIForMoves
|
||||
if $game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
scene = FusionSelectOptionsScene.new(nil, naturesList, @pokemon1, @pokemon2)
|
||||
screen = PokemonOptionScreen.new(scene)
|
||||
screen.pbStartScreen
|
||||
|
||||
@pokemon1.ability = abilitiesList[0]
|
||||
@pokemon1.ability2 = abilitiesList[1]
|
||||
else
|
||||
scene = FusionSelectOptionsScene.new(abilitiesList, naturesList, @pokemon1, @pokemon2)
|
||||
screen = PokemonOptionScreen.new(scene)
|
||||
screen.pbStartScreen
|
||||
|
||||
selectedAbility = scene.selectedAbility
|
||||
@pokemon1.body_original_ability_index = @pokemon1.ability_index
|
||||
@pokemon1.head_original_ability_index = @pokemon2.ability_index
|
||||
|
||||
@pokemon1.ability = selectedAbility
|
||||
@pokemon1.ability_index = getAbilityIndexFromID(selectedAbility.id,@pokemon1)
|
||||
end
|
||||
|
||||
@pokemon1.nature = scene.selectedNature
|
||||
if scene.hasNickname
|
||||
@pokemon1.name = scene.nickname
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
#
|
||||
# module BattleHandlers
|
||||
# #
|
||||
# # Speed calculation
|
||||
# #
|
||||
#
|
||||
# def self.triggerSpeedCalcAbility(ability, battler, mult)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# calculateAbilitySpeedMultiplier(ability1, battler, mult)
|
||||
# if $game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
# calculateAbilitySpeedMultiplier(ability2, battler, mult)
|
||||
# end
|
||||
# return mult
|
||||
# end
|
||||
#
|
||||
# def self.calculateAbilitySpeedMultiplier(ability, battler, mult)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = SpeedCalcAbility.trigger(ability1, battler, mult) || SpeedCalcAbility.trigger(ability2, battler, mult)
|
||||
# return (ret != nil) ? ret : mult
|
||||
# end
|
||||
#
|
||||
# def self.triggerWeightCalcAbility(ability,battler,w)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = WeightCalcAbility.trigger(ability1,battler,w) || WeightCalcAbility.trigger(ability2,battler,w)
|
||||
# return (ret!=nil) ? ret : w
|
||||
# end
|
||||
#
|
||||
#
|
||||
#
|
||||
#
|
||||
# def self.triggerEOREffectAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
#
|
||||
# EOREffectAbility.trigger(ability1,battler,battle)
|
||||
# EOREffectAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerEORGainItemAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
#
|
||||
# EORGainItemAbility.trigger(ability1,battler,battle)
|
||||
# EORGainItemAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerCertainSwitchingUserAbility(ability,switcher,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = switcher.ability2
|
||||
#
|
||||
# ret = CertainSwitchingUserAbility.trigger(ability1,switcher,battle) || CertainSwitchingUserAbility.trigger(ability2,switcher,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerCertainSwitchingUserAbility(ability,switcher,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = switcher.ability2
|
||||
#
|
||||
# ret = CertainSwitchingUserAbility.trigger(ability1,switcher,battle) || CertainSwitchingUserAbility.trigger(ability2,switcher,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerTrappingTargetAbility(ability,switcher,bearer,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = switcher.ability2
|
||||
# ret = TrappingTargetAbility.trigger(ability1,switcher,bearer,battle) || TrappingTargetAbility.trigger(ability2,switcher,bearer,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnSwitchIn(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnSwitchIn.trigger(ability1,battler,battle)
|
||||
# AbilityOnSwitchIn.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnSwitchOut(ability,battler,endOfBattle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnSwitchOut.trigger(ability1,battler,endOfBattle)
|
||||
# AbilityOnSwitchOut.trigger(ability2,battler,endOfBattle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityChangeOnBattlerFainting(ability,battler,fainted,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityChangeOnBattlerFainting.trigger(ability1,battler,fainted,battle)
|
||||
# AbilityChangeOnBattlerFainting.trigger(ability2,battler,fainted,battle)
|
||||
#
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnBattlerFainting(ability,battler,fainted,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnBattlerFainting.trigger(ability1,battler,fainted,battle)
|
||||
# AbilityOnBattlerFainting.trigger(ability2,battler,fainted,battle)
|
||||
# end
|
||||
#
|
||||
#
|
||||
# def self.triggerRunFromBattleAbility(ability,battler)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = RunFromBattleAbility.trigger(ability1,battler) || RunFromBattleAbility.trigger(ability2,battler)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
# ########
|
||||
# # FROM HERE
|
||||
# #
|
||||
#
|
||||
# def self.triggerAbilityOnHPDroppedBelowHalf(ability,user,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# ret = AbilityOnHPDroppedBelowHalf.trigger(ability1,user,battle) || AbilityOnHPDroppedBelowHalf.trigger(ability2,user,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatusCheckAbilityNonIgnorable(ability,battler,status)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatusCheckAbilityNonIgnorable.trigger(ability1,battler,status) || StatusCheckAbilityNonIgnorable.trigger(ability2,battler,status)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatusImmunityAbility(ability,battler,status)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatusImmunityAbility.trigger(ability1,battler,status) || StatusImmunityAbility.trigger(ability2,battler,status)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatusImmunityAbilityNonIgnorable(ability,battler,status)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatusImmunityAbilityNonIgnorable.trigger(ability1,battler,status) || StatusImmunityAbilityNonIgnorable.trigger(ability2,battler,status)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatusImmunityAllyAbility(ability,battler,status)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatusImmunityAllyAbility.trigger(ability1,battler,status) || StatusImmunityAllyAbility.trigger(ability2,battler,status)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnStatusInflicted(ability,battler,user,status)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnStatusInflicted.trigger(ability1,battler,user,status)
|
||||
# AbilityOnStatusInflicted.trigger(ability2,battler,user,status)
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatusCureAbility(ability,battler)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatusCureAbility.trigger(ability1,battler) || StatusCureAbility.trigger(ability2,battler)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
#
|
||||
# def self.triggerStatLossImmunityAbility(ability,battler,stat,battle,showMessages)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatLossImmunityAbility.trigger(ability1,battler,stat,battle,showMessages) || StatLossImmunityAbility.trigger(ability2,battler,stat,battle,showMessages)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatLossImmunityAbilityNonIgnorable(ability,battler,stat,battle,showMessages)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatLossImmunityAbilityNonIgnorable.trigger(ability1,battler,stat,battle,showMessages) || StatLossImmunityAbilityNonIgnorable.trigger(ability2,battler,stat,battle,showMessages)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerStatLossImmunityAllyAbility(ability,bearer,battler,stat,battle,showMessages)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = StatLossImmunityAllyAbility.trigger(ability1,bearer,battler,stat,battle,showMessages) || StatLossImmunityAllyAbility.trigger(ability2,bearer,battler,stat,battle,showMessages)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnStatGain(ability,battler,stat,user)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnStatGain.trigger(ability1,battler,stat,user)
|
||||
# AbilityOnStatGain.trigger(ability2,battler,stat,user)
|
||||
# end
|
||||
#
|
||||
# def self.triggerAbilityOnStatLoss(ability,battler,stat,user)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnStatLoss.trigger(ability1,battler,stat,user)
|
||||
# AbilityOnStatLoss.trigger(ability2,battler,stat,user)
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
#
|
||||
# def self.triggerPriorityChangeAbility(ability,battler,move,pri)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = PriorityChangeAbility.trigger(ability1,battler,move,pri) || PriorityChangeAbility.trigger(ability2,battler,move,pri)
|
||||
# return (ret!=nil) ? ret : pri
|
||||
# end
|
||||
#
|
||||
# def self.triggerPriorityBracketChangeAbility(ability,battler,subPri,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# ret = PriorityBracketChangeAbility.trigger(ability1,battler,subPri,battle) || PriorityBracketChangeAbility.trigger(ability2,battler,subPri,battle)
|
||||
# return (ret!=nil) ? ret : subPri
|
||||
# end
|
||||
#
|
||||
# def self.triggerPriorityBracketUseAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# PriorityBracketUseAbility.trigger(ability1,battler,battle)
|
||||
# PriorityBracketUseAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerAbilityOnFlinch(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# AbilityOnFlinch.trigger(ability1,battler,battle)
|
||||
# AbilityOnFlinch.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerMoveBlockingAbility(ability,bearer,user,targets,move,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = bearer.ability2
|
||||
# ret = MoveBlockingAbility.trigger(ability1,bearer,user,targets,move,battle) || MoveBlockingAbility.trigger(ability2,bearer,user,targets,move,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# def self.triggerMoveImmunityTargetAbility(ability,user,target,move,type,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# ret = MoveImmunityTargetAbility.trigger(ability1,user,target,move,type,battle) || MoveImmunityTargetAbility.trigger(ability2,user,target,move,type,battle)
|
||||
# return (ret!=nil) ? ret : false
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerMoveBaseTypeModifierAbility(ability,user,move,type)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# ret = MoveBaseTypeModifierAbility.trigger(ability1,user,move,type) || MoveBaseTypeModifierAbility.trigger(ability2,user,move,type)
|
||||
# return (ret!=nil) ? ret : type
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerAccuracyCalcUserAbility(ability,mods,user,target,move,type)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# AccuracyCalcUserAbility.trigger(ability1,mods,user,target,move,type)
|
||||
# AccuracyCalcUserAbility.trigger(ability2,mods,user,target,move,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerAccuracyCalcUserAllyAbility(ability,mods,user,target,move,type)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# AccuracyCalcUserAllyAbility.trigger(ability1,mods,user,target,move,type)
|
||||
# AccuracyCalcUserAllyAbility.trigger(ability2,mods,user,target,move,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerAccuracyCalcTargetAbility(ability,mods,user,target,move,type)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# AccuracyCalcTargetAbility.trigger(ability1,mods,user,target,move,type)
|
||||
# AccuracyCalcTargetAbility.trigger(ability2,mods,user,target,move,type)
|
||||
# end
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerDamageCalcUserAbility(ability,user,target,move,mults,baseDmg,type)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# DamageCalcUserAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
|
||||
# DamageCalcUserAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerDamageCalcUserAllyAbility(ability,user,target,move,mults,baseDmg,type)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# DamageCalcUserAllyAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
|
||||
# DamageCalcUserAllyAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerDamageCalcTargetAbility(ability,user,target,move,mults,baseDmg,type)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# DamageCalcTargetAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
|
||||
# DamageCalcTargetAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerDamageCalcTargetAbilityNonIgnorable(ability,user,target,move,mults,baseDmg,type)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# DamageCalcTargetAbilityNonIgnorable.trigger(ability1,user,target,move,mults,baseDmg,type)
|
||||
# DamageCalcTargetAbilityNonIgnorable.trigger(ability2,user,target,move,mults,baseDmg,type)
|
||||
# end
|
||||
#
|
||||
# def self.triggerDamageCalcTargetAllyAbility(ability,user,target,move,mults,baseDmg,type)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# DamageCalcTargetAllyAbility.trigger(ability1,user,target,move,mults,baseDmg,type)
|
||||
# DamageCalcTargetAllyAbility.trigger(ability2,user,target,move,mults,baseDmg,type)
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerCriticalCalcUserAbility(ability,user,target,c)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# ret = CriticalCalcUserAbility.trigger(ability1,user,target,c) || CriticalCalcUserAbility.trigger(ability2,user,target,c)
|
||||
# return (ret!=nil) ? ret : c
|
||||
# end
|
||||
#
|
||||
# def self.triggerCriticalCalcTargetAbility(ability,user,target,c)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# ret = CriticalCalcTargetAbility.trigger(ability1,user,target,c) || CriticalCalcTargetAbility.trigger(ability2,user,target,c)
|
||||
# return (ret!=nil) ? ret : c
|
||||
# end
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerTargetAbilityOnHit(ability,user,target,move,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# TargetAbilityOnHit.trigger(ability1,user,target,move,battle)
|
||||
# TargetAbilityOnHit.trigger(ability2,user,target,move,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerUserAbilityOnHit(ability,user,target,move,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# UserAbilityOnHit.trigger(ability1,user,target,move,battle)
|
||||
# UserAbilityOnHit.trigger(ability2,user,target,move,battle)
|
||||
# end
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerUserAbilityEndOfMove(ability,user,targets,move,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = user.ability2
|
||||
# UserAbilityEndOfMove.trigger(ability1,user,targets,move,battle)
|
||||
# UserAbilityEndOfMove.trigger(ability2,user,targets,move,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerTargetAbilityAfterMoveUse(ability,target,user,move,switched,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = target.ability2
|
||||
# TargetAbilityAfterMoveUse.trigger(ability1,target,user,move,switched,battle)
|
||||
# TargetAbilityAfterMoveUse.trigger(ability2,target,user,move,switched,battle)
|
||||
# end
|
||||
#
|
||||
# #=============================================================================
|
||||
#
|
||||
# def self.triggerEORWeatherAbility(ability,weather,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# EORWeatherAbility.trigger(ability1,weather,battler,battle)
|
||||
# EORWeatherAbility.trigger(ability2,weather,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerEORHealingAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# EORHealingAbility.trigger(ability1,battler,battle)
|
||||
# EORHealingAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerEOREffectAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# EOREffectAbility.trigger(ability1,battler,battle)
|
||||
# EOREffectAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# def self.triggerEORGainItemAbility(ability,battler,battle)
|
||||
# ability1 = ability
|
||||
# ability2 = battler.ability2
|
||||
# EORGainItemAbility.trigger(ability1,battler,battle)
|
||||
# EORGainItemAbility.trigger(ability2,battler,battle)
|
||||
# end
|
||||
#
|
||||
# end
|
||||
@@ -0,0 +1,130 @@
|
||||
#
|
||||
# class AbilitySplashBar < SpriteWrapper
|
||||
# def refresh
|
||||
# self.bitmap.clear
|
||||
# return if !@battler
|
||||
# textPos = []
|
||||
# textX = (@side==0) ? 10 : self.bitmap.width-8
|
||||
# # Draw Pokémon's name
|
||||
# textPos.push(["{1}'s",@battler.name,textX,-4,@side==1,
|
||||
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
|
||||
# # Draw Pokémon's ability
|
||||
# textPos.push([@battler.abilityName,textX,26,@side==1,
|
||||
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
|
||||
# pbDrawTextPositions(self.bitmap,textPos)
|
||||
#
|
||||
# #2nd ability
|
||||
# if $game_switches[SWITCH_DOUBLE_ABILITIES]
|
||||
# textPos.push([@battler.ability2Name,textX,26,@side==1,
|
||||
# TEXT_BASE_COLOR,TEXT_SHADOW_COLOR,true])
|
||||
# pbDrawTextPositions(self.bitmap,textPos)
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
|
||||
|
||||
class AbilitySplashDisappearAnimation < PokeBattle_Animation
|
||||
def initialize(sprites,viewport,side)
|
||||
@side = side
|
||||
super(sprites,viewport)
|
||||
end
|
||||
|
||||
def createProcesses
|
||||
return if !@sprites["abilityBar_#{@side}"]
|
||||
bar = addSprite(@sprites["abilityBar_#{@side}"])
|
||||
bar2 = addSprite(@sprites["ability2Bar_#{@side}"]) if @sprites["ability2Bar_#{@side}"]
|
||||
|
||||
dir = (@side==0) ? -1 : 1
|
||||
bar.moveDelta(0,8,dir*Graphics.width/2,0)
|
||||
bar2.moveDelta(0,8,dir*Graphics.width/2,0) if bar2
|
||||
|
||||
bar.setVisible(8,false)
|
||||
bar2.setVisible(8,false) if bar2
|
||||
end
|
||||
end
|
||||
|
||||
class PokeBattle_Scene
|
||||
def pbShowAbilitySplash(battler,secondAbility=false, abilityName=nil)
|
||||
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
|
||||
side = battler.index%2
|
||||
if secondAbility
|
||||
pbHideAbilitySplash(battler) if @sprites["ability2Bar_#{side}"].visible
|
||||
else
|
||||
pbHideAbilitySplash(battler) if @sprites["abilityBar_#{side}"].visible
|
||||
end
|
||||
if abilityName
|
||||
@sprites["abilityBar_#{side}"].ability_name = abilityName if !secondAbility
|
||||
@sprites["ability2Bar_#{side}"].ability_name = abilityName if secondAbility
|
||||
end
|
||||
|
||||
|
||||
@sprites["abilityBar_#{side}"].battler = battler
|
||||
@sprites["ability2Bar_#{side}"].battler = battler if @sprites["ability2Bar_#{side}"]
|
||||
|
||||
abilitySplashAnim = AbilitySplashAppearAnimation.new(@sprites,@viewport,side,secondAbility)
|
||||
loop do
|
||||
abilitySplashAnim.update
|
||||
pbUpdate
|
||||
break if abilitySplashAnim.animDone?
|
||||
end
|
||||
abilitySplashAnim.dispose
|
||||
end
|
||||
end
|
||||
|
||||
class PokeBattle_Battle
|
||||
|
||||
def pbShowSecondaryAbilitySplash(battler,delay=false,logTrigger=true)
|
||||
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
|
||||
@scene.pbShowAbilitySplash(battler,true)
|
||||
if delay
|
||||
Graphics.frame_rate.times { @scene.pbUpdate } # 1 second
|
||||
end
|
||||
end
|
||||
|
||||
def pbShowPrimaryAbilitySplash(battler,delay=false,logTrigger=true)
|
||||
return if !PokeBattle_SceneConstants::USE_ABILITY_SPLASH
|
||||
@scene.pbShowAbilitySplash(battler,false)
|
||||
if delay
|
||||
Graphics.frame_rate.times { @scene.pbUpdate } # 1 second
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
class FusionSelectOptionsScene < PokemonOption_Scene
|
||||
def pbGetOptions(inloadscreen = false)
|
||||
|
||||
options = []
|
||||
if shouldSelectNickname
|
||||
options << EnumOption.new(_INTL("Nickname"), [_INTL(@pokemon1.name), _INTL(@pokemon2.name)],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
if value ==0
|
||||
@nickname = @pokemon1.name
|
||||
else
|
||||
@nickname = @pokemon2.name
|
||||
end
|
||||
}, _INTL("Select the Pokémon's nickname"))
|
||||
end
|
||||
|
||||
if @abilityList != nil
|
||||
options << EnumOption.new(_INTL("Ability"), [_INTL(getAbilityName(@abilityList[0])), _INTL(getAbilityName(@abilityList[1]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@selectedAbility=@abilityList[value]
|
||||
}, [getAbilityDescription(@abilityList[0]), getAbilityDescription(@abilityList[1])]
|
||||
)
|
||||
end
|
||||
|
||||
options << EnumOption.new(_INTL("Nature"), [_INTL(getNatureName(@natureList[0])), _INTL(getNatureName(@natureList[1]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@selectedNature=@natureList[value]
|
||||
}, [getNatureDescription(@natureList[0]), getNatureDescription(@natureList[1])]
|
||||
)
|
||||
return options
|
||||
end
|
||||
end
|
||||
|
||||
222
Data/Scripts/052_InfiniteFusion/Fusion/DoublePreviewScreen.rb
Normal file
222
Data/Scripts/052_InfiniteFusion/Fusion/DoublePreviewScreen.rb
Normal file
@@ -0,0 +1,222 @@
|
||||
class DoublePreviewScreen
|
||||
SELECT_ARROW_X_LEFT= 100
|
||||
SELECT_ARROW_X_RIGHT= 350
|
||||
SELECT_ARROW_X_CANCEL= 230
|
||||
|
||||
SELECT_ARROW_Y_SELECT= 0
|
||||
SELECT_ARROW_Y_CANCEL= 210
|
||||
ARROW_GRAPHICS_PATH = "Graphics/Pictures/selHand"
|
||||
CANCEL_BUTTON_PATH = "Graphics/Pictures/previewScreen_Cancel"
|
||||
BACKGROUND_PATH = "Graphics/Pictures/shadeFull_"
|
||||
|
||||
|
||||
CANCEL_BUTTON_X= 140
|
||||
CANCEL_BUTTON_Y= 260
|
||||
|
||||
def initialize(species_left, species_right)
|
||||
@species_left = species_left
|
||||
@species_right = species_right
|
||||
|
||||
@typewindows = []
|
||||
@picture1 = nil
|
||||
@picture2 = nil
|
||||
@draw_types = nil
|
||||
@draw_level = nil
|
||||
@draw_sprite_info = nil
|
||||
@selected = 0
|
||||
@last_post=0
|
||||
@sprites = {}
|
||||
|
||||
initializeBackground
|
||||
initializeSelectArrow
|
||||
initializeCancelButton
|
||||
end
|
||||
|
||||
def getBackgroundPicture
|
||||
return BACKGROUND_PATH
|
||||
end
|
||||
|
||||
|
||||
def getSelection
|
||||
selected = startSelection
|
||||
@sprites["cancel"].visible=false
|
||||
#@sprites["arrow"].visible=false
|
||||
|
||||
#todo: il y a un fuck en quelque part.... en attendant ca marche inversé ici
|
||||
return @species_left if selected == 0
|
||||
return @species_right if selected == 1
|
||||
return -1
|
||||
end
|
||||
|
||||
def startSelection
|
||||
loop do
|
||||
Graphics.update
|
||||
Input.update
|
||||
updateSelection
|
||||
if Input.trigger?(Input::USE)
|
||||
return @selected
|
||||
end
|
||||
if Input.trigger?(Input::BACK)
|
||||
return -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def updateSelection
|
||||
currentSelected = @selected
|
||||
updateSelectionIndex
|
||||
if @selected != currentSelected
|
||||
updateSelectionGraphics
|
||||
end
|
||||
end
|
||||
|
||||
def updateSelectionIndex
|
||||
if Input.trigger?(Input::LEFT)
|
||||
@selected = 0
|
||||
elsif Input.trigger?(Input::RIGHT)
|
||||
@selected = 1
|
||||
end
|
||||
if @selected == -1
|
||||
if Input.trigger?(Input::UP)
|
||||
@selected = @last_post
|
||||
end
|
||||
else
|
||||
if Input.trigger?(Input::DOWN)
|
||||
@last_post = @selected
|
||||
@selected = -1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def updateSelectionGraphics
|
||||
if @selected == 0
|
||||
@sprites["arrow"].x = SELECT_ARROW_X_LEFT
|
||||
@sprites["arrow"].y = SELECT_ARROW_Y_SELECT
|
||||
elsif @selected == 1
|
||||
@sprites["arrow"].x = SELECT_ARROW_X_RIGHT
|
||||
@sprites["arrow"].y = SELECT_ARROW_Y_SELECT
|
||||
else
|
||||
@sprites["arrow"].x = SELECT_ARROW_X_CANCEL
|
||||
@sprites["arrow"].y = SELECT_ARROW_Y_CANCEL
|
||||
end
|
||||
pbUpdateSpriteHash(@sprites)
|
||||
end
|
||||
|
||||
def draw_window(dexNumber, level, x, y, isShiny=false, bodyShiny = false, headShiny=false)
|
||||
body_pokemon = getBodyID(dexNumber)
|
||||
head_pokemon = getHeadID(dexNumber, body_pokemon)
|
||||
|
||||
# picturePath = getPicturePath(head_pokemon, body_pokemon)
|
||||
# bitmap = AnimatedBitmap.new(picturePath)
|
||||
spriteLoader = BattleSpriteLoader.new
|
||||
|
||||
bitmap = GameData::Species.front_sprite_bitmap(dexNumber)
|
||||
bitmap.shiftAllColors(dexNumber, bodyShiny, headShiny)
|
||||
|
||||
bitmap.scale_bitmap(Settings::FRONTSPRITE_SCALE)
|
||||
pif_sprite = spriteLoader.obtain_fusion_pif_sprite(head_pokemon,body_pokemon)
|
||||
#hasCustom = picturePath.include?("CustomBattlers")
|
||||
#hasCustom = customSpriteExistsBase(body_pokemon,head_pokemon)
|
||||
hasCustom = customSpriteExists(body_pokemon,head_pokemon)
|
||||
previewwindow = PictureWindow.new(bitmap)
|
||||
previewwindow.x = x
|
||||
previewwindow.y = y
|
||||
previewwindow.z = 100000
|
||||
|
||||
drawFusionInformation(dexNumber, level, x)
|
||||
|
||||
if !$Trainer.seen?(dexNumber)
|
||||
if pif_sprite.local_path()
|
||||
previewwindow.picture.pbSetColor(170, 200, 250, 200) #blue
|
||||
elsif hasCustom
|
||||
previewwindow.picture.pbSetColor(150, 255, 150, 200) #green
|
||||
else
|
||||
previewwindow.picture.pbSetColor(255, 255, 255, 200) #white
|
||||
end
|
||||
end
|
||||
return previewwindow
|
||||
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
|
||||
drawFusionPreviewText(viewport, "Lv. " + level.to_s, x + 80, 40,) if @draw_level
|
||||
drawSpriteInfoIcons(getPokemon(fusedDexNum),viewport) if @draw_sprite_info
|
||||
end
|
||||
|
||||
|
||||
def initializeSelectArrow
|
||||
@sprites["arrow"] = IconSprite.new(0, 0, @viewport)
|
||||
@sprites["arrow"].setBitmap(ARROW_GRAPHICS_PATH)
|
||||
@sprites["arrow"].x = SELECT_ARROW_X_LEFT
|
||||
@sprites["arrow"].y = SELECT_ARROW_Y_SELECT
|
||||
@sprites["arrow"].z = 100001
|
||||
end
|
||||
|
||||
|
||||
def initializeCancelButton()
|
||||
@sprites["cancel"] = IconSprite.new(0, 0, @viewport)
|
||||
@sprites["cancel"].setBitmap(CANCEL_BUTTON_PATH)
|
||||
@sprites["cancel"].x = CANCEL_BUTTON_X
|
||||
@sprites["cancel"].y = CANCEL_BUTTON_Y
|
||||
@sprites["cancel"].z = 100000
|
||||
end
|
||||
|
||||
def initializeBackground()
|
||||
@sprites["background"] = IconSprite.new(0, 0, @viewport)
|
||||
@sprites["background"].setBitmap(getBackgroundPicture)
|
||||
@sprites["background"].x = 0
|
||||
@sprites["background"].y = 0
|
||||
@sprites["background"].z = 99999
|
||||
end
|
||||
|
||||
def drawFusionPreviewText(viewport, text, x, y)
|
||||
label_base_color = Color.new(248, 248, 248)
|
||||
label_shadow_color = Color.new(104, 104, 104)
|
||||
overlay = BitmapSprite.new(Graphics.width, Graphics.height, viewport).bitmap
|
||||
textpos = [[text, x, y, 0, label_base_color, label_shadow_color]]
|
||||
pbDrawTextPositions(overlay, textpos)
|
||||
end
|
||||
|
||||
#todo
|
||||
# Adds the icons indicating if the fusion has alt sprites and if the final evo has a custom sprite
|
||||
# also add a second icon to indidcate if the final evolution has a custom
|
||||
def drawSpriteInfoIcons(fusedPokemon, viewport)
|
||||
#pokedexUtils = PokedexUtils.new
|
||||
#hasAltSprites = pokedexUtils.pbGetAvailableAlts(fusedPokemon).size>1
|
||||
#pokedexUtils.getFinalEvolution(fusedPokemon).real_name
|
||||
#todo
|
||||
end
|
||||
|
||||
def dispose
|
||||
@picture1.dispose
|
||||
@picture2.dispose
|
||||
for typeWindow in @typewindows
|
||||
typeWindow.dispose
|
||||
end
|
||||
pbDisposeSpriteHash(@sprites)
|
||||
|
||||
end
|
||||
|
||||
def drawPokemonType(pokemon_id, viewport, x_pos = 192, y_pos = 264)
|
||||
width = 66
|
||||
viewport.z = 1000001
|
||||
overlay = BitmapSprite.new(Graphics.width, Graphics.height, viewport).bitmap
|
||||
|
||||
pokemon = GameData::Species.get(pokemon_id)
|
||||
typebitmap = AnimatedBitmap.new(_INTL("Graphics/Pictures/types"))
|
||||
type1_number = GameData::Type.get(pokemon.type1).id_number
|
||||
type2_number = GameData::Type.get(pokemon.type2).id_number
|
||||
type1rect = Rect.new(0, type1_number * 28, 64, 28)
|
||||
type2rect = Rect.new(0, type2_number * 28, 64, 28)
|
||||
if pokemon.type1 == pokemon.type2
|
||||
overlay.blt(x_pos + (width / 2), y_pos, typebitmap.bitmap, type1rect)
|
||||
else
|
||||
overlay.blt(x_pos, y_pos, typebitmap.bitmap, type1rect)
|
||||
overlay.blt(x_pos + width, y_pos, typebitmap.bitmap, type2rect)
|
||||
end
|
||||
return viewport
|
||||
end
|
||||
|
||||
end
|
||||
432
Data/Scripts/052_InfiniteFusion/Fusion/FusedSpecies.rb
Normal file
432
Data/Scripts/052_InfiniteFusion/Fusion/FusedSpecies.rb
Normal file
@@ -0,0 +1,432 @@
|
||||
module GameData
|
||||
class FusedSpecies < GameData::Species
|
||||
attr_reader :growth_rate
|
||||
attr_reader :body_pokemon
|
||||
attr_reader :head_pokemon
|
||||
|
||||
def initialize(id)
|
||||
if id.is_a?(Integer)
|
||||
body_id = getBodyID(id)
|
||||
head_id = getHeadID(id, body_id)
|
||||
pokemon_id = getFusedPokemonIdFromDexNum(body_id, head_id)
|
||||
return GameData::FusedSpecies.new(pokemon_id)
|
||||
end
|
||||
|
||||
|
||||
id = normalize_id(id)
|
||||
body_id = get_body_number_from_symbol(id)
|
||||
head_id = get_head_number_from_symbol(id)
|
||||
|
||||
@body_pokemon = GameData::Species.get(body_id)
|
||||
@head_pokemon = GameData::Species.get(head_id)
|
||||
|
||||
@id = id
|
||||
@id_number = calculate_dex_number()
|
||||
@species = @id
|
||||
@form = 0
|
||||
@real_name = calculate_name()
|
||||
@real_form_name = nil
|
||||
|
||||
@type1 = calculate_type1()
|
||||
@type2 = calculate_type2()
|
||||
|
||||
#Stats
|
||||
@base_stats = calculate_base_stats()
|
||||
@evs = calculate_evs()
|
||||
adjust_stats_with_evs()
|
||||
|
||||
@base_exp = calculate_base_exp()
|
||||
@growth_rate = calculate_growth_rate()
|
||||
@gender_ratio = calculate_gender() #todo
|
||||
@catch_rate = calculate_catch_rate()
|
||||
@happiness = calculate_base_happiness()
|
||||
|
||||
#Moves
|
||||
@moves = calculate_moveset()
|
||||
@tutor_moves = calculate_tutor_moves() # hash[:tutor_moves] || []
|
||||
@egg_moves = calculate_egg_moves() # hash[:egg_moves] || []
|
||||
|
||||
#Abilities
|
||||
@abilities = calculate_abilities() # hash[:abilities] || []
|
||||
@hidden_abilities = calculate_hidden_abilities() # hash[:hidden_abilities] || []
|
||||
|
||||
#wild held items
|
||||
@wild_item_common = get_wild_item(@head_pokemon.wild_item_common, @body_pokemon.wild_item_common) # hash[:wild_item_common]
|
||||
@wild_item_uncommon = get_wild_item(@head_pokemon.wild_item_uncommon, @body_pokemon.wild_item_uncommon) # hash[:wild_item_uncommon]
|
||||
@wild_item_rare = get_wild_item(@head_pokemon.wild_item_rare, @body_pokemon.wild_item_rare) # hash[:wild_item_rare]
|
||||
|
||||
@evolutions = calculate_evolutions() # hash[:evolutions] || []
|
||||
|
||||
#breeding
|
||||
@egg_groups = [:Undiscovered] #calculate_egg_groups() # hash[:egg_groups] || [:Undiscovered]
|
||||
@hatch_steps = calculate_hatch_steps() # hash[:hatch_steps] || 1
|
||||
@incense = nil #hash[:incense]
|
||||
|
||||
#pokedex
|
||||
@pokedex_form = @form #ignored
|
||||
@real_category = calculate_category()
|
||||
@real_pokedex_entry = calculate_dex_entry()
|
||||
@height = average_values(@head_pokemon.height, @body_pokemon.height)
|
||||
@weight = average_values(@head_pokemon.weight, @body_pokemon.weight)
|
||||
@color = @head_pokemon.color
|
||||
@shape = @body_pokemon.shape
|
||||
|
||||
#sprite positioning
|
||||
@back_sprite_x = @body_pokemon.back_sprite_x
|
||||
@back_sprite_y = @body_pokemon.back_sprite_y
|
||||
@front_sprite_x = @body_pokemon.front_sprite_x
|
||||
@front_sprite_y = @body_pokemon.front_sprite_y
|
||||
@front_sprite_altitude = @body_pokemon.front_sprite_altitude
|
||||
@shadow_x = @body_pokemon.shadow_x
|
||||
@shadow_size = @body_pokemon.shadow_size
|
||||
|
||||
# #unused attributes from Species class
|
||||
#
|
||||
# @shape = :Head
|
||||
# @habitat = :None
|
||||
# @generation = 0
|
||||
# @mega_stone = nil
|
||||
# @mega_move = nil
|
||||
# @unmega_form = 0
|
||||
# @mega_message = 0
|
||||
end
|
||||
|
||||
#Input formats:
|
||||
# :1_x_2
|
||||
# :BULBASAUR_x_IVYSAUR
|
||||
# :B2H1
|
||||
#
|
||||
# Output: :B2H1
|
||||
def normalize_id(id)
|
||||
if id.to_s.include?("/")
|
||||
full_id_split = id.to_s.split("/")
|
||||
# Detect if both sides are numeric
|
||||
if full_id_split[0] =~ /^\d+$/ && full_id_split[1] =~ /^\d+$/
|
||||
head_dex = full_id_split[0].to_i
|
||||
body_dex = full_id_split[1].to_i
|
||||
else
|
||||
head_species = full_id_split[0].to_sym
|
||||
body_species = full_id_split[1].to_sym
|
||||
|
||||
head_dex = getDexNumberForSpecies(head_species)
|
||||
body_dex = getDexNumberForSpecies(body_species)
|
||||
end
|
||||
return "B#{body_dex}H#{head_dex}".to_sym
|
||||
else #Passed internal ID directly, just return it
|
||||
return id
|
||||
end
|
||||
end
|
||||
|
||||
def get_body_number_from_symbol(id)
|
||||
return id.to_s.match(/\d+/)[0].to_i
|
||||
end
|
||||
|
||||
def get_head_number_from_symbol(id)
|
||||
return id.to_s.match(/(?<=H)\d+/)[0].to_i
|
||||
end
|
||||
|
||||
def get_body_species
|
||||
return @body_pokemon.id_number
|
||||
end
|
||||
|
||||
def get_head_species
|
||||
return @head_pokemon.id_number
|
||||
end
|
||||
|
||||
def get_body_species_symbol
|
||||
return @body_pokemon.id
|
||||
end
|
||||
|
||||
def get_head_species_symbol
|
||||
return @head_pokemon.id
|
||||
end
|
||||
|
||||
def adjust_stats_with_evs
|
||||
GameData::Stat.each_main do |s|
|
||||
@base_stats[s.id] = 1 if !@base_stats[s.id] || @base_stats[s.id] <= 0
|
||||
@evs[s.id] = 0 if !@evs[s.id] || @evs[s.id] < 0
|
||||
end
|
||||
end
|
||||
|
||||
#FUSION CALCULATIONS
|
||||
def calculate_dex_number()
|
||||
return (@body_pokemon.id_number * NB_POKEMON) + @head_pokemon.id_number
|
||||
end
|
||||
|
||||
def calculate_type1()
|
||||
return @head_pokemon.type2 if @head_pokemon.type1 == :NORMAL && @head_pokemon.type2 == :FLYING
|
||||
return @head_pokemon.type1
|
||||
end
|
||||
|
||||
def calculate_type2()
|
||||
return @body_pokemon.type1 if @body_pokemon.type2 == @type1
|
||||
return @body_pokemon.type2
|
||||
end
|
||||
|
||||
def calculate_base_stats()
|
||||
head_stats = @head_pokemon.base_stats
|
||||
body_stats = @body_pokemon.base_stats
|
||||
|
||||
fused_stats = {}
|
||||
|
||||
#Head dominant stats
|
||||
fused_stats[:HP] = calculate_fused_stats(head_stats[:HP], body_stats[:HP])
|
||||
fused_stats[:SPECIAL_DEFENSE] = calculate_fused_stats(head_stats[:SPECIAL_DEFENSE], body_stats[:SPECIAL_DEFENSE])
|
||||
fused_stats[:SPECIAL_ATTACK] = calculate_fused_stats(head_stats[:SPECIAL_ATTACK], body_stats[:SPECIAL_ATTACK])
|
||||
|
||||
#Body dominant stats
|
||||
fused_stats[:ATTACK] = calculate_fused_stats(body_stats[:ATTACK], head_stats[:ATTACK])
|
||||
fused_stats[:DEFENSE] = calculate_fused_stats(body_stats[:DEFENSE], head_stats[:DEFENSE])
|
||||
fused_stats[:SPEED] = calculate_fused_stats(body_stats[:SPEED], head_stats[:SPEED])
|
||||
|
||||
return fused_stats
|
||||
end
|
||||
|
||||
def calculate_base_exp()
|
||||
head_exp = @head_pokemon.base_exp
|
||||
body_exp = @body_pokemon.base_exp
|
||||
return average_values(head_exp, body_exp)
|
||||
end
|
||||
|
||||
def calculate_catch_rate
|
||||
return get_lowest_value(@body_pokemon.catch_rate, @head_pokemon.catch_rate)
|
||||
end
|
||||
|
||||
def calculate_base_happiness
|
||||
return @head_pokemon.happiness
|
||||
end
|
||||
|
||||
def calculate_moveset
|
||||
return combine_arrays(@body_pokemon.moves, @head_pokemon.moves)
|
||||
end
|
||||
|
||||
def calculate_egg_moves
|
||||
return combine_arrays(@body_pokemon.egg_moves, @head_pokemon.egg_moves)
|
||||
end
|
||||
|
||||
def calculate_tutor_moves
|
||||
return combine_arrays(@body_pokemon.tutor_moves, @head_pokemon.tutor_moves)
|
||||
end
|
||||
|
||||
def get_wild_item(body_item, head_item)
|
||||
rand_num = rand(2)
|
||||
if rand_num == 0
|
||||
return body_item
|
||||
else
|
||||
return head_item
|
||||
end
|
||||
end
|
||||
|
||||
def calculate_abilities()
|
||||
abilities_hash = []
|
||||
|
||||
ability1 = @body_pokemon.abilities[0]
|
||||
ability2 = @head_pokemon.abilities[0]
|
||||
abilities_hash << ability1
|
||||
abilities_hash << ability2
|
||||
return abilities_hash
|
||||
end
|
||||
|
||||
# def calculate_abilities(pokemon1, pokemon2)
|
||||
# abilities_hash = []
|
||||
#
|
||||
# ability1 = pokemon1.abilities[0]
|
||||
# ability2 = pokemon2.abilities[1]
|
||||
# if !ability2
|
||||
# ability2 = pokemon2.abilities[0]
|
||||
# end
|
||||
# abilities_hash << ability1
|
||||
# abilities_hash << ability2
|
||||
# return abilities_hash
|
||||
# end
|
||||
|
||||
def calculate_hidden_abilities()
|
||||
abilities_hash = []
|
||||
|
||||
#First two spots are the other abilities of the two pokemon
|
||||
ability1 = @body_pokemon.abilities[1]
|
||||
ability2 = @head_pokemon.abilities[1]
|
||||
ability1 = @body_pokemon.abilities[0] if !ability1
|
||||
ability2 = @head_pokemon.abilities[0] if !ability2
|
||||
|
||||
abilities_hash << ability1
|
||||
abilities_hash << ability2
|
||||
|
||||
#add the hidden ability for the two base pokemon
|
||||
hiddenAbility1 = @body_pokemon.hidden_abilities[0]
|
||||
hiddenAbility1 = ability1 if !hiddenAbility1
|
||||
|
||||
hiddenAbility2 = @head_pokemon.hidden_abilities[0]
|
||||
hiddenAbility2 = ability2 if !hiddenAbility2
|
||||
|
||||
abilities_hash << hiddenAbility1
|
||||
abilities_hash << hiddenAbility2
|
||||
return abilities_hash
|
||||
end
|
||||
|
||||
def calculate_name()
|
||||
body_nat_dex = GameData::NAT_DEX_MAPPING[@body_pokemon.id_number] ? GameData::NAT_DEX_MAPPING[@body_pokemon.id_number] : @body_pokemon.id_number
|
||||
head_nat_dex = GameData::NAT_DEX_MAPPING[@head_pokemon.id_number] ? GameData::NAT_DEX_MAPPING[@head_pokemon.id_number] : @head_pokemon.id_number
|
||||
begin
|
||||
prefix = GameData::SPLIT_NAMES[head_nat_dex][0]
|
||||
suffix = GameData::SPLIT_NAMES[body_nat_dex][1]
|
||||
if prefix[-1] == suffix[0]
|
||||
prefix = prefix[0..-2]
|
||||
end
|
||||
suffix = suffix.capitalize if prefix.end_with?(" ")
|
||||
return prefix + suffix
|
||||
|
||||
rescue
|
||||
print("species with error: " + @species.to_s)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def calculate_evolutions()
|
||||
body_evolutions = @body_pokemon.evolutions
|
||||
head_evolutions = @head_pokemon.evolutions
|
||||
|
||||
fused_evolutions = []
|
||||
|
||||
#body
|
||||
for evolution in body_evolutions
|
||||
evolutionSpecies = evolution[0]
|
||||
evolutionSpecies_dex = GameData::Species.get(evolutionSpecies).id_number
|
||||
fused_species = _INTL("B{1}H{2}", evolutionSpecies_dex, @head_pokemon.id_number)
|
||||
fused_evolutions << build_evolution_array(evolution, fused_species)
|
||||
end
|
||||
|
||||
#head
|
||||
for evolution in head_evolutions
|
||||
evolutionSpecies = evolution[0]
|
||||
evolutionSpecies_dex = GameData::Species.get(evolutionSpecies).id_number
|
||||
fused_species = _INTL("B{1}H{2}", @body_pokemon.id_number, evolutionSpecies_dex)
|
||||
fused_evolutions << build_evolution_array(evolution, fused_species)
|
||||
end
|
||||
|
||||
return fused_evolutions
|
||||
end
|
||||
|
||||
#Change the evolution species depending if head & body and keep the rest of the data the same
|
||||
def build_evolution_array(evolution_data, new_species)
|
||||
fused_evolution_array = []
|
||||
fused_evolution_array << new_species.to_sym
|
||||
|
||||
#add the rest
|
||||
for data in evolution_data
|
||||
next if evolution_data.index(data) == 0
|
||||
fused_evolution_array << data
|
||||
end
|
||||
return fused_evolution_array
|
||||
end
|
||||
|
||||
def calculate_dex_entry
|
||||
body_entry = @body_pokemon.real_pokedex_entry.gsub(@body_pokemon.real_name, @real_name)
|
||||
head_entry = @head_pokemon.real_pokedex_entry.gsub(@head_pokemon.real_name, @real_name)
|
||||
|
||||
return split_and_combine_text(body_entry, head_entry, ".")
|
||||
end
|
||||
|
||||
def get_random_dex_entry()
|
||||
begin
|
||||
file_path = Settings::POKEDEX_ENTRIES_PATH
|
||||
json_data = File.read(file_path)
|
||||
all_body_entries = HTTPLite::JSON.parse(json_data)
|
||||
|
||||
|
||||
body_entry = all_body_entries[@body_pokemon.id_number.to_s].sample
|
||||
body_entry = body_entry.gsub(/#{@body_pokemon.real_name}/i, @real_name)
|
||||
body_entry = clean_json_string(body_entry).gsub(@body_pokemon.real_name, @real_name)
|
||||
|
||||
head_entry = all_body_entries[@head_pokemon.id_number.to_s].sample
|
||||
head_entry = head_entry.gsub(/#{@head_pokemon.real_name}/i, @real_name)
|
||||
head_entry = clean_json_string(head_entry).gsub(@head_pokemon.real_name, @real_name)
|
||||
rescue
|
||||
body_entry = @body_pokemon.real_pokedex_entry.gsub(@body_pokemon.real_name, @real_name)
|
||||
head_entry = @head_pokemon.real_pokedex_entry.gsub(@head_pokemon.real_name, @real_name)
|
||||
end
|
||||
echoln body_entry
|
||||
echoln head_entry
|
||||
combined_entry = split_and_combine_text(body_entry, head_entry, ".")
|
||||
combined_entry += "." unless combined_entry.end_with?(".")
|
||||
return combined_entry
|
||||
end
|
||||
|
||||
def calculate_egg_groups
|
||||
body_egg_groups = @body_pokemon.egg_groups
|
||||
head_egg_groups = @head_pokemon.egg_groups
|
||||
return :Undiscovered if body_egg_groups.include?(:Undiscovered) || head_egg_groups.include?(:Undiscovered)
|
||||
return combine_arrays(body_egg_groups, head_egg_groups)
|
||||
end
|
||||
|
||||
def calculate_hatch_steps
|
||||
return average_values(@head_pokemon.hatch_steps, @body_pokemon.hatch_steps)
|
||||
end
|
||||
|
||||
def calculate_evs()
|
||||
return average_map_values(@body_pokemon.evs, @head_pokemon.evs)
|
||||
end
|
||||
|
||||
def calculate_category
|
||||
return split_and_combine_text(@body_pokemon.category, @head_pokemon.category, " ")
|
||||
end
|
||||
|
||||
def calculate_growth_rate
|
||||
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]
|
||||
for rate in growth_rate_priority
|
||||
return rate if base_growth_rates.include?(rate)
|
||||
end
|
||||
return :Medium
|
||||
end
|
||||
|
||||
#TODO
|
||||
# ################## UNFINISHED ####################
|
||||
def calculate_gender
|
||||
return :Genderless
|
||||
end
|
||||
|
||||
############################# UTIL METHODS ###############################
|
||||
|
||||
#Takes 2 strings, splits and combines them using the beginning of the first one and the end of the second one
|
||||
# (for example for pokedex entries)
|
||||
def split_and_combine_text(beginingText_full, endText_full, separator)
|
||||
beginingText_split = beginingText_full.split(separator, 2)
|
||||
endText_split = endText_full.split(separator, 2)
|
||||
|
||||
beginningText = beginingText_split[0]
|
||||
endText = endText_split[1] && endText_split[1] != "" ? endText_split[1] : endText_split[0]
|
||||
return beginningText + separator + " " + endText
|
||||
end
|
||||
|
||||
def calculate_fused_stats(dominantStat, otherStat)
|
||||
return ((2 * dominantStat) / 3) + (otherStat / 3).floor
|
||||
end
|
||||
|
||||
def average_values(value1, value2)
|
||||
return ((value1 + value2) / 2).floor
|
||||
end
|
||||
|
||||
def average_map_values(map1, map2)
|
||||
averaged_map = map1.merge(map2) do |key, value1, value2|
|
||||
((value1 + value2) / 2.0).floor
|
||||
end
|
||||
return averaged_map
|
||||
end
|
||||
|
||||
def get_highest_value(value1, value2)
|
||||
return value1 > value2 ? value1 : value2
|
||||
end
|
||||
|
||||
def get_lowest_value(value1, value2)
|
||||
return value1 < value2 ? value1 : value2
|
||||
end
|
||||
|
||||
def combine_arrays(array1, array2)
|
||||
return array1 + array2
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
38
Data/Scripts/052_InfiniteFusion/Fusion/FusionAnim.rb
Normal file
38
Data/Scripts/052_InfiniteFusion/Fusion/FusionAnim.rb
Normal file
@@ -0,0 +1,38 @@
|
||||
# class PokemonFusionScene
|
||||
# HEAD_SPRITE_STARTING_POS = Graphics.width / 2
|
||||
#
|
||||
#
|
||||
# def pbStartScreen(pokemon_head,pokemon_body,pokemon_fused)
|
||||
#
|
||||
# @pokemon_head = pokemon_head
|
||||
# @pokemon_body = pokemon_body
|
||||
#
|
||||
# @pokemon_fused = pokemon_fused
|
||||
#
|
||||
# @sprites = {}
|
||||
# @viewport = Viewport.new(0, 0, Graphics.width, Graphics.height)
|
||||
# @viewport.z = 99999
|
||||
#
|
||||
# initialize_background()
|
||||
# initialize_sprites()
|
||||
# end
|
||||
#
|
||||
# def initialize_background()
|
||||
# addBackgroundOrColoredPlane(@sprites, "background", "DNAbg",
|
||||
# Color.new(248, 248, 248), @viewport)
|
||||
# end
|
||||
#
|
||||
# def initialize_sprites()
|
||||
# pokeHead_number = GameData::Species.get(@pokemon_head.species).id_number
|
||||
# pokeBody_number = GameData::Species.get(@pokemon_body.species).id_number
|
||||
#
|
||||
# @sprites["poke_head"] = PokemonSprite.new(@viewport)
|
||||
# @sprites["poke_head"].setPokemonBitmapFromId(pokeHead_number, false, @pokemon_head.shiny?)
|
||||
#
|
||||
# @sprites["poke_head"].ox = @sprites["rsprite1"].bitmap.width / 2
|
||||
# @sprites["poke_head"].x = Graphics.width / 2
|
||||
# @sprites["poke_head"].zoom_x = Settings::FRONTSPRITE_SCALE
|
||||
#
|
||||
# end
|
||||
#
|
||||
# end
|
||||
115
Data/Scripts/052_InfiniteFusion/Fusion/FusionMenu.rb
Normal file
115
Data/Scripts/052_InfiniteFusion/Fusion/FusionMenu.rb
Normal file
@@ -0,0 +1,115 @@
|
||||
class FusionSelectOptionsScene < PokemonOption_Scene
|
||||
attr_accessor :selectedAbility
|
||||
attr_accessor :selectedNature
|
||||
attr_accessor :hasNickname
|
||||
attr_accessor :nickname
|
||||
|
||||
|
||||
def initialize(abilityList,natureList, pokemon1, pokemon2)
|
||||
@abilityList = abilityList
|
||||
@natureList = natureList
|
||||
@selectedAbility=nil
|
||||
@selectedNature=nil
|
||||
@selBaseColor = Color.new(48,96,216)
|
||||
@selShadowColor = Color.new(32,32,32)
|
||||
@show_frame=false
|
||||
@hasNickname = false
|
||||
@nickname = nil
|
||||
|
||||
@pokemon1=pokemon1
|
||||
@pokemon2=pokemon2
|
||||
end
|
||||
|
||||
|
||||
def initUIElements
|
||||
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
|
||||
_INTL("Select your Pokémon's ability and nature"), 0, 0, Graphics.width, 64, @viewport)
|
||||
@sprites["textbox"] = pbCreateMessageWindow
|
||||
@sprites["textbox"].letterbyletter = false
|
||||
pbSetSystemFont(@sprites["textbox"].contents)
|
||||
@sprites["title"].opacity=0
|
||||
end
|
||||
|
||||
def pbStartScene(inloadscreen = nil)
|
||||
super
|
||||
@sprites["option"].opacity=0
|
||||
end
|
||||
|
||||
|
||||
def getAbilityName(ability)
|
||||
return GameData::Ability.get(ability.id).real_name
|
||||
end
|
||||
|
||||
def getAbilityDescription(ability)
|
||||
return GameData::Ability.get(ability.id).real_description
|
||||
end
|
||||
|
||||
def getNatureName(nature)
|
||||
return GameData::Nature.get(nature.id).real_name
|
||||
end
|
||||
|
||||
def getNatureDescription(nature)
|
||||
change= GameData::Nature.get(nature.id).stat_changes
|
||||
return _INTL("Neutral nature") if change.empty?
|
||||
positiveChange = change[0]
|
||||
negativeChange = change[1]
|
||||
return _INTL("+ {1}\n- {2}",GameData::Stat.get(positiveChange[0]).name,GameData::Stat.get(negativeChange[0]).name)
|
||||
end
|
||||
|
||||
def shouldSelectNickname
|
||||
if @pokemon1.nicknamed? && @pokemon2.nicknamed?
|
||||
@hasNickname=true
|
||||
return true
|
||||
end
|
||||
if @pokemon1.nicknamed? && !@pokemon2.nicknamed?
|
||||
@hasNickname=true
|
||||
@nickname = @pokemon1.name
|
||||
return false
|
||||
end
|
||||
if !@pokemon1.nicknamed? && @pokemon2.nicknamed?
|
||||
@hasNickname=true
|
||||
@nickname = @pokemon2.name
|
||||
return false
|
||||
end
|
||||
@hasNickname=false
|
||||
return false
|
||||
end
|
||||
|
||||
def pbGetOptions(inloadscreen = false)
|
||||
|
||||
options = []
|
||||
if shouldSelectNickname
|
||||
options << EnumOption.new(_INTL("Nickname"), [_INTL(@pokemon1.name), _INTL(@pokemon2.name)],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
if value ==0
|
||||
@nickname = @pokemon1.name
|
||||
else
|
||||
@nickname = @pokemon2.name
|
||||
end
|
||||
}, _INTL("Select the Pokémon's nickname"))
|
||||
end
|
||||
|
||||
options << EnumOption.new(_INTL("Ability"), [_INTL(getAbilityName(@abilityList[0])), _INTL(getAbilityName(@abilityList[1]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@selectedAbility=@abilityList[value]
|
||||
}, [getAbilityDescription(@abilityList[0]), getAbilityDescription(@abilityList[1])]
|
||||
)
|
||||
|
||||
options << EnumOption.new(_INTL("Nature"), [_INTL(getNatureName(@natureList[0])), _INTL(getNatureName(@natureList[1]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@selectedNature=@natureList[value]
|
||||
}, [getNatureDescription(@natureList[0]), getNatureDescription(@natureList[1])]
|
||||
)
|
||||
return options
|
||||
end
|
||||
|
||||
|
||||
def isConfirmedOnKeyPress
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
240
Data/Scripts/052_InfiniteFusion/Fusion/FusionMovesMenu.rb
Normal file
240
Data/Scripts/052_InfiniteFusion/Fusion/FusionMovesMenu.rb
Normal file
@@ -0,0 +1,240 @@
|
||||
class FusionMovesOptionsScene < PokemonOption_Scene
|
||||
attr_accessor :move1
|
||||
attr_accessor :move2
|
||||
attr_accessor :move3
|
||||
attr_accessor :move4
|
||||
|
||||
def initialize(poke1, poke2)
|
||||
@poke1 = poke1
|
||||
@poke2 = poke2
|
||||
|
||||
@move1 = @poke1.moves[0]
|
||||
@move2 = @poke1.moves[1]
|
||||
@move3 = @poke1.moves[2]
|
||||
@move4 = @poke1.moves[3]
|
||||
|
||||
|
||||
@index1=0
|
||||
@index2=0
|
||||
@index3=0
|
||||
@index4=0
|
||||
|
||||
|
||||
@selBaseColor = Color.new(48,96,216)
|
||||
@selShadowColor = Color.new(32,32,32)
|
||||
end
|
||||
|
||||
def initUIElements
|
||||
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
|
||||
_INTL(""), 0, 0, Graphics.width, 64, @viewport)
|
||||
@sprites["textbox"] = pbCreateMessageWindow
|
||||
@sprites["textbox"].letterbyletter = false
|
||||
pbSetSystemFont(@sprites["textbox"].contents)
|
||||
end
|
||||
|
||||
|
||||
|
||||
def pbStartScene(inloadscreen = false)
|
||||
super
|
||||
@typebitmap = AnimatedBitmap.new(_INTL("Graphics/Pictures/types"))
|
||||
@sprites["overlay"] = BitmapSprite.new(Graphics.width, Graphics.height, @viewport)
|
||||
@sprites["overlay"].z = 9999
|
||||
pbSetSystemFont(@sprites["overlay"].bitmap)
|
||||
|
||||
@sprites["option"].nameBaseColor = MessageConfig::BLUE_TEXT_MAIN_COLOR
|
||||
@sprites["option"].nameShadowColor = MessageConfig::BLUE_TEXT_SHADOW_COLOR
|
||||
@changedColor = true
|
||||
for i in 0...@PokemonOptions.length
|
||||
@sprites["option"][i] = (@PokemonOptions[i].get || 0)
|
||||
end
|
||||
@sprites["title"] = Window_UnformattedTextPokemon.newWithSize(
|
||||
_INTL("Select moves"), 0, 0, Graphics.width, 64, @viewport)
|
||||
@sprites["title"].setSkin("Graphics/Windowskins/invisible")
|
||||
@sprites["option"].setSkin("Graphics/Windowskins/invisible")
|
||||
@sprites["textbox"].setSkin("Graphics/Windowskins/invisible")
|
||||
# @sprites["textbox"].text = "Select moves"
|
||||
updateDescription(0)
|
||||
pbFadeInAndShow(@sprites) { pbUpdate }
|
||||
end
|
||||
|
||||
def draw_empty_move_info
|
||||
# code here
|
||||
end
|
||||
|
||||
def draw_move_info(pokemonMove)
|
||||
move = GameData::Move.get(pokemonMove.id)
|
||||
move_base_color = Color.new(50, 40, 230)
|
||||
move_base_shadow = Color.new(14, 14, 114)
|
||||
|
||||
label_base_color = Color.new(248, 248, 248)
|
||||
label_shadow_color = Color.new(104, 104, 104)
|
||||
|
||||
value_base_color = Color.new(248, 248, 248)
|
||||
value_shadow_color = Color.new(104, 104, 104)
|
||||
|
||||
@sprites["title"].text = _INTL("{1}", move.real_name)
|
||||
|
||||
damage = move.base_damage == 0 ? "-" : move.base_damage.to_s
|
||||
accuracy = move.accuracy == 0 ? "100" : move.accuracy.to_s
|
||||
pp = move.total_pp.to_s
|
||||
if !move
|
||||
damage="-"
|
||||
accuracy="-"
|
||||
pp="-"
|
||||
end
|
||||
|
||||
textpos = [
|
||||
[_INTL("Type"), 20, 84, 0, label_base_color, label_shadow_color],
|
||||
[_INTL("Category"), 20, 116, 0, label_base_color, label_shadow_color],
|
||||
|
||||
[_INTL("Power"), 20, 148, 0, label_base_color, label_shadow_color],
|
||||
[_INTL("{1}", damage), 140, 148, 0, value_base_color, value_shadow_color],
|
||||
|
||||
[_INTL("Accuracy"), 20, 180, 0, label_base_color, label_shadow_color],
|
||||
[_INTL("{1}%", accuracy), 140, 180, 0, value_base_color, value_shadow_color],
|
||||
|
||||
[_INTL("PP"), 20, 212, 0, label_base_color, label_shadow_color], #move.total_pp
|
||||
[_INTL("{1}", pp), 140, 212, 0, value_base_color, value_shadow_color] #move.total_pp
|
||||
|
||||
]
|
||||
imagepos = []
|
||||
|
||||
yPos = 90
|
||||
type_number = GameData::Type.get(move.type).id_number
|
||||
category = move.category
|
||||
imagepos.push(["Graphics/Pictures/types", 120, 94, 0, type_number * 28, 64, 28]) #248
|
||||
imagepos.push(["Graphics/Pictures/category", 120, 124, 0, category * 28, 64, 28])
|
||||
if !move
|
||||
imagepos=[]
|
||||
end
|
||||
@sprites["overlay"].bitmap.clear
|
||||
pbDrawTextPositions(@sprites["overlay"].bitmap, textpos)
|
||||
pbDrawImagePositions(@sprites["overlay"].bitmap, imagepos)
|
||||
|
||||
end
|
||||
|
||||
def draw_pokemon_type
|
||||
type1_number = GameData::Type.get(@poke1.type1).id_number
|
||||
type2_number = GameData::Type.get(@poke1.type2).id_number
|
||||
type1rect = Rect.new(0, type1_number * 28, 64, 28)
|
||||
type2rect = Rect.new(0, type2_number * 28, 64, 28)
|
||||
if @poke1.type1 == @poke1.type2
|
||||
overlay.blt(130, 78, @typebitmap.bitmap, type1rect)
|
||||
else
|
||||
overlay.blt(96, 78, @typebitmap.bitmap, type1rect)
|
||||
overlay.blt(166, 78, @typebitmap.bitmap, type2rect)
|
||||
end
|
||||
end
|
||||
|
||||
def updateDescription(index)
|
||||
index = 0 if !index
|
||||
begin
|
||||
move = getMoveForIndex(index)
|
||||
draw_move_info(move)
|
||||
new_description = getMoveDescription(move)
|
||||
@sprites["textbox"].text = _INTL(new_description)
|
||||
rescue
|
||||
@sprites["textbox"].text = getDefaultDescription
|
||||
end
|
||||
end
|
||||
|
||||
def getDefaultDescription
|
||||
return _INTL("No move selected")
|
||||
end
|
||||
|
||||
def getMoveForIndex(index)
|
||||
case index
|
||||
when 0
|
||||
return @move1
|
||||
when 1
|
||||
return @move2
|
||||
when 2
|
||||
return @move3
|
||||
when 3
|
||||
return @move4
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def pbFadeInAndShow(sprites, visiblesprites = nil)
|
||||
return if !@changedColor
|
||||
super
|
||||
end
|
||||
|
||||
def getMoveName(move)
|
||||
return " - " if !@sprites["option"] && !move
|
||||
move = @poke1.moves[@sprites["option"].index] if !move
|
||||
return GameData::Move.get(move.id).real_name
|
||||
end
|
||||
|
||||
def getMoveDescription(move)
|
||||
return " - " if !@sprites["option"] && !move
|
||||
move = @poke1.moves[@sprites["option"].index] if !move
|
||||
return GameData::Move.get(move.id).real_description
|
||||
end
|
||||
|
||||
def pbGetOptions(inloadscreen = false)
|
||||
options = [
|
||||
EnumOption.new(_INTL(""), [_INTL(getMoveName(@poke1.moves[0])), _INTL(getMoveName(@poke2.moves[0]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@move1 = value == 0 ? @poke1.moves[0] : @poke2.moves[0]
|
||||
}, [getMoveDescription(@poke1.moves[0]), getMoveDescription(@poke2.moves[0])]
|
||||
),
|
||||
EnumOption.new(_INTL(""), [_INTL(getMoveName(@poke1.moves[1])), _INTL(getMoveName(@poke2.moves[1]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@move2 = value == 0 ? @poke1.moves[1] : @poke2.moves[1]
|
||||
}, [getMoveDescription(@poke1.moves[1]), getMoveDescription(@poke2.moves[1])]
|
||||
),
|
||||
EnumOption.new(_INTL(""), [_INTL(getMoveName(@poke1.moves[2])), _INTL(getMoveName(@poke2.moves[2]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@move3 = value == 0 ? @poke1.moves[2] : @poke2.moves[2]
|
||||
}, [getMoveDescription(@poke1.moves[2]), getMoveDescription(@poke2.moves[2])]
|
||||
),
|
||||
EnumOption.new(_INTL(""), [_INTL(getMoveName(@poke1.moves[3])), _INTL(getMoveName(@poke2.moves[3]))],
|
||||
proc { 0 },
|
||||
proc { |value|
|
||||
@move4 = value == 0 ? @poke1.moves[3] : @poke2.moves[3]
|
||||
}, [getMoveDescription(@poke1.moves[3]), getMoveDescription(@poke2.moves[3])]
|
||||
)
|
||||
]
|
||||
return options
|
||||
end
|
||||
|
||||
def isConfirmedOnKeyPress
|
||||
return true
|
||||
end
|
||||
|
||||
def initOptionsWindow
|
||||
optionsWindow = Window_PokemonOptionFusionMoves.new(@PokemonOptions, 0,
|
||||
@sprites["title"].height, Graphics.width,
|
||||
Graphics.height - @sprites["title"].height - @sprites["textbox"].height)
|
||||
optionsWindow.viewport = @viewport
|
||||
optionsWindow.visible = true
|
||||
return optionsWindow
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
class Window_PokemonOptionFusionMoves < Window_PokemonOption
|
||||
def initialize(options, x, y, width, height)
|
||||
super
|
||||
@mustUpdateOptions=true
|
||||
@mustUpdateDescription=true
|
||||
@confirmed=false
|
||||
end
|
||||
|
||||
def drawCursor(index,rect)
|
||||
if self.index==index
|
||||
pbCopyBitmap(self.contents, @selarrow.bitmap,rect.x+175,rect.y)
|
||||
end
|
||||
return Rect.new(rect.x+16,rect.y,rect.width-16,rect.height)
|
||||
end
|
||||
|
||||
def dont_draw_item(index)
|
||||
return index == @options.length
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,50 @@
|
||||
class FusionPreviewScreen < DoublePreviewScreen
|
||||
attr_reader :poke1
|
||||
attr_reader :poke2
|
||||
attr_reader :fusedPokemon
|
||||
attr_reader :fusedPokemon
|
||||
|
||||
attr_writer :draw_types
|
||||
attr_writer :draw_level
|
||||
|
||||
BACKGROUND_PATH = "Graphics/Pictures/DNAbg"
|
||||
|
||||
|
||||
def initialize(poke1,poke2, usingSuperSplicers=false)
|
||||
super(poke1,poke2)
|
||||
@draw_types = true
|
||||
@draw_level = true
|
||||
@draw_sprite_info=true
|
||||
|
||||
#@viewport = viewport
|
||||
@poke1 = poke1
|
||||
@poke2 = poke2
|
||||
@fusedPokemon=nil
|
||||
|
||||
if poke1.isShiny?
|
||||
shiny = true
|
||||
poke1_shiny = true
|
||||
end
|
||||
|
||||
if poke2.isShiny?
|
||||
shiny = true
|
||||
poke2_shiny = true
|
||||
end
|
||||
|
||||
new_level = calculateFusedPokemonLevel(poke1.level, poke2.level, usingSuperSplicers)
|
||||
|
||||
fusion_left = (poke1.species_data.id_number) * NB_POKEMON + poke2.species_data.id_number
|
||||
fusion_right = (poke2.species_data.id_number) * NB_POKEMON + poke1.species_data.id_number
|
||||
|
||||
@picture1 = draw_window(fusion_left,new_level,20,30,shiny,poke1_shiny,poke2_shiny)
|
||||
@picture2 = draw_window(fusion_right,new_level,270,30,shiny,poke2_shiny,poke1_shiny)
|
||||
|
||||
@sprites["picture1"] = @picture1
|
||||
@sprites["picture2"] = @picture2
|
||||
|
||||
end
|
||||
|
||||
def getBackgroundPicture
|
||||
super
|
||||
end
|
||||
end
|
||||
412
Data/Scripts/052_InfiniteFusion/Fusion/FusionSprites.rb
Normal file
412
Data/Scripts/052_InfiniteFusion/Fusion/FusionSprites.rb
Normal file
@@ -0,0 +1,412 @@
|
||||
module GameData
|
||||
class Species
|
||||
def self.sprite_bitmap_from_pokemon(pkmn, back = false, species = nil)
|
||||
species = pkmn.species if !species
|
||||
species = GameData::Species.get(species).id_number # Just to be sure it's a number
|
||||
return self.egg_sprite_bitmap(species, pkmn.form) if pkmn.egg?
|
||||
if back
|
||||
ret = self.back_sprite_bitmap(species, pkmn.shiny?, pkmn.bodyShiny?, pkmn.headShiny?)
|
||||
else
|
||||
ret = self.front_sprite_bitmap(species, pkmn.shiny?, pkmn.bodyShiny?, pkmn.headShiny?)
|
||||
end
|
||||
ret.scale_bitmap(pkmn.sprite_scale) if ret #for pokemon with size differences
|
||||
return ret
|
||||
end
|
||||
|
||||
|
||||
|
||||
def self.sprite_bitmap_from_pokemon_id(id, back = false, shiny = false, bodyShiny = false, headShiny = false)
|
||||
if back
|
||||
ret = self.back_sprite_bitmap(id, shiny, bodyShiny, headShiny)
|
||||
else
|
||||
ret = self.front_sprite_bitmap(id, shiny, bodyShiny, headShiny)
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
MAX_SHIFT_VALUE = 360
|
||||
MINIMUM_OFFSET = 40
|
||||
ADDITIONAL_OFFSET_WHEN_TOO_CLOSE = 40
|
||||
MINIMUM_DEX_DIF = 20
|
||||
|
||||
def self.calculateShinyHueOffset(dex_number, isBodyShiny = false, isHeadShiny = false, color = :c1)
|
||||
if dex_number <= NB_POKEMON
|
||||
if SHINY_COLOR_OFFSETS[dex_number]&.dig(color)
|
||||
return SHINY_COLOR_OFFSETS[dex_number]&.dig(color)
|
||||
end
|
||||
body_number = dex_number
|
||||
head_number = dex_number
|
||||
else
|
||||
body_number = getBodyID(dex_number)
|
||||
head_number = getHeadID(dex_number, body_number)
|
||||
end
|
||||
if isBodyShiny && isHeadShiny && SHINY_COLOR_OFFSETS[body_number]&.dig(color) && SHINY_COLOR_OFFSETS[head_number]&.dig(color)
|
||||
offset = SHINY_COLOR_OFFSETS[body_number]&.dig(color) + SHINY_COLOR_OFFSETS[head_number]&.dig(color)
|
||||
elsif isHeadShiny && SHINY_COLOR_OFFSETS[head_number]&.dig(color)
|
||||
offset = SHINY_COLOR_OFFSETS[head_number]&.dig(color)
|
||||
elsif isBodyShiny && SHINY_COLOR_OFFSETS[body_number]&.dig(color)
|
||||
offset = SHINY_COLOR_OFFSETS[body_number]&.dig(color)
|
||||
else
|
||||
return 0 if color != :v1
|
||||
offset = calculateShinyHueOffsetDefaultMethod(body_number, head_number, dex_number, isBodyShiny, isHeadShiny)
|
||||
end
|
||||
return offset
|
||||
end
|
||||
|
||||
|
||||
def self.hex_to_rgb(hex)
|
||||
hex = hex.delete("#")
|
||||
r = hex[0..1].to_i(16)
|
||||
g = hex[2..3].to_i(16)
|
||||
b = hex[4..5].to_i(16)
|
||||
[r, g, b]
|
||||
end
|
||||
|
||||
def self.calculateShinyHueOffsetDefaultMethod(body_number, head_number, dex_number, isBodyShiny = false, isHeadShiny = false)
|
||||
dex_offset = dex_number
|
||||
#body_number = getBodyID(dex_number)
|
||||
#head_number=getHeadID(dex_number,body_number)
|
||||
dex_diff = (body_number - head_number).abs
|
||||
if isBodyShiny && isHeadShiny
|
||||
dex_offset = dex_number
|
||||
elsif isHeadShiny
|
||||
dex_offset = head_number
|
||||
elsif isBodyShiny
|
||||
dex_offset = dex_diff > MINIMUM_DEX_DIF ? body_number : body_number + ADDITIONAL_OFFSET_WHEN_TOO_CLOSE
|
||||
end
|
||||
offset = dex_offset + Settings::SHINY_HUE_OFFSET
|
||||
offset /= MAX_SHIFT_VALUE if offset > NB_POKEMON
|
||||
offset = MINIMUM_OFFSET if offset < MINIMUM_OFFSET
|
||||
offset = MINIMUM_OFFSET if (MAX_SHIFT_VALUE - offset).abs < MINIMUM_OFFSET
|
||||
offset += pbGet(VAR_SHINY_HUE_OFFSET) #for testing - always 0 during normal gameplay
|
||||
return offset
|
||||
end
|
||||
|
||||
def self.getAutogenSprite(head_id, body_id)
|
||||
|
||||
end
|
||||
|
||||
|
||||
# species can be either a number, a Species objet of a symbol
|
||||
def self.front_sprite_bitmap(species, isShiny = false, bodyShiny = false, headShiny = false)
|
||||
dex_number = getDexNumberForSpecies(species)
|
||||
if species.is_a?(Species)
|
||||
dex_number = species.id_number
|
||||
end
|
||||
|
||||
spriteLoader = BattleSpriteLoader.new
|
||||
if isFusion(dex_number)
|
||||
body_id = getBodyID(dex_number)
|
||||
head_id = getHeadID(dex_number, body_id)
|
||||
sprite = spriteLoader.load_fusion_sprite(head_id,body_id)
|
||||
else
|
||||
if isTripleFusion?(dex_number)
|
||||
sprite = spriteLoader.load_triple_fusion_sprite(dex_number)
|
||||
else
|
||||
sprite = spriteLoader.load_base_sprite(dex_number)
|
||||
end
|
||||
end
|
||||
if isShiny
|
||||
sprite.shiftAllColors(dex_number, bodyShiny, headShiny)
|
||||
end
|
||||
return sprite
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# def self.front_sprite_bitmap(dex_number, isShiny = false, bodyShiny = false, headShiny = false)
|
||||
# # body_id = getBodyID(dex_number)
|
||||
# # head_id = getHeadID(dex_number, body_id)
|
||||
# # return getAutogenSprite(head_id,body_id)
|
||||
#
|
||||
# #la méthode est utilisé ailleurs avec d'autres arguments (gender, form, etc.) mais on les veut pas
|
||||
# if dex_number.is_a?(Symbol)
|
||||
# dex_number = GameData::Species.get(dex_number).id_number
|
||||
# end
|
||||
# filename = self.sprite_filename(dex_number)
|
||||
# sprite = (filename) ? AnimatedBitmap.new(filename) : nil
|
||||
# if isShiny
|
||||
# sprite.shiftColors(self.calculateShinyHueOffset(dex_number, bodyShiny, headShiny))
|
||||
# end
|
||||
# return sprite
|
||||
# end
|
||||
|
||||
def self.back_sprite_bitmap(dex_number, isShiny = false, bodyShiny = false, headShiny = false)
|
||||
# filename = self.sprite_filename(dex_number)
|
||||
# sprite = (filename) ? AnimatedBitmap.new(filename) : nil
|
||||
# if isShiny
|
||||
# sprite.shiftColors(self.calculateShinyHueOffset(dex_number, bodyShiny, headShiny))
|
||||
# end
|
||||
# return sprite
|
||||
sprite = self.front_sprite_bitmap(dex_number,isShiny,bodyShiny,headShiny)
|
||||
return sprite#.mirror
|
||||
end
|
||||
|
||||
def self.egg_sprite_bitmap(dex_number, form = nil)
|
||||
filename = self.egg_sprite_filename(dex_number, form)
|
||||
return (filename) ? AnimatedBitmap.new(filename) : nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# def self.sprite_filename(dex_number)
|
||||
# #dex_number = GameData::NAT_DEX_MAPPING[dex_number] ? GameData::NAT_DEX_MAPPING[dex_number] : dex_number
|
||||
# if dex_number.is_a?(GameData::Species)
|
||||
# dex_number = dex_number.id_number
|
||||
# end
|
||||
# if dex_number.is_a?(Symbol)
|
||||
# dex_number = getDexNumberForSpecies(dex_number)
|
||||
# end
|
||||
# return nil if dex_number == nil
|
||||
# if dex_number <= Settings::NB_POKEMON
|
||||
# return get_unfused_sprite_path(dex_number)
|
||||
# else
|
||||
# if dex_number >= Settings::ZAPMOLCUNO_NB
|
||||
# specialPath = getSpecialSpriteName(dex_number)
|
||||
# return pbResolveBitmap(specialPath)
|
||||
# head_id = nil
|
||||
# else
|
||||
# body_id = getBodyID(dex_number)
|
||||
# head_id = getHeadID(dex_number, body_id)
|
||||
# return get_fusion_sprite_path(head_id, body_id)
|
||||
# # folder = head_id.to_s
|
||||
# # filename = sprintf("%s.%s.png", head_id, body_id)
|
||||
# end
|
||||
# end
|
||||
# # customPath = pbResolveBitmap(Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + "/" + head_id.to_s + "/" +filename)
|
||||
# # customPath = download_custom_sprite(head_id,body_id)
|
||||
# #
|
||||
# # species = getSpecies(dex_number)
|
||||
# # use_custom = customPath && !species.always_use_generated
|
||||
# # if use_custom
|
||||
# # return customPath
|
||||
# # end
|
||||
# # #return Settings::BATTLERS_FOLDER + folder + "/" + filename
|
||||
# # return download_autogen_sprite(head_id,body_id)
|
||||
# end
|
||||
|
||||
|
||||
# def get_unfused_sprite_path(dex_number_id, localOnly = false)
|
||||
# dex_number = dex_number_id.to_s
|
||||
# folder = dex_number.to_s
|
||||
# substitution_id = "{1}", dex_number
|
||||
#
|
||||
# if alt_sprites_substitutions_available && $PokemonGlobal.alt_sprite_substitutions.keys.include?(substitution_id)
|
||||
# substitutionPath = $PokemonGlobal.alt_sprite_substitutions[substitution_id]
|
||||
# return substitutionPath if pbResolveBitmap(substitutionPath)
|
||||
# end
|
||||
# random_alt = get_random_alt_letter_for_unfused(dex_number, true) #nil if no main
|
||||
# random_alt = "" if !random_alt || localOnly
|
||||
#
|
||||
#
|
||||
# filename = "{1}{2}.png", dex_number,random_alt
|
||||
#
|
||||
# path = Settings::CUSTOM_BASE_SPRITES_FOLDER + filename
|
||||
# if pbResolveBitmap(path)
|
||||
# record_sprite_substitution(substitution_id,path)
|
||||
# return path
|
||||
# end
|
||||
# echoln "downloading main sprite #{filename}"
|
||||
# downloaded_path = download_unfused_main_sprite(dex_number, random_alt) if !localOnly
|
||||
# if pbResolveBitmap(downloaded_path)
|
||||
# record_sprite_substitution(substitution_id,downloaded_path)
|
||||
# return downloaded_path
|
||||
# end
|
||||
# return path
|
||||
# end
|
||||
|
||||
def alt_sprites_substitutions_available
|
||||
return $PokemonGlobal && $PokemonGlobal.alt_sprite_substitutions
|
||||
end
|
||||
|
||||
def print_stack_trace
|
||||
stack_trace = caller
|
||||
stack_trace.each_with_index do |call, index|
|
||||
echo("#{index + 1}: #{call}")
|
||||
end
|
||||
end
|
||||
|
||||
# def record_sprite_substitution(substitution_id, sprite_name)
|
||||
# return if !$PokemonGlobal
|
||||
# return if !$PokemonGlobal.alt_sprite_substitutions
|
||||
# $PokemonGlobal.alt_sprite_substitutions[substitution_id] = sprite_name
|
||||
# end
|
||||
|
||||
def add_to_autogen_cache(pokemon_id, sprite_name)
|
||||
return if !$PokemonGlobal
|
||||
return if !$PokemonGlobal.autogen_sprites_cache
|
||||
$PokemonGlobal.autogen_sprites_cache[pokemon_id]=sprite_name
|
||||
end
|
||||
|
||||
class PokemonGlobalMetadata
|
||||
attr_accessor :autogen_sprites_cache
|
||||
end
|
||||
|
||||
#To force a specific sprites before a battle
|
||||
#
|
||||
# ex:
|
||||
# $PokemonTemp.forced_alt_sprites={"20.25" => "20.25a"}
|
||||
#
|
||||
class PokemonTemp
|
||||
attr_accessor :forced_alt_sprites
|
||||
end
|
||||
|
||||
#todo:
|
||||
# DO NOT USE ANYMORE
|
||||
# Replace by BattleSpriteLoader
|
||||
# def get_fusion_sprite_path(head_id, body_id, localOnly=false)
|
||||
# $PokemonGlobal.autogen_sprites_cache = {} if $PokemonGlobal && !$PokemonGlobal.autogen_sprites_cache
|
||||
# #Todo: ça va chier si on fusionne une forme d'un pokemon avec une autre forme, mais pas un problème pour tout de suite
|
||||
# form_suffix = ""
|
||||
#
|
||||
# #Swap path if alt is selected for this pokemon
|
||||
# dex_num = getSpeciesIdForFusion(head_id, body_id)
|
||||
# substitution_id = dex_num.to_s + form_suffix
|
||||
#
|
||||
# if alt_sprites_substitutions_available && $PokemonGlobal.alt_sprite_substitutions.keys.include?(substitution_id)
|
||||
# substitutionPath= $PokemonGlobal.alt_sprite_substitutions[substitution_id]
|
||||
# return substitutionPath if pbResolveBitmap(substitutionPath)
|
||||
# end
|
||||
#
|
||||
#
|
||||
# pokemon_name = "{1}.{2}",head_id, body_id
|
||||
#
|
||||
# #get altSprite letter
|
||||
# random_alt = get_random_alt_letter_for_custom(head_id, body_id) #nil if no main
|
||||
# random_alt = "" if !random_alt
|
||||
# forcingSprite=false
|
||||
# if $PokemonTemp.forced_alt_sprites && $PokemonTemp.forced_alt_sprites.key?(pokemon_name)
|
||||
# random_alt = $PokemonTemp.forced_alt_sprites[pokemon_name]
|
||||
# forcingSprite=true
|
||||
# end
|
||||
#
|
||||
#
|
||||
# filename = "{1}{2}.png", pokemon_name, random_alt
|
||||
# #Try local custom sprite
|
||||
# local_custom_path = Settings::CUSTOM_BATTLERS_FOLDER_INDEXED + head_id.to_s + "/" + filename
|
||||
# if pbResolveBitmap(local_custom_path)
|
||||
# record_sprite_substitution(substitution_id, local_custom_path) if !forcingSprite
|
||||
# return local_custom_path
|
||||
# end
|
||||
# #if the game has loaded an autogen earlier, no point in trying to redownload, so load that instead
|
||||
# return $PokemonGlobal.autogen_sprites_cache[substitution_id] if $PokemonGlobal && $PokemonGlobal.autogen_sprites_cache[substitution_id]
|
||||
#
|
||||
# #Try to download custom sprite if none found locally
|
||||
# downloaded_custom = download_custom_sprite(head_id, body_id, random_alt) if !localOnly
|
||||
# if downloaded_custom
|
||||
# record_sprite_substitution(substitution_id, downloaded_custom) if !forcingSprite
|
||||
# return downloaded_custom
|
||||
# end
|
||||
#
|
||||
# #Try local generated sprite
|
||||
# local_generated_path = Settings::BATTLERS_FOLDER + head_id.to_s + "/" + filename
|
||||
# if pbResolveBitmap(local_generated_path)
|
||||
# add_to_autogen_cache(substitution_id,local_generated_path)
|
||||
# return local_generated_path
|
||||
# end
|
||||
#
|
||||
# #Download generated sprite if nothing else found
|
||||
# autogen_path = download_autogen_sprite(head_id, body_id) if !localOnly
|
||||
# if pbResolveBitmap(autogen_path)
|
||||
# add_to_autogen_cache(substitution_id,autogen_path)
|
||||
# return autogen_path
|
||||
# end
|
||||
#
|
||||
# return Settings::DEFAULT_SPRITE_PATH
|
||||
# end
|
||||
|
||||
def get_random_alt_letter_for_custom(head_id, body_id, onlyMain = true)
|
||||
spriteName = _INTL("{1}.{2}", head_id, body_id)
|
||||
if onlyMain
|
||||
alts_list = list_main_sprites_letters(spriteName)
|
||||
return nil if alts_list.empty?
|
||||
return alts_list.sample
|
||||
else
|
||||
alts_list = list_all_sprites_letters(spriteName)
|
||||
return nil if alts_list.empty?
|
||||
return alts_list.sample
|
||||
end
|
||||
end
|
||||
|
||||
def get_random_alt_letter_for_unfused(dex_num, onlyMain = true)
|
||||
spriteName = _INTL("{1}", dex_num)
|
||||
if onlyMain
|
||||
letters_list= list_main_sprites_letters(spriteName)
|
||||
else
|
||||
letters_list= list_all_sprites_letters(spriteName)
|
||||
end
|
||||
letters_list << "" #add main sprite
|
||||
return letters_list.sample
|
||||
end
|
||||
|
||||
def list_main_sprites_letters(spriteName)
|
||||
return list_all_sprites_letters(spriteName) if $PokemonSystem.include_alt_sprites_in_random
|
||||
all_sprites = map_alt_sprite_letters_for_pokemon(spriteName)
|
||||
main_sprites = []
|
||||
all_sprites.each do |key, value|
|
||||
main_sprites << key if value == "main"
|
||||
end
|
||||
|
||||
#add temp sprites if no main sprites found
|
||||
if main_sprites.empty?
|
||||
all_sprites.each do |key, value|
|
||||
main_sprites << key if value == "temp"
|
||||
end
|
||||
end
|
||||
return main_sprites
|
||||
end
|
||||
|
||||
def list_all_sprites_letters_head_body(head_id,body_id)
|
||||
spriteName = _INTL("{1}.{2}", head_id, body_id)
|
||||
all_sprites_map = map_alt_sprite_letters_for_pokemon(spriteName)
|
||||
letters = []
|
||||
all_sprites_map.each do |key, value|
|
||||
letters << key
|
||||
end
|
||||
return letters
|
||||
end
|
||||
|
||||
def list_all_sprites_letters(spriteName)
|
||||
all_sprites_map = map_alt_sprite_letters_for_pokemon(spriteName)
|
||||
letters = []
|
||||
all_sprites_map.each do |key, value|
|
||||
letters << key
|
||||
end
|
||||
return letters
|
||||
end
|
||||
|
||||
def list_alt_sprite_letters(spriteName)
|
||||
all_sprites = map_alt_sprite_letters_for_pokemon(spriteName)
|
||||
alt_sprites = []
|
||||
all_sprites.each do |key, value|
|
||||
alt_sprites << key if value == "alt"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
#ex: "1" -> "main"
|
||||
# "1a" -> "alt"
|
||||
def map_alt_sprite_letters_for_pokemon(spriteName)
|
||||
alt_sprites = {}
|
||||
File.foreach(Settings::CREDITS_FILE_PATH) do |line|
|
||||
row = line.split(',')
|
||||
sprite_name = row[0]
|
||||
if sprite_name.start_with?(spriteName)
|
||||
if sprite_name.length > spriteName.length #alt letter
|
||||
letter = sprite_name[spriteName.length]
|
||||
if letter.match?(/[a-zA-Z]/)
|
||||
main_or_alt = row[2] ? row[2] : nil
|
||||
alt_sprites[letter] = main_or_alt
|
||||
end
|
||||
else #letterless
|
||||
main_or_alt = row[2] ? row[2].gsub("\n","") : nil
|
||||
alt_sprites[""] = main_or_alt
|
||||
end
|
||||
end
|
||||
end
|
||||
return alt_sprites
|
||||
end
|
||||
510
Data/Scripts/052_InfiniteFusion/Fusion/FusionUtils.rb
Normal file
510
Data/Scripts/052_InfiniteFusion/Fusion/FusionUtils.rb
Normal file
@@ -0,0 +1,510 @@
|
||||
def playerHasFusionItems()
|
||||
return pbHasItem?(:DNASPLICERS) || pbHasItem?(:SUPERSPLICERS) || pbHasItem?(:INFINITESPLICERS) || pbHasItem?(:INFINITESPLICERS2)
|
||||
end
|
||||
|
||||
def selectSplicer()
|
||||
dna_splicers_const = _INTL("DNA Splicers")
|
||||
super_splicers_const = _INTL("Super Splicers")
|
||||
infinite_splicers_const = _INTL("Infinite Splicers")
|
||||
|
||||
dnaSplicersQt = $PokemonBag.pbQuantity(:DNASPLICERS)
|
||||
superSplicersQt = $PokemonBag.pbQuantity(:SUPERSPLICERS)
|
||||
infiniteSplicersQt = $PokemonBag.pbQuantity(:INFINITESPLICERS)
|
||||
infiniteSplicers2Qt = $PokemonBag.pbQuantity(:INFINITESPLICERS2)
|
||||
|
||||
options = []
|
||||
options.push("#{infinite_splicers_const}") if infiniteSplicers2Qt > 0 || infiniteSplicersQt > 0
|
||||
options.push("#{super_splicers_const} (#{superSplicersQt})") if superSplicersQt > 0
|
||||
options.push("#{dna_splicers_const} (#{dnaSplicersQt})") if dnaSplicersQt > 0
|
||||
|
||||
if options.length <= 0
|
||||
pbDisplay(_INTL("You have no fusion items available."))
|
||||
return nil
|
||||
end
|
||||
|
||||
cmd = pbShowCommands(_INTL("Use which splicers?"), options)
|
||||
if cmd == -1
|
||||
return nil
|
||||
end
|
||||
ret = options[cmd]
|
||||
if ret.start_with?(dna_splicers_const)
|
||||
return :DNASPLICERS
|
||||
elsif ret.start_with?(super_splicers_const)
|
||||
return :SUPERSPLICERS
|
||||
elsif ret.start_with?(infinite_splicers_const)
|
||||
return infiniteSplicers2Qt >= 1 ? :INFINITESPLICERS2 : :INFINITESPLICERS
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
def is_fusion_of_any(species_id, pokemonList)
|
||||
is_species = false
|
||||
for fusionPokemon in pokemonList
|
||||
if is_fusion_of(species_id, fusionPokemon)
|
||||
is_species = true
|
||||
end
|
||||
end
|
||||
return is_species
|
||||
end
|
||||
|
||||
def is_fusion_of(checked_species, checked_against)
|
||||
return species_has_body_of(checked_species, checked_against) || species_has_head_of(checked_species, checked_against)
|
||||
end
|
||||
|
||||
def is_species(checked_species, checked_against)
|
||||
return checked_species == checked_against
|
||||
end
|
||||
|
||||
def species_has_body_of(checked_species, checked_against)
|
||||
if !species_is_fusion(checked_species)
|
||||
return is_species(checked_species, checked_against)
|
||||
end
|
||||
bodySpecies = get_body_species_from_symbol(checked_species)
|
||||
ret = bodySpecies == checked_against
|
||||
#echoln "{1} HAS BODY OF {2} : {3} (body is {4})",checked_species,checked_against,ret,bodySpecies
|
||||
return ret
|
||||
end
|
||||
|
||||
def species_has_head_of(checked_species, checked_against)
|
||||
if !species_is_fusion(checked_species)
|
||||
return is_species(checked_species, checked_against)
|
||||
end
|
||||
headSpecies = get_head_species_from_symbol(checked_species)
|
||||
ret = headSpecies == checked_against
|
||||
#echoln "{1} HAS HEAD OF {2} : {3}",checked_species,checked_against,ret
|
||||
return ret
|
||||
end
|
||||
|
||||
def species_is_fusion(species_id)
|
||||
dex_number = get_dex_number(species_id)
|
||||
return dex_number > NB_POKEMON && dex_number < Settings::ZAPMOLCUNO_NB
|
||||
end
|
||||
|
||||
def get_dex_number(species_id)
|
||||
return GameData::Species.get(species_id).id_number
|
||||
end
|
||||
|
||||
def getBodyID(species, nb_pokemon = NB_POKEMON)
|
||||
if species.is_a?(Integer)
|
||||
dexNum = species
|
||||
else
|
||||
dexNum = getDexNumberForSpecies(species)
|
||||
end
|
||||
if dexNum % nb_pokemon == 0
|
||||
return (dexNum / nb_pokemon) - 1
|
||||
end
|
||||
return (dexNum / nb_pokemon).round
|
||||
end
|
||||
|
||||
def getHeadID(species, bodyId = nil, nb_pokemon = NB_POKEMON)
|
||||
if species.is_a?(Integer)
|
||||
fused_dexNum = species
|
||||
else
|
||||
fused_dexNum = getDexNumberForSpecies(species)
|
||||
end
|
||||
|
||||
if bodyId == nil
|
||||
bodyId = getBodyID(species)
|
||||
end
|
||||
body_dexNum = getDexNumberForSpecies(bodyId)
|
||||
|
||||
calculated_number = (fused_dexNum - (body_dexNum * nb_pokemon)).round
|
||||
return calculated_number == 0 ? nb_pokemon : calculated_number
|
||||
end
|
||||
|
||||
def get_fusion_id(head_number, body_number)
|
||||
return "B#{body_number}H#{head_number}".to_sym
|
||||
end
|
||||
|
||||
def get_body_id_from_symbol(id)
|
||||
split_id = id.to_s.match(/\d+/)
|
||||
if !split_id #non-fusion
|
||||
return GameData::Species.get(id).id_number
|
||||
end
|
||||
return split_id[0].to_i
|
||||
end
|
||||
|
||||
def get_head_id_from_symbol(id)
|
||||
split_id = id.to_s.match(/(?<=H)\d+/)
|
||||
if !split_id #non-fusion
|
||||
return GameData::Species.get(id).id_number
|
||||
end
|
||||
|
||||
return split_id[0].to_i
|
||||
end
|
||||
|
||||
def obtainPokemonSpritePath(id, includeCustoms = true)
|
||||
head = getBasePokemonID(param.to_i, false)
|
||||
body = getBasePokemonID(param.to_i, true)
|
||||
|
||||
return obtainPokemonSpritePath(body, head, includeCustoms)
|
||||
end
|
||||
|
||||
def obtainPokemonSpritePath(bodyId, headId, include_customs = true)
|
||||
#download_pokemon_sprite_if_missing(bodyId, headId)
|
||||
picturePath = "Graphics/Battlers/#{headId}/#{headId}.#{bodyId}.png"
|
||||
|
||||
if include_customs && customSpriteExistsBodyHead(bodyId, headId)
|
||||
pathCustom = getCustomSpritePath(bodyId, headId)
|
||||
if (pbResolveBitmap(pathCustom))
|
||||
picturePath = pathCustom
|
||||
end
|
||||
end
|
||||
return picturePath
|
||||
end
|
||||
|
||||
def getCustomSpritePath(body, head)
|
||||
return "#{Settings::CUSTOM_BATTLERS_FOLDER_INDEXED}#{head}/#{head}.#{body}.png"
|
||||
end
|
||||
|
||||
def customSpriteExistsForm(species, form_id_head = nil, form_id_body = nil)
|
||||
head = getBasePokemonID(species, false)
|
||||
body = getBasePokemonID(species, true)
|
||||
|
||||
folder = head.to_s
|
||||
|
||||
folder += "_" + form_id_head.to_s if form_id_head
|
||||
|
||||
spritename = head.to_s
|
||||
spritename += "_" + form_id_head.to_s if form_id_head
|
||||
spritename += "." + body.to_s
|
||||
spritename += "_" + form_id_body.to_s if form_id_body
|
||||
|
||||
pathCustom = "Graphics/.CustomBattlers/indexed/#{folder}/#{spritename}.png"
|
||||
return true if pbResolveBitmap(pathCustom) != nil
|
||||
return download_custom_sprite(head, body) != nil
|
||||
end
|
||||
|
||||
def get_fusion_spritename(head_id, body_id, alt_letter = "")
|
||||
return "#{head_id}.#{body_id}#{alt_letter}"
|
||||
end
|
||||
|
||||
def customSpriteExistsSpecies(species)
|
||||
head = getBasePokemonID(species, false)
|
||||
body = getBasePokemonID(species, true)
|
||||
return customSpriteExists(body, head)
|
||||
# pathCustom = getCustomSpritePath(body, head)
|
||||
#
|
||||
# return true if pbResolveBitmap(pathCustom) != nil
|
||||
# return download_custom_sprite(head, body) != nil
|
||||
end
|
||||
|
||||
def getRandomCustomFusion(returnRandomPokemonIfNoneFound = true, customPokeList = [], maxPoke = -1, recursionLimit = 3)
|
||||
if customPokeList.length == 0
|
||||
customPokeList = getCustomSpeciesList(false)
|
||||
end
|
||||
randPoke = []
|
||||
if customPokeList.length >= 5000
|
||||
chosen = false
|
||||
i = 0 #loop pas plus que 3 fois pour pas lag
|
||||
while chosen == false
|
||||
fusedPoke = customPokeList[rand(customPokeList.length)]
|
||||
poke1 = getBasePokemonID(fusedPoke, false)
|
||||
poke2 = getBasePokemonID(fusedPoke, true)
|
||||
|
||||
if ((poke1 <= maxPoke && poke2 <= maxPoke) || i >= recursionLimit) || maxPoke == -1
|
||||
randPoke << getBasePokemonID(fusedPoke, false)
|
||||
randPoke << getBasePokemonID(fusedPoke, true)
|
||||
chosen = true
|
||||
end
|
||||
end
|
||||
else
|
||||
if returnRandomPokemonIfNoneFound
|
||||
randPoke << rand(maxPoke) + 1
|
||||
randPoke << rand(maxPoke) + 1
|
||||
end
|
||||
end
|
||||
return randPoke
|
||||
end
|
||||
|
||||
def checkIfCustomSpriteExistsByPath(path)
|
||||
return true if pbResolveBitmap(path) != nil
|
||||
end
|
||||
|
||||
def customSpriteExistsBodyHead(body, head)
|
||||
pathCustom = getCustomSpritePath(body, head)
|
||||
|
||||
return true if pbResolveBitmap(pathCustom) != nil
|
||||
return download_custom_sprite(head, body) != nil
|
||||
end
|
||||
|
||||
def customSpriteExistsSpecies(species)
|
||||
body_id = getBodyID(species)
|
||||
head_id = getHeadID(species, body_id)
|
||||
fusion_id = get_fusion_symbol(head_id, body_id)
|
||||
return $game_temp.custom_sprites_list.include?(fusion_id)
|
||||
end
|
||||
|
||||
def customSpriteExists(body, head)
|
||||
fusion_id = get_fusion_symbol(head, body)
|
||||
return $game_temp.custom_sprites_list.include?(fusion_id)
|
||||
end
|
||||
|
||||
#shortcut for using in game events because of script characters limit
|
||||
def dexNum(species)
|
||||
return getDexNumberForSpecies(species)
|
||||
end
|
||||
|
||||
def isTripleFusion?(num)
|
||||
return num >= Settings::ZAPMOLCUNO_NB
|
||||
end
|
||||
|
||||
def isFusion(num)
|
||||
return num > Settings::NB_POKEMON && !isTripleFusion?(num)
|
||||
end
|
||||
|
||||
def isSpeciesFusion(species)
|
||||
num = getDexNumberForSpecies(species)
|
||||
return isFusion(num)
|
||||
end
|
||||
|
||||
def getRandomLocalFusion()
|
||||
spritesList = []
|
||||
$PokemonGlobal.alt_sprite_substitutions.each_value do |value|
|
||||
if value.is_a?(PIFSprite)
|
||||
spritesList << value
|
||||
end
|
||||
end
|
||||
return spritesList.sample
|
||||
end
|
||||
|
||||
def getRandomFusionForIntro()
|
||||
random_pokemon = $game_temp.custom_sprites_list.keys.sample || :PIKACHU
|
||||
alt_letter = $game_temp.custom_sprites_list[random_pokemon]
|
||||
body_id = get_body_number_from_symbol(random_pokemon)
|
||||
head_id = get_head_number_from_symbol(random_pokemon)
|
||||
return PIFSprite.new(:CUSTOM, head_id, body_id, alt_letter)
|
||||
end
|
||||
|
||||
def getSpeciesIdForFusion(head_number, body_number)
|
||||
return (body_number) * Settings::NB_POKEMON + head_number
|
||||
end
|
||||
|
||||
def get_body_species_from_symbol(fused_id)
|
||||
body_num = get_body_number_from_symbol(fused_id)
|
||||
return GameData::Species.get(body_num).species
|
||||
end
|
||||
|
||||
def get_head_species_from_symbol(fused_id)
|
||||
head_num = get_head_number_from_symbol(fused_id)
|
||||
return GameData::Species.get(head_num).species
|
||||
end
|
||||
|
||||
def get_body_number_from_symbol(id)
|
||||
dexNum = getDexNumberForSpecies(id)
|
||||
return dexNum if !isFusion(dexNum)
|
||||
id.to_s.match(/\d+/)[0]
|
||||
return id.to_s.match(/\d+/)[0].to_i
|
||||
end
|
||||
|
||||
def get_head_number_from_symbol(id)
|
||||
dexNum = getDexNumberForSpecies(id)
|
||||
return dexNum if !isFusion(dexNum)
|
||||
return id.to_s.match(/(?<=H)\d+/)[0].to_i
|
||||
end
|
||||
|
||||
def get_fusion_symbol(head_id, body_id)
|
||||
if head_id.is_a?(Symbol)
|
||||
head_id = get_head_number_from_symbol(head_id)
|
||||
end
|
||||
if body_id.is_a?(Symbol)
|
||||
body_id = get_body_number_from_symbol(body_id)
|
||||
end
|
||||
|
||||
return "B#{body_id}H#{head_id}".to_sym
|
||||
end
|
||||
|
||||
def get_readable_fusion_name(fusion_species)
|
||||
head_dex = get_head_number_from_symbol(fusion_species)
|
||||
body_dex = get_body_number_from_symbol(fusion_species)
|
||||
|
||||
return fusion_species if head_dex > NB_POKEMON || body_dex > NB_POKEMON
|
||||
|
||||
head_species = GameData::Species.get(head_dex)
|
||||
body_species = GameData::Species.get(body_dex)
|
||||
|
||||
return "#{head_species.name}/#{body_species.name}"
|
||||
|
||||
end
|
||||
|
||||
def getFusionSpecies(body, head)
|
||||
body_num = getDexNumberForSpecies(body)
|
||||
head_num = getDexNumberForSpecies(head)
|
||||
id = body_num * Settings::NB_POKEMON + head_num
|
||||
return GameData::Species.get(id)
|
||||
end
|
||||
|
||||
def getDexNumberForSpecies(species)
|
||||
return species if species.is_a?(Integer)
|
||||
if species.is_a?(Symbol)
|
||||
dexNum = GameData::Species.get(species).id_number
|
||||
elsif species.is_a?(Pokemon)
|
||||
dexNum = GameData::Species.get(species.species).id_number
|
||||
elsif species.is_a?(GameData::Species)
|
||||
return species.id_number
|
||||
else
|
||||
dexNum = species
|
||||
end
|
||||
return dexNum
|
||||
end
|
||||
|
||||
def getFusedPokemonIdFromDexNum(body_dex, head_dex)
|
||||
return ("B" + body_dex.to_s + "H" + head_dex.to_s).to_sym
|
||||
end
|
||||
|
||||
def getFusedPokemonIdFromSymbols(body_dex, head_dex)
|
||||
bodyDexNum = GameData::Species.get(body_dex).id_number
|
||||
headDexNum = GameData::Species.get(head_dex).id_number
|
||||
return getFusedPokemonIdFromDexNum(bodyDexNum, headDexNum)
|
||||
end
|
||||
|
||||
def generateFusionIcon(dexNum, path)
|
||||
begin
|
||||
IO.copy_stream(dexNum, path)
|
||||
return true
|
||||
rescue
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
def ensureFusionIconExists
|
||||
directory_name = "Graphics/Pokemon/FusionIcons"
|
||||
Dir.mkdir(directory_name) unless File.exists?(directory_name)
|
||||
end
|
||||
|
||||
def addNewTripleFusion(pokemon1, pokemon2, pokemon3, level = 1)
|
||||
return if !pokemon1
|
||||
return if !pokemon2
|
||||
return if !pokemon3
|
||||
|
||||
if pbBoxesFull?
|
||||
pbMessage(_INTL("There's no more room for Pokémon!\1"))
|
||||
pbMessage(_INTL("The Pokémon Boxes are full and can't accept any more!"))
|
||||
return false
|
||||
end
|
||||
|
||||
pokemon = TripleFusion.new(pokemon1, pokemon2, pokemon3, level)
|
||||
pokemon.calc_stats
|
||||
pbMessage(_INTL("{1} obtained {2}!\\me[Pkmn get]\\wtnp[80]\1", $Trainer.name, pokemon.name))
|
||||
pbNicknameAndStore(pokemon)
|
||||
#$Trainer.pokedex.register(pokemon)
|
||||
return true
|
||||
end
|
||||
|
||||
def get_pokemon_readable_internal_name(pokemon)
|
||||
if pokemon.isFusion?
|
||||
body_pokemon = get_body_species_from_symbol(pokemon.species)
|
||||
head_pokemon = get_head_species_from_symbol(pokemon.species)
|
||||
name = "#{head_pokemon}_#{body_pokemon}"
|
||||
else
|
||||
name = pokemon.species
|
||||
end
|
||||
return name
|
||||
end
|
||||
|
||||
def get_species_readable_internal_name(species_symbol)
|
||||
if isSpeciesFusion(species_symbol)
|
||||
body_pokemon = get_body_species_from_symbol(species_symbol)
|
||||
head_pokemon = get_head_species_from_symbol(species_symbol)
|
||||
name = "#{head_pokemon}_#{body_pokemon}"
|
||||
else
|
||||
name = species_symbol
|
||||
end
|
||||
return name
|
||||
end
|
||||
|
||||
def getSpeciesRealName(species_symbol)
|
||||
return nil if !species_symbol
|
||||
species = GameData::Species.get(species_symbol)
|
||||
return species.real_name
|
||||
end
|
||||
|
||||
def playerHasFusedPokemonInTeam()
|
||||
$Trainer.party.each do |pokemon|
|
||||
if pokemon.isFusion?
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def get_triple_fusion_components(species_id)
|
||||
dex_num = GameData::Species.get(species_id).id_number
|
||||
case dex_num
|
||||
when Settings::ZAPMOLCUNO_NB
|
||||
return [144,145,146]
|
||||
when Settings::ZAPMOLCUNO_NB + 1
|
||||
return [144,145,146]
|
||||
when Settings::ZAPMOLCUNO_NB + 2
|
||||
return [243,244,245]
|
||||
when Settings::ZAPMOLCUNO_NB + 3
|
||||
return [340,341,342]
|
||||
when Settings::ZAPMOLCUNO_NB + 4
|
||||
return [343,344,345]
|
||||
when Settings::ZAPMOLCUNO_NB + 5
|
||||
return [349,350,351]
|
||||
when Settings::ZAPMOLCUNO_NB + 6
|
||||
return [151,251,381]
|
||||
when Settings::ZAPMOLCUNO_NB + 11
|
||||
return [150,348,380]
|
||||
#starters
|
||||
when Settings::ZAPMOLCUNO_NB + 7
|
||||
return [3,6,9]
|
||||
when Settings::ZAPMOLCUNO_NB + 8
|
||||
return [154,157,160]
|
||||
when Settings::ZAPMOLCUNO_NB + 9
|
||||
return [278,281,284]
|
||||
when Settings::ZAPMOLCUNO_NB + 10
|
||||
return [318,321,324]
|
||||
#starters prevos
|
||||
when Settings::ZAPMOLCUNO_NB + 12
|
||||
return [1,4,7]
|
||||
when Settings::ZAPMOLCUNO_NB + 13
|
||||
return [2,5,8]
|
||||
when Settings::ZAPMOLCUNO_NB + 14
|
||||
return [152,155,158]
|
||||
when Settings::ZAPMOLCUNO_NB + 15
|
||||
return [153,156,159]
|
||||
when Settings::ZAPMOLCUNO_NB + 16
|
||||
return [276,279,282]
|
||||
when Settings::ZAPMOLCUNO_NB + 17
|
||||
return [277,280,283]
|
||||
when Settings::ZAPMOLCUNO_NB + 18
|
||||
return [316,319,322]
|
||||
when Settings::ZAPMOLCUNO_NB + 19
|
||||
return [317,320,323]
|
||||
when Settings::ZAPMOLCUNO_NB + 20 #birdBoss Left
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 21 #birdBoss middle
|
||||
return [144,145,146]
|
||||
when Settings::ZAPMOLCUNO_NB + 22 #birdBoss right
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 23 #sinnohboss left
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 24 #sinnohboss middle
|
||||
return [343,344,345]
|
||||
when Settings::ZAPMOLCUNO_NB + 25 #sinnohboss right
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 25 #cardboard
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 26 #cardboard
|
||||
return []
|
||||
when Settings::ZAPMOLCUNO_NB + 27 #Triple regi
|
||||
return [447,448,449]
|
||||
#Triple Kalos 1
|
||||
when Settings::ZAPMOLCUNO_NB + 28
|
||||
return [479,482,485]
|
||||
when Settings::ZAPMOLCUNO_NB + 29
|
||||
return [480,483,486]
|
||||
when Settings::ZAPMOLCUNO_NB + 30
|
||||
return [481,484,487]
|
||||
else
|
||||
return [000]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
def gotFusedPokemonAsStarter()
|
||||
return $game_switches[SWITCH_RANDOM_WILD_TO_FUSION] || $game_switches[SWITCH_LEGENDARY_MODE]
|
||||
end
|
||||
1170
Data/Scripts/052_InfiniteFusion/Fusion/PokemonFusion.rb
Normal file
1170
Data/Scripts/052_InfiniteFusion/Fusion/PokemonFusion.rb
Normal file
File diff suppressed because it is too large
Load Diff
1229
Data/Scripts/052_InfiniteFusion/Fusion/SplitNames.rb
Normal file
1229
Data/Scripts/052_InfiniteFusion/Fusion/SplitNames.rb
Normal file
File diff suppressed because it is too large
Load Diff
@@ -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,98 @@
|
||||
class PIFSpriteExtracter
|
||||
COLUMNS = 20 # Number of columns in the spritesheet
|
||||
@@spritesheet_cache = SpritesBitmapCache.new
|
||||
|
||||
#factor by which the sprite needs to be resized to get it to base game resolution (288x288)
|
||||
def get_resize_scale
|
||||
return 1
|
||||
end
|
||||
|
||||
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)
|
||||
sprite_bitmap.scale_bitmap(get_resize_scale())
|
||||
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
|
||||
@@ -0,0 +1,160 @@
|
||||
class AutogenExtracter < PIFSpriteExtracter
|
||||
SPRITESHEET_FOLDER_PATH = "Graphics\\Battlers\\spritesheets_autogen\\"
|
||||
SPRITE_SIZE = 96 # Size of each sprite in the spritesheet
|
||||
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
|
||||
|
||||
def get_resize_scale
|
||||
return 3
|
||||
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 it’s 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,61 @@
|
||||
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 = 96 # Original 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
|
||||
|
||||
def get_resize_scale
|
||||
return 3
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,279 @@
|
||||
class BattleSpriteLoader
|
||||
def initialize
|
||||
@download_allowed = true
|
||||
end
|
||||
|
||||
def load_pif_sprite_directly(pif_sprite)
|
||||
if pif_sprite.local_path && pbResolveBitmap(pif_sprite.local_path)
|
||||
return AnimatedBitmap.new(pif_sprite.local_path)
|
||||
end
|
||||
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 registerSpriteSubstitution(pif_sprite)
|
||||
substitution_id = get_sprite_substitution_id_from_dex_number(pif_sprite.species)
|
||||
$PokemonGlobal.alt_sprite_substitutions[substitution_id] = pif_sprite
|
||||
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
|
||||
#pif_sprite.dump_info if pif_sprite
|
||||
if !pif_sprite
|
||||
pif_sprite = select_new_pif_fusion_sprite(head_id, body_id)
|
||||
local_path = check_for_local_sprite(pif_sprite)
|
||||
if local_path
|
||||
pif_sprite.local_path = local_path
|
||||
pif_sprite.type = :CUSTOM
|
||||
end
|
||||
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)
|
||||
if pif_sprite.local_path
|
||||
return AnimatedBitmap.new(pif_sprite.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
|
||||
if pif_sprite.local_path
|
||||
return AnimatedBitmap.new(pif_sprite.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
|
||||
$Trainer.seen_qmarks_sprite=true if $Trainer
|
||||
#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)
|
||||
return pif_sprite.local_path if pif_sprite.local_path
|
||||
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)
|
||||
substitution_id = get_sprite_substitution_id_from_dex_number(species)
|
||||
pif_sprite = $PokemonGlobal.alt_sprite_substitutions[substitution_id] if $PokemonGlobal
|
||||
return pif_sprite if pif_sprite
|
||||
species_data = GameData::Species.get(species)
|
||||
if species_data.id_number <= NB_POKEMON #base pokemon
|
||||
return select_new_pif_base_sprite(species_data.id_number)
|
||||
else #isFusion
|
||||
return select_new_pif_fusion_sprite(species_data.get_head_species, species_data.get_body_species)
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Flow:
|
||||
# # if none found in cache, 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
|
||||
|
||||
#todo refactor by using get_triple_fusion_components()
|
||||
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,106 @@
|
||||
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 = 96 # Original 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 get_resize_scale
|
||||
return 3
|
||||
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 it’s 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
|
||||
122
Data/Scripts/052_InfiniteFusion/Fusion/Sprites/PIFSprite.rb
Normal file
122
Data/Scripts/052_InfiniteFusion/Fusion/Sprites/PIFSprite.rb
Normal file
@@ -0,0 +1,122 @@
|
||||
# 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
|
||||
attr_accessor :local_path
|
||||
|
||||
# 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
|
||||
@local_path = nil
|
||||
end
|
||||
|
||||
def dump_info()
|
||||
echoln "Type: #{@type}"
|
||||
echoln "Head: #{@head_id}"
|
||||
echoln "Body: #{@body_id}"
|
||||
echoln "Alt letter: #{@alt_letter}"
|
||||
echoln "Local path: #{@local_path}"
|
||||
end
|
||||
def species
|
||||
if @type == :BASE
|
||||
return GameData::Species.get(@head_id).species
|
||||
else
|
||||
return "B#{@body_id}H#{@head_id}".to_sym
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def exists()
|
||||
filename = get_spritesheet_path()
|
||||
echoln filename
|
||||
return File.file?(filename)
|
||||
end
|
||||
|
||||
def get_spritesheet_path()
|
||||
case @type
|
||||
when :BASE
|
||||
path = "#{BaseSpriteExtracter::SPRITESHEET_FOLDER_PATH}#{@head_id}.png"
|
||||
when :CUSTOM
|
||||
path = "#{CustomSpriteExtracter::SPRITESHEET_FOLDER_PATH}#{@head_id}/#{@head_id}#{@alt_letter}.png"
|
||||
when :AUTOGEN
|
||||
path = "#{AutogenExtracter::SPRITESHEET_FOLDER_PATH}#{@head_id}.png"
|
||||
else
|
||||
return nil
|
||||
end
|
||||
echoln path
|
||||
return path
|
||||
end
|
||||
end
|
||||
|
||||
def equals(other_pif_sprite)
|
||||
return @type == other_pif_sprite.type &&
|
||||
@head_id == other_pif_sprite.head_id &&
|
||||
@body_id == other_pif_sprite.body_id &&
|
||||
@alt_letter == other_pif_sprite.alt_letter &&
|
||||
@local_path == other_pif_sprite.local_path
|
||||
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
|
||||
|
||||
|
||||
|
||||
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
|
||||
90
Data/Scripts/052_InfiniteFusion/Fusion/TripleFusion.rb
Normal file
90
Data/Scripts/052_InfiniteFusion/Fusion/TripleFusion.rb
Normal file
@@ -0,0 +1,90 @@
|
||||
class TripleFusion < Pokemon
|
||||
attr_reader :species1
|
||||
attr_reader :species2
|
||||
attr_reader :species3
|
||||
|
||||
def initialize(species1, species2,species3, level, owner = $Trainer, withMoves = true, recheck_form = true)
|
||||
@species1=species1
|
||||
@species2=species2
|
||||
@species3=species3
|
||||
|
||||
@species1_data = GameData::Species.get(@species1)
|
||||
@species2_data = GameData::Species.get(@species2)
|
||||
@species3_data = GameData::Species.get(@species3)
|
||||
|
||||
@species_name = generate_triple_fusion_name()
|
||||
|
||||
super(:ZAPMOLTICUNO,level,owner,withMoves,recheck_form)
|
||||
end
|
||||
|
||||
|
||||
|
||||
def types
|
||||
return [@species1_data.type1, @species2_data.type1,@species3_data.type1]
|
||||
end
|
||||
|
||||
def baseStats
|
||||
ret = {}
|
||||
GameData::Stat.each_main do |s|
|
||||
stat1 = @species1_data.base_stats[s.id]
|
||||
stat2 = @species2_data.base_stats[s.id]
|
||||
stat3 = @species3_data.base_stats[s.id]
|
||||
|
||||
ret[s.id] = (stat1 + stat2 + stat3) / 3
|
||||
end
|
||||
return ret
|
||||
end
|
||||
|
||||
def name
|
||||
return (nicknamed?) ? @name : @species_name
|
||||
end
|
||||
|
||||
def speciesName
|
||||
return @species_name
|
||||
end
|
||||
|
||||
def generate_triple_fusion_name()
|
||||
part1 = split_string_with_syllables(@species1_data.name)[0]
|
||||
part2 = split_string_with_syllables(@species2_data.name)[1]
|
||||
part3 = split_string_with_syllables(@species3_data.name)[2]
|
||||
return "#{part1}#{part2}#{part3}".capitalize!
|
||||
end
|
||||
|
||||
|
||||
def split_string_with_syllables(name)
|
||||
syllable_pattern = /[bcdfghjklmnpqrstvwxyz]*[aeiou]+[bcdfghjklmnpqrstvwxyz]*/
|
||||
syllables = name.downcase.scan(syllable_pattern)
|
||||
first_syllable= syllables.first
|
||||
last_syllable = syllables.last
|
||||
if syllables.length > 1
|
||||
middle_syllable = syllables[1]
|
||||
else
|
||||
middle_syllable = first_syllable.downcase
|
||||
end
|
||||
|
||||
last_syllable.nil? ? first_syllable : last_syllable
|
||||
return [first_syllable,middle_syllable,last_syllable]
|
||||
|
||||
end
|
||||
|
||||
def ability_id
|
||||
if !@ability
|
||||
abil_index = ability_index
|
||||
if !@ability # Natural ability or no hidden ability defined
|
||||
chosen_poke_for_ability= rand(1..3)
|
||||
if chosen_poke_for_ability == 1
|
||||
@ability = @species1_data.abilities[abil_index] || @species1_data.abilities[0]
|
||||
elsif chosen_poke_for_ability == 2
|
||||
@ability = @species2_data.abilities[abil_index] || @species2_data.abilities[0]
|
||||
else
|
||||
@ability = @species3_data.abilities[abil_index] || @species3_data.abilities[0]
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return @ability
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user