pokemon/window/menu.cpp

307 lines
7.4 KiB
C++

#include "menu.hpp"
#include "window.hpp"
#include "../graphic.hpp"
#include "../control.hpp"
#include "../trainer.hpp"
#include "../font.hpp"
#include "../number.hpp"
#include "../gen/pokemon/moves.hpp"
#include "../gen/pokemon/types.hpp"
#define POKE "\x94"
#define TRAINER "\x92"
#define PKMN "\x96"
#define S(v) reinterpret_cast<const uint8_t *>(v)
static void draw_cursor(const uint32_t base_pattern,
const menu_t& menu,
const cursor_t& cursor)
{
const uint32_t cell_x = menu.top_left.x + 1 + (menu.h_advance * cursor.x);
const uint32_t cell_y = menu.top_left.y + menu.v_advance + (menu.v_advance * cursor.y);
put_char(base_pattern, cell_x, cell_y, interactive::l_arrow_solid);
}
static void draw_menu(const uint32_t base_pattern,
const menu_t& menu,
const trainer_state_t& trainer_state)
{
draw_box_border(base_pattern,
menu.top_left, menu.bottom_right);
draw_box_background(base_pattern,
menu.top_left, menu.bottom_right);
for (uint32_t y = 0; y < menu.height; y++) {
for (uint32_t x = 0; x < menu.width; x++) {
const uint32_t cell_x = menu.top_left.x + 2 + (menu.h_advance * x);
const uint32_t cell_y = menu.top_left.y + menu.v_advance + (menu.v_advance * y);
const uint32_t menu_entry_index = menu.width * y + x;
const menu_entry_t& entry = menu.entry;
if (menu.entry_type == menu_t::labels) {
draw_text(base_pattern,
entry.labels[menu_entry_index],
cell_x, cell_y);
} else {
draw_text(base_pattern,
entry.label_func(menu_entry_index, trainer_state),
cell_x, cell_y);
}
}
}
}
void
window__menu_t::draw(const uint32_t base_pattern,
const union window_descriptor_t::data& data,
const window_t& window,
const trainer_state_t& trainer_state)
{
const menu_t& menu = *data.menu;
draw_menu(base_pattern, menu, trainer_state);
draw_cursor(base_pattern, menu, window.cursor);
}
static void
_draw_move_types(const uint32_t base_pattern,
const uint8_t index,
const trainer_state_t& trainer_state)
{
// this is fully custom, not worth making a data model for this
constexpr screen_cell_t top_left = {0, 8};
constexpr screen_cell_t bottom_right = {10, 12};
draw_box_border(base_pattern, top_left, bottom_right);
draw_box_background(base_pattern,
top_left, bottom_right);
const pokemon_instance_t& pokemon_instance = trainer_state.party.active_pokemon();
const move_instance_t& move_instance = pokemon_instance.move_instances[index];
const move_t& move = moves[move_instance.type];
draw_text(base_pattern,
S("TYPE/"),
top_left.x + 1, top_left.y + 1);
draw_text(base_pattern,
types[move.type].name,
top_left.x + 2, top_left.y + 2);
draw_number_right_align(base_pattern,
{top_left.x + 5, top_left.y + 3},
move_instance.pp,
2,
ascii_to_font(' '));
put_char(base_pattern,
top_left.x + 7, top_left.y + 3,
ascii_to_font('/'));
draw_number_right_align(base_pattern,
{top_left.x + 8, top_left.y + 3},
move.pp,
2,
ascii_to_font(' '));
}
void
window__menu_t::draw_fight_moves(const uint32_t base_pattern,
const union window_descriptor_t::data& data,
const window_t& window,
const trainer_state_t& trainer_state)
{
window__menu_t::draw(base_pattern,
data,
window,
trainer_state);
const menu_t& menu = *data.menu;
const cursor_t& cursor = window.cursor;
const uint32_t menu_entry_index = menu.width * cursor.y + cursor.x;
_draw_move_types(base_pattern,
menu_entry_index,
trainer_state);
}
static inline constexpr void
_move_cursor(const uint8_t width,
const uint8_t height,
const enum window_t::input_event event,
cursor_t& cursor)
{
switch (event) {
case window_t::input_left:
if ((--cursor.x) < 0) cursor.x = width - 1;
break;
case window_t::input_right:
if ((++cursor.x) >= width) cursor.x = 0;
break;
case window_t::input_up:
if ((--cursor.y) < 0) cursor.y = height - 1;
break;
case window_t::input_down:
if ((++cursor.y) >= height) cursor.y = 0;
break;
default: break;
}
}
window_descriptor_t::result
window__menu_t::update(const union window_descriptor_t::data& data,
window_t& window,
trainer_state_t& trainer_state,
const enum window_t::input_event event)
{
const menu_t& menu = *data.menu;
switch (event) {
case window_t::input_left: [[fallthrough]];
case window_t::input_right: [[fallthrough]];
case window_t::input_up: [[fallthrough]];
case window_t::input_down:
_move_cursor(menu.width, menu.height, event, window.cursor);
break;
case window_t::input_a: break;
case window_t::input_b: break;
default: break;
}
return { window_t::no_op };
}
window_descriptor_t::result
window__menu_t::update_fight(const union window_descriptor_t::data& data,
window_t& window,
trainer_state_t& trainer_state,
const enum window_t::input_event event)
{
const menu_t& menu = *data.menu;
switch (event) {
case window_t::input_a:
{
const cursor_t& cursor = window.cursor;
const uint32_t menu_entry_index = menu.width * cursor.y + cursor.x;
switch (menu_entry_index) {
case 0: // FIGHT
return { window_t::spawn, window_descriptor_t::fight_moves };
break;
case 1: // PKMN
break;
case 2: // ITEM
break;
case 3: // RUN
break;
default:
break;
}
}
break;
case window_t::input_b:
break;
default:
_move_cursor(menu.width, menu.width, event, window.cursor);
break;
}
return { window_t::no_op };
}
static uint8_t const * const
_get_move_string(const uint32_t index,
const trainer_state_t& trainer_state)
{
const pokemon_instance_t& pokemon_instance = trainer_state.party.active_pokemon();
if (index >= pokemon_instance_t::maximum_moves ||
pokemon_instance.move_instances[index].type == move_t::no_move)
return S("-");
else {
return moves[pokemon_instance.move_instances[index].type].name;
}
}
window_descriptor_t::result
window__menu_t::update_fight_moves(const union window_descriptor_t::data& data,
window_t& window,
trainer_state_t& trainer_state,
const enum window_t::input_event event)
{
const menu_t& menu = *data.menu;
const uint8_t max_height = trainer_state.party.active_pokemon().moves_count();
switch (event) {
case window_t::input_a:
break;
case window_t::input_b:
return { window_t::dismiss };
break;
default:
_move_cursor(menu.width, max_height, event, window.cursor);
break;
}
return { window_t::no_op };
}
const menu_t menu_fight_moves = {
.top_left = {4, 12},
.bottom_right = {19, 17},
.width = 1,
.height = 4,
.h_advance = 0,
.v_advance = 1,
.entry_type = menu_t::func,
.entry = {
{ .label_func = _get_move_string }
}
};
const menu_t menu_start = {
.top_left = {10, 0},
.bottom_right = {19, 15},
.width = 1,
.height = 7,
.h_advance = 0,
.v_advance = 2,
.entry_type = menu_t::labels,
.entry {
.labels = (menu_label_t[]){
{ S(POKE "DEX") },
{ S(POKE "MON") },
{ S("ITEM" ) },
{ S(TRAINER ) },
{ S("SAVE" ) },
{ S("OPTION" ) },
{ S("EXIT" ) },
},
}
};
const menu_t menu_fight = {
.top_left = {8, 12},
.bottom_right = {19, 17},
.width = 2,
.height = 2,
.h_advance = 6,
.v_advance = 2,
.entry_type = menu_t::labels,
.entry = {
.labels = (menu_label_t[]) {
{ S("FIGHT") }, { S(PKMN ) },
{ S("ITEM" ) }, { S("RUN") },
}
},
};
#undef S