From bfa1a4caa8330141dfe1e8eeb1157eac68e2ba0b Mon Sep 17 00:00:00 2001 From: Philippe Symons Date: Thu, 29 Jan 2026 12:26:44 +0100 Subject: [PATCH] Add entries for the PokeShop (WIP) --- include/menu/PokeShopEntries.h | 29 + src/menu/PokeShopEntries.cpp | 2279 +++++++++++++++++++++++++ src/scenes/PokeShopScene.cpp | 277 ++- src/widget/PokeShopMenuItemWidget.cpp | 4 +- 4 files changed, 2586 insertions(+), 3 deletions(-) create mode 100644 include/menu/PokeShopEntries.h create mode 100644 src/menu/PokeShopEntries.cpp diff --git a/include/menu/PokeShopEntries.h b/include/menu/PokeShopEntries.h new file mode 100644 index 0000000..44a1511 --- /dev/null +++ b/include/menu/PokeShopEntries.h @@ -0,0 +1,29 @@ +#ifndef _POKESHOPENTRIES_H +#define _POKESHOPENTRIES_H + +#include "gen1/Gen1DistributionPokemon.h" +#include "gen2/Gen2DistributionPokemon.h" + +typedef struct Gen1PokeShopEntry +{ + const Gen1DistributionPokemon* pokemon; + uint32_t price; +} Gen1PokeShopEntry; + +typedef struct Gen2PokeShopEntry +{ + const Gen2DistributionPokemon* pokemon; + uint32_t price; +} Gen2PokeShopEntry; + +/** + * @brief This function returns the menu entries for the PokéShop scene for a specific gen 1 game variant + */ +void getGen1PokeShopEntries(uint8_t gameVariant, uint8_t localization, const Gen1PokeShopEntry *&entries, uint32_t &outNumEntries); + +/** + * @brief This function returns the menu entries for the PokéShop scene for a specific gen 2 game variant + */ +void getGen2PokeShopEntries(uint8_t gameVariant, uint8_t localization, const Gen2PokeShopEntry *&entries, uint32_t &outNumEntries); + +#endif \ No newline at end of file diff --git a/src/menu/PokeShopEntries.cpp b/src/menu/PokeShopEntries.cpp new file mode 100644 index 0000000..ea59e96 --- /dev/null +++ b/src/menu/PokeShopEntries.cpp @@ -0,0 +1,2279 @@ +#include "menu/PokeShopEntries.h" +#include "Moves.h" +#include "gen1/Gen1Localization.h" +#include "gen2/Gen2Localization.h" + +static const Gen1DistributionPokemon g1_starter_Charmander = { + .name = "Charmander", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0xB0, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 20, // FIRE + .type2 = 20, // FIRE + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::SCRATCH, + .index_move2 = (uint8_t)Move::GROWL, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 40, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_starter_Squirtle = { + .name = "Squirtle", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0xB1, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 21, // WATER + .type2 = 21, // WATER + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = (uint8_t)Move::TAIL_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_starter_Bulbasaur = { + .name = "Bulbasaur", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x99, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 22, // GRASS + .type2 = 22, // GRASS + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = (uint8_t)Move::GROWL, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 40, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Weedle = { + .name = "Weedle", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x70, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 7, // BUG + .type2 = 3, // POISON + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::POISON_STING, + .index_move2 = (uint8_t)Move::STRING_SHOT, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 40, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Ekans = { + .name = "Ekans", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x6C, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 3, // POISON + .type2 = 3, // POISON + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::WRAP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 20, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Pikachu = { + .name = "Pikachu", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x54, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 23, // ELECTRIC + .type2 = 23, // ELECTRIC + .catch_rate_or_held_item = 0xBE, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::THUNDER_SHOCK, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Sandshrew = { + .name = "Sandshrew", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x60, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 4, // GROUND + .type2 = 4, // GROUND + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::SCRATCH, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Vulpix = { + .name = "Vulpix", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x52, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 20, // FIRE + .type2 = 20, // FIRE + .catch_rate_or_held_item = 0xBE, + .index_move1 = (uint8_t)Move::EMBER, + .index_move2 = (uint8_t)Move::TAIL_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Oddish = { + .name = "Oddish", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0xB9, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 22, // GRASS + .type2 = 22, // GRASS + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::ABSORB, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Meowth = { + .name = "Meowth", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x4D, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 0, // NORMAL + .type2 = 0, // NORMAL + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Mankey = { + .name = "Mankey", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x39, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 1, // FIGHTING + .type2 = 1, // FIGHTING + .catch_rate_or_held_item = 0xBE, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Growlithe = { + .name = "Growlithe", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x21, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 20, // FIRE + .type2 = 20, // FIRE + .catch_rate_or_held_item = 0xBE, + .index_move1 = (uint8_t)Move::BITE, + .index_move2 = (uint8_t)Move::ROAR, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 20, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Bellsprout = { + .name = "Bellsprout", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0xBC, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 22, // GRASS + .type2 = 22, // GRASS + .catch_rate_or_held_item = 0xFF, + .index_move1 = (uint8_t)Move::GROWTH, + .index_move2 = (uint8_t)Move::VINE_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 20, + .pp_move2 = 25, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Koffing = { + .name = "Koffing", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x37, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 3, // POISON + .type2 = 3, // POISON + .catch_rate_or_held_item = 0xBE, + .index_move1 = (uint8_t)Move::SMOG, + .index_move2 = (uint8_t)Move::TACKLE, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 20, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Scyther = { + .name = "Scyther", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x1A, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 7, // BUG + .type2 = 2, // FLYING + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::QUICK_ATTACK, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Jynx = { + .name = "Jynx", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x48, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 25, // ICE + .type2 = 24, // PSYCHIC + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::LOVELY_KISS, + .index_move2 = (uint8_t)Move::POUND, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 10, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Electabuzz = { + .name = "Electabuzz", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x35, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 23, // ELECTRIC + .type2 = 23, // ELECTRIC + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::QUICK_ATTACK, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Magmar = { + .name = "Magmar", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x33, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 20, // FIRE + .type2 = 20, // FIRE + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::EMBER, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen1DistributionPokemon g1_versionexclusive_Pinsir = { + .name = "Pinsir", + .originalTrainer = "", + .originalTrainerID = 0, + .iv_data = {0, 0}, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .isJapanese = false, + .held_item_override = 0, + .poke = { + .poke_index = 0x1D, + .current_hp = 1, + .level = 5, + .status_condition = 0, + .type1 = 7, // BUG + .type2 = 7, // BUG + .catch_rate_or_held_item = 0x2D, + .index_move1 = (uint8_t)Move::VICE_GRIP, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GRW_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Cyndaquil = { + .name = "Cyndaquil", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x9B, + .held_item_index = 0xAD, // Berry + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::TACKLE, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Totodile = { + .name = "Totodile", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x9E, + .held_item_index = 0xAD, // Berry + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Chikorita = { + .name = "Chikorita", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x98, + .held_item_index = 0xAD, // Berry + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = (uint8_t)Move::TAIL_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Charmander = { + .name = "Charmander", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x04, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Squirtle = { + .name = "Squirtle", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x07, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = (uint8_t)Move::TAIL_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_starter_Bulbasaur = { + .name = "Bulbasaur", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x01, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = (uint8_t)Move::GROWL, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 40, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Vulpix = { + .name = "Vulpix", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x25, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::EMBER, + .index_move2 = (uint8_t)Move::TAIL_WHIP, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 30, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Meowth = { + .name = "Meowth", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x34, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Mankey = { + .name = "Mankey", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x38, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Growlithe = { + .name = "Growlithe", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0x3A, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::BITE, + .index_move2 = (uint8_t)Move::ROAR, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 20, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Ledyba = { + .name = "Ledyba", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xA5, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::TACKLE, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Spinarak = { + .name = "Spinarak", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xA7, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::POISON_STING, + .index_move2 = (uint8_t)Move::STRING_SHOT, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 40, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Mareep = { + .name = "Mareep", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xB3, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::TACKLE, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Girafarig = { + .name = "Girafarig", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xCB, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::CONFUSION, + .index_move2 = (uint8_t)Move::GROWL, + .index_move3 = (uint8_t)Move::STOMP, + .index_move4 = (uint8_t)Move::TACKLE, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 40, + .pp_move3 = 20, + .pp_move4 = 35, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Gligar = { + .name = "Gligar", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xCF, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::POISON_STING, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 35, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Teddiursa = { + .name = "Teddiursa", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xD8, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::SCRATCH, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Remoraid = { + .name = "Remoraid", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xDF, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::WATER_GUN, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 25, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Delibird = { + .name = "Delibird", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xE1, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::PRESENT, + .index_move2 = 0, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 15, + .pp_move2 = 0, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Mantine = { + .name = "Mantine", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xE2, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::BUBBLE, + .index_move2 = (uint8_t)Move::TACKLE, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Skarmory = { + .name = "Skarmory", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xE3, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::LEER, + .index_move2 = (uint8_t)Move::PECK, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_SLOW), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 30, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static const Gen2DistributionPokemon g2_versionexclusive_Phanpy = { + .name = "Phanpy", + .originalTrainer = "", + .originalTrainerID = 0, + .setPlayerAsOriginalTrainer = true, + .regenerateTrainerID = false, + .shinyChance = 0, + .overrideLevel = 0, + .isEgg = false, + .iv_data = {0, 0}, + .randomizeIVs = true, + .isJapanese = false, + .poke = { + .poke_index = 0xE7, + .held_item_index = 0, + .index_move1 = (uint8_t)Move::GROWL, + .index_move2 = (uint8_t)Move::TACKLE, + .index_move3 = 0, + .index_move4 = 0, + .original_trainer_ID = 0, + .exp = getExpNeededForLevel(5, GEN2_GRW_MEDIUM_FAST), + .hp_effort_value = 0, + .atk_effort_value = 0, + .def_effort_value = 0, + .speed_effort_value = 0, + .special_effort_value = 0, + .iv_data = {0, 0}, + .pp_move1 = 40, + .pp_move2 = 35, + .pp_move3 = 0, + .pp_move4 = 0, + .friendship_or_remaining_egg_cycles = 70, + .pokerus = 0, + .caught_data = 0, + .level = 5, + .status_condition = 0, + .unused_byte = 0, + .current_hp = 0, + .max_hp = 0, + .atk = 0, + .def = 0, + .speed = 0, + .special_atk = 0, + .special_def = 0 + } +}; + +static Gen1PokeShopEntry dummyGen1Entries[] = {}; +static Gen2PokeShopEntry dummyGen2Entries[] = {}; + +static Gen1PokeShopEntry g1_shop_red_entries[] = { + { + .pokemon = &g1_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g1_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g1_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Sandshrew, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Vulpix, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Meowth, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Bellsprout, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Magmar, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Pinsir, + .price = 3000 + } +}; + +static Gen1PokeShopEntry g1_shop_green_entries[] = { + { + .pokemon = &g1_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g1_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g1_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Ekans, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Oddish, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Mankey, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Growlithe, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Scyther, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Electabuzz, + .price = 3000 + } +}; + +static Gen1PokeShopEntry g1_shop_jpn_blue_entries[] = { + { + .pokemon = &g1_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g1_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g1_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Ekans, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Vulpix, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Mankey, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Bellsprout, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Electabuzz, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Magmar, + .price = 3000 + } +}; + +static Gen1PokeShopEntry g1_shop_yellow_entries[] = { + { + .pokemon = &g1_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g1_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g1_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Weedle, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Ekans, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Pikachu, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Meowth, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Koffing, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Jynx, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Electabuzz, + .price = 3000 + }, + { + .pokemon = &g1_versionexclusive_Magmar, + .price = 3000 + } +}; + +static Gen2PokeShopEntry g2_shop_gold_entries[] = { + { + .pokemon = &g2_starter_Cyndaquil, + .price = 3000 + }, + { + .pokemon = &g2_starter_Totodile, + .price = 3000 + }, + { + .pokemon = &g2_starter_Chikorita, + .price = 3000 + }, + { + .pokemon = &g2_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g2_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g2_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Vulpix, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Meowth, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Ledyba, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Delibird, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Skarmory, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Phanpy, + .price = 3000 + } +}; + +static Gen2PokeShopEntry g2_shop_silver_entries[] = { + { + .pokemon = &g2_starter_Cyndaquil, + .price = 3000 + }, + { + .pokemon = &g2_starter_Totodile, + .price = 3000 + }, + { + .pokemon = &g2_starter_Chikorita, + .price = 3000 + }, + { + .pokemon = &g2_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g2_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g2_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mankey, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Growlithe, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Spinarak, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Gligar, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Teddiursa, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mantine, + .price = 3000 + } +}; + +static Gen2PokeShopEntry g2_shop_crystal_entries[] = { + { + .pokemon = &g2_starter_Cyndaquil, + .price = 3000 + }, + { + .pokemon = &g2_starter_Totodile, + .price = 3000 + }, + { + .pokemon = &g2_starter_Chikorita, + .price = 3000 + }, + { + .pokemon = &g2_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g2_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g2_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Vulpix, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mankey, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mareep, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Girafarig, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Remoraid, + .price = 3000 + } +}; + +static Gen2PokeShopEntry g2_shop_jpn_kor_gold_entries[] = { + { + .pokemon = &g2_starter_Cyndaquil, + .price = 3000 + }, + { + .pokemon = &g2_starter_Totodile, + .price = 3000 + }, + { + .pokemon = &g2_starter_Chikorita, + .price = 3000 + }, + { + .pokemon = &g2_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g2_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g2_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Vulpix, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Meowth, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Ledyba, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Delibird, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Skarmory, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Teddiursa, + .price = 3000 + } +}; + +static Gen2PokeShopEntry g2_shop_jpn_kor_silver_entries[] = { + { + .pokemon = &g2_starter_Cyndaquil, + .price = 3000 + }, + { + .pokemon = &g2_starter_Totodile, + .price = 3000 + }, + { + .pokemon = &g2_starter_Chikorita, + .price = 3000 + }, + { + .pokemon = &g2_starter_Charmander, + .price = 3000 + }, + { + .pokemon = &g2_starter_Squirtle, + .price = 3000 + }, + { + .pokemon = &g2_starter_Bulbasaur, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mankey, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Growlithe, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Spinarak, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Gligar, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Phanpy, + .price = 3000 + }, + { + .pokemon = &g2_versionexclusive_Mantine, + .price = 3000 + } +}; + +void getGen1PokeShopEntries(uint8_t gameVariant, uint8_t localization, const Gen1PokeShopEntry *&entries, uint32_t &outNumEntries) +{ + // The version exclusives for the international Blue release are the same as the Japanese Green release. + // But there's a dedicated set of exclusives for the Japanese Blue release. + // source: https://bulbapedia.bulbagarden.net/wiki/Version-exclusive_Pok%C3%A9mon#Generation_I + if( static_cast(localization) == Gen1LocalizationLanguage::JAPANESE && + static_cast(gameVariant) == Gen1GameType::BLUE) + { + entries = g1_shop_jpn_blue_entries; + outNumEntries = sizeof(g1_shop_jpn_blue_entries) / sizeof(Gen1PokeShopEntry); + return; + } + + switch(static_cast(gameVariant)) + { + case Gen1GameType::RED: + entries = g1_shop_red_entries; + outNumEntries = sizeof(g1_shop_red_entries) / sizeof(Gen1PokeShopEntry); + break; + // International Blue has the same exclusives as Green. + // see comment above + case Gen1GameType::GREEN: + case Gen1GameType::BLUE: + entries = g1_shop_green_entries; + outNumEntries = sizeof(g1_shop_green_entries) / sizeof(Gen1PokeShopEntry); + break; + case Gen1GameType::YELLOW: + entries = g1_shop_yellow_entries; + outNumEntries = sizeof(g1_shop_yellow_entries) / sizeof(Gen1PokeShopEntry); + break; + default: + entries = dummyGen1Entries; + outNumEntries = 0; + break; + } +} + +void getGen2PokeShopEntries(uint8_t gameVariant, uint8_t localization, const Gen2PokeShopEntry *&entries, uint32_t &outNumEntries) +{ + // While it's a bit silly to duplicate the switch statements specifically for Japanese/Korean, + // it's the easiest way to keep things clear and avoid mistakes. + // Even though the only real difference between these and the international versions is the fact that + // Phanpy and Teddiursa are swapped between Silver and Gold. + if( static_cast(localization) == Gen2LocalizationLanguage::JAPANESE || + static_cast(localization) == Gen2LocalizationLanguage::KOREAN) + { + switch(static_cast(gameVariant)) + { + case Gen2GameType::GOLD: + entries = g2_shop_jpn_kor_gold_entries; + outNumEntries = sizeof(g2_shop_jpn_kor_gold_entries) / sizeof(Gen2PokeShopEntry); + break; + case Gen2GameType::SILVER: + entries = g2_shop_jpn_kor_silver_entries; + outNumEntries = sizeof(g2_shop_jpn_kor_silver_entries) / sizeof(Gen2PokeShopEntry); + break; + case Gen2GameType::CRYSTAL: + entries = g2_shop_crystal_entries; + outNumEntries = sizeof(g2_shop_crystal_entries) / sizeof(Gen2PokeShopEntry); + break; + default: + entries = dummyGen2Entries; + outNumEntries = 0; + break; + } + return; + } + else + { + switch(static_cast(gameVariant)) + { + case Gen2GameType::GOLD: + entries = g2_shop_gold_entries; + outNumEntries = sizeof(g2_shop_gold_entries) / sizeof(Gen2PokeShopEntry); + break; + case Gen2GameType::SILVER: + entries = g2_shop_silver_entries; + outNumEntries = sizeof(g2_shop_silver_entries) / sizeof(Gen2PokeShopEntry); + break; + case Gen2GameType::CRYSTAL: + entries = g2_shop_crystal_entries; + outNumEntries = sizeof(g2_shop_crystal_entries) / sizeof(Gen2PokeShopEntry); + break; + default: + entries = dummyGen2Entries; + outNumEntries = 0; + break; + } + } +} \ No newline at end of file diff --git a/src/scenes/PokeShopScene.cpp b/src/scenes/PokeShopScene.cpp index d4a8218..bb46f74 100644 --- a/src/scenes/PokeShopScene.cpp +++ b/src/scenes/PokeShopScene.cpp @@ -2,12 +2,13 @@ #include "scenes/SceneManager.h" #include "scenes/StatsScene.h" #include "transferpak/TransferPakManager.h" +#include "menu/PokeShopEntries.h" static const Rectangle menuListBounds = {20, 20, 280, 0}; static const Rectangle imgScrollArrowUpBounds = {.x = 154, .y = 14, .width = 11, .height = 6}; static const Rectangle imgScrollArrowDownBounds = {.x = 154, .y = 220, .width = 11, .height = 6}; -static void injectDistributionPokemon(void* context, const void* data) +static void injectShopPokemon(void* context, const void* data) { auto scene = static_cast(context); scene->triggerPokemonInjection(data); @@ -36,4 +37,278 @@ void PokeShopScene::init() iconBackgroundSprite_ = sprite_load("rom://bg-party-icon.sprite"); loadShopList(); MenuScene::init(); +} + +void PokeShopScene::destroy() +{ + MenuScene::destroy(); + + delete[] context_->menuEntries; + context_->menuEntries = nullptr; + context_->numMenuEntries = 0; + + sprite_free(iconBackgroundSprite_); + iconBackgroundSprite_ = nullptr; +} + +bool PokeShopScene::handleUserInput(joypad_port_t port, const joypad_inputs_t& inputs) +{ + if(pokeToInject_) + { + injectPokemon(pokeToInject_); + pokeToInject_ = nullptr; + return true; + } + else + { + return MenuScene::handleUserInput(port, inputs); + } +} + +void PokeShopScene::triggerPokemonInjection(const void* data) +{ + pokeToInject_ = data; + + setDialogDataText(diag_, "Saving... Don't turn off the power."); + diag_.userAdvanceBlocked = true; + showDialog(&diag_); +} + +void PokeShopScene::injectPokemon(const void* data) +{ +#if 0 + StatsSceneContext* statsContext; + const Gen1DistributionPokemon* g1Poke; + const Gen2DistributionPokemon* g2Poke; + const char* trainerName; + + deps_.tpakManager.setRAMEnabled(true); + + statsContext = new StatsSceneContext{ + .showReceivedPokemonDialog = true + }; + + switch(convert(context_)->listType) + { + case DistributionPokemonListType::GEN1: + g1Poke = static_cast(data); + statsContext->poke_g1 = g1Poke->poke; + // I have not used gen1Reader_->addDistributionPokemon here because I want to show the resulting pokemon in a stats screen + // gen1_prepareDistributionPokemon() + addPokemon() gives me access to the resulting Gen1TrainerPokemon instance + // in which things are done like IV generation, OT name decision, OT id + gen1_prepareDistributionPokemon(gen1Reader_, (*g1Poke), statsContext->poke_g1, trainerName); + gen1Reader_.addPokemon(statsContext->poke_g1, trainerName); + break; + case DistributionPokemonListType::GEN2: + case DistributionPokemonListType::GEN2_POKEMON_CENTER_NEW_YORK: + g2Poke = static_cast(data); + statsContext->poke_g2 = g2Poke->poke; + statsContext->isEgg = g2Poke->isEgg; + // I have not used gen2Reader_->addDistributionPokemon here because I want to show the resulting pokemon in a stats screen + // gen2_prepareDistributionPokemon() + addPokemon() gives me access to the resulting Gen2TrainerPokemon instance + // in which things are done like IV generation, OT name decision, OT id, shininess + gen2_prepareDistributionPokemon(gen2Reader_, (*g2Poke), statsContext->poke_g2, trainerName); + gen2Reader_.addPokemon(statsContext->poke_g2, g2Poke->isEgg, trainerName); + gen2Reader_.finishSave(); + break; + default: + debugf("%s: ERROR: got DistributionPokemonListType::INVALID! This should never happen!\r\n", __FUNCTION__); + /* Quote: + * "It is recommended to disable external RAM after accessing it, in order to protect its contents from corruption + * during power down of the Game Boy or removal of the cartridge. Once the cartridge has completely lost power from + * the Game Boy, the RAM is automatically disabled to protect it." + * + * source: https://gbdev.io/pandocs/MBC1.html + * + * Yes, I'm aware we're dealing with MBC3 here, but there's some overlap and what applies to MBC1 here likely also applies + * to MBC3 + */ + deps_.tpakManager.setRAMEnabled(false); + delete statsContext; + statsContext = nullptr; + return; + } + + deps_.tpakManager.finishWrites(); + + // The reason is the same as previous setRAMEnabled(false) statement above + deps_.tpakManager.setRAMEnabled(false); + + strncpy(statsContext->trainerName, trainerName, 12); + deps_.sceneManager.switchScene(SceneType::STATS, deleteStatsSceneContext, statsContext); + + // operation done. Now the dialog can be advanced and we can show confirmation that the user got the pokémon +#endif +} + +void PokeShopScene::onDialogDone() +{ + if(diag_.userAdvanceBlocked) + { + // ignore this notification. We advanced this one ourselves to get to the next one + return; + } + // We're done with the injection. Go back to the previous menu + deps_.sceneManager.goBackToPreviousScene(); +} + +void PokeShopScene::setupMenu() +{ + const VerticalListStyle listStyle = { + .margin = { + .top = 5, + .bottom = 5 + }, + .verticalSpacingBetweenWidgets = 1, + .autogrow = { + .enabled = true, + .maxHeight = 200 + } + }; + + menuList_.setStyle(listStyle); + menuList_.setBounds(menuListBounds); + menuList_.setVisible(true); + menuList_.registerScrollWindowListener(this); + + cursorWidget_.setVisible(false); + + const PokeShopMenuItemStyle itemStyle = { + .size = {280, 22}, + .background = { + .sprite = menu9SliceSprite_, + .spriteSettings = { + .renderMode = SpriteRenderMode::NINESLICE, + .srcRect = { 6, 6, 6, 6 } + } + }, + .icon = { + .style = { + .background = { + .sprite = iconBackgroundSprite_ + }, + .icon = { + .bounds = { 2, 2, 16, 16 }, + .yOffsetWhenTheresNoFrame2 = -1 + }, + .fpsWhenFocused = 8, + .fpsWhenNotFocused = 2 + }, + .bounds = {0, 1, 20, 20} + }, + .title = { + .labelNotFocused = { + .fontId = mainFontId_, + .fontStyleId = fontStyleWhiteId_ + }, + .labelFocused = { + .fontId = mainFontId_, + .fontStyleId = fontStyleYellowId_ + }, + .bounds = {24, 4, 100, 18} + }, + .price = { + .labelNotFocused = { + .fontId = mainFontId_, + .fontStyleId = fontStyleWhiteId_ + }, + .labelFocused = { + .fontId = mainFontId_, + .fontStyleId = fontStyleYellowId_ + }, + .bounds = {104, 4, 80, 18} + } + }; + + customListFiller_.addItems(static_cast(context_->menuEntries), context_->numMenuEntries, itemStyle); + + const ImageWidgetStyle scrollArrowUpStyle = { + .image = { + .sprite = uiArrowUpSprite_, + .spriteBounds = {0, 0, imgScrollArrowUpBounds.width, imgScrollArrowUpBounds.height} + } + }; + + scrollArrowUp_.setStyle(scrollArrowUpStyle); + scrollArrowUp_.setBounds(imgScrollArrowUpBounds); + + const ImageWidgetStyle scrollArrowDownStyle = { + .image = { + .sprite = uiArrowDownSprite_, + .spriteBounds = { 0, 0, imgScrollArrowDownBounds.width, imgScrollArrowDownBounds.height} + } + }; + + // note: even though autogrow is turned on for the vertical list, it doesn't matter for the down arrow. + // because when the list is still growing, no scrolling is needed anyway, so the arrow would be invisible anyway. + scrollArrowDown_.setStyle(scrollArrowDownStyle); + scrollArrowDown_.setBounds(imgScrollArrowDownBounds); +} + +void PokeShopScene::loadShopList() +{ + MenuSceneContext *context = (MenuSceneContext*)context_; + const Gen1PokeShopEntry *gen1shopEntries = nullptr; + const Gen2PokeShopEntry *gen2shopEntries = nullptr; + uint32_t listSize = 0; + uint32_t i; + uint8_t iconType; + + switch(deps_.generation) + { + case 1: + getGen1PokeShopEntries(deps_.specificGenVersion, deps_.localization, gen1shopEntries, listSize); + break; + case 2: + getGen2PokeShopEntries(deps_.specificGenVersion, deps_.localization, gen2shopEntries, listSize); + break; + default: + return; + } + + if(!listSize) + { + return; + } + context->menuEntries = new PokeShopMenuItemData[listSize]; + context->numMenuEntries = listSize; + + for(i = 0; i < listSize; ++i) + { + PokeShopMenuItemData* menuEntry = static_cast(context_->menuEntries) + i; + + if(deps_.generation == 1) + { + iconType = (uint8_t)gen1Reader_.getPokemonIconType(gen1shopEntries[i].pokemon->poke.poke_index); + + menuEntry->title = gen1shopEntries[i].pokemon->name; + menuEntry->itemParam = &(gen1shopEntries[i]); + menuEntry->price = gen1shopEntries[i].price; + } + else + { + if(gen2shopEntries[i].pokemon->isEgg) + { + iconType = (uint8_t)Gen2PokemonIconType::GEN2_ICONTYPE_EGG; + } + else + { + iconType = (uint8_t)gen2Reader_.getPokemonIconType(gen2shopEntries[i].pokemon->poke.poke_index); + } + + menuEntry->title = gen2shopEntries[i].pokemon->name; + menuEntry->itemParam = &(gen2shopEntries[i]); + menuEntry->price = gen2shopEntries[i].price; + } + + menuEntry->onConfirmAction = injectShopPokemon; + menuEntry->context = this; + menuEntry->iconData = { + .iconFactory = &iconFactory_, + .generation = deps_.generation, + .specificGenVersion = deps_.specificGenVersion, + .localization = deps_.localization, + .iconType = iconType + }; + } } \ No newline at end of file diff --git a/src/widget/PokeShopMenuItemWidget.cpp b/src/widget/PokeShopMenuItemWidget.cpp index 0987511..542bc51 100644 --- a/src/widget/PokeShopMenuItemWidget.cpp +++ b/src/widget/PokeShopMenuItemWidget.cpp @@ -4,7 +4,7 @@ PokeShopMenuItem::PokeShopMenuItem() : partyIconWidget_() , style_({0}) , data_() - , priceText_({0}) + , priceText_("\0") , focused_(false) , visible_(true) , aButtonPressed_(false) @@ -24,7 +24,7 @@ void PokeShopMenuItem::setData(const PokeShopMenuItemData& data) { data_ = data; - snprintf(priceText_, sizeof(priceText_), "$%u", data.price); + snprintf(priceText_, sizeof(priceText_), "$%lu", data.price); partyIconWidget_.setData(data.iconData); }