draw stats page 2
This commit is contained in:
parent
c71a7b7b59
commit
3fffdab78d
1
Makefile
1
Makefile
@ -39,6 +39,7 @@ SRC += menu.cpp
|
|||||||
SRC += number.cpp
|
SRC += number.cpp
|
||||||
SRC += pokemon_instance.cpp
|
SRC += pokemon_instance.cpp
|
||||||
SRC += ailment.cpp
|
SRC += ailment.cpp
|
||||||
|
SRC += menu/stats.cpp
|
||||||
|
|
||||||
DEP = $(patsubst %.cpp,%.cpp.d,$(SRC))
|
DEP = $(patsubst %.cpp,%.cpp.d,$(SRC))
|
||||||
|
|
||||||
|
BIN
derived/font.png
BIN
derived/font.png
Binary file not shown.
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 5.3 KiB |
147
graphic.cpp
147
graphic.cpp
@ -7,11 +7,6 @@
|
|||||||
#include "control.hpp"
|
#include "control.hpp"
|
||||||
#include "number.hpp"
|
#include "number.hpp"
|
||||||
|
|
||||||
#include "gen/pokemon/types.hpp"
|
|
||||||
|
|
||||||
#include "pokemon_instance.hpp"
|
|
||||||
#include "ailment.hpp"
|
|
||||||
|
|
||||||
#define S reinterpret_cast<const uint8_t *>
|
#define S reinterpret_cast<const uint8_t *>
|
||||||
|
|
||||||
void draw_text(const uint32_t base_pattern,
|
void draw_text(const uint32_t base_pattern,
|
||||||
@ -134,7 +129,7 @@ constexpr inline uint8_t hp_seg(const int32_t hp_48, const int32_t ix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_hp_bar(const uint32_t base_pattern,
|
static inline void _draw_hp_bar(const uint32_t base_pattern,
|
||||||
const screen_cell_t& top_left,
|
const screen_cell_t& top_left,
|
||||||
const uint8_t end_cap,
|
const uint8_t end_cap,
|
||||||
const int32_t hp_48)
|
const int32_t hp_48)
|
||||||
@ -150,148 +145,22 @@ void draw_hp_bar(const uint32_t base_pattern,
|
|||||||
put_char(base_pattern, top_left.x + 8, top_left.y, end_cap);
|
put_char(base_pattern, top_left.x + 8, top_left.y, end_cap);
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t * status_string(const pokemon_instance_t& pokemon_instance)
|
void draw_hp_bar_with_numbers(const uint32_t base_pattern,
|
||||||
{
|
const pokemon_instance_t& pokemon_instance,
|
||||||
if (pokemon_instance.current_hit_points == 0)
|
const screen_cell_t& pos)
|
||||||
return S("FNT");
|
|
||||||
else
|
|
||||||
return ailments[pokemon_instance.ailment].name;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_stats1(const uint32_t base_pattern,
|
|
||||||
const pokemon_instance_t& pokemon_instance)
|
|
||||||
{
|
|
||||||
// white out the entire screen
|
|
||||||
draw_box_background(base_pattern, {-1, -1}, {20, 18});
|
|
||||||
|
|
||||||
// top status battle box
|
|
||||||
{
|
|
||||||
draw_battle_border(base_pattern, {19, 1}, {8, 7});
|
|
||||||
|
|
||||||
// hp
|
|
||||||
{
|
{
|
||||||
const int32_t hp_48 = (pokemon_instance.current_hit_points * 48) / pokemon_instance.stat_values.hit_points;
|
const int32_t hp_48 = (pokemon_instance.current_hit_points * 48) / pokemon_instance.stat_values.hit_points;
|
||||||
draw_hp_bar(base_pattern, {11, 3}, hp_bar::end_cap_bar, hp_48);
|
_draw_hp_bar(base_pattern, pos, hp_bar::end_cap_bar, hp_48);
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {12, 4},
|
draw_number_right_align(base_pattern, {pos.x + 1, pos.y + 1},
|
||||||
pokemon_instance.current_hit_points,
|
pokemon_instance.current_hit_points,
|
||||||
3, ascii_to_font(' ')); // width, fill
|
3, ascii_to_font(' ')); // width, fill
|
||||||
|
|
||||||
put_char(base_pattern, 15, 4, ascii_to_font('/'));
|
put_char(base_pattern, pos.x + 4, pos.y + 1, ascii_to_font('/'));
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {16, 4},
|
draw_number_right_align(base_pattern, {pos.x + 5, pos.y + 1},
|
||||||
pokemon_instance.stat_values.hit_points,
|
pokemon_instance.stat_values.hit_points,
|
||||||
3, ascii_to_font(' ')); // width, fill
|
3, ascii_to_font(' ')); // width, fill
|
||||||
}
|
}
|
||||||
|
|
||||||
// name
|
|
||||||
draw_text(base_pattern, pokemon[pokemon_instance.species].name, 9, 1);
|
|
||||||
|
|
||||||
// level
|
|
||||||
put_char(base_pattern, 14, 2, battle_border::level);
|
|
||||||
draw_number_left_align(base_pattern, {15, 2},
|
|
||||||
pokemon_instance.level,
|
|
||||||
3); // width
|
|
||||||
|
|
||||||
draw_text(base_pattern, S("STATUS/"), 9, 6);
|
|
||||||
draw_text(base_pattern, status_string(pokemon_instance), 16, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bottom right border
|
|
||||||
{
|
|
||||||
draw_battle_border(base_pattern, {19, 9}, {12, 17});
|
|
||||||
|
|
||||||
int32_t distinct_types = (pokemon[pokemon_instance.species].types[0]
|
|
||||||
!= pokemon[pokemon_instance.species].types[1]) + 1;
|
|
||||||
|
|
||||||
for (int32_t ix = 0; ix < distinct_types; ix++) {
|
|
||||||
const enum type_t::type type = pokemon[pokemon_instance.species].types[ix];
|
|
||||||
draw_text(base_pattern, S("TYPE"), 10, 9 + (2 * ix));
|
|
||||||
put_char(base_pattern, 14, 9 + (2 * ix), ascii_to_font('1' + ix));
|
|
||||||
put_char(base_pattern, 15, 9 + (2 * ix), ascii_to_font('/'));
|
|
||||||
draw_text(base_pattern, types[type].name, 11, 10 + (2 * ix));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{ // bottom left dialog box
|
|
||||||
draw_box_border(base_pattern, {0, 8}, {9, 17});
|
|
||||||
|
|
||||||
draw_text(base_pattern, S("ATTACK"), 1, 9 + 0);
|
|
||||||
draw_text(base_pattern, S("DEFENSE"), 1, 9 + 2);
|
|
||||||
draw_text(base_pattern, S("SPEED"), 1, 9 + 4);
|
|
||||||
draw_text(base_pattern, S("SPECIAL"), 1, 9 + 6);
|
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {6, 10 + 0},
|
|
||||||
pokemon_instance.stat_values.attack,
|
|
||||||
3, ascii_to_font(' ')); // width, fill
|
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {6, 10 + 2},
|
|
||||||
pokemon_instance.stat_values.defense,
|
|
||||||
3, ascii_to_font(' ')); // width, fill
|
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {6, 10 + 4},
|
|
||||||
pokemon_instance.stat_values.speed,
|
|
||||||
3, ascii_to_font(' ')); // width, fill
|
|
||||||
|
|
||||||
draw_number_right_align(base_pattern, {6, 10 + 6},
|
|
||||||
pokemon_instance.stat_values.special,
|
|
||||||
3, ascii_to_font(' ')); // width, fill
|
|
||||||
} // end bottom left dialog box
|
|
||||||
|
|
||||||
// pokedex number
|
|
||||||
{
|
|
||||||
put_char(base_pattern, 1, 7, stats::no);
|
|
||||||
put_char(base_pattern, 2, 7, stats::no_dot);
|
|
||||||
|
|
||||||
const int32_t pokedex_number = static_cast<int32_t>(pokemon_instance.species) + 1;
|
|
||||||
draw_number_right_align(base_pattern,
|
|
||||||
{3, 7},
|
|
||||||
pokedex_number,
|
|
||||||
3, // width
|
|
||||||
ascii_to_font('0') // fill
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void dialog_t::draw(const uint32_t base_pattern,
|
|
||||||
const start_size_t& text)
|
|
||||||
{
|
|
||||||
draw_box_border(base_pattern, top_left, bottom_right);
|
|
||||||
draw_box_background(base_pattern, top_left, bottom_right);
|
|
||||||
|
|
||||||
uint32_t ix = 0;
|
|
||||||
int32_t x = top_left.x + 1;
|
|
||||||
int32_t y = top_left.y + 2;
|
|
||||||
// ignore C-string null terminator
|
|
||||||
while (ix < (text.size - 1)) {
|
|
||||||
const uint8_t c = text.start[ix];
|
|
||||||
switch (c) {
|
|
||||||
case control_t::text: break;
|
|
||||||
case control_t::done: break;
|
|
||||||
case control_t::prompt: break;
|
|
||||||
case control_t::page: break;
|
|
||||||
|
|
||||||
case control_t::next: [[fallthrough]];
|
|
||||||
case control_t::line:
|
|
||||||
while (x < bottom_right.x) {
|
|
||||||
put_char(base_pattern, x, y, ascii_to_font(' '));
|
|
||||||
x++;
|
|
||||||
}
|
|
||||||
x = top_left.x + 1;
|
|
||||||
y += 2;
|
|
||||||
break;
|
|
||||||
case control_t::para: [[fallthrough]];
|
|
||||||
case control_t::cont:
|
|
||||||
// fixme:
|
|
||||||
ix = text.size;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
put_char(base_pattern, x, y, ascii_to_font(c));
|
|
||||||
x += 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ix++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#undef S
|
#undef S
|
||||||
|
18
graphic.hpp
18
graphic.hpp
@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
#include "coordinates.hpp"
|
#include "coordinates.hpp"
|
||||||
#include "start_size.hpp"
|
#include "start_size.hpp"
|
||||||
#include "render_map.hpp" // for cell_offset
|
#include "render_map.hpp" // for cell_offset
|
||||||
@ -54,6 +56,8 @@ struct hp_bar {
|
|||||||
struct stats {
|
struct stats {
|
||||||
static constexpr uint8_t id = 0x70; // ID
|
static constexpr uint8_t id = 0x70; // ID
|
||||||
static constexpr uint8_t no = 0x71; // No
|
static constexpr uint8_t no = 0x71; // No
|
||||||
|
static constexpr uint8_t to = 0x4c; // to
|
||||||
|
static constexpr uint8_t p = 0x4d; // p (bold)
|
||||||
static constexpr uint8_t no_dot = 0x4e; // .
|
static constexpr uint8_t no_dot = 0x4e; // .
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -79,14 +83,6 @@ void draw_box_background(const uint32_t base_pattern,
|
|||||||
void draw_battle_border(const uint32_t base_pattern,
|
void draw_battle_border(const uint32_t base_pattern,
|
||||||
const screen_cell_t& top_corner, const screen_cell_t& bottom_corner);
|
const screen_cell_t& top_corner, const screen_cell_t& bottom_corner);
|
||||||
|
|
||||||
void draw_stats1(const uint32_t base_pattern,
|
void draw_hp_bar_with_numbers(const uint32_t base_pattern,
|
||||||
const pokemon_instance_t& pokemon_instance);
|
const pokemon_instance_t& pokemon_instance,
|
||||||
|
const screen_cell_t& pos);
|
||||||
struct dialog_t
|
|
||||||
{
|
|
||||||
static constexpr screen_cell_t top_left = { 0, 12};
|
|
||||||
static constexpr screen_cell_t bottom_right = {19, 17};
|
|
||||||
|
|
||||||
static void draw(const uint32_t base_pattern,
|
|
||||||
const start_size_t& text);
|
|
||||||
};
|
|
||||||
|
32
main.cpp
32
main.cpp
@ -29,6 +29,8 @@
|
|||||||
#include "pokemon.hpp"
|
#include "pokemon.hpp"
|
||||||
#include "pokemon_instance.hpp"
|
#include "pokemon_instance.hpp"
|
||||||
|
|
||||||
|
#include "menu/stats.hpp"
|
||||||
|
|
||||||
static int32_t pokemon_raw_index = 0;
|
static int32_t pokemon_raw_index = 0;
|
||||||
|
|
||||||
struct draw_t {
|
struct draw_t {
|
||||||
@ -166,7 +168,7 @@ uint32_t pokemon_sprite_dimension(const uint32_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id,
|
void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id,
|
||||||
const screen_cell_t& screen_cell)
|
const screen_cell_t& screen_cell, bool horizontal_inversion)
|
||||||
{
|
{
|
||||||
const uint32_t base_pattern = state.draw.base_pattern.pokemon[pokemon_id].front;
|
const uint32_t base_pattern = state.draw.base_pattern.pokemon[pokemon_id].front;
|
||||||
const uint32_t character_address = (base_pattern * 16) / 8;
|
const uint32_t character_address = (base_pattern * 16) / 8;
|
||||||
@ -181,7 +183,9 @@ void render_pokemon(const uint32_t ix, const enum pokemon_t::pokemon pokemon_id,
|
|||||||
case 56: x_offset = 1; y_offset = 0; break;
|
case 56: x_offset = 1; y_offset = 0; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE;
|
uint16_t dir = horizontal_inversion ? CTRL__DIR__INVERTED_HORIZONTALLY : 0;
|
||||||
|
|
||||||
|
vdp1.vram.cmd[ix].CTRL = CTRL__JP__JUMP_NEXT | CTRL__COMM__NORMAL_SPRITE | dir;
|
||||||
vdp1.vram.cmd[ix].LINK = 0;
|
vdp1.vram.cmd[ix].LINK = 0;
|
||||||
// The "end code" is 0xf, which is being used in the mai sprite palette. If
|
// The "end code" is 0xf, which is being used in the mai sprite palette. If
|
||||||
// both transparency and end codes are enabled, it seems there are only 14
|
// both transparency and end codes are enabled, it seems there are only 14
|
||||||
@ -209,7 +213,8 @@ void render_sprites(const offset_t& offset)
|
|||||||
ix++;
|
ix++;
|
||||||
|
|
||||||
render_pokemon(ix, static_cast<enum pokemon_t::pokemon>(pokemon_raw_index),
|
render_pokemon(ix, static_cast<enum pokemon_t::pokemon>(pokemon_raw_index),
|
||||||
{0, 0});
|
{0, 0},
|
||||||
|
true); // invert horizontally
|
||||||
ix++;
|
ix++;
|
||||||
|
|
||||||
const object_t& obj = map_objects[state.map];
|
const object_t& obj = map_objects[state.map];
|
||||||
@ -470,11 +475,13 @@ void check_sign()
|
|||||||
const bool position_match = event.position.x == coord.x && event.position.y == coord.y;
|
const bool position_match = event.position.x == coord.x && event.position.y == coord.y;
|
||||||
if (position_match && event.sign_id != 0xff) {
|
if (position_match && event.sign_id != 0xff) {
|
||||||
const start_size_t& text = map.text_pointers[event.sign_id];
|
const start_size_t& text = map.text_pointers[event.sign_id];
|
||||||
dialog_t::draw(state.draw.base_pattern.font, text);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint32_t stats_page = 1;
|
||||||
|
static uint8_t level = 70;
|
||||||
|
|
||||||
void update()
|
void update()
|
||||||
{
|
{
|
||||||
state.player.tick();
|
state.player.tick();
|
||||||
@ -486,14 +493,18 @@ void update()
|
|||||||
else if (event::cursor_right()) collision_move(maps[state.map], actor_t::right);
|
else if (event::cursor_right()) collision_move(maps[state.map], actor_t::right);
|
||||||
else if (event::cursor_up() ) collision_move(maps[state.map], actor_t::up);
|
else if (event::cursor_up() ) collision_move(maps[state.map], actor_t::up);
|
||||||
else if (event::cursor_down() ) collision_move(maps[state.map], actor_t::down);
|
else if (event::cursor_down() ) collision_move(maps[state.map], actor_t::down);
|
||||||
|
else if (event::button_a() ) check_sign();
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (event::cursor_left() ) pokemon_raw_index = (pokemon_raw_index - 1);
|
if (event::cursor_left() ) pokemon_raw_index = (pokemon_raw_index - 1);
|
||||||
else if (event::cursor_right()) pokemon_raw_index = (pokemon_raw_index + 1);
|
else if (event::cursor_right()) pokemon_raw_index = (pokemon_raw_index + 1);
|
||||||
|
else if (event::cursor_up() ) level++;
|
||||||
|
else if (event::cursor_down() ) level--;
|
||||||
|
else if (event::button_a() ) stats_page = !stats_page;
|
||||||
|
|
||||||
if (pokemon_raw_index < 0) pokemon_raw_index = pokemon_t::count - 1;
|
if (pokemon_raw_index < 0) pokemon_raw_index = pokemon_t::count - 1;
|
||||||
else if (pokemon_raw_index >= pokemon_t::count) pokemon_raw_index = 0;
|
else if (pokemon_raw_index >= pokemon_t::count) pokemon_raw_index = 0;
|
||||||
|
|
||||||
//else if (event::button_a() ) check_sign();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t frame = 0;
|
static uint32_t frame = 0;
|
||||||
@ -523,14 +534,23 @@ void render()
|
|||||||
pokemon_instance.species = static_cast<enum pokemon_t::pokemon>(pokemon_raw_index);
|
pokemon_instance.species = static_cast<enum pokemon_t::pokemon>(pokemon_raw_index);
|
||||||
pokemon_instance.stat_experience = {0, 0, 0, 0, 0};
|
pokemon_instance.stat_experience = {0, 0, 0, 0, 0};
|
||||||
pokemon_instance.determinant_values.dvs = 0b1110'0101'1000'0110;
|
pokemon_instance.determinant_values.dvs = 0b1110'0101'1000'0110;
|
||||||
pokemon_instance.level = 70;
|
pokemon_instance.level = level;
|
||||||
pokemon_instance.determine_stats();
|
pokemon_instance.determine_stats();
|
||||||
|
pokemon_instance.learn_all_moves();
|
||||||
if (frame % 4 == 0)
|
if (frame % 4 == 0)
|
||||||
pokemon_instance.current_hit_points++;
|
pokemon_instance.current_hit_points++;
|
||||||
if (pokemon_instance.current_hit_points > pokemon_instance.stat_values.hit_points)
|
if (pokemon_instance.current_hit_points > pokemon_instance.stat_values.hit_points)
|
||||||
pokemon_instance.current_hit_points = 0;
|
pokemon_instance.current_hit_points = 0;
|
||||||
|
|
||||||
|
switch (stats_page) {
|
||||||
|
default:
|
||||||
|
case 0:
|
||||||
draw_stats1(state.draw.base_pattern.font, pokemon_instance);
|
draw_stats1(state.draw.base_pattern.font, pokemon_instance);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
draw_stats2(state.draw.base_pattern.font, pokemon_instance);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C"
|
extern "C"
|
||||||
|
43
menu/dialog.cpp
Normal file
43
menu/dialog.cpp
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
void draw(const uint32_t base_pattern,
|
||||||
|
const start_size_t& text)
|
||||||
|
{
|
||||||
|
static constexpr screen_cell_t top_left = { 0, 12};
|
||||||
|
static constexpr screen_cell_t bottom_right = {19, 17};
|
||||||
|
|
||||||
|
draw_box_border(base_pattern, top_left, bottom_right);
|
||||||
|
draw_box_background(base_pattern, top_left, bottom_right);
|
||||||
|
|
||||||
|
uint32_t ix = 0;
|
||||||
|
int32_t x = top_left.x + 1;
|
||||||
|
int32_t y = top_left.y + 2;
|
||||||
|
// ignore C-string null terminator
|
||||||
|
while (ix < (text.size - 1)) {
|
||||||
|
const uint8_t c = text.start[ix];
|
||||||
|
switch (c) {
|
||||||
|
case control_t::text: break;
|
||||||
|
case control_t::done: break;
|
||||||
|
case control_t::prompt: break;
|
||||||
|
case control_t::page: break;
|
||||||
|
|
||||||
|
case control_t::next: [[fallthrough]];
|
||||||
|
case control_t::line:
|
||||||
|
while (x < bottom_right.x) {
|
||||||
|
put_char(base_pattern, x, y, ascii_to_font(' '));
|
||||||
|
x++;
|
||||||
|
}
|
||||||
|
x = top_left.x + 1;
|
||||||
|
y += 2;
|
||||||
|
break;
|
||||||
|
case control_t::para: [[fallthrough]];
|
||||||
|
case control_t::cont:
|
||||||
|
// fixme:
|
||||||
|
ix = text.size;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
put_char(base_pattern, x, y, ascii_to_font(c));
|
||||||
|
x += 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ix++;
|
||||||
|
}
|
||||||
|
}
|
229
menu/stats.cpp
Normal file
229
menu/stats.cpp
Normal file
@ -0,0 +1,229 @@
|
|||||||
|
#include "../font.hpp"
|
||||||
|
#include "../number.hpp"
|
||||||
|
#include "../graphic.hpp"
|
||||||
|
|
||||||
|
#include "../gen/pokemon/types.hpp"
|
||||||
|
#include "../gen/pokemon/moves.hpp"
|
||||||
|
|
||||||
|
#include "../pokemon_instance.hpp"
|
||||||
|
#include "../ailment.hpp"
|
||||||
|
|
||||||
|
#define S reinterpret_cast<const uint8_t *>
|
||||||
|
|
||||||
|
const uint8_t * status_string(const pokemon_instance_t& pokemon_instance)
|
||||||
|
{
|
||||||
|
if (pokemon_instance.current_hit_points == 0)
|
||||||
|
return S("FNT");
|
||||||
|
else
|
||||||
|
return ailments[pokemon_instance.ailment].name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_stats_top_right_border_with_name(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance)
|
||||||
|
{
|
||||||
|
draw_battle_border(base_pattern, {19, 1}, {8, 7});
|
||||||
|
|
||||||
|
// name
|
||||||
|
draw_text(base_pattern, pokemon[pokemon_instance.species].name, 9, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_stats_pokedex_number(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance)
|
||||||
|
{
|
||||||
|
// pokedex number
|
||||||
|
put_char(base_pattern, 1, 7, stats::no);
|
||||||
|
put_char(base_pattern, 2, 7, stats::no_dot);
|
||||||
|
|
||||||
|
const int32_t pokedex_number = static_cast<int32_t>(pokemon_instance.species) + 1;
|
||||||
|
draw_number_right_align(base_pattern,
|
||||||
|
{3, 7},
|
||||||
|
pokedex_number,
|
||||||
|
3, // width
|
||||||
|
ascii_to_font('0') // fill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_stats1(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance)
|
||||||
|
{
|
||||||
|
// white out the entire screen
|
||||||
|
draw_box_background(base_pattern, {-1, -1}, {20, 18});
|
||||||
|
|
||||||
|
// front picture label
|
||||||
|
{
|
||||||
|
draw_stats_pokedex_number(base_pattern, pokemon_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// top status battle box
|
||||||
|
{
|
||||||
|
// name and border
|
||||||
|
draw_stats_top_right_border_with_name(base_pattern, pokemon_instance);
|
||||||
|
|
||||||
|
// level
|
||||||
|
put_char(base_pattern, 14, 2, battle_border::level);
|
||||||
|
draw_number_left_align(base_pattern, {15, 2},
|
||||||
|
pokemon_instance.level,
|
||||||
|
3); // width
|
||||||
|
|
||||||
|
// hp
|
||||||
|
draw_hp_bar_with_numbers(base_pattern, pokemon_instance, {11, 3});
|
||||||
|
|
||||||
|
// status
|
||||||
|
draw_text(base_pattern, S("STATUS/"), 9, 6);
|
||||||
|
draw_text(base_pattern, status_string(pokemon_instance), 16, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom right border
|
||||||
|
{
|
||||||
|
draw_battle_border(base_pattern, {19, 9}, {12, 17});
|
||||||
|
|
||||||
|
int32_t distinct_types = (pokemon[pokemon_instance.species].types[0]
|
||||||
|
!= pokemon[pokemon_instance.species].types[1]) + 1;
|
||||||
|
|
||||||
|
for (int32_t ix = 0; ix < distinct_types; ix++) {
|
||||||
|
const enum type_t::type type = pokemon[pokemon_instance.species].types[ix];
|
||||||
|
draw_text(base_pattern, S("TYPE"), 10, 9 + (2 * ix));
|
||||||
|
put_char(base_pattern, 14, 9 + (2 * ix), ascii_to_font('1' + ix));
|
||||||
|
put_char(base_pattern, 15, 9 + (2 * ix), ascii_to_font('/'));
|
||||||
|
draw_text(base_pattern, types[type].name, 11, 10 + (2 * ix));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{ // bottom left dialog box
|
||||||
|
draw_box_border(base_pattern, {0, 8}, {9, 17});
|
||||||
|
|
||||||
|
draw_text(base_pattern, S("ATTACK"), 1, 9 + 0);
|
||||||
|
draw_text(base_pattern, S("DEFENSE"), 1, 9 + 2);
|
||||||
|
draw_text(base_pattern, S("SPEED"), 1, 9 + 4);
|
||||||
|
draw_text(base_pattern, S("SPECIAL"), 1, 9 + 6);
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {6, 10 + 0},
|
||||||
|
pokemon_instance.stat_values.attack,
|
||||||
|
3, ascii_to_font(' ')); // width, fill
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {6, 10 + 2},
|
||||||
|
pokemon_instance.stat_values.defense,
|
||||||
|
3, ascii_to_font(' ')); // width, fill
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {6, 10 + 4},
|
||||||
|
pokemon_instance.stat_values.speed,
|
||||||
|
3, ascii_to_font(' ')); // width, fill
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {6, 10 + 6},
|
||||||
|
pokemon_instance.stat_values.special,
|
||||||
|
3, ascii_to_font(' ')); // width, fill
|
||||||
|
} // end bottom left dialog box
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_stats_move(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance,
|
||||||
|
const int32_t _ix)
|
||||||
|
{
|
||||||
|
const int32_t ix = _ix & 0b11;
|
||||||
|
const int32_t y_offset = 2 * ix;
|
||||||
|
|
||||||
|
constexpr int32_t name_x = 2;
|
||||||
|
constexpr int32_t name_y = 9;
|
||||||
|
constexpr int32_t pp_x = 11;
|
||||||
|
constexpr int32_t pp_y = 10;
|
||||||
|
|
||||||
|
// move name
|
||||||
|
const move_instance_t& move_instance = pokemon_instance.move_instances[ix];
|
||||||
|
if (move_instance.type != move_t::no_move) {
|
||||||
|
const move_t& move = moves[move_instance.type];
|
||||||
|
// name
|
||||||
|
draw_text(base_pattern, move.name, name_x, name_y + y_offset);
|
||||||
|
|
||||||
|
// pp
|
||||||
|
put_char(base_pattern, pp_x + 0, pp_y + y_offset, stats::p);
|
||||||
|
put_char(base_pattern, pp_x + 1, pp_y + y_offset, stats::p);
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {pp_x + 3, pp_y + y_offset},
|
||||||
|
move_instance.pp,
|
||||||
|
2, ascii_to_font(' ')); // width, fill
|
||||||
|
|
||||||
|
put_char(base_pattern, pp_x + 5, pp_y + y_offset, ascii_to_font('/'));
|
||||||
|
|
||||||
|
draw_number_right_align(base_pattern, {pp_x + 6, pp_y + y_offset},
|
||||||
|
moves[move_instance.type].pp,
|
||||||
|
2, ascii_to_font(' ')); // width, fill
|
||||||
|
} else {
|
||||||
|
// name
|
||||||
|
put_char(base_pattern, name_x, name_y + y_offset, ascii_to_font('-'));
|
||||||
|
// pp
|
||||||
|
put_char(base_pattern, pp_x + 0, pp_y + y_offset, ascii_to_font('-'));
|
||||||
|
put_char(base_pattern, pp_x + 1, pp_y + y_offset, ascii_to_font('-'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_stats2(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance)
|
||||||
|
{
|
||||||
|
// white out the entire screen
|
||||||
|
draw_box_background(base_pattern, {-1, -1}, {20, 18});
|
||||||
|
|
||||||
|
// front picture label
|
||||||
|
{
|
||||||
|
draw_stats_pokedex_number(base_pattern, pokemon_instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
// top status battle box
|
||||||
|
{
|
||||||
|
// name and border
|
||||||
|
draw_stats_top_right_border_with_name(base_pattern, pokemon_instance);
|
||||||
|
|
||||||
|
// exp points
|
||||||
|
draw_text(base_pattern, S("EXP POINTS"), 9, 3);
|
||||||
|
draw_number_right_align(base_pattern,
|
||||||
|
{13, 4},
|
||||||
|
pokemon_instance.total_experience,
|
||||||
|
6, // width
|
||||||
|
ascii_to_font(' ') // fill
|
||||||
|
);
|
||||||
|
|
||||||
|
// level up
|
||||||
|
draw_text(base_pattern, S("LEVEL UP"), 9, 5);
|
||||||
|
|
||||||
|
put_char(base_pattern, 14, 6, stats::to);
|
||||||
|
put_char(base_pattern, 16, 6, battle_border::level);
|
||||||
|
|
||||||
|
const int32_t next_level = pokemon_instance.level < 100
|
||||||
|
? (pokemon_instance.level + 1)
|
||||||
|
: 100;
|
||||||
|
int32_t exp_to = 1234;
|
||||||
|
|
||||||
|
if (next_level < 100) {
|
||||||
|
draw_number_left_align(base_pattern,
|
||||||
|
{17, 6},
|
||||||
|
next_level,
|
||||||
|
2 // width
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
draw_number_left_align(base_pattern,
|
||||||
|
{16, 6},
|
||||||
|
next_level,
|
||||||
|
3 // width
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// exp
|
||||||
|
draw_number_right_align(base_pattern,
|
||||||
|
{9, 6},
|
||||||
|
exp_to,
|
||||||
|
5, // width
|
||||||
|
ascii_to_font(' ') // fill
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// bottom move list
|
||||||
|
{
|
||||||
|
draw_box_border(base_pattern, {0, 8}, {19, 17});
|
||||||
|
|
||||||
|
draw_stats_move(base_pattern, pokemon_instance, 0);
|
||||||
|
draw_stats_move(base_pattern, pokemon_instance, 1);
|
||||||
|
draw_stats_move(base_pattern, pokemon_instance, 2);
|
||||||
|
draw_stats_move(base_pattern, pokemon_instance, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef S
|
11
menu/stats.hpp
Normal file
11
menu/stats.hpp
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#include "../pokemon_instance.hpp"
|
||||||
|
|
||||||
|
void draw_stats1(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance);
|
||||||
|
|
||||||
|
void draw_stats2(const uint32_t base_pattern,
|
||||||
|
const pokemon_instance_t& pokemon_instance);
|
@ -59,13 +59,41 @@ pokemon_instance_t::learn_move(enum move_t::move move, int32_t index)
|
|||||||
case 1: [[fallthrough]];
|
case 1: [[fallthrough]];
|
||||||
case 2: [[fallthrough]];
|
case 2: [[fallthrough]];
|
||||||
case 3:
|
case 3:
|
||||||
moves[index] = move;
|
move_instances[index].type = move;
|
||||||
|
move_instances[index].pp = moves[move].pp;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
moves[0] = moves[1];
|
{
|
||||||
moves[1] = moves[2];
|
int32_t ix = 0;
|
||||||
moves[2] = moves[3];
|
while (move_instances[ix].type != move_t::no_move) {
|
||||||
moves[3] = move;
|
if (move_instances[ix].type == move) return; // do not double-learn move_instances
|
||||||
|
if (++ix == 4) {
|
||||||
|
move_instances[0] = move_instances[1];
|
||||||
|
move_instances[1] = move_instances[2];
|
||||||
|
move_instances[2] = move_instances[3];
|
||||||
|
ix--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
move_instances[ix].type = move;
|
||||||
|
move_instances[ix].pp = moves[move].pp;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pokemon_instance_t::learn_all_moves()
|
||||||
|
{
|
||||||
|
move_instances[0].type = move_t::no_move;
|
||||||
|
move_instances[1].type = move_t::no_move;
|
||||||
|
move_instances[2].type = move_t::no_move;
|
||||||
|
move_instances[3].type = move_t::no_move;
|
||||||
|
|
||||||
|
const level_move_t * level_moves = pokemon[species].by_level.moves;
|
||||||
|
for (int32_t ix = 0; ix < pokemon[species].by_level.length; ix++) {
|
||||||
|
if (level_moves[ix].level <= level)
|
||||||
|
learn_move(level_moves[ix].move, -1);
|
||||||
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,6 +64,11 @@ struct stat_values_t {
|
|||||||
|
|
||||||
static_assert((sizeof (stat_values_t)) == 10);
|
static_assert((sizeof (stat_values_t)) == 10);
|
||||||
|
|
||||||
|
struct move_instance_t {
|
||||||
|
enum move_t::move type;
|
||||||
|
uint8_t pp;
|
||||||
|
};
|
||||||
|
|
||||||
struct pokemon_instance_t {
|
struct pokemon_instance_t {
|
||||||
uint8_t nickname[12];
|
uint8_t nickname[12];
|
||||||
enum pokemon_t::pokemon species;
|
enum pokemon_t::pokemon species;
|
||||||
@ -72,7 +77,7 @@ struct pokemon_instance_t {
|
|||||||
determinant_values_t determinant_values;
|
determinant_values_t determinant_values;
|
||||||
stat_values_t stat_values;
|
stat_values_t stat_values;
|
||||||
stat_experience_t stat_experience;
|
stat_experience_t stat_experience;
|
||||||
enum move_t::move moves[4];
|
move_instance_t move_instances[4];
|
||||||
uint16_t current_hit_points;
|
uint16_t current_hit_points;
|
||||||
enum ailment_t::ailment ailment;
|
enum ailment_t::ailment ailment;
|
||||||
|
|
||||||
@ -84,4 +89,5 @@ struct pokemon_instance_t {
|
|||||||
void determine_stats();
|
void determine_stats();
|
||||||
|
|
||||||
void learn_move(enum move_t::move move, int32_t index);
|
void learn_move(enum move_t::move move, int32_t index);
|
||||||
|
void learn_all_moves();
|
||||||
};
|
};
|
||||||
|
@ -51,7 +51,7 @@ def struct_move_t():
|
|||||||
_move_constants_str = (f"{s.lower()}," for s in _move_constants)
|
_move_constants_str = (f"{s.lower()}," for s in _move_constants)
|
||||||
return [
|
return [
|
||||||
"struct move_t {",
|
"struct move_t {",
|
||||||
"const uint8_t * name;"
|
"const uint8_t * name;",
|
||||||
"uint8_t animation;",
|
"uint8_t animation;",
|
||||||
"uint8_t effect;",
|
"uint8_t effect;",
|
||||||
"uint8_t power;",
|
"uint8_t power;",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user