DNA Splicers WIP

This commit is contained in:
chardub
2025-05-08 22:59:30 -04:00
parent 6536fcda77
commit 4ecf97b777
287 changed files with 5291 additions and 31635 deletions

View File

@@ -0,0 +1,225 @@
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/Fusion/selHand"
CANCEL_BUTTON_PATH = "Graphics/Pictures/Fusion/previewScreen_Cancel"
BACKGROUND_PATH = "Graphics/Pictures/Fusion/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)
body_pokemon = getBodyID(dexNumber)
head_pokemon = getHeadID(dexNumber, body_pokemon)
# picturePath = getPicturePath(head_pokemon, body_pokemon)
# bitmap = AnimatedBitmap.new(picturePath)
spriteLoader = BattleSpriteLoader.new
bitmap = spriteLoader.load_fusion_sprite(head_pokemon,body_pokemon)
bitmap.scale_bitmap(Settings::FRONTSPRITE_SCALE)
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"))
echoln pokemon
echoln pokemon.types
echoln pokemon.id
type1_number = GameData::Type.get(pokemon.type1).icon_position
type2_number = GameData::Type.get(pokemon.type2).icon_position if pokemon.type2
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

View File

@@ -9,28 +9,19 @@ end
# don't remember why there's two Supersplicers arguments.... probably a mistake
def pbDNASplicing(pokemon, scene, item = :DNASPLICERS)
echoln pokemon
echoln scene
echoln item
is_supersplicer = isSuperSplicersMechanics(item)
playingBGM = $game_system.getPlayingBGM
dexNumber = pokemon.species_data.id_number
if (pokemon.species_data.id_number <= NB_POKEMON)
if pokemon.fused != nil
if $player.party.length >= 6
scene.pbDisplay(_INTL("Your party is full! You can't unfuse {1}.", pokemon.name))
return false
else
$player.party[$player.party.length] = pokemon.fused
pokemon.fused = nil
pokemon.form = 0
scene.pbHardRefresh
scene.pbDisplay(_INTL("{1} changed Forme!", pokemon.name))
return true
end
else
if (pokemon.species_data.id_number <= Settings::NB_POKEMON)
chosen = scene.pbChoosePokemon(_INTL("Fuse with which Pokémon?"))
if chosen >= 0
poke2 = $player.party[chosen]
if (poke2.species_data.id_number <= NB_POKEMON) && poke2 != pokemon
if (poke2.species_data.id_number <= Settings::NB_POKEMON) && poke2 != pokemon
# check if fainted
if pokemon.egg? || poke2.egg?
@@ -79,7 +70,7 @@ def pbDNASplicing(pokemon, scene, item = :DNASPLICERS)
else
return false
end
end
else
# UNFUSE
return true if pbUnfuse(pokemon, scene, is_supersplicer)
@@ -96,34 +87,10 @@ def selectFusion(pokemon, poke2, supersplicers = false)
return selectedHead
end
# firstOptionSelected= selectedHead == pokemon
# selectedBody = selectedHead == pokemon ? poke2 : pokemon
# newid = (selectedBody.species_data.id_number) * NB_POKEMON + selectedHead.species_data.id_number
# def pbFuse(pokemon, poke2, supersplicers = false)
# newid = (pokemon.species_data.id_number) * NB_POKEMON + poke2.species_data.id_number
# previewwindow = FusionPreviewScreen.new(pokemon, poke2)#PictureWindow.new(picturePath)
#
# if (Kernel.pbConfirmMessage(_INTL("Fuse the two Pokémon?", newid)))
# previewwindow.dispose
# fus = PokemonFusionScene.new
# if (fus.pbStartScreen(pokemon, poke2, newid))
# returnItemsToBag(pokemon, poke2)
# fus.pbFusionScreen(false, supersplicers)
# $game_variables[126] += 1 #fuse counter
# fus.pbEndScreen
# return true
# end
# else
# previewwindow.dispose
# return false
# end
# end
def pbFuse(pokemon_body, pokemon_head, splicer_item)
use_supersplicers_mechanics = isSuperSplicersMechanics(splicer_item)
newid = (pokemon_body.species_data.id_number) * NB_POKEMON + pokemon_head.species_data.id_number
newid = (pokemon_body.species_data.id_number) * Settings::NB_POKEMON + pokemon_head.species_data.id_number
fus = PokemonFusionScene.new
if (fus.pbStartScreen(pokemon_body, pokemon_head, newid, splicer_item))
@@ -137,7 +104,7 @@ end
# Todo: refactor this, holy shit this is a mess
def pbUnfuse(pokemon, scene, supersplicers, pcPosition = nil)
if pokemon.species_data.id_number > (NB_POKEMON * NB_POKEMON) + NB_POKEMON # triple fusion
if pokemon.species_data.id_number > (Settings::NB_POKEMON * Settings::NB_POKEMON) + Settings::NB_POKEMON # triple fusion
scene.pbDisplay(_INTL("{1} cannot be unfused.", pokemon.name))
return false
end

View File

@@ -1,403 +1,421 @@
# 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
# head_id = get_head_number_from_symbol(id)
# body_id = get_body_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
#
# 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
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
head_id = get_head_number_from_symbol(id)
body_id = get_body_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()
@types = [@type1, @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
#todo: this was moved to pokemon_metrics
# read the data for the body pokemon's species whenever it tries to position a fusedSpecies
#
# @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
def type1
return @type1
end
def type2
return @type2
end
def apply_metrics_to_sprite(sprite, index, shadow = false)
body_species = get_body_species()
metrics_data = GameData::SpeciesMetrics.get_species_form(body_species, 0)
metrics_data.apply_metrics_to_sprite(sprite, index, shadow)
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 * Settings::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

File diff suppressed because it is too large Load Diff

View File

@@ -1,31 +1,74 @@
# module GameData
# module ClassMethods
# def get(other)
# validate other => [Symbol, self, String, Integer]
# return other if other.is_a?(self)
# other = other.to_sym if other.is_a?(String)
#
# if other.to_s.match?(/\AB\d+H\d+\z/)
# species = GameData::FusedSpecies.new(other)
# return species
# end
#
# if other.is_a?(Integer) && self == GameData::Species
# if other > NB_POKEMON
# body_id = getBodyID(other)
# head_id = getHeadID(other, body_id)
# pokemon_id = getFusedPokemonIdFromDexNum(body_id, head_id)
# return GameData::FusedSpecies.new(pokemon_id)
# end
# end
#
# if !self::DATA.has_key?(other)
# # echoln _INTL("Unknown ID {1}.", other)
# return self::get(:PIKACHU)
# end
#
# raise "Unknown ID #{other}." unless self::DATA.has_key?(other)
# return self::DATA[other]
# end
# end
# end
module GameData
module ClassMethods
def get(other)
validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self)
other = other.to_sym if other.is_a?(String)
if other.to_s.match?(/\AB\d+H\d+\z/)
species = GameData::FusedSpecies.new(other)
return species
end
if other.is_a?(Integer) && self == GameData::Species
if other > Settings::NB_POKEMON
body_id = getBodyID(other)
head_id = getHeadID(other, body_id)
pokemon_id = getFusedPokemonIdFromDexNum(body_id, head_id)
return GameData::FusedSpecies.new(pokemon_id)
else
species_id = GameData::Species.keys[other-1]
return GameData::Species.get(species_id) if species_id
end
end
if !self::DATA.has_key?(other)
# echoln _INTL("Unknown ID {1}.", other)
return self::get(:PIKACHU)
end
raise "Unknown ID #{other}." unless self::DATA.has_key?(other)
return self::DATA[other]
end
end
module ClassMethodsSymbols
def get(other)
validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self)
other = other.to_sym if other.is_a?(String)
if other.to_s.match?(/\AB\d+H\d+\z/)
species = GameData::FusedSpecies.new(other)
return species
end
if other.is_a?(Integer) && self == GameData::Species
if other > Settings::NB_POKEMON
body_id = getBodyID(other)
head_id = getHeadID(other, body_id)
pokemon_id = getFusedPokemonIdFromDexNum(body_id, head_id)
return GameData::FusedSpecies.new(pokemon_id)
else
species_id = GameData::Species.keys[other-1]
return GameData::Species.get(species_id) if species_id
end
end
raise "Unknown ID #{other}." unless self::DATA.has_key?(other)
return self::DATA[other]
end
def try_get(other)
return nil if other.nil?
validate other => [Symbol, self, String, Integer]
return other if other.is_a?(self)
other = other.to_sym if other.is_a?(String)
return (self::DATA.has_key?(other)) ? self::DATA[other] : nil
end
end
end

View 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

View 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 "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
}, "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

View File

@@ -0,0 +1,39 @@
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
new_level = calculateFusedPokemonLevel(poke1.level, poke2.level, usingSuperSplicers)
fusion_left = (poke1.species_data.id_number) * Settings::NB_POKEMON + poke2.species_data.id_number
fusion_right = (poke2.species_data.id_number) * Settings::NB_POKEMON + poke1.species_data.id_number
@picture1 = draw_window(fusion_left,new_level,20,30)
@picture2 = draw_window(fusion_right,new_level,270,30)
@sprites["picture1"] = @picture1
@sprites["picture2"] = @picture2
end
def getBackgroundPicture
super
end
end

File diff suppressed because it is too large Load Diff

View File

@@ -38,14 +38,14 @@ end
def species_is_fusion(species_id)
dex_number = get_dex_number(species_id)
return dex_number > NB_POKEMON && dex_number < Settings::ZAPMOLCUNO_NB
return dex_number > Settings::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)
def getBodyID(species, nb_pokemon = Settings::NB_POKEMON)
if species.is_a?(Integer)
dexNum = species
else
@@ -57,7 +57,7 @@ def getBodyID(species, nb_pokemon = NB_POKEMON)
return (dexNum / nb_pokemon).round
end
def getHeadID(species, bodyId = nil, nb_pokemon = NB_POKEMON)
def getHeadID(species, bodyId = nil, nb_pokemon = Settings::NB_POKEMON)
if species.is_a?(Integer)
fused_dexNum = species
else
@@ -408,3 +408,13 @@ def get_triple_fusion_components(species_id)
end
def reverseFusionSpecies(species)
dexId = getDexNumberForSpecies(species)
return species if dexId <= NB_POKEMON
return species if dexId > (NB_POKEMON * NB_POKEMON) + NB_POKEMON
body = getBasePokemonID(dexId, true)
head = getBasePokemonID(dexId, false)
newspecies = (head) * NB_POKEMON + body
return getPokemon(newspecies)
end