pokemon_gen.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include <src/include/pokemon_app.h>
  2. #include <src/include/pokemon_data.h>
  3. #include <src/include/pokemon_char_encode.h>
  4. #include <src/include/named_list.h>
  5. #include <src/views/trade.h>
  6. #include <src/views/select_pokemon.h>
  7. #include <src/scenes/include/pokemon_scene.h>
  8. #include <src/include/pokemon_attribute.h>
  9. static void scene_change_from_main_cb(void* context, uint32_t index) {
  10. PokemonFap* pokemon_fap = (PokemonFap*)context;
  11. /* Set scene state to the current index so we can have that element highlighted when
  12. * we return. Note that GenI scene is always used as a reference for this in this
  13. * scene, whether its GenI or GenII.
  14. */
  15. scene_manager_set_scene_state(pokemon_fap->scene_manager, PokemonSceneGenITrade, index);
  16. view_dispatcher_send_custom_event(pokemon_fap->view_dispatcher, index);
  17. }
  18. void pokemon_scene_gen_on_enter(void* context) {
  19. char buf[32];
  20. char name_buf[11]; // All name buffers are 11 bytes at most, including term
  21. PokemonFap* pokemon_fap = (PokemonFap*)context;
  22. PokemonData* pdata = pokemon_fap->pdata;
  23. int pkmn_num;
  24. uint32_t state;
  25. // Set up trade party struct
  26. if(!pdata) {
  27. state = scene_manager_get_scene_state(pokemon_fap->scene_manager, PokemonSceneGenITrade);
  28. switch(state) {
  29. case PokemonSceneGenITrade:
  30. state = GEN_I;
  31. break;
  32. case PokemonSceneGenIITrade:
  33. state = GEN_II;
  34. break;
  35. default:
  36. state = 0;
  37. break;
  38. }
  39. pokemon_fap->pdata = pokemon_data_alloc(state);
  40. pdata = pokemon_fap->pdata;
  41. /* Clear the scene state as this is the first entry in to this scene
  42. * we definitely want to be completely reset.
  43. */
  44. scene_manager_set_scene_state(pokemon_fap->scene_manager, PokemonSceneGenITrade, 0);
  45. /* Allocate select and trade views */
  46. /* Allocates its own view and adds it to the main view_dispatcher */
  47. pokemon_fap->select =
  48. select_pokemon_alloc(pdata, pokemon_fap->view_dispatcher, AppViewSelectPokemon);
  49. // Trade View
  50. /* Allocates its own view and adds it to the main view_dispatcher */
  51. pokemon_fap->trade = trade_alloc(
  52. pdata, pokemon_fap->gblink_handle, pokemon_fap->view_dispatcher, AppViewTrade);
  53. }
  54. pkmn_num = pokemon_stat_get(pdata, STAT_NUM, NONE);
  55. /* Clear the scene state of the Move scene since that is used to set the
  56. * highlighted menu item.
  57. * This could be done in move, but move would need its own custom exit handler
  58. * which is fine but would just waste a few more bytes compared to us handling
  59. * it here.
  60. */
  61. scene_manager_set_scene_state(pokemon_fap->scene_manager, PokemonSceneMove, 0);
  62. scene_manager_set_scene_state(pokemon_fap->scene_manager, PokemonSceneItemSet, 0);
  63. submenu_reset(pokemon_fap->submenu);
  64. snprintf(
  65. buf, sizeof(buf), "Pokemon: %s", table_stat_name_get(pdata->pokemon_table, pkmn_num));
  66. submenu_add_item(
  67. pokemon_fap->submenu, buf, PokemonSceneSelect, scene_change_from_main_cb, pokemon_fap);
  68. pokemon_name_get(pdata, STAT_NICKNAME, name_buf, sizeof(name_buf));
  69. snprintf(buf, sizeof(buf), "Nickname: %s", name_buf);
  70. submenu_add_item(
  71. pokemon_fap->submenu, buf, PokemonSceneNickname, scene_change_from_main_cb, pokemon_fap);
  72. snprintf(buf, sizeof(buf), "Level: %d", pokemon_stat_get(pdata, STAT_LEVEL, NONE));
  73. submenu_add_item(
  74. pokemon_fap->submenu, buf, PokemonSceneLevel, scene_change_from_main_cb, pokemon_fap);
  75. if(pdata->gen == GEN_II) {
  76. snprintf(
  77. buf,
  78. sizeof(buf),
  79. "Held Item: %s",
  80. namedlist_name_get_index(
  81. pdata->item_list, pokemon_stat_get(pdata, STAT_HELD_ITEM, NONE)));
  82. submenu_add_item(
  83. pokemon_fap->submenu, buf, PokemonSceneItem, scene_change_from_main_cb, pokemon_fap);
  84. }
  85. submenu_add_item(
  86. pokemon_fap->submenu,
  87. "Select Moves",
  88. PokemonSceneMove,
  89. scene_change_from_main_cb,
  90. pokemon_fap);
  91. if(pdata->gen == GEN_I) {
  92. submenu_add_item(
  93. pokemon_fap->submenu,
  94. "Select Types",
  95. PokemonSceneType,
  96. scene_change_from_main_cb,
  97. pokemon_fap);
  98. }
  99. submenu_add_item(
  100. pokemon_fap->submenu,
  101. namedlist_name_get_index(pdata->stat_list, pokemon_stat_get(pdata, STAT_SEL, NONE)),
  102. PokemonSceneStats,
  103. scene_change_from_main_cb,
  104. pokemon_fap);
  105. if(pdata->gen == GEN_II) {
  106. snprintf(
  107. buf, sizeof(buf), "Shiny: %s", pokemon_is_shiny(pdata) ? "Yes" : "No");
  108. submenu_add_item(
  109. pokemon_fap->submenu, buf, PokemonSceneShiny, scene_change_from_main_cb, pokemon_fap);
  110. snprintf(buf, sizeof(buf), "Gender: %s", pokemon_gender_get(pdata));
  111. submenu_add_item(
  112. pokemon_fap->submenu, buf, PokemonSceneGender, scene_change_from_main_cb, pokemon_fap);
  113. snprintf(buf, sizeof(buf), "Pokerus: %s", pokerus_get_status_str(pdata));
  114. submenu_add_item(
  115. pokemon_fap->submenu, buf, PokemonScenePokerus, scene_change_from_main_cb, pokemon_fap);
  116. if(pokemon_stat_get(pdata, STAT_NUM, NONE) == 0xC8) { // Unown
  117. snprintf(buf, sizeof(buf), "Unown Form: %c", unown_form_get(pdata));
  118. submenu_add_item(
  119. pokemon_fap->submenu,
  120. buf,
  121. PokemonSceneUnownForm,
  122. scene_change_from_main_cb,
  123. pokemon_fap);
  124. }
  125. }
  126. snprintf(buf, sizeof(buf), "OT ID#: %05d", pokemon_stat_get(pdata, STAT_OT_ID, NONE));
  127. submenu_add_item(
  128. pokemon_fap->submenu, buf, PokemonSceneOTID, scene_change_from_main_cb, pokemon_fap);
  129. pokemon_name_get(pdata, STAT_OT_NAME, name_buf, sizeof(name_buf));
  130. snprintf(buf, sizeof(buf), "OT Name: %s", name_buf);
  131. submenu_add_item(
  132. pokemon_fap->submenu, buf, PokemonSceneOTName, scene_change_from_main_cb, pokemon_fap);
  133. submenu_add_item(
  134. pokemon_fap->submenu,
  135. "Trade PKMN",
  136. PokemonSceneTrade,
  137. scene_change_from_main_cb,
  138. pokemon_fap);
  139. if(trade_connected(pokemon_fap->trade)) {
  140. submenu_add_item(
  141. pokemon_fap->submenu,
  142. "Reset Connection",
  143. PokemonSceneResetConfirm,
  144. scene_change_from_main_cb,
  145. pokemon_fap);
  146. }
  147. /* TODO: Add Save pokemon option here */
  148. /* HACK: No matter what gen were in, we just store the scene state in PokemonSceneGenITrade */
  149. submenu_set_selected_item(
  150. pokemon_fap->submenu,
  151. scene_manager_get_scene_state(pokemon_fap->scene_manager, PokemonSceneGenITrade));
  152. view_dispatcher_switch_to_view(pokemon_fap->view_dispatcher, AppViewSubmenu);
  153. }
  154. bool pokemon_scene_gen_on_event(void* context, SceneManagerEvent event) {
  155. PokemonFap* pokemon_fap = context;
  156. bool consumed = false;
  157. PokemonData* pdata = pokemon_fap->pdata;
  158. uint8_t pokemon_num;
  159. uint8_t gender_ratio;
  160. /* If the user tries to go back from this scene to main menu, instead
  161. * shift to the exit confirmation scene. That scene will handle freeing
  162. * data as well as going back to the main menu.
  163. */
  164. if(event.type == SceneManagerEventTypeBack) {
  165. scene_manager_next_scene(pokemon_fap->scene_manager, PokemonSceneExitConfirm);
  166. consumed = true;
  167. }
  168. if(event.type == SceneManagerEventTypeCustom) {
  169. consumed = true;
  170. /* Reuse of scenes to allow for using the same functions to set names */
  171. switch(event.event) {
  172. case PokemonSceneNickname:
  173. case PokemonSceneOTName:
  174. case PokemonSceneUnownForm:
  175. scene_manager_set_scene_state(
  176. pokemon_fap->scene_manager, PokemonSceneNickname, event.event);
  177. break;
  178. case PokemonSceneLevel:
  179. case PokemonSceneOTID:
  180. scene_manager_set_scene_state(
  181. pokemon_fap->scene_manager, PokemonSceneLevel, event.event);
  182. break;
  183. case PokemonSceneGender:
  184. pokemon_num = pokemon_stat_get(pdata, STAT_NUM, NONE);
  185. gender_ratio = table_stat_base_get(
  186. pdata->pokemon_table, pokemon_num, STAT_BASE_GENDER_RATIO, NONE);
  187. /* If the pokemon's gender is static (always male, always female,
  188. * or unknown), then don't transition to the gender selection scene.
  189. */
  190. if(pokemon_gender_is_static(pdata, gender_ratio)) goto out;
  191. break;
  192. }
  193. scene_manager_next_scene(pokemon_fap->scene_manager, event.event);
  194. }
  195. out:
  196. return consumed;
  197. }
  198. void pokemon_scene_gen_on_exit(void* context) {
  199. UNUSED(context);
  200. }