96 lines
3.0 KiB
C
96 lines
3.0 KiB
C
#include "menu_cmdr.h"
|
|
#include "menus.h"
|
|
#include "config.h"
|
|
#include "state.h"
|
|
#include "draw.h"
|
|
#include "game.h"
|
|
#include "ble.h"
|
|
#include "events.h"
|
|
#include <stdio.h>
|
|
|
|
// ── Offline vtable ────────────────────────────────────────────────────────────
|
|
|
|
static const uint8_t s_icon_shield[2][ICON_W] = {
|
|
// Shield (commander damage)
|
|
{0x00,0xFC,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFE,0xFC,0x00,0x00},
|
|
{0x00,0x07,0x0F,0x1F,0x3F,0x3F,0x3F,0x7F,0x7F,0x3F,0x3F,0x1F,0x0F,0x07,0x00,0x00},
|
|
};
|
|
|
|
static const uint8_t s_icon_net[2][ICON_W] = {
|
|
// Signal bars (BLE commander)
|
|
{0x00,0x00,0x00,0x00,0x00,0x00,0x80,0x80,0x00,0xF8,0xF8,0x00,0xFE,0xFE,0x00,0x00},
|
|
{0x00,0x00,0x00,0x38,0x38,0x00,0x3F,0x3F,0x00,0x3F,0x3F,0x00,0x3F,0x3F,0x00,0x00},
|
|
};
|
|
|
|
static void cmdr_offline_nav_short(int d)
|
|
{
|
|
g_active_opponent = (g_active_opponent + d + g_num_opponents) % g_num_opponents;
|
|
}
|
|
|
|
static void cmdr_offline_lr_delta(int d)
|
|
{
|
|
g_cmdr_damage[g_active_opponent] += d;
|
|
if (g_cmdr_damage[g_active_opponent] < 0) g_cmdr_damage[g_active_opponent] = 0;
|
|
check_elimination();
|
|
mark_dirty();
|
|
}
|
|
|
|
static void cmdr_offline_draw(void)
|
|
{
|
|
char opponent_labels[MAX_OPPONENTS][PLAYER_NAME_LEN + 1];
|
|
const char *opponent_label_ptrs[MAX_OPPONENTS];
|
|
for (int i = 0; i < g_num_opponents; i++) {
|
|
snprintf(opponent_labels[i], sizeof(opponent_labels[i]), "CMD %d", i + 1);
|
|
opponent_label_ptrs[i] = opponent_labels[i];
|
|
}
|
|
oled_draw_list(opponent_label_ptrs, g_cmdr_damage, g_num_opponents, g_active_opponent);
|
|
}
|
|
|
|
const menu_vtable_t menu_cmdr_offline_vtable = {
|
|
.nav_short = cmdr_offline_nav_short,
|
|
.lr_delta = cmdr_offline_lr_delta,
|
|
.draw = cmdr_offline_draw,
|
|
.on_tick = NULL,
|
|
.icon = s_icon_shield,
|
|
};
|
|
|
|
// ── BLE vtable ────────────────────────────────────────────────────────────────
|
|
|
|
static void cmdr_ble_nav_short(int d)
|
|
{
|
|
int total = MAX_BLE_PEERS + 1;
|
|
int next = (g_active_player + d + total) % total;
|
|
while (next != g_active_player && next != 0 && !g_peers[next - 1].active)
|
|
next = (next + d + total) % total;
|
|
g_active_player = next;
|
|
}
|
|
|
|
static void cmdr_ble_lr_delta(int d)
|
|
{
|
|
if (g_active_player == 0) {
|
|
g_life += d;
|
|
g_life_delta += d;
|
|
restart_life_delta_timer();
|
|
check_elimination();
|
|
} else {
|
|
int slot = g_active_player - 1;
|
|
g_cmdr_damage[slot] += d;
|
|
if (g_cmdr_damage[slot] < 0) g_cmdr_damage[slot] = 0;
|
|
check_elimination();
|
|
}
|
|
mark_dirty();
|
|
}
|
|
|
|
static void cmdr_ble_draw(void)
|
|
{
|
|
oled_draw_players();
|
|
}
|
|
|
|
const menu_vtable_t menu_cmdr_ble_vtable = {
|
|
.nav_short = cmdr_ble_nav_short,
|
|
.lr_delta = cmdr_ble_lr_delta,
|
|
.draw = cmdr_ble_draw,
|
|
.on_tick = NULL,
|
|
.icon = s_icon_net,
|
|
};
|