Mercurial > molko
changeset 398:14ce7c4871e3
rpg: overhaul of battle bar
line wrap: on
line diff
--- a/examples/example-battle/main.c Fri Feb 18 16:16:38 2022 +0100 +++ b/examples/example-battle/main.c Sun Feb 27 10:08:51 2022 +0100 @@ -40,9 +40,10 @@ #include <ui/theme.h> #include <ui/ui.h> +#include <rpg/battle-bar-default.h> +#include <rpg/battle-bar.h> +#include <rpg/battle.h> #include <rpg/character.h> -#include <rpg/battle-bar-default.h> -#include <rpg/battle.h> #include <rpg/rpg.h> #include <rpg/spell.h> @@ -64,6 +65,8 @@ ch->luck = 50; } +#if 0 + static void haunted_wood_reset(struct character *ch) { @@ -75,10 +78,12 @@ ch->luck = 100; } +#endif + static void black_cat_reset(struct character *ch) { - ch->hpmax = ch->hp = 126; + ch->hpmax = ch->hp = 120; ch->mpmax = ch->mp = 38; ch->atk = 22; ch->def = 19; @@ -86,24 +91,7 @@ ch->luck = 14; } -static struct character team[] = { - { - .name = "Molko", - .level = 1, - .hp = 120, - .mp = 50, - .reset = adventurer_reset, - .sprites = { - [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_WALK], - [CHARACTER_SPRITE_SWORD] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_SWORD], - }, - .spells = { - &spell_fire - } - }, -}; - -static struct state *states[2]; +#if 0 static void haunted_wood_strat(struct character *ch, struct battle *bt) @@ -111,18 +99,22 @@ (void)ch; /* TODO: Select randomly. */ - battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); + battle_attack(bt, battle_current(bt)->ch, bt->team[0]->ch); } +#endif + static void black_cat_strat(struct character *ch, struct battle *bt) { (void)ch; /* TODO: Select randomly. */ - battle_attack(bt, bt->order_cur->ch, bt->team[0].ch); + battle_attack(bt, battle_current(bt)->ch, bt->team[0]->ch); } +#if 0 + static struct character haunted_wood = { .name = "Haunted Wood", .level = 30, @@ -133,15 +125,7 @@ .exec = haunted_wood_strat }; -static struct character black_cat = { - .name = "Black Cat", - .level = 6, - .reset = black_cat_reset, - .sprites = { - [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], - }, - .exec = black_cat_strat -}; +#endif static void init(void) @@ -157,39 +141,94 @@ theme_default()->sprites[THEME_SPRITE_CURSOR] = ®istry_sprites[REGISTRY_TEXTURE_CURSOR]; } +static struct state *states[2]; static struct state fight_state; +static struct { + struct character ch; + struct battle_entity entity; +} entities[] = { + /* == Enemies == */ + { + .ch = { + .name = "Black Cat", + .level = 6, + .reset = black_cat_reset, + .sprites = { + [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_BLACK_CAT], + }, + .exec = black_cat_strat + }, + .entity = { + .ch = &entities[0].ch + } + }, + + /* == Team == */ + { + .ch = { + .name = "Molko", + .level = 1, + .hp = 120, + .mp = 50, + .reset = adventurer_reset, + .sprites = { + [CHARACTER_SPRITE_NORMAL] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_WALK], + [CHARACTER_SPRITE_SWORD] = ®istry_sprites[REGISTRY_TEXTURE_JOHN_SWORD], + }, + .spells = { + &spell_fire + } + }, + .entity = { + .ch = &entities[1].ch + } + }, +}; + +static struct drawable *drawables[16]; +static struct drawable_stack drawable_stack; + +static struct action *actions[16]; +static struct action_stack action_stack; + +static struct battle_entity *entities_enemies[1]; +static struct battle_entity *entities_team[1]; +static struct battle bt; +static struct battle_bar_default default_bar; +static struct battle_bar bar; + static void prepare_to_fight(void) { - struct battle *bt = alloc_new0(sizeof (*bt)); - -// bt->enemies[0].ch = &haunted_wood; - bt->team[0].ch = &team[0]; - //bt->team[1].ch = &team[1]; + action_stack_init(&action_stack, actions, UTIL_SIZE(actions)); + drawable_stack_init(&drawable_stack, drawables, UTIL_SIZE(drawables)); - /* Positionate the single ennemy to the left. */ - align(ALIGN_LEFT, - &bt->enemies[0].x, &bt->enemies[0].y, - haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellw, - haunted_wood.sprites[CHARACTER_SPRITE_NORMAL]->cellh, - 0, 0, window.w, window.h); + battle_init(&bt); + battle_bar_default_init(&default_bar); + battle_bar_default(&default_bar, &bar); + + bt.team = entities_team; + bt.teamsz = UTIL_SIZE(entities_team); + + bt.enemies = entities_enemies; + bt.enemiesz = UTIL_SIZE(entities_enemies); /* Black cat is near the previous monster. */ - bt->enemies[1].ch = &black_cat; - bt->enemies[1].x = 500; - bt->enemies[1].y = 100; + entities_team[0] = &entities[1].entity; + entities_enemies[0] = &entities[0].entity; + entities_enemies[0]->x = 500; + entities_enemies[0]->y = 100; - bt->background = ®istry_images[REGISTRY_IMAGE_BATTLE_BACKGROUND]; + bt.background = ®istry_images[REGISTRY_IMAGE_BATTLE_BACKGROUND]; + bt.bar = &bar; + bt.actions = &action_stack; + bt.effects = &drawable_stack; - battle_bar_default(bt); - battle_start(bt); - - fight_state.data = bt; + battle_start(&bt); game_push(&fight_state); } - static void empty_handle(struct state *st, const union event *ev) { @@ -234,32 +273,39 @@ static void fight_handle(struct state *st, const union event *ev) { - battle_handle(st->data, ev); + (void)st; + + battle_handle(&bt, ev); } static void fight_update(struct state *st, unsigned int ticks) { - struct battle *bt = st->data; + (void)st; - if (battle_update(bt, ticks)) + if (battle_update(&bt, ticks)) game_pop(); } static void fight_draw(struct state *st) { + (void)st; + painter_set_color(0x000000ff); painter_clear(); - battle_draw(st->data); + battle_draw(&bt); painter_present(); } static void fight_finish(struct state *st) { - battle_finish(st->data); - free(st->data); + (void)st; + + battle_bar_finish(&bar, &bt); + battle_bar_default_finish(&default_bar); + battle_finish(&bt); } static struct state fight_state = {
--- a/examples/example-battle/spell-fire.c Fri Feb 18 16:16:38 2022 +0100 +++ b/examples/example-battle/spell-fire.c Sun Feb 27 10:08:51 2022 +0100 @@ -20,10 +20,13 @@ #include <core/action.h> #include <core/animation.h> +#include <core/drawable.h> #include <core/alloc.h> #include <ui/align.h> +#include <rpg/battle-state-check.h> +#include <rpg/battle-state-rendering.h> #include <rpg/battle.h> #include <rpg/character.h> #include <rpg/spell.h> @@ -31,42 +34,42 @@ #include "registry.h" #include "spell-fire.h" -struct data { +struct self { struct battle *battle; struct character *target; struct animation animation; - struct action action; + struct drawable drawable; unsigned int selection; }; static int -update(struct action *act, unsigned int ticks) +update(struct drawable *dw, unsigned int ticks) { - struct data *data = act->data; + struct self *self = dw->data; - return animation_update(&data->animation, ticks); + return animation_update(&self->animation, ticks); } static void -draw(struct action *act) +draw(struct drawable *dw) { - const struct data *data = act->data; - const struct battle_entity *et = &data->battle->enemies[data->selection]; + const struct self *self = dw->data; + const struct battle_entity *et = self->battle->enemies[self->selection]; const struct sprite *sprite = et->ch->sprites[CHARACTER_SPRITE_NORMAL]; int x, y; align(ALIGN_CENTER, - &x, &y, data->animation.sprite->cellw, data->animation.sprite->cellh, + &x, &y, self->animation.sprite->cellw, self->animation.sprite->cellh, et->x, et->y, sprite->cellw, sprite->cellh); - animation_draw(&data->animation, x, y); + animation_draw(&self->animation, x, y); } static void -end(struct action *act) +end(struct drawable *dw) { - struct data *data = act->data; - struct character *ch = data->battle->enemies[data->selection].ch; + struct self *self = dw->data; + struct character *ch = self->battle->enemies[self->selection]->ch; /* TODO: compute damage. */ const unsigned int damage = 100; @@ -76,13 +79,14 @@ else ch->hp -= damage; - battle_indicator_hp(data->battle, data->battle->enemies[data->selection].ch, 100); + battle_indicator_hp(self->battle, self->battle->enemies[self->selection]->ch, 100); + battle_state_check(self->battle); } static void -finish(struct action *act) +finish(struct drawable *dw) { - free(act->data); + free(dw->data); } static void @@ -96,25 +100,24 @@ static void fire_action(struct battle *bt, struct character *owner, const struct selection *slt) { - struct data *data; + struct self *self; (void)owner; - data = alloc_new0(sizeof (*data)); - data->selection = slt->index_character; - data->battle = bt; - data->action.data = data; - data->action.update = update; - data->action.draw = draw; - data->action.finish = finish; - data->action.end = end; + self = alloc_new0(sizeof (*self)); + self->selection = slt->index_character; + self->battle = bt; + self->drawable.data = self; + self->drawable.update = update; + self->drawable.draw = draw; + self->drawable.finish = finish; + self->drawable.end = end; - animation_init(&data->animation, ®istry_sprites[REGISTRY_TEXTURE_EXPLOSION], 12); - animation_start(&data->animation); + animation_init(&self->animation, ®istry_sprites[REGISTRY_TEXTURE_EXPLOSION], 12); + animation_start(&self->animation); sound_play(®istry_sounds[REGISTRY_SOUND_FIRE]); - - action_stack_add(&bt->actions[0], &data->action); + battle_state_rendering(bt, &self->drawable); } const struct spell spell_fire = {
--- a/src/libmlk-rpg/CMakeLists.txt Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/CMakeLists.txt Sun Feb 27 10:08:51 2022 +0100 @@ -56,6 +56,8 @@ ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-menu.h ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-opening.c ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-opening.h + ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-rendering.c + ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-rendering.h ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-selection.c ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-selection.h ${libmlk-rpg_SOURCE_DIR}/rpg/battle-state-victory.c
--- a/src/libmlk-rpg/rpg/battle-bar-default.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-bar-default.c Sun Feb 27 10:08:51 2022 +0100 @@ -43,11 +43,29 @@ #include "rpg_p.h" #include "spell.h" -struct self { - struct battle_bar_default data; - struct battle_bar bar; +#define THEME(bar) ((bar)->theme ? (bar)->theme : theme_default()) + +struct geo { + int x, y; + unsigned int w, h; }; +static inline void +dimensions(struct geo geo[2], const struct battle_bar_default *bar) +{ + /* 0 == main menu */ + geo[0].w = bar->w * 0.2; + geo[0].h = bar->h; + geo[0].x = bar->x + (bar->w / 2) - (geo[0].w / 2); + geo[0].y = window.h - bar->h; + + /* 1 == status frame */ + geo[1].x = geo[0].x + geo[0].w; + geo[1].y = geo[0].y; + geo[1].w = (bar->w - geo[0].w) / 2; + geo[1].h = bar->h; +} + /* * The following validate_* functions are called when the user has validated a * selection depending on the current menu (e.g. Magic, Items). @@ -63,18 +81,18 @@ struct character *target; if (sel->index_side == 0) - target = bt->enemies[sel->index_character].ch; + target = bt->enemies[sel->index_character]->ch; else - target = bt->team[sel->index_character].ch; + target = bt->team[sel->index_character]->ch; - battle_attack(bt, bt->order_cur->ch, target); + battle_attack(bt, battle_current(bt)->ch, target); } static void validate_magic(struct battle_bar_default *bar, struct battle *bt, const struct selection *sel) { - struct character *source = bt->order_cur->ch; - const struct spell *spell = source->spells[bar->sub_grid.selected]; + struct character *source = battle_current(bt)->ch; + const struct spell *spell = source->spells[bar->grid.selected]; battle_cast(bt, source, spell, sel); } @@ -85,15 +103,15 @@ struct inventory_slot *slot; struct battle_entity *source, *target; - if (bar->sub_grid.selected >= INVENTORY_ITEM_MAX) + if (bar->grid.selected >= INVENTORY_ITEM_MAX) return; - if (!(slot = &bt->inventory->items[bar->sub_grid.selected])) + if (!(slot = &bt->inventory->items[bar->grid.selected])) return; - source = bt->order_cur; + source = battle_current(bt); target = sel->index_side == 0 - ? &bt->enemies[sel->index_character] - : &bt->team[sel->index_character]; + ? bt->enemies[sel->index_character] + : bt->team[sel->index_character]; /* TODO: battle_use? */ battle_state_item(bt, source, target, slot); @@ -106,7 +124,7 @@ */ static void -switch_selection_attack(struct battle *bt) +switch_selection_attack(struct battle_bar_default *bar, struct battle *bt) { struct selection sel = { .allowed_kinds = SELECTION_KIND_ONE, @@ -114,7 +132,8 @@ .index_side = 0 }; - /* Just make sure */ + /* Disable handling anymore. */ + bar->state = BATTLE_BAR_DEFAULT_STATE_NONE; selection_first(&sel, bt); battle_state_selection(bt, &sel); @@ -123,13 +142,13 @@ static void switch_selection_spell(struct battle_bar_default *bar, struct battle *bt) { - const struct character *ch = bt->order_cur->ch; - const struct spell *sp = ch->spells[bar->sub_grid.selected]; + const struct character *ch = battle_current(bt)->ch; + const struct spell *sp = ch->spells[bar->grid.selected]; struct selection sel = {0}; - if (bar->sub_grid.selected > CHARACTER_SPELL_MAX) + if (bar->grid.selected > CHARACTER_SPELL_MAX) return; - if (!(sp = ch->spells[bar->sub_grid.selected]) || sp->mp > (unsigned int)(ch->mp)) + if (!(sp = ch->spells[bar->grid.selected]) || sp->mp > (unsigned int)ch->mp) return; /* Use the spell selection algorithm to fill default values. */ @@ -148,7 +167,7 @@ .allowed_kinds = SELECTION_KIND_ONE, .allowed_sides = SELECTION_SIDE_TEAM | SELECTION_SIDE_ENEMY, .index_side = 1, - .index_character = bt->order_curindex + .index_character = battle_index(bt) }; battle_state_selection(bt, &slt); @@ -160,7 +179,7 @@ */ static void -draw_help(const struct battle_bar_default *bar, const struct battle *bt, const char *what) +draw_help(const struct battle_bar_default *bar, const char *what) { struct label label = {0}; unsigned int lw = 0, lh = 0; @@ -168,23 +187,23 @@ label.flags = LABEL_FLAGS_SHADOW; label.text = what; label_query(&label, &lw, &lh); - label.x = bar->sub_grid.x + (bar->sub_grid.w / 2) - (lw / 2); - label.y = bar->sub_grid.y - lh - BATTLE_THEME(bt)->padding; + label.x = bar->grid.x + (bar->grid.w / 2) - (lw / 2); + label.y = bar->grid.y - lh - THEME(bar)->padding; label_draw(&label); } static void draw_spell_help(const struct battle_bar_default *bar, const struct battle *bt) { - const struct character *ch = bt->order_cur->ch; + const struct character *ch = battle_current(bt)->ch; const struct spell *sp; - if (bar->sub_grid.selected >= CHARACTER_SPELL_MAX) + if (bar->grid.selected >= CHARACTER_SPELL_MAX) return; - if (!(sp = ch->spells[bar->sub_grid.selected])) + if (!(sp = ch->spells[bar->grid.selected])) return; - draw_help(bar, bt, sp->description); + draw_help(bar, sp->description); } static void @@ -192,26 +211,25 @@ { const struct inventory_slot *slot; - if (bar->sub_grid.selected >= INVENTORY_ITEM_MAX) + if (bar->grid.selected >= INVENTORY_ITEM_MAX) return; - slot = &bt->inventory->items[bar->sub_grid.selected]; + slot = &bt->inventory->items[bar->grid.selected]; if (!slot->item) return; - draw_help(bar, bt, slot->item->description); + draw_help(bar, slot->item->description); } static void -draw_status_character_stats(const struct battle *bt, +draw_status_character_stats(const struct battle_bar_default *bar, const struct character *ch, int x, int y, - unsigned int w, unsigned int h) { - struct theme *theme = BATTLE_THEME(bt); + const struct theme *theme = THEME(bar); struct label label; unsigned int spacing, lw, lh; char line[64]; @@ -225,17 +243,24 @@ label.text = line; label.flags = LABEL_FLAGS_SHADOW; + /* Name. */ + snprintf(line, sizeof (line), "%s", ch->name); + label_query(&label, &lw, &lh); + label.x = x + theme->padding; + label.y = y + spacing; + label_draw(&label); + /* HP. */ snprintf(line, sizeof (line), "%d/%u", ch->hp, ch->hpmax); label_query(&label, &lw, &lh); - label.x = x + w - lw - theme->padding; - label.y = y + spacing; + label.x = x + theme->padding; + label.y = label.y + lh + spacing; label_draw(&label); /* MP. */ snprintf(line, sizeof (line), "%d/%u", ch->mp, ch->mpmax); label_query(&label, &lw, &lh); - label.x = x + w - lw - theme->padding; + label.x = x + theme->padding; label.y = label.y + lh + spacing; label_draw(&label); @@ -247,43 +272,52 @@ draw_status_character(const struct battle_bar_default *bar, const struct battle *bt, const struct character *ch, + const struct geo *geo, unsigned int index) { int x, y; unsigned int w, h; /* Compute bounding box for rendering. */ - w = bar->status_frame.w / BATTLE_TEAM_MAX; - h = bar->status_frame.h; - x = bar->status_frame.x + (index * w); - y = bar->status_frame.y; + w = geo->w / bt->teamsz; + h = geo->h; + x = geo->x + (index * w); + y = geo->y; - draw_status_character_stats(bt, ch, x, y, w, h); + draw_status_character_stats(bar, ch, x, y, h); } static void -draw_status_characters(const struct battle_bar_default *bar, const struct battle *bt) +draw_status_characters(const struct battle_bar_default *bar, + const struct battle *bt, + const struct geo *geo) { const struct battle_entity *et; unsigned int index = 0; BATTLE_TEAM_FOREACH(bt, et) { if (character_ok(et->ch)) - draw_status_character(bar, bt, et->ch, index); + draw_status_character(bar, bt, et->ch, geo, index); ++index; } } static void -draw_status(const struct battle_bar_default *bar, const struct battle *bt) +draw_status(const struct battle_bar_default *bar, const struct battle *bt, const struct geo *geo) { - frame_draw(&bar->status_frame); - draw_status_characters(bar, bt); + frame_draw(&(const struct frame) { + .x = geo->x, + .y = geo->y, + .w = geo->w, + .h = geo->h + }); + + draw_status_characters(bar, bt, geo); } static void -draw_menu(const struct battle_bar_default *bar, const struct battle *bt) +draw_menu(const struct battle_bar_default *bar, const struct geo *geo) { struct { unsigned int w, h; @@ -320,32 +354,34 @@ } }; - struct theme theme; + const struct theme *theme = THEME(bar); int bx, by; unsigned int bw, bh; - /* Copy theme according to menu selection. */ - theme_shallow(&theme, bt->theme); - /* Compute bounding box with margins removed. */ - bx = bar->menu_frame.x + theme.padding; - by = bar->menu_frame.y + theme.padding; - bw = bar->menu_frame.w - theme.padding * 2; - bh = bar->menu_frame.h - theme.padding * 2; + bx = geo->x + theme->padding; + by = geo->y + theme->padding; + bw = geo->w - theme->padding * 2; + bh = geo->h - theme->padding * 2; /* Draw menu frame. */ - frame_draw(&bar->menu_frame); + frame_draw(&(const struct frame) { + .x = geo->x, + .y = geo->y, + .w = geo->w, + .h = geo->h + }); for (size_t i = 0; i < UTIL_SIZE(buttons); ++i) { - buttons[i].label.theme = &theme; + buttons[i].label.theme = theme; label_query(&buttons[i].label, &buttons[i].w, &buttons[i].h); /* Change theme if it's selected. */ - if ((size_t)bar->menu == i /*&& bar->state != BATTLE_BAR_DEFAULT_STATE_NONE*/) - theme.colors[THEME_COLOR_NORMAL] = BATTLE_THEME(bt)->colors[THEME_COLOR_SELECTED]; + if ((size_t)bar->menu == i) + buttons[i].label.flags |= LABEL_FLAGS_SELECTED; else - theme.colors[THEME_COLOR_NORMAL] = BATTLE_THEME(bt)->colors[THEME_COLOR_NORMAL]; + buttons[i].label.flags &= ~LABEL_FLAGS_SELECTED; align(buttons[i].align, &buttons[i].label.x, &buttons[i].label.y, buttons[i].w, buttons[i].h, @@ -383,13 +419,13 @@ */ switch (bar->menu) { case BATTLE_BAR_DEFAULT_MENU_ATTACK: - switch_selection_attack(bt); + switch_selection_attack(bar, bt); break; case BATTLE_BAR_DEFAULT_MENU_ITEM: battle_bar_default_open_item(bar, bt); break; case BATTLE_BAR_DEFAULT_MENU_MAGIC: - battle_bar_default_open_magic(bar, bt, bt->order_cur->ch); + battle_bar_default_open_magic(bar, bt, battle_current(bt)->ch); break; default: break; @@ -408,18 +444,9 @@ handle_keydown_grid(struct battle_bar_default *bar, struct battle *bt, const union event *ev) { /* Go back to main menu if I press escape. */ - if (ev->key.key == KEY_ESCAPE) { - //gridmenu_reset(&bar->sub_grid); + if (ev->key.key == KEY_ESCAPE) bar->state = BATTLE_BAR_DEFAULT_STATE_MENU; - return; - } - - gridmenu_handle(&bar->sub_grid, ev); - -#if 0 - if (bar->sub_grid.state == GRIDMENU_STATE_ACTIVATED) { - gridmenu_reset(&bar->sub_grid); - + else if (gridmenu_handle(&bar->grid, ev)) { switch (bar->menu) { case BATTLE_BAR_DEFAULT_MENU_MAGIC: switch_selection_spell(bar, bt); @@ -431,7 +458,6 @@ break; } } -#endif } static void @@ -444,7 +470,8 @@ [BATTLE_BAR_DEFAULT_STATE_GRID] = handle_keydown_grid }; - handlers[bar->state](bar, bt, ev); + if (handlers[bar->state]) + handlers[bar->state](bar, bt, ev); } #if 0 @@ -452,10 +479,10 @@ static void handle_clickdown(struct battle_bar_default *bar, struct battle *bt, const union event *ev) { + assert(ev->type == EVENT_CLICKDOWN); + (void)bar; (void)bt; - (void)ev; - assert(ev->type == EVENT_CLICKDOWN); switch (bar->state) { case BATTLE_BAR_DEFAULT_STATE_MENU: @@ -464,8 +491,6 @@ break; case BATTLE_BAR_DEFAULT_STATE_SUB: /* We are in the sub menu (objects/spells). */ - gridmenu_handle(&bar->sub_grid, ev); - if (bar->sub_grid.state == GRIDMENU_STATE_ACTIVATED) default: break; @@ -477,21 +502,7 @@ #endif static void -init_gridmenu(struct battle_bar_default *bar, const struct battle *bt) -{ - bar->sub_grid.x = bar->x; - bar->sub_grid.y = bar->menu_frame.y; - bar->sub_grid.w = bar->status_frame.w; - bar->sub_grid.h = bar->h; - bar->sub_grid.theme = bt->theme; - bar->sub_grid.nrows = 3; - bar->sub_grid.ncols = 4; - - //memset(bar->sub_grid.menu, 0, sizeof (bar->sub_grid.menu)); -} - -static void -start(struct battle_bar *bar, struct battle *bt) +self_start(struct battle_bar *bar, struct battle *bt) { (void)bt; @@ -505,50 +516,36 @@ } static void -handle(struct battle_bar *bar, struct battle *bt, const union event *ev) +self_handle(struct battle_bar *bar, struct battle *bt, const union event *ev) { battle_bar_default_handle(bar->data, bt, ev); } static void -draw(const struct battle_bar *bar, const struct battle *bt) +self_draw(const struct battle_bar *bar, const struct battle *bt) { battle_bar_default_draw(bar->data, bt); } -static void -finish(struct battle_bar *bar, struct battle *bt) -{ - (void)bt; - - battle_bar_default_finish(bar->data); - free(bar->data); -} - void -battle_bar_default_positionate(struct battle_bar_default *bar, const struct battle *bt) +battle_bar_default_init(struct battle_bar_default *bar) { assert(bar); - assert(bt); + + struct geo geo[2]; + + memset(bar, 0, sizeof (*bar)); bar->w = window.w; bar->h = window.h * 0.12; bar->x = 0; bar->y = window.h - bar->h; - /* Menu in the middle of the bar (take 20%). */ - bar->menu_frame.w = bar->w * 0.2; - bar->menu_frame.h = bar->h; - bar->menu_frame.x = bar->x + (bar->w / 2) - (bar->menu_frame.w / 2); - bar->menu_frame.y = window.h - bar->h; - bar->menu_frame.theme = bt->theme; + dimensions(geo, bar); - /* Status bar on the right. */ - bar->status_frame.x = bar->menu_frame.x + bar->menu_frame.w; - bar->status_frame.y = bar->menu_frame.y; - bar->status_frame.w = (bar->w - bar->menu_frame.w) / 2; - bar->status_frame.h = bar->h; - bar->status_frame.theme = bt->theme; + gridmenu_init(&bar->grid, 2, 2, NULL, 0); + gridmenu_resize(&bar->grid, bar->x, geo[0].y, geo[1].w, bar->h); + bar->grid.theme = bar->theme; } void @@ -558,17 +555,14 @@ assert(bt); assert(ch); -#if 0 - init_gridmenu(bar, bt); + bar->items = bar->grid.items = alloc_rearray0(bar->items, bar->itemsz, + CHARACTER_SPELL_MAX, sizeof (*bar->items)); + bar->itemsz = bar->grid.itemsz = CHARACTER_SPELL_MAX; + bar->state = BATTLE_BAR_DEFAULT_STATE_GRID; for (size_t i = 0; i < CHARACTER_SPELL_MAX; ++i) if (ch->spells[i]) - bar->sub_grid.menu[i] = ch->spells[i]->name; - - gridmenu_repaint(&bar->sub_grid); - - bar->state = BATTLE_BAR_DEFAULT_STATE_GRID; -#endif + bar->grid.items[i] = ch->spells[i]->name; } void @@ -577,10 +571,8 @@ assert(bar); assert(bt); + /* TODO: not implemented yet. */ #if 0 - - init_gridmenu(bar, bt); - for (size_t i = 0; i < INVENTORY_ITEM_MAX; ++i) { if (bt->inventory->items[i].item) { snprintf(bar->sub_items[i], sizeof (bar->sub_items[i]), "%-16s %u", @@ -589,8 +581,6 @@ } } - gridmenu_repaint(&bar->sub_grid); - bar->state = BATTLE_BAR_DEFAULT_STATE_GRID; #endif } @@ -600,8 +590,6 @@ { assert(bar); - //gridmenu_reset(&bar->sub_grid); - bar->menu = BATTLE_BAR_DEFAULT_MENU_ATTACK; bar->state = BATTLE_BAR_DEFAULT_STATE_MENU; } @@ -618,10 +606,10 @@ assert(sel); static void (*validate[])(struct battle_bar_default *, struct battle *, const struct selection *) = { - [BATTLE_BAR_DEFAULT_MENU_ATTACK] = validate_attack, - [BATTLE_BAR_DEFAULT_MENU_ITEM] = validate_item, - [BATTLE_BAR_DEFAULT_MENU_MAGIC] = validate_magic, - [BATTLE_BAR_DEFAULT_MENU_SPECIAL] = NULL + [BATTLE_BAR_DEFAULT_MENU_ATTACK] = validate_attack, + [BATTLE_BAR_DEFAULT_MENU_ITEM] = validate_item, + [BATTLE_BAR_DEFAULT_MENU_MAGIC] = validate_magic, + [BATTLE_BAR_DEFAULT_MENU_SPECIAL] = NULL }; if (validate[bar->menu]) @@ -650,8 +638,11 @@ assert(bar); assert(bt); - draw_status(bar, bt); - draw_menu(bar, bt); + struct geo geo[2]; + + dimensions(geo, bar); + draw_menu(bar, &geo[0]); + draw_status(bar, bt, &geo[1]); if (bar->state == BATTLE_BAR_DEFAULT_STATE_GRID) { switch (bar->menu) { @@ -668,7 +659,7 @@ /* Sub menu is only shown if state is set to it. */ if (bar->state == BATTLE_BAR_DEFAULT_STATE_GRID) - gridmenu_draw(&bar->sub_grid); + gridmenu_draw(&bar->grid); } void @@ -676,27 +667,21 @@ { assert(bar); - //gridmenu_finish(&bar->sub_grid); - + free(bar->items); memset(bar, 0, sizeof (*bar)); } void -battle_bar_default(struct battle *bt) +battle_bar_default(struct battle_bar_default *self, struct battle_bar *bar) { - assert(bt); + assert(self); + assert(bar); - struct self *self; + memset(bar, 0, sizeof (*bar)); - self = alloc_new0(sizeof (*self)); - self->bar.data = self; - self->bar.start = start; - self->bar.select = self_select; - self->bar.handle = handle; - self->bar.draw = draw; - self->bar.finish = finish; - - battle_bar_default_positionate(&self->data, bt); - - bt->bar = &self->bar; + bar->data = self; + bar->start = self_start; + bar->select = self_select; + bar->handle = self_handle; + bar->draw = self_draw; }
--- a/src/libmlk-rpg/rpg/battle-bar-default.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-bar-default.h Sun Feb 27 10:08:51 2022 +0100 @@ -21,12 +21,13 @@ #include <core/core.h> -#include <ui/frame.h> #include <ui/gridmenu.h> struct battle; +struct battle_bar; struct character; struct selection; +struct theme; union event; @@ -38,6 +39,7 @@ }; enum battle_bar_default_state { + BATTLE_BAR_DEFAULT_STATE_NONE, BATTLE_BAR_DEFAULT_STATE_MENU, BATTLE_BAR_DEFAULT_STATE_GRID }; @@ -47,24 +49,20 @@ int y; unsigned int w; unsigned int h; + struct theme *theme; enum battle_bar_default_state state; - - /* Right status frame. */ - struct frame status_frame; - - /* Main menu selection. */ - struct frame menu_frame; enum battle_bar_default_menu menu; - /* Sub menu selection (spells/objects). */ - char sub_items[16][128]; - struct gridmenu sub_grid; + /* Private fields. */ + const char **items; + size_t itemsz; + struct gridmenu grid; }; CORE_BEGIN_DECLS void -battle_bar_default_positionate(struct battle_bar_default *, const struct battle *); +battle_bar_default_init(struct battle_bar_default *); void battle_bar_default_open_magic(struct battle_bar_default *, const struct battle *, struct character *); @@ -79,7 +77,7 @@ battle_bar_default_select(struct battle_bar_default *, struct battle *, const struct selection *); void -battle_bar_default_handle(struct battle_bar_default *bar, struct battle *bt, const union event *); +battle_bar_default_handle(struct battle_bar_default *, struct battle *, const union event *); void battle_bar_default_draw(const struct battle_bar_default *, const struct battle *); @@ -88,7 +86,7 @@ battle_bar_default_finish(struct battle_bar_default *); void -battle_bar_default(struct battle *); +battle_bar_default(struct battle_bar_default *, struct battle_bar *); CORE_END_DECLS
--- a/src/libmlk-rpg/rpg/battle-entity.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-entity.c Sun Feb 27 10:08:51 2022 +0100 @@ -32,14 +32,14 @@ static void draw_name(const struct battle_entity *et, const struct battle *bt) { - struct theme theme; struct label label = et->name; - if (et == bt->order_cur) { - theme_shallow(&theme, bt->theme); - label.theme = &theme; - theme.colors[THEME_COLOR_NORMAL] = theme.colors[THEME_COLOR_SELECTED]; - } + label.theme = BATTLE_THEME(bt); + + if (et == battle_current(bt)) + label.flags |= LABEL_FLAGS_SELECTED; + else + label.flags &= ~LABEL_FLAGS_SELECTED; label_draw(&label); }
--- a/src/libmlk-rpg/rpg/battle-state-ai.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-ai.c Sun Feb 27 10:08:51 2022 +0100 @@ -32,7 +32,17 @@ (void)st; (void)ticks; - return battle_state_ai_update(bt); + battle_state_ai_update(bt); + + return 0; +} + +static void +draw(const struct battle_state *st, const struct battle *bt) +{ + (void)st; + + battle_state_ai_draw(bt); } static void @@ -43,20 +53,26 @@ free(st); } -int +void battle_state_ai_update(struct battle *bt) { - assert(bt); + assert(battle_ok(bt)); - struct character *ch = bt->order_cur->ch; + struct character *ch = battle_current(bt)->ch; /* * Immediately invoke the enemy exec strategy and put the battle state * to check. */ character_exec(ch, bt); +} - return 0; +void +battle_state_ai_draw(const struct battle *bt) +{ + assert(battle_ok(bt)); + + battle_draw_component(bt, BATTLE_COMPONENT_ALL); } void @@ -69,6 +85,7 @@ self = alloc_new0(sizeof (*self)); self->data = bt; self->update = update; + self->draw = draw; self->finish = finish; battle_switch(bt, self);
--- a/src/libmlk-rpg/rpg/battle-state-ai.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-ai.h Sun Feb 27 10:08:51 2022 +0100 @@ -21,10 +21,13 @@ struct battle; -int +void battle_state_ai_update(struct battle *); void +battle_state_ai_draw(const struct battle *); + +void battle_state_ai(struct battle *); #endif /* !MLK_RPG_BATTLE_STATE_AI_H */
--- a/src/libmlk-rpg/rpg/battle-state-attacking.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-attacking.c Sun Feb 27 10:08:51 2022 +0100 @@ -56,9 +56,15 @@ static int update(struct battle_state *st, struct battle *bt, unsigned int ticks) { - (void)ticks; + battle_state_attacking_update(st->data, bt, ticks); + + return 0; +} - return battle_state_attacking_update(st->data, bt); +static void +draw(const struct battle_state *st, const struct battle *bt) +{ + battle_state_attacking_draw(st->data, bt); } static void @@ -98,14 +104,16 @@ battle_entity_state_moving(source, x, y); } -int -battle_state_attacking_update(struct battle_state_attacking *atk, struct battle *bt) +void +battle_state_attacking_update(struct battle_state_attacking *atk, struct battle *bt, unsigned int ticks) { assert(atk); assert(bt); + battle_update_component(bt, ticks, BATTLE_COMPONENT_ALL); + if (!battle_entity_update(atk->source, 0)) - return 0; + return; switch (atk->status) { case BATTLE_STATE_ATTACKING_ADVANCING: @@ -135,8 +143,15 @@ default: break; } +} - return 0; +void +battle_state_attacking_draw(const struct battle_state_attacking *atk, const struct battle *bt) +{ + assert(atk); + assert(battle_ok(bt)); + + battle_draw_component(bt, BATTLE_COMPONENT_ALL); } void @@ -151,6 +166,7 @@ self = alloc_new0(sizeof (*self)); self->state.data = self; self->state.update = update; + self->state.draw = draw; self->state.finish = finish; battle_state_attacking_init(&self->data, source, target);
--- a/src/libmlk-rpg/rpg/battle-state-attacking.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-attacking.h Sun Feb 27 10:08:51 2022 +0100 @@ -45,8 +45,11 @@ struct battle_entity *, struct battle_entity *); -int -battle_state_attacking_update(struct battle_state_attacking *, struct battle *); +void +battle_state_attacking_update(struct battle_state_attacking *, struct battle *, unsigned int); + +void +battle_state_attacking_draw(const struct battle_state_attacking *, const struct battle *); void battle_state_attacking(struct battle_entity *, struct battle_entity *, struct battle *);
--- a/src/libmlk-rpg/rpg/battle-state-check.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-check.c Sun Feb 27 10:08:51 2022 +0100 @@ -24,6 +24,7 @@ #include <core/panic.h> #include <core/sprite.h> #include <core/texture.h> +#include <core/trace.h> #include "battle-state-check.h" #include "battle-state-lost.h" @@ -31,20 +32,21 @@ #include "battle-state.h" #include "battle.h" #include "character.h" +#include "rpg_p.h" struct fadeout { struct character *ch; int x; int y; - struct action action; + struct drawable dw; unsigned int alpha; unsigned int elapsed; }; static int -fadeout_update(struct action *act, unsigned int ticks) +fadeout_update(struct drawable *dw, unsigned int ticks) { - struct fadeout *fade = act->data; + struct fadeout *fade = dw->data; fade->elapsed += ticks; @@ -61,9 +63,9 @@ } static void -fadeout_draw(struct action *act) +fadeout_draw(struct drawable *dw) { - const struct fadeout *fade = act->data; + const struct fadeout *fade = dw->data; struct sprite *sprite = fade->ch->sprites[CHARACTER_SPRITE_NORMAL]; texture_set_alpha_mod(sprite->texture, fade->alpha); @@ -72,9 +74,9 @@ } static void -fadeout_finish(struct action *act) +fadeout_finish(struct drawable *dw) { - free(act->data); + free(dw->data); } static void @@ -82,22 +84,23 @@ { struct fadeout *fade; - if (!(fade = alloc_new0(sizeof (*fade)))) - panic(); + if (!bt->effects) { + tracef(_("can't create a fadeout effect without a drawable_stack")); + return; + } + fade = alloc_new0(sizeof (*fade)); fade->ch = et->ch; fade->x = et->x; fade->y = et->y; fade->alpha = 250; - fade->action.data = fade; - fade->action.draw = fadeout_draw; - fade->action.update = fadeout_update; - fade->action.finish = fadeout_finish; + fade->dw.data = fade; + fade->dw.draw = fadeout_draw; + fade->dw.update = fadeout_update; + fade->dw.finish = fadeout_finish; - if (action_stack_add(&bt->actions[1], &fade->action) < 0) + if (drawable_stack_add(bt->effects, &fade->dw) < 0) free(fade); - - memset(et, 0, sizeof (*et)); } static int @@ -130,11 +133,12 @@ static void clean(struct battle *bt) { - struct battle_entity *et; - - BATTLE_ENEMY_FOREACH(bt, et) - if (character_ok(et->ch) && et->ch->hp == 0) - fadeout(bt, et); + for (size_t i = 0; i < bt->enemiesz; ++i) { + if (bt->enemies[i] && character_ok(bt->enemies[i]->ch) && bt->enemies[i]->ch->hp == 0) { + fadeout(bt, bt->enemies[i]); + bt->enemies[i] = NULL; + } + } } static int @@ -143,7 +147,17 @@ (void)st; (void)ticks; - return battle_state_check_update(bt); + battle_state_check_update(bt); + + return 0; +} + +static void +draw(const struct battle_state *st, const struct battle *bt) +{ + (void)st; + + battle_state_check_draw(bt); } static void @@ -154,10 +168,10 @@ free(st); } -int +void battle_state_check_update(struct battle *bt) { - assert(bt); + assert(battle_ok(bt)); clean(bt); @@ -167,20 +181,27 @@ battle_state_victory(bt); else battle_next(bt); +} - return 0; +void +battle_state_check_draw(const struct battle *bt) +{ + assert(battle_ok(bt)); + + battle_draw_component(bt, BATTLE_COMPONENT_ALL); } void battle_state_check(struct battle *bt) { - assert(bt); + assert(battle_ok(bt)); struct battle_state *self; self = alloc_new0(sizeof (*self)); self->data = bt; self->update = update; + self->draw = draw; self->finish = finish; battle_switch(bt, self);
--- a/src/libmlk-rpg/rpg/battle-state-check.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-check.h Sun Feb 27 10:08:51 2022 +0100 @@ -21,10 +21,13 @@ struct battle; -int +void battle_state_check_update(struct battle *); void +battle_state_check_draw(const struct battle *); + +void battle_state_check(struct battle *); #endif /* !MLK_RPG_BATTLE_STATE_CHECK_H */
--- a/src/libmlk-rpg/rpg/battle-state-closing.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-closing.c Sun Feb 27 10:08:51 2022 +0100 @@ -48,7 +48,7 @@ { (void)bt; - battle_state_closing_draw(st->data); + battle_state_closing_draw(st->data, bt); } static void @@ -105,10 +105,11 @@ } void -battle_state_closing_draw(const struct battle_state_closing *cls) +battle_state_closing_draw(const struct battle_state_closing *cls, const struct battle *bt) { assert(cls); + battle_draw_component(bt, BATTLE_COMPONENT_ALL); texture_draw(&cls->texture, 0, 0); }
--- a/src/libmlk-rpg/rpg/battle-state-closing.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-closing.h Sun Feb 27 10:08:51 2022 +0100 @@ -36,7 +36,7 @@ battle_state_closing_update(struct battle_state_closing *, unsigned int); void -battle_state_closing_draw(const struct battle_state_closing *); +battle_state_closing_draw(const struct battle_state_closing *, const struct battle *); void battle_state_closing_finish(struct battle_state_closing *);
--- a/src/libmlk-rpg/rpg/battle-state-lost.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-lost.c Sun Feb 27 10:08:51 2022 +0100 @@ -53,7 +53,7 @@ { (void)bt; - battle_state_lost_draw(st->data); + battle_state_lost_draw(st->data, bt); } void @@ -108,10 +108,12 @@ } void -battle_state_lost_draw(struct battle_state_lost *lost) +battle_state_lost_draw(struct battle_state_lost *lost, const struct battle *bt) { assert(lost); + assert(battle_ok(bt)); + battle_draw_component(bt, BATTLE_COMPONENT_ALL); message_draw(&lost->msg); }
--- a/src/libmlk-rpg/rpg/battle-state-lost.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-lost.h Sun Feb 27 10:08:51 2022 +0100 @@ -40,7 +40,7 @@ battle_state_lost_update(struct battle_state_lost *, struct battle *, unsigned int); void -battle_state_lost_draw(struct battle_state_lost *); +battle_state_lost_draw(struct battle_state_lost *, const struct battle *); void battle_state_lost(struct battle *);
--- a/src/libmlk-rpg/rpg/battle-state-menu.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-menu.c Sun Feb 27 10:08:51 2022 +0100 @@ -26,35 +26,6 @@ #include "battle-state.h" #include "battle.h" -#if 0 - -static void -open_spells(struct battle *bt) -{ - battle_bar_open_spells(&bt->bar, bt, bt->order_cur->ch); - battle_state_sub(bt); -} - -static void -open_attack(struct battle *bt) -{ - struct selection slt = { - .allowed_sides = SELECTION_SIDE_ENEMY - }; - - selection_first(&slt, bt); - battle_state_selection(bt, &slt); -} - -static void -open_items(struct battle *bt) -{ - battle_bar_open_items(&bt->bar, bt); - battle_state_sub(bt); -} - -#endif - static void handle(struct battle_state *st, struct battle *bt, const union event *ev) { @@ -63,6 +34,24 @@ battle_state_menu_handle(bt, ev); } +static int +update(struct battle_state *st, struct battle *bt, unsigned int ticks) +{ + (void)st; + + battle_state_menu_update(bt, ticks); + + return 0; +} + +static void +draw(const struct battle_state *st, const struct battle *bt) +{ + (void)st; + + battle_state_menu_draw(bt); +} + static void finish(struct battle_state *st, struct battle *bt) { @@ -81,6 +70,22 @@ } void +battle_state_menu_update(struct battle *bt, unsigned int ticks) +{ + assert(battle_ok(bt)); + + battle_update_component(bt, ticks, BATTLE_COMPONENT_ALL); +} + +void +battle_state_menu_draw(const struct battle *bt) +{ + assert(battle_ok(bt)); + + battle_draw_component(bt, BATTLE_COMPONENT_ALL); +} + +void battle_state_menu(struct battle *bt) { assert(bt); @@ -90,6 +95,8 @@ state = alloc_new0(sizeof (*state)); state->data = bt; state->handle = handle; + state->update = update; + state->draw = draw; state->finish = finish; battle_bar_start(bt->bar, bt);
--- a/src/libmlk-rpg/rpg/battle-state-menu.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-menu.h Sun Feb 27 10:08:51 2022 +0100 @@ -27,6 +27,12 @@ battle_state_menu_handle(struct battle *, const union event *); void +battle_state_menu_update(struct battle *, unsigned int); + +void +battle_state_menu_draw(const struct battle *); + +void battle_state_menu(struct battle *); #endif /* !MLK_RPG_BATTLE_STATE_MENU_H */
--- a/src/libmlk-rpg/rpg/battle-state-opening.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-opening.c Sun Feb 27 10:08:51 2022 +0100 @@ -50,7 +50,7 @@ { (void)bt; - battle_state_opening_draw(st->data); + battle_state_opening_draw(st->data, bt); } static void @@ -77,12 +77,17 @@ } void -battle_state_opening_draw(const struct battle_state_opening *op) +battle_state_opening_draw(const struct battle_state_opening *op, const struct battle *bt) { + assert(op); + assert(bt); + const unsigned int w = window.w; const unsigned int h = window.h / 2; const unsigned int ch = op->elapsed * h / DELAY; + battle_draw_component(bt, BATTLE_COMPONENT_BACKGROUND | BATTLE_COMPONENT_ENTITIES); + /* Draw some bezels opening. */ painter_set_color(0x000000ff); painter_draw_rectangle(0, 0, w, h - ch);
--- a/src/libmlk-rpg/rpg/battle-state-opening.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-opening.h Sun Feb 27 10:08:51 2022 +0100 @@ -29,7 +29,7 @@ battle_state_opening_update(struct battle_state_opening *, struct battle *, unsigned int); void -battle_state_opening_draw(const struct battle_state_opening *); +battle_state_opening_draw(const struct battle_state_opening *, const struct battle *); void battle_state_opening(struct battle *);
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/rpg/battle-state-rendering.c Sun Feb 27 10:08:51 2022 +0100 @@ -0,0 +1,114 @@ +/* + * battle-state-rendering.c -- battle state (rendering an action) + * + * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include <assert.h> +#include <stdlib.h> + +#include <core/alloc.h> +#include <core/drawable.h> + +#include "battle-state-rendering.h" +#include "battle.h" + +struct self { + struct battle_state_rendering data; + struct battle_state state; +}; + +static int +update(struct battle_state *st, struct battle *bt, unsigned int ticks) +{ + battle_state_rendering_update(st->data, bt, ticks); + + return 0; +} + +static void +draw(const struct battle_state *st, const struct battle *bt) +{ + battle_state_rendering_draw(st->data, bt); +} + +static void +finish(struct battle_state *st, struct battle *bt) +{ + (void)bt; + + battle_state_rendering_finish(st->data); + free(st->data); +} + +void +battle_state_rendering_init(struct battle_state_rendering *rdr, struct drawable *dw) +{ + assert(rdr); + assert(dw); + + rdr->drawable = dw; +} + +int +battle_state_rendering_update(struct battle_state_rendering *rdr, struct battle *bt, unsigned int ticks) +{ + assert(rdr); + assert(battle_ok(bt)); + + battle_update_component(bt, BATTLE_COMPONENT_ALL, ticks); + + if (drawable_update(rdr->drawable, ticks)) { + drawable_end(rdr->drawable); + return 1; + } + + return 0; +} + +void +battle_state_rendering_draw(const struct battle_state_rendering *rdr, const struct battle *bt) +{ + assert(rdr); + + battle_draw_component(bt, BATTLE_COMPONENT_ALL); + drawable_draw(rdr->drawable); +} + +void +battle_state_rendering_finish(struct battle_state_rendering *rdr) +{ + assert(rdr); + + drawable_finish(rdr->drawable); +} + +void +battle_state_rendering(struct battle *bt, struct drawable *dw) +{ + assert(bt); + assert(dw); + + struct self *self; + + self = alloc_new0(sizeof (*self)); + self->state.data = self; + self->state.update = update; + self->state.draw = draw; + self->state.finish = finish; + + battle_state_rendering_init(&self->data, dw); + battle_switch(bt, &self->state); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/libmlk-rpg/rpg/battle-state-rendering.h Sun Feb 27 10:08:51 2022 +0100 @@ -0,0 +1,44 @@ +/* + * battle-state-rendering.h -- battle state (rendering an action) + * + * Copyright (c) 2020-2022 David Demelier <markand@malikania.fr> + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef MLK_RPG_BATTLE_STATE_RENDERING_H +#define MLK_RPG_BATTLE_STATE_RENDERING_H + +struct battle; +struct drawable; + +struct battle_state_rendering { + struct drawable *drawable; +}; + +void +battle_state_rendering_init(struct battle_state_rendering *, struct drawable *); + +int +battle_state_rendering_update(struct battle_state_rendering *, struct battle *, unsigned int); + +void +battle_state_rendering_draw(const struct battle_state_rendering *, const struct battle *); + +void +battle_state_rendering_finish(struct battle_state_rendering *); + +void +battle_state_rendering(struct battle *, struct drawable *); + +#endif /* !MLK_RPG_BATTLE_STATE_RENDERING_H */
--- a/src/libmlk-rpg/rpg/battle-state-selection.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-selection.c Sun Feb 27 10:08:51 2022 +0100 @@ -45,7 +45,7 @@ }; static void -select_adj_in(struct battle_state_selection *slt, const struct battle_entity *entities, size_t entitiesz, int step) +select_adj_in(struct battle_state_selection *slt, struct battle_entity **entities, size_t entitiesz, int step) { assert(slt->select.index_character != (unsigned int)-1); @@ -53,14 +53,14 @@ if (step < 0) { while (newselection > 0) { - if (character_ok(entities[--newselection].ch)) { + if (character_ok(entities[--newselection]->ch)) { slt->select.index_character = newselection; break; } } } else { while (newselection < entitiesz) { - if (character_ok(entities[++newselection].ch)) { + if (character_ok(entities[++newselection]->ch)) { slt->select.index_character = newselection; break; } @@ -72,9 +72,9 @@ select_adj(struct battle_state_selection *slt, const struct battle *bt, int step) { if (slt->select.index_side == 0) - select_adj_in(slt, bt->enemies, UTIL_SIZE(bt->enemies), step); + select_adj_in(slt, bt->enemies, bt->enemiesz, step); else - select_adj_in(slt, bt->team, UTIL_SIZE(bt->team), step); + select_adj_in(slt, bt->team, bt->teamsz, step); } static void @@ -133,13 +133,13 @@ static void draw_cursors(const struct battle *bt, - const struct battle_entity *entities, + struct battle_entity * const *entities, size_t entitiesz) { for (size_t i = 0; i < entitiesz; ++i) { - const struct battle_entity *et = &entities[i]; + const struct battle_entity *et = entities[i]; - if (character_ok(et->ch)) + if (et && character_ok(et->ch)) draw_cursor(bt, et); } } @@ -195,18 +195,20 @@ assert(stl); assert(bt); + battle_draw_component(bt, BATTLE_COMPONENT_ALL); + if (stl->select.index_character == -1U) { /* All selected. */ if (stl->select.index_side == 0) - draw_cursors(bt, bt->enemies, UTIL_SIZE(bt->enemies)); + draw_cursors(bt, bt->enemies, bt->enemiesz); else - draw_cursors(bt, bt->team, UTIL_SIZE(bt->team)); + draw_cursors(bt, bt->team, bt->teamsz); } else { /* Select one. */ if (stl->select.index_side == 0) - draw_cursor(bt, &bt->enemies[stl->select.index_character]); + draw_cursor(bt, bt->enemies[stl->select.index_character]); else - draw_cursor(bt, &bt->team[stl->select.index_character]); + draw_cursor(bt, bt->team[stl->select.index_character]); } }
--- a/src/libmlk-rpg/rpg/battle-state-victory.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-victory.c Sun Feb 27 10:08:51 2022 +0100 @@ -55,7 +55,7 @@ { (void)bt; - battle_state_victory_draw(st->data); + battle_state_victory_draw(st->data, bt); } void @@ -101,6 +101,8 @@ assert(vic); assert(bt); + battle_update_component(bt, BATTLE_COMPONENT_ALL, ticks); + if (message_update(&vic->msg, ticks)) battle_state_closing(bt); @@ -108,10 +110,11 @@ } void -battle_state_victory_draw(const struct battle_state_victory *vic) +battle_state_victory_draw(const struct battle_state_victory *vic, const struct battle *bt) { assert(vic); + battle_draw_component(bt, BATTLE_COMPONENT_ALL); message_draw(&vic->msg); }
--- a/src/libmlk-rpg/rpg/battle-state-victory.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle-state-victory.h Sun Feb 27 10:08:51 2022 +0100 @@ -40,7 +40,7 @@ battle_state_victory_update(struct battle_state_victory *, struct battle *, unsigned int); void -battle_state_victory_draw(const struct battle_state_victory *); +battle_state_victory_draw(const struct battle_state_victory *, const struct battle *); void battle_state_victory(struct battle *);
--- a/src/libmlk-rpg/rpg/battle.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle.c Sun Feb 27 10:08:51 2022 +0100 @@ -25,9 +25,9 @@ #include <core/event.h> #include <core/font.h> #include <core/music.h> -#include <core/painter.h> #include <core/sprite.h> #include <core/texture.h> +#include <core/trace.h> #include <core/util.h> #include <core/window.h> @@ -48,6 +48,7 @@ #include "character.h" #include "inventory.h" #include "item.h" +#include "rpg_p.h" #include "spell.h" struct indicator { @@ -96,14 +97,14 @@ } static struct battle_entity * -random_select(struct battle_entity *group, size_t groupsz) +random_select(struct battle_entity **group, size_t groupsz) { struct battle_entity *ret = NULL, *et = NULL; do { - et = &group[util_nrand(0, groupsz - 1)]; + et = group[util_nrand(0, groupsz - 1)]; - if (et->ch) + if (et && et->ch) ret = et; } while (!ret); @@ -116,14 +117,14 @@ const struct battle_entity *et1 = *(const struct battle_entity **)d1; const struct battle_entity *et2 = *(const struct battle_entity **)d2; - return et1->ch->agt < et2->ch->agt; + return et2->ch->agt < et1->ch->agt; } static int is_team(const struct battle *bt, const struct character *ch) { - for (size_t i = 0; i < BATTLE_TEAM_MAX; ++i) - if (bt->team[i].ch == ch) + for (size_t i = 0; i < bt->teamsz; ++i) + if (bt->team[i] && bt->team[i]->ch == ch) return 1; return 0; @@ -170,7 +171,7 @@ if (et->x != 0 || et->y != 0) return; - if (battle_entity_ok(&bt->team[i])) { + if (battle_entity_ok(bt->team[i])) { nmemb++; requirement += et->ch->sprites[CHARACTER_SPRITE_NORMAL]->cellh; } @@ -180,7 +181,7 @@ spacing = (window.h - requirement) / (nmemb + 1); x = window.w - 200; y = spacing; - + BATTLE_TEAM_FOREACH(bt, et) { if (battle_entity_ok(et)) { et->x = x; @@ -191,26 +192,42 @@ } static void -draw_entities(const struct battle *bt, struct battle_entity *entities, size_t entitiesz) +draw_entities(const struct battle *bt, struct battle_entity **entities, size_t entitiesz) { for (size_t i = 0; i < entitiesz; ++i) { - if (battle_entity_ok(&entities[i])) - battle_entity_draw(&entities[i], bt); + if (battle_entity_ok(entities[i])) + battle_entity_draw(entities[i], bt); } } static void -update_entities(struct battle_entity *entities, size_t entitiesz, unsigned int ticks) +update_entities(struct battle_entity **entities, size_t entitiesz, unsigned int ticks) { for (size_t i = 0; i < entitiesz; ++i) { - if (battle_entity_ok(&entities[i])) - battle_entity_update(&entities[i], ticks); + if (battle_entity_ok(entities[i])) + battle_entity_update(entities[i], ticks); } } void +battle_init(struct battle *bt) +{ + assert(bt); + + memset(bt, 0, sizeof (*bt)); +} + +int +battle_ok(const struct battle *bt) +{ + return bt && bt->state && bt->bar && bt->enemiesz && bt->team; +} + +void battle_start(struct battle *bt) { + assert(bt); + struct battle_entity *et; BATTLE_TEAM_FOREACH(bt, et) @@ -229,6 +246,8 @@ /* Play music if present. */ if (bt->music[0]) music_play(bt->music[0], MUSIC_LOOP); + + battle_order(bt); } void @@ -246,20 +265,39 @@ void battle_order(struct battle *bt) { - struct battle_entity *et, **porder; - - /* First, put a pointer for every enemy/team member. */ - porder = &bt->order[0]; + struct battle_entity **porder; - BATTLE_TEAM_FOREACH(bt, et) - if (character_ok(et->ch)) - *porder++ = et; - BATTLE_ENEMY_FOREACH(bt, et) - if (character_ok(et->ch)) - *porder++ = et; + /* Create a pointer list to every entity. */ + bt->order = alloc_rearray0(bt->order, bt->ordersz, + bt->teamsz + bt->enemiesz, sizeof (*bt->order)); + bt->ordersz = bt->teamsz + bt->enemiesz; + bt->ordercur = porder = bt->order; + + for (size_t i = 0; i < bt->teamsz; ++i) + if (bt->team[i] && character_ok(bt->team[i]->ch)) + *porder++ = bt->team[i]; + for (size_t i = 0; i < bt->enemiesz; ++i) + if (bt->enemies[i] && character_ok(bt->enemies[i]->ch)) + *porder++ = bt->enemies[i]; /* Now sort. */ - qsort(bt->order, porder - bt->order, sizeof (*porder), cmp_order); + qsort(bt->order, bt->ordersz, sizeof (*bt->order), cmp_order); +} + +struct battle_entity * +battle_current(const struct battle *bt) +{ + assert(bt); + + return *bt->ordercur; +} + +size_t +battle_index(const struct battle *bt) +{ + assert(bt); + + return bt->ordercur - bt->order; } void @@ -273,9 +311,9 @@ /* Target is empty? select randomly. */ if (!target) { if (is_team(bt, source)) - target = random_select(bt->enemies, BATTLE_ENEMY_MAX)->ch; + target = random_select(bt->enemies, bt->enemiesz)->ch; else - target = random_select(bt->team, BATTLE_TEAM_MAX)->ch; + target = random_select(bt->team, bt->teamsz)->ch; } battle_state_attacking(battle_find(bt, source), battle_find(bt, target), bt); @@ -295,7 +333,6 @@ /* TODO: animate. */ source->mp -= spell->mp; spell_action(spell, bt, source, selection); - battle_state_check(bt); } void @@ -321,26 +358,16 @@ { assert(bt); - if (!bt->order_cur) { + if (!bt->ordercur) battle_order(bt); - bt->order_cur = bt->order[bt->order_curindex = 0]; - } else { - for (++bt->order_curindex; bt->order_curindex < BATTLE_ENTITY_MAX; ++bt->order_curindex) { - if (battle_entity_ok(bt->order[bt->order_curindex])) { - bt->order_cur = bt->order[bt->order_curindex]; - break; - } - } - - /* End of "turn". */ - if (bt->order_curindex >= BATTLE_ENTITY_MAX) { + else { + if (bt->ordercur - bt->order + (size_t)1U >= bt->ordersz) battle_order(bt); - bt->order_cur = bt->order[bt->order_curindex = 0]; - } + else + bt->ordercur++; } - /* Change state depending on the kind of entity. */ - if (is_team(bt, bt->order_cur->ch)) { + if (is_team(bt, battle_current(bt)->ch)) { battle_bar_start(bt->bar, bt); battle_state_menu(bt); } else @@ -362,8 +389,14 @@ assert(target); const struct battle_entity *et = find(bt, target); - struct indicator *id = alloc_new0(sizeof (*id)); + struct indicator *id; + if (!(bt->effects)) { + tracef(_("unable to add id without a drawable_stack")); + return; + } + + id = alloc_new0(sizeof (*id)); id->bti.color = BATTLE_INDICATOR_HP_COLOR; id->bti.amount = labs(amount); @@ -377,23 +410,46 @@ battle_indicator_start(&id->bti); - if (drawable_stack_add(&bt->effects, &id->dw) < 0) + if (drawable_stack_add(bt->effects, &id->dw) < 0) drawable_finish(&id->dw); } void +battle_handle_component(struct battle *bt, const union event *ev, enum battle_component comp) +{ + assert(bt); + assert(ev); + + if (comp & BATTLE_COMPONENT_BAR) + battle_bar_handle(bt->bar, bt, ev); + if ((comp & BATTLE_COMPONENT_ACTIONS) && bt->actions) + action_stack_handle(bt->actions, ev); +} + +void battle_handle(struct battle *bt, const union event *ev) { - assert(bt && bt->state); + assert(bt); assert(ev); - /* Handle actions. */ - action_stack_handle(&bt->actions[0], ev); - action_stack_handle(&bt->actions[1], ev); + battle_state_handle(bt->state, bt, ev); +} + +void +battle_update_component(struct battle *bt, unsigned int ticks, enum battle_component comp) +{ + assert(bt); - /* Handling of action is disallowed if there are pending actions. */ - if (action_stack_completed(&bt->actions[0])) - battle_state_handle(bt->state, bt, ev); + if (comp & BATTLE_COMPONENT_ENTITIES) { + update_entities(bt->team, bt->teamsz, ticks); + update_entities(bt->enemies, bt->enemiesz, ticks); + } + if (comp & BATTLE_COMPONENT_BAR) + battle_bar_update(bt->bar, bt, ticks); + if ((comp & BATTLE_COMPONENT_ACTIONS) && bt->actions) + action_stack_update(bt->actions, ticks); + if ((comp & BATTLE_COMPONENT_DRAWABLES) && bt->effects) + drawable_stack_update(bt->effects, ticks); } int @@ -401,44 +457,35 @@ { assert(bt && bt->state); - action_stack_update(&bt->actions[0], ticks); - action_stack_update(&bt->actions[1], ticks); - drawable_stack_update(&bt->effects, ticks); - - update_entities(bt->team, UTIL_SIZE(bt->team), ticks); - update_entities(bt->enemies, UTIL_SIZE(bt->enemies), ticks); - - /* Game cannot update if the actions[0] stack isn't completed. */ - if (!action_stack_completed(&bt->actions[0])) - return 0; - return battle_state_update(bt->state, bt, ticks); } void -battle_draw(struct battle *bt) +battle_draw_component(const struct battle *bt, enum battle_component comp) { - assert(bt && bt->state); + assert(bt); - painter_set_color(0xffffffff); - painter_clear(); - - if (bt->background && texture_ok(bt->background)) + if ((comp & BATTLE_COMPONENT_BACKGROUND) && texture_ok(bt->background)) texture_scale(bt->background, 0, 0, bt->background->w, bt->background->h, 0, 0, window.w, window.h, 0.f); - - /* Draw entities. */ - draw_entities(bt, bt->team, UTIL_SIZE(bt->team)); - draw_entities(bt, bt->enemies, UTIL_SIZE(bt->enemies)); + if (comp & BATTLE_COMPONENT_ENTITIES) { + draw_entities(bt, bt->team, bt->teamsz); + draw_entities(bt, bt->enemies, bt->enemiesz); + } + if (comp & BATTLE_COMPONENT_BAR) + battle_bar_draw(bt->bar, bt); + if ((comp & BATTLE_COMPONENT_ACTIONS) && bt->actions) + action_stack_draw(bt->actions); + if ((comp & BATTLE_COMPONENT_DRAWABLES) && bt->effects) + drawable_stack_draw(bt->effects); +} - battle_bar_draw(bt->bar, bt); - - action_stack_draw(&bt->actions[0]); - action_stack_draw(&bt->actions[1]); - - drawable_stack_draw(&bt->effects); +void +battle_draw(const struct battle *bt) +{ + assert(battle_ok(bt)); battle_state_draw(bt->state, bt); } @@ -451,12 +498,6 @@ if (bt->state) battle_state_finish(bt->state, bt); - drawable_stack_finish(&bt->effects); - - action_stack_finish(&bt->actions[0]); - action_stack_finish(&bt->actions[1]); - - battle_bar_finish(bt->bar, bt); - + free(bt->order); memset(bt, 0, sizeof (*bt)); }
--- a/src/libmlk-rpg/rpg/battle.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/battle.h Sun Feb 27 10:08:51 2022 +0100 @@ -44,14 +44,10 @@ struct spell; struct theme; -#define BATTLE_TEAM_MAX (4) -#define BATTLE_ENEMY_MAX (8) -#define BATTLE_ENTITY_MAX (BATTLE_TEAM_MAX + BATTLE_ENEMY_MAX) - #define BATTLE_TEAM_FOREACH(bt, iter) \ - for (size_t i = 0; i < BATTLE_TEAM_MAX && ((iter) = &(bt)->team[i]); ++i) + for (size_t i = 0; i < (bt)->teamsz && ((iter) = (bt)->team[i]); ++i) #define BATTLE_ENEMY_FOREACH(bt, iter) \ - for (size_t i = 0; i < BATTLE_ENEMY_MAX && ((iter) = &(bt)->enemies[i]); ++i) + for (size_t i = 0; i < (bt)->enemiesz && ((iter) = (bt)->enemies[i]); ++i) #define BATTLE_THEME(bt) ((bt)->theme ? (bt)->theme : theme_default()) @@ -62,19 +58,30 @@ BATTLE_STATUS_LOST, }; +enum battle_component { + BATTLE_COMPONENT_BACKGROUND = (1 << 0), + BATTLE_COMPONENT_ENTITIES = (1 << 1), + BATTLE_COMPONENT_BAR = (1 << 2), + BATTLE_COMPONENT_ACTIONS = (1 << 3), + BATTLE_COMPONENT_DRAWABLES = (1 << 4), + BATTLE_COMPONENT_ALL = 0xff +}; + struct battle { struct battle_state *state; enum battle_status status; - struct battle_entity team[BATTLE_TEAM_MAX]; - struct battle_entity enemies[BATTLE_ENEMY_MAX]; - struct battle_entity *order[BATTLE_ENTITY_MAX]; - struct battle_entity *order_cur; - size_t order_curindex; + struct battle_entity **team; + size_t teamsz; + struct battle_entity **enemies; + size_t enemiesz; + struct battle_entity **order; + struct battle_entity **ordercur; + size_t ordersz; struct texture *background; struct music *music[3]; struct theme *theme; - struct drawable_stack effects; - struct action_stack actions[2]; + struct drawable_stack *effects; + struct action_stack *actions; struct inventory *inventory; struct battle_bar *bar; }; @@ -82,6 +89,12 @@ CORE_BEGIN_DECLS void +battle_init(struct battle *); + +int +battle_ok(const struct battle *); + +void battle_start(struct battle *); void @@ -96,6 +109,12 @@ void battle_order(struct battle *); +struct battle_entity * +battle_current(const struct battle *); + +size_t +battle_index(const struct battle *); + void battle_attack(struct battle *, struct character *, struct character *); @@ -109,13 +128,22 @@ battle_indicator_hp(struct battle *, const struct character *, long); void +battle_handle_component(struct battle *, const union event *, enum battle_component); + +void battle_handle(struct battle *, const union event *); +void +battle_update_component(struct battle *, unsigned int, enum battle_component); + int battle_update(struct battle *, unsigned int); void -battle_draw(struct battle *); +battle_draw_component(const struct battle *, enum battle_component); + +void +battle_draw(const struct battle *); void battle_finish(struct battle *);
--- a/src/libmlk-rpg/rpg/selection.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-rpg/rpg/selection.c Sun Feb 27 10:08:51 2022 +0100 @@ -25,38 +25,18 @@ #include "selection.h" static void -random(struct selection *slt, const struct battle *bt, const struct battle_entity *entities, size_t entitiesz) +random(struct selection *slt, struct battle_entity **entities, size_t entitiesz) { - (void)bt; - - struct { - const struct battle_entity *entity; - size_t position; - } table[BATTLE_ENTITY_MAX] = {0}; - - size_t tablesz = 0; - - /* - * Merge the list of valid entities into the table to select a random - * one. - */ - for (size_t i = 0; i < entitiesz; ++i) { - if (battle_entity_ok(&entities[i])) { - table[tablesz].entity = &entities[i]; - table[tablesz++].position = i; - } - } - - slt->index_character = table[util_nrand(0, tablesz)].position; + do { + slt->index_character = util_nrand(0, entitiesz); + } while (!battle_entity_ok(entities[slt->index_character])); } static void -first(struct selection *slt, const struct battle *bt, const struct battle_entity *entities, size_t entitiesz) +first(struct selection *slt, struct battle_entity **entities, size_t entitiesz) { - (void)bt; - for (size_t i = 0; i < entitiesz; ++i) { - if (battle_entity_ok(&entities[i])) { + if (battle_entity_ok(entities[i])) { slt->index_character = i; break; } @@ -70,9 +50,9 @@ assert(bt); if (slt->index_side == 0) - first(slt, bt, bt->enemies, BATTLE_ENEMY_MAX); + first(slt, bt->enemies, bt->enemiesz); else - first(slt, bt, bt->team, BATTLE_TEAM_MAX); + first(slt, bt->team, bt->teamsz); } void @@ -82,7 +62,7 @@ assert(bt); if (slt->index_side == 0) - random(slt, bt, bt->enemies, BATTLE_ENEMY_MAX); + random(slt, bt->enemies, bt->enemiesz); else - random(slt, bt, bt->team, BATTLE_TEAM_MAX); + random(slt, bt->team, bt->teamsz); }
--- a/src/libmlk-ui/ui/gridmenu.c Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-ui/ui/gridmenu.c Sun Feb 27 10:08:51 2022 +0100 @@ -133,7 +133,7 @@ for (size_t i = 0; i < pagesz; ++i) { item = i + pagenr * pagesz; - if (item >= menu->itemsz) + if (item >= menu->itemsz || !menu->items[item]) continue; label.text = menu->items[item]; @@ -230,7 +230,7 @@ gridmenu_init(struct gridmenu *menu, unsigned int nr, unsigned int nc, - const char * const *items, + const char **items, size_t itemsz) { assert(menu);
--- a/src/libmlk-ui/ui/gridmenu.h Fri Feb 18 16:16:38 2022 +0100 +++ b/src/libmlk-ui/ui/gridmenu.h Sun Feb 27 10:08:51 2022 +0100 @@ -36,7 +36,7 @@ unsigned int h; size_t selected; const struct theme *theme; - const char * const *items; + const char **items; size_t itemsz; unsigned int nrows; unsigned int ncols; @@ -51,7 +51,7 @@ CORE_BEGIN_DECLS void -gridmenu_init(struct gridmenu *, unsigned int, unsigned int, const char * const *, size_t); +gridmenu_init(struct gridmenu *, unsigned int, unsigned int, const char **, size_t); void gridmenu_resize(struct gridmenu *, int, int, unsigned int, unsigned int);