Compare commits
11 Commits
514198d136
...
master
Author | SHA1 | Date | |
---|---|---|---|
522fc7c8c4 | |||
f62f2414b0 | |||
f501dc046e | |||
244a340764 | |||
9543851867 | |||
1caf43c6de | |||
d9c063cba7 | |||
8adb89ef2b | |||
ea5f1a7902 | |||
18831c3e0e | |||
4d1074e60c |
@@ -1,6 +1,7 @@
|
||||
import configparser
|
||||
import logging
|
||||
import os
|
||||
import signal
|
||||
import sys
|
||||
|
||||
import infi.systray
|
||||
@@ -42,12 +43,16 @@ def main():
|
||||
|
||||
conf = configparser.ConfigParser()
|
||||
conf.read_dict({
|
||||
'general': {'log_level': 'info'},
|
||||
'general': {
|
||||
'log_level': 'info',
|
||||
'dummy_impl': False,
|
||||
},
|
||||
'valorant': {'player_uuid': ''},
|
||||
})
|
||||
conf.read(CONFIG_FILE)
|
||||
with open(CONFIG_FILE, 'w') as f:
|
||||
conf.write(f)
|
||||
use_dummy_impl = conf.getboolean('general', 'dummy_impl')
|
||||
|
||||
log_level = parse_log_level(conf['general']['log_level'])
|
||||
logging.basicConfig(
|
||||
@@ -59,20 +64,28 @@ def main():
|
||||
log.error(f'No player UUID set, exiting...')
|
||||
sys.exit(1)
|
||||
|
||||
val_handler = valconomy.ValconomyHandler()
|
||||
if use_dummy_impl:
|
||||
val_handler = valconomy.ValconomyHandler()
|
||||
else:
|
||||
val_handler = valconomy.HIDValconomyHandler()
|
||||
val_handler.start()
|
||||
val_sm = valconomy.ValconomyStateMachine(conf['valorant']['player_uuid'], val_handler)
|
||||
|
||||
val_client = valconomy.ValorantLocalClient(val_sm.handle_presence)
|
||||
def do_quit(tray: infi.systray.SysTrayIcon):
|
||||
def do_quit(*args):
|
||||
log.info('Shutting down')
|
||||
val_client.stop()
|
||||
if not use_dummy_impl:
|
||||
val_handler.stop()
|
||||
|
||||
with infi.systray.SysTrayIcon(
|
||||
data_file('icon.ico'), 'Valconomy', on_quit=do_quit,
|
||||
menu_options=(
|
||||
('Open data directory', None, do_open_datadir),
|
||||
)) as tray:
|
||||
val_client.run()
|
||||
signal.signal(signal.SIGINT, do_quit)
|
||||
signal.signal(signal.SIGTERM, do_quit)
|
||||
val_client.run()
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
|
@@ -2,6 +2,7 @@
|
||||
import logging
|
||||
|
||||
import valconomy
|
||||
from valconomy import ValorantPlayerInfo, RiotPlayerInfo, EconomyDecision
|
||||
|
||||
def main():
|
||||
logging.basicConfig(
|
||||
@@ -11,8 +12,32 @@ def main():
|
||||
try:
|
||||
h.menu(None, False)
|
||||
h.none()
|
||||
h.queue_start(RiotPlayerInfo.dummy(
|
||||
valorant=ValorantPlayerInfo()))
|
||||
h.menu(None, True)
|
||||
h.idle(None)
|
||||
h.queue_start(RiotPlayerInfo.dummy(
|
||||
valorant=ValorantPlayerInfo(queue_type='unrated', is_party_owner=True)))
|
||||
h.match_found(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(queue_type='premier-seasonmatch')))
|
||||
h.pregame(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(map='/Game/Maps/Bonsai/Bonsai')))
|
||||
h.match_found(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo()))
|
||||
h.pregame(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo()))
|
||||
h.game_generic(RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(queue_type='ggteam')))
|
||||
h.game_start(None)
|
||||
h.game_over(None, False)
|
||||
h.game_over(None, True)
|
||||
h.round_start(
|
||||
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=3, enemy_score=7)),
|
||||
won=True, economy=EconomyDecision.SAVE)
|
||||
h.round_start(
|
||||
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=10, enemy_score=2)),
|
||||
won=False, economy=EconomyDecision.BUY)
|
||||
h.round_start(
|
||||
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=10, enemy_score=2)),
|
||||
won=None, economy=EconomyDecision.MATCH_TEAM)
|
||||
h.round_start(
|
||||
RiotPlayerInfo.dummy(valorant=ValorantPlayerInfo(score=2, enemy_score=0)),
|
||||
won=True, economy=EconomyDecision.BONUS)
|
||||
|
||||
h.service()
|
||||
finally:
|
||||
|
@@ -81,7 +81,8 @@ class TestSm:
|
||||
('round_start', True, 2, 0, EconomyDecision.BONUS),
|
||||
('round_start', False, 2, 1, EconomyDecision.MATCH_TEAM),
|
||||
] + [
|
||||
('round_start', False, 2, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(8)] + [
|
||||
('round_start', False, 2, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(7)] + [
|
||||
('round_start', False, 2, 9, EconomyDecision.BUY), # last round in half
|
||||
('round_start', False, 2, 10, EconomyDecision.BUY),
|
||||
('round_start', False, 2, 11, EconomyDecision.SAVE),
|
||||
('round_start', False, 2, 12, EconomyDecision.BUY),
|
||||
@@ -112,7 +113,8 @@ class TestSm:
|
||||
('round_start', True, 1, 0, EconomyDecision.BUY),
|
||||
('round_start', False, 1, 1, EconomyDecision.SAVE),
|
||||
] + [
|
||||
('round_start', False, 1, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(9)] + [
|
||||
('round_start', False, 1, 2 + i, EconomyDecision.MATCH_TEAM) for i in range(8)] + [
|
||||
('round_start', False, 1, 10, EconomyDecision.BUY), # last round in half
|
||||
('round_start', False, 1, 11, EconomyDecision.BUY),
|
||||
('round_start', False, 1, 12, EconomyDecision.BUY),
|
||||
] + [
|
||||
@@ -133,8 +135,10 @@ class TestSm:
|
||||
|
||||
self.do(queue_type='swiftplay', game_state='PREGAME')
|
||||
self.do(queue_type='swiftplay', game_state='INGAME')
|
||||
for i in range(5):
|
||||
for i in range(4):
|
||||
self.do(queue_type='swiftplay', game_state='INGAME', enemy_score=1 + i)
|
||||
for i in range(5):
|
||||
self.do(queue_type='swiftplay', game_state='INGAME', score=1 + i, enemy_score=4)
|
||||
self.do(queue_type='swiftplay', game_state='INGAME')
|
||||
|
||||
assert self.mock.seq == [
|
||||
@@ -144,9 +148,15 @@ class TestSm:
|
||||
('pregame', False),
|
||||
'game_start',
|
||||
('round_start', None, 0, 0, EconomyDecision.BUY),
|
||||
] + [
|
||||
('round_start', False, 0, 1 + i, EconomyDecision.BUY) for i in range(4)] + [
|
||||
('game_over', False),
|
||||
('round_start', False, 0, 1, EconomyDecision.BUY),
|
||||
('round_start', False, 0, 2, EconomyDecision.BUY),
|
||||
('round_start', False, 0, 3, EconomyDecision.BUY),
|
||||
('round_start', False, 0, 4, EconomyDecision.BUY),
|
||||
('round_start', True, 1, 4, EconomyDecision.BUY),
|
||||
('round_start', True, 2, 4, EconomyDecision.BUY),
|
||||
('round_start', True, 3, 4, EconomyDecision.BUY),
|
||||
('round_start', True, 4, 4, EconomyDecision.BUY),
|
||||
('game_over', True),
|
||||
]
|
||||
|
||||
def test_tdm(self):
|
||||
|
@@ -1,13 +1,13 @@
|
||||
import base64
|
||||
from dataclasses import dataclass
|
||||
from enum import Enum
|
||||
import errno
|
||||
import json
|
||||
import logging
|
||||
from pprint import pprint
|
||||
import os
|
||||
import queue
|
||||
import struct
|
||||
import threading
|
||||
import time
|
||||
from typing import Callable
|
||||
|
||||
@@ -48,6 +48,10 @@ class RiotPlayerInfo:
|
||||
|
||||
valorant: ValorantPlayerInfo = None
|
||||
|
||||
@classmethod
|
||||
def dummy(cls, **kwargs):
|
||||
return cls('00000000-0000-0000-0000-000000000000', 'Player', 'gamer', 'dnd', **kwargs)
|
||||
|
||||
def full_name(self) -> str:
|
||||
return f'{self.name}#{self.tag}'
|
||||
|
||||
@@ -238,6 +242,7 @@ class HIDValconomyHandler(ValconomyHandler):
|
||||
self.dev = None
|
||||
self.running = True
|
||||
self.queue = queue.Queue(128)
|
||||
self._thread = None
|
||||
|
||||
def close(self):
|
||||
if self.dev is not None:
|
||||
@@ -281,7 +286,7 @@ class HIDValconomyHandler(ValconomyHandler):
|
||||
|
||||
while not self._dev_ready():
|
||||
if not self.running:
|
||||
break
|
||||
return
|
||||
time.sleep(0.1)
|
||||
|
||||
try:
|
||||
@@ -292,10 +297,23 @@ class HIDValconomyHandler(ValconomyHandler):
|
||||
def run(self):
|
||||
while self.running:
|
||||
while self.queue.empty():
|
||||
if not self.running:
|
||||
return
|
||||
time.sleep(0.5)
|
||||
|
||||
self.service()
|
||||
|
||||
def start(self):
|
||||
assert self._thread is None
|
||||
self._thread = threading.Thread(name='HIDValconomyHandler', target=self.run)
|
||||
self._thread.start()
|
||||
|
||||
def stop(self):
|
||||
if self._thread is None or not self.running:
|
||||
return
|
||||
self.running = False
|
||||
self._thread.join()
|
||||
|
||||
def none(self):
|
||||
self._enq(0)
|
||||
|
||||
@@ -305,6 +323,56 @@ class HIDValconomyHandler(ValconomyHandler):
|
||||
def idle(self, info: RiotPlayerInfo):
|
||||
self._enq(2)
|
||||
|
||||
def queue_start(self, info: RiotPlayerInfo):
|
||||
ms_not_comp = info.valorant.is_party_owner and info.valorant.queue_type == 'unrated'
|
||||
self._enq(3, 1 if ms_not_comp else 0, fmt='B')
|
||||
|
||||
def match_found(self, info: RiotPlayerInfo):
|
||||
self._enq(4, 1 if info.valorant.queue_type == 'premier-seasonmatch' else 0, fmt='B')
|
||||
|
||||
def pregame(self, info: RiotPlayerInfo):
|
||||
self._enq(5, 1 if info.valorant.map == '/Game/Maps/Bonsai/Bonsai' else 0, fmt='B')
|
||||
|
||||
def game_generic(self, info: RiotPlayerInfo):
|
||||
match info.valorant.queue_type:
|
||||
case 'hurm': # tdm
|
||||
gm = 0
|
||||
case 'deathmatch':
|
||||
gm = 1
|
||||
case 'ggteam': # escalation
|
||||
gm = 2
|
||||
case 'spikerush':
|
||||
gm = 3
|
||||
case _:
|
||||
if info.valorant.max_party_size == 12: # custom
|
||||
gm = 4
|
||||
else:
|
||||
gm = 5
|
||||
|
||||
self._enq(6, gm, fmt='B')
|
||||
|
||||
def game_start(self, info: RiotPlayerInfo):
|
||||
self._enq(7)
|
||||
|
||||
def round_start(self, info: RiotPlayerInfo, won: bool, economy: EconomyDecision):
|
||||
match won:
|
||||
case False:
|
||||
won_val = 0
|
||||
case True:
|
||||
won_val = 1
|
||||
case None:
|
||||
won_val = 2
|
||||
|
||||
self._enq(
|
||||
8,
|
||||
info.valorant.score, info.valorant.enemy_score,
|
||||
won_val,
|
||||
economy.value,
|
||||
fmt='BBBB')
|
||||
|
||||
def game_over(self, info: RiotPlayerInfo, won: bool):
|
||||
self._enq(9, 1 if won else 0, fmt='B')
|
||||
|
||||
class GameState(Enum):
|
||||
NONE = 0
|
||||
MENU = 1
|
||||
@@ -340,17 +408,16 @@ class ValconomyStateMachine:
|
||||
won_last = True if p.valorant.score > self.score else False
|
||||
self.round_history.append(won_last)
|
||||
|
||||
over = False
|
||||
if p.valorant.queue_type == 'swiftplay':
|
||||
if p.valorant.score == 5 or p.valorant.enemy_score == 5:
|
||||
# Game is over
|
||||
return
|
||||
over = True
|
||||
|
||||
eco = EconomyDecision.BUY
|
||||
else:
|
||||
if p.valorant.score > 12 or p.valorant.enemy_score > 12:
|
||||
if p.valorant.queue_type == 'unrated' or abs(p.valorant.score - p.valorant.enemy_score) >= 2:
|
||||
# Match is over
|
||||
return
|
||||
over = True
|
||||
|
||||
eco = EconomyDecision.MATCH_TEAM
|
||||
rounds_played = p.valorant.score + p.valorant.enemy_score
|
||||
@@ -375,8 +442,12 @@ class ValconomyStateMachine:
|
||||
elif rounds_played >= 24:
|
||||
# Sudden death or overtime (buy either way)
|
||||
eco = EconomyDecision.BUY
|
||||
elif rounds_played == 11:
|
||||
# Last round of half
|
||||
eco = EconomyDecision.BUY
|
||||
|
||||
self.handler.round_start(p, won_last, eco)
|
||||
if not over:
|
||||
self.handler.round_start(p, won_last, eco)
|
||||
self.score = p.valorant.score
|
||||
self.score_enemy = p.valorant.enemy_score
|
||||
self.last = GameState.IN_GAME
|
||||
|
@@ -2,18 +2,41 @@
|
||||
|
||||
#include "ui.h"
|
||||
|
||||
const char *val_ext_gamemodes[] = {
|
||||
"TDM",
|
||||
"DEATHMATCH",
|
||||
"ESCALATION",
|
||||
"SPIKE RUSH",
|
||||
"CUSTOM",
|
||||
"GAME",
|
||||
};
|
||||
|
||||
static const char* M_VAL_TIME = "VAL TIME?";
|
||||
static const char *val_eco_titles[] = {
|
||||
"BUY",
|
||||
"SAVE",
|
||||
"BONUS",
|
||||
"MATCH TEAM",
|
||||
};
|
||||
static const char *val_eco_subtitles[] = {
|
||||
"SPEND ALL YOUR MONEY!",
|
||||
"MAKE SURE YOU CAN BUY NEXT ROUND!",
|
||||
"KEEP YOUR GUN FROM LAST ROUND!",
|
||||
"FOLLOW THE TEAM ECONOMY",
|
||||
};
|
||||
|
||||
static const lv_font_t *font_normal = &lv_font_montserrat_24;
|
||||
|
||||
static lv_color_t color_primary, color_secondary;
|
||||
static lv_color_t color_text_hero, color_text_subtitle;
|
||||
static lv_color_t color_text_won, color_text_lost;
|
||||
|
||||
static lv_style_t s_hero, s_subtitle;
|
||||
|
||||
static lv_obj_t *o_container = NULL;
|
||||
|
||||
static lv_anim_timeline_t *at_active = NULL;
|
||||
static lv_anim_timeline_t *at_active_rep = NULL;
|
||||
static lv_obj_t *o_active = NULL;
|
||||
static bool state_ready = true;
|
||||
|
||||
@@ -38,8 +61,8 @@ static const void* imgfont_get_path(
|
||||
|
||||
static void b_cfg_cb(lv_event_t *e) {
|
||||
lv_obj_t *box = lv_msgbox_create(NULL);
|
||||
lv_msgbox_add_title(box, "Hello");
|
||||
lv_msgbox_add_text(box, "test message");
|
||||
lv_msgbox_add_title(box, "Settings");
|
||||
lv_msgbox_add_text(box, "Sorry, there aren't any right now.");
|
||||
lv_msgbox_add_close_button(box);
|
||||
}
|
||||
|
||||
@@ -51,6 +74,10 @@ static void setup_next_state() {
|
||||
lv_anim_timeline_delete(at_active);
|
||||
at_active = NULL;
|
||||
}
|
||||
if (at_active_rep) {
|
||||
lv_anim_timeline_delete(at_active_rep);
|
||||
at_active_rep = NULL;
|
||||
}
|
||||
if (o_active) {
|
||||
lv_obj_delete(o_active);
|
||||
o_active = NULL;
|
||||
@@ -61,8 +88,11 @@ static void setup_next_state() {
|
||||
lv_obj_set_style_bg_opa(o_active, LV_OPA_0, 0);
|
||||
lv_obj_set_style_border_width(o_active, 0, 0);
|
||||
lv_obj_set_size(o_active, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_scrollbar_mode(o_active, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
at_active = lv_anim_timeline_create();
|
||||
at_active_rep = lv_anim_timeline_create();
|
||||
lv_anim_timeline_set_repeat_count(at_active_rep, LV_ANIM_REPEAT_INFINITE);
|
||||
}
|
||||
|
||||
bool val_ui_state_ready() {
|
||||
@@ -70,6 +100,7 @@ bool val_ui_state_ready() {
|
||||
}
|
||||
|
||||
static void anim_state_ready_cb(lv_anim_t *anim) {
|
||||
lv_anim_timeline_start(at_active_rep);
|
||||
state_ready = true;
|
||||
}
|
||||
static void anim_x_cb(void *var, int32_t v) {
|
||||
@@ -81,10 +112,10 @@ static void anim_y_cb(void *var, int32_t v) {
|
||||
static void anim_opa_cb(void *var, int32_t v) {
|
||||
lv_obj_set_style_opa(var, v, 0);
|
||||
}
|
||||
|
||||
static void anim_val_time_text(lv_anim_t *anim) {
|
||||
lv_label_set_text_static(anim->var, M_VAL_TIME);
|
||||
}
|
||||
|
||||
void val_ui_none() {
|
||||
setup_next_state();
|
||||
|
||||
@@ -175,7 +206,7 @@ void val_ui_menu(bool was_idle) {
|
||||
lv_anim_set_var(&a_title, l_main);
|
||||
lv_anim_set_values(
|
||||
&a_title,
|
||||
-(lv_obj_get_height(o_container) - lv_obj_get_height(l_main)) / 2, 0);
|
||||
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||
lv_anim_set_exec_cb(&a_title, anim_y_cb);
|
||||
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_in);
|
||||
lv_anim_set_duration(&a_title, 500);
|
||||
@@ -185,7 +216,7 @@ void val_ui_menu(bool was_idle) {
|
||||
lv_anim_set_var(&a_sub, l_subtitle);
|
||||
lv_anim_set_values(
|
||||
&a_sub,
|
||||
(lv_obj_get_height(o_container) - lv_obj_get_height(l_main)) / 2,
|
||||
(lv_obj_get_height(o_container) + lv_obj_get_height(l_subtitle)) / 2,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
lv_anim_set_exec_cb(&a_sub, anim_y_cb);
|
||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_in);
|
||||
@@ -194,6 +225,32 @@ void val_ui_menu(bool was_idle) {
|
||||
|
||||
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||
|
||||
// Repeating loop swing back and forth
|
||||
lv_anim_t a_title_swing;
|
||||
lv_anim_init(&a_title_swing);
|
||||
lv_anim_set_early_apply(&a_title_swing, false);
|
||||
lv_anim_set_var(&a_title_swing, l_main);
|
||||
lv_anim_set_exec_cb(&a_title_swing, anim_x_cb);
|
||||
|
||||
// Left
|
||||
lv_anim_set_path_cb(&a_title_swing, lv_anim_path_ease_out);
|
||||
lv_anim_set_values(&a_title_swing, 0, -10);
|
||||
lv_anim_set_duration(&a_title_swing, 500);
|
||||
lv_anim_timeline_add(at_active_rep, 0, &a_title_swing);
|
||||
|
||||
// Left to right
|
||||
lv_anim_set_path_cb(&a_title_swing, lv_anim_path_ease_in_out);
|
||||
lv_anim_set_values(&a_title_swing, -10, 10);
|
||||
lv_anim_set_duration(&a_title_swing, 1000);
|
||||
lv_anim_timeline_add(at_active_rep, 500, &a_title_swing);
|
||||
|
||||
// Right to centre
|
||||
lv_anim_set_path_cb(&a_title_swing, lv_anim_path_ease_in);
|
||||
lv_anim_set_values(&a_title_swing, 10, 0);
|
||||
lv_anim_set_duration(&a_title_swing, 500);
|
||||
lv_anim_timeline_add(at_active_rep, 1500, &a_title_swing);
|
||||
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
@@ -234,19 +291,432 @@ void val_ui_idle() {
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
static void anim_text_color_mix_hero_sub(void *var, int32_t v) {
|
||||
lv_obj_set_style_text_color(
|
||||
var, lv_color_mix(color_text_hero, color_text_subtitle, v), 0);
|
||||
}
|
||||
void val_ui_queue_start(bool ms_not_comp) {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, "SEARCHING...");
|
||||
|
||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||
lv_obj_center(l_subtitle);
|
||||
lv_label_set_text_static(l_subtitle, ms_not_comp ? "UHHH SHOULD THAT BE COMP?" : "HOPE YOU FIND A GAME QUICKLY!");
|
||||
|
||||
lv_obj_t *spinner = lv_spinner_create(o_active);
|
||||
lv_obj_set_size(spinner, 100, 100);
|
||||
lv_obj_center(spinner);
|
||||
lv_obj_set_style_arc_color(spinner, color_text_hero, LV_PART_INDICATOR);
|
||||
lv_spinner_set_anim_params(spinner, 1500, 200);
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
const int32_t offset = -60;
|
||||
lv_obj_set_y(l_main, offset);
|
||||
lv_obj_set_y(
|
||||
l_subtitle,
|
||||
offset + (lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
lv_obj_set_y(
|
||||
spinner,
|
||||
lv_obj_get_height(o_container) / 4);
|
||||
|
||||
// Animations
|
||||
lv_anim_t a_title;
|
||||
lv_anim_init(&a_title);
|
||||
lv_anim_set_var(&a_title, l_main);
|
||||
lv_anim_set_values(
|
||||
&a_title,
|
||||
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||
lv_anim_set_exec_cb(&a_title, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_out);
|
||||
lv_anim_set_duration(&a_title, 750);
|
||||
|
||||
lv_anim_t a_sub;
|
||||
lv_anim_init(&a_sub);
|
||||
lv_anim_set_var(&a_sub, l_subtitle);
|
||||
lv_anim_set_values(
|
||||
&a_sub,
|
||||
(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2, 0);
|
||||
lv_anim_set_exec_cb(&a_sub, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_out);
|
||||
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||
lv_anim_set_duration(&a_sub, 750);
|
||||
|
||||
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||
|
||||
if (ms_not_comp) {
|
||||
lv_anim_t a_warn;
|
||||
lv_anim_init(&a_warn);
|
||||
lv_anim_set_early_apply(&a_warn, false);
|
||||
lv_anim_set_var(&a_warn, l_subtitle);
|
||||
lv_anim_set_path_cb(&a_warn, lv_anim_path_linear);
|
||||
lv_anim_set_duration(&a_warn, 1000);
|
||||
lv_anim_set_exec_cb(&a_warn, anim_text_color_mix_hero_sub);
|
||||
|
||||
lv_anim_set_values(&a_warn, 0, 255);
|
||||
lv_anim_timeline_add(at_active_rep, 0, &a_warn);
|
||||
|
||||
lv_anim_set_values(&a_warn, 255, 0);
|
||||
lv_anim_timeline_add(at_active_rep, 1000, &a_warn);
|
||||
}
|
||||
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_ui_match_found(bool is_premier) {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, "MATCH FOUND");
|
||||
|
||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||
lv_obj_center(l_subtitle);
|
||||
lv_label_set_text_static(l_subtitle, is_premier ? "DO THE COSMONAUTS PROUD!" : "I HOPE IT'S NOT SPLIT...");
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
|
||||
// Animations
|
||||
lv_anim_t a_title;
|
||||
lv_anim_init(&a_title);
|
||||
lv_anim_set_var(&a_title, l_main);
|
||||
lv_anim_set_values(
|
||||
&a_title,
|
||||
(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||
lv_anim_set_exec_cb(&a_title, anim_y_cb);
|
||||
lv_anim_set_path_cb(&a_title, lv_anim_path_ease_in);
|
||||
lv_anim_set_duration(&a_title, 500);
|
||||
|
||||
lv_anim_t a_sub;
|
||||
lv_anim_init(&a_sub);
|
||||
lv_anim_set_var(&a_sub, l_subtitle);
|
||||
lv_anim_set_values(
|
||||
&a_sub,
|
||||
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
lv_anim_set_exec_cb(&a_sub, anim_y_cb);
|
||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_ease_in);
|
||||
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||
lv_anim_set_duration(&a_sub, 500);
|
||||
|
||||
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_ui_pregame(bool is_split) {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, "CHOOSE AGENT");
|
||||
|
||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||
lv_obj_center(l_subtitle);
|
||||
lv_label_set_text_static(l_subtitle, is_split ? "EWWW, SPLIT..." : "PICK SOMETHING GOOD!");
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
lv_obj_set_y(
|
||||
l_subtitle,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
|
||||
// Animations
|
||||
lv_anim_t a_fade_in;
|
||||
lv_anim_init(&a_fade_in);
|
||||
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||
lv_anim_set_duration(&a_fade_in, 500);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_main);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_subtitle);
|
||||
lv_anim_set_completed_cb(&a_fade_in, anim_state_ready_cb);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
|
||||
lv_anim_t a_warn;
|
||||
lv_anim_init(&a_warn);
|
||||
lv_anim_set_early_apply(&a_warn, false);
|
||||
lv_anim_set_var(&a_warn, l_main);
|
||||
lv_anim_set_path_cb(&a_warn, lv_anim_path_linear);
|
||||
lv_anim_set_duration(&a_warn, 2000);
|
||||
lv_anim_set_exec_cb(&a_warn, anim_text_color_mix_hero_sub);
|
||||
|
||||
lv_anim_set_values(&a_warn, 255, 0);
|
||||
lv_anim_timeline_add(at_active_rep, 0, &a_warn);
|
||||
|
||||
lv_anim_set_values(&a_warn, 0, 255);
|
||||
lv_anim_timeline_add(at_active_rep, 2000, &a_warn);
|
||||
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_ui_game_generic(const char *gamemode) {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, "HAVE FUN!");
|
||||
|
||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||
lv_obj_center(l_subtitle);
|
||||
lv_label_set_text_fmt(l_subtitle, "ENJOY YOUR %s!", gamemode);
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
lv_obj_set_y(
|
||||
l_subtitle,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
|
||||
// Animations
|
||||
lv_anim_t a_title;
|
||||
lv_anim_init(&a_title);
|
||||
lv_anim_set_var(&a_title, l_main);
|
||||
lv_anim_set_values(
|
||||
&a_title,
|
||||
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||
lv_anim_set_exec_cb(&a_title, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a_title, lv_anim_path_bounce);
|
||||
lv_anim_set_duration(&a_title, 750);
|
||||
|
||||
lv_anim_t a_sub;
|
||||
lv_anim_init(&a_sub);
|
||||
lv_anim_set_var(&a_sub, l_subtitle);
|
||||
lv_anim_set_values(
|
||||
&a_sub,
|
||||
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2,
|
||||
-(lv_obj_get_width(l_main) - lv_obj_get_width(l_subtitle)) / 2);
|
||||
lv_anim_set_exec_cb(&a_sub, anim_x_cb);
|
||||
lv_anim_set_path_cb(&a_sub, lv_anim_path_bounce);
|
||||
lv_anim_set_completed_cb(&a_sub, anim_state_ready_cb);
|
||||
lv_anim_set_duration(&a_sub, 750);
|
||||
|
||||
lv_anim_timeline_add(at_active, 0, &a_title);
|
||||
lv_anim_timeline_add(at_active, 0, &a_sub);
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_ui_game_start() {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, "GOOD LUCK!");
|
||||
|
||||
state_ready = true;
|
||||
}
|
||||
|
||||
static void anim_text_color_mix_hero_won(void *var, int32_t v) {
|
||||
lv_obj_set_style_text_color(
|
||||
var, lv_color_mix(color_text_hero, color_text_won, v), 0);
|
||||
}
|
||||
static void anim_text_color_mix_hero_lost(void *var, int32_t v) {
|
||||
lv_obj_set_style_text_color(
|
||||
var, lv_color_mix(color_text_hero, color_text_lost, v), 0);
|
||||
}
|
||||
void val_ui_round_start(uint8_t score, uint8_t score_enemy, val_won_t won, val_eco_decision_t eco) {
|
||||
assert(won <= ROUND_NONE && eco <= ECO_MATCH_TEAM);
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_score = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_score, &s_hero, 0);
|
||||
lv_obj_center(l_score);
|
||||
lv_label_set_text_fmt(l_score, "%hhu-%hhu", score, score_enemy);
|
||||
|
||||
lv_obj_t *l_eco = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_eco, &s_hero, 0);
|
||||
lv_obj_center(l_eco);
|
||||
lv_label_set_text_static(l_eco, val_eco_titles[eco]);
|
||||
|
||||
lv_obj_t *l_advice = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_advice, &s_subtitle, 0);
|
||||
lv_obj_center(l_advice);
|
||||
lv_label_set_text_static(l_advice, val_eco_subtitles[eco]);
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
lv_obj_set_y(
|
||||
l_score,
|
||||
-(lv_obj_get_height(l_score) / 2) - 20);
|
||||
lv_obj_set_y(
|
||||
l_eco,
|
||||
lv_obj_get_height(l_eco) / 2);
|
||||
|
||||
// Animations
|
||||
// Score and eco fade in
|
||||
lv_anim_t a_fade_in;
|
||||
lv_anim_init(&a_fade_in);
|
||||
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||
lv_anim_set_duration(&a_fade_in, 750);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_score);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_eco);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
|
||||
// Advice slide up
|
||||
lv_anim_t a_advice;
|
||||
lv_anim_init(&a_advice);
|
||||
lv_anim_set_var(&a_advice, l_advice);
|
||||
lv_anim_set_values(
|
||||
&a_advice,
|
||||
(lv_obj_get_height(o_container) + lv_obj_get_height(l_advice)) / 2,
|
||||
lv_obj_get_height(l_eco) + (lv_obj_get_height(l_advice) / 2) + 5);
|
||||
lv_anim_set_exec_cb(&a_advice, anim_y_cb);
|
||||
lv_anim_set_path_cb(&a_advice, lv_anim_path_ease_out);
|
||||
lv_anim_set_duration(&a_advice, 750);
|
||||
|
||||
if (won != ROUND_NONE) {
|
||||
// Score colour
|
||||
lv_anim_t a_score;
|
||||
lv_anim_init(&a_score);
|
||||
lv_anim_set_var(&a_score, l_score);
|
||||
lv_anim_set_path_cb(&a_score, lv_anim_path_ease_in);
|
||||
lv_anim_set_exec_cb(
|
||||
&a_score,
|
||||
won == ROUND_WON ? anim_text_color_mix_hero_won : anim_text_color_mix_hero_lost);
|
||||
lv_anim_set_duration(&a_score, 2000);
|
||||
lv_anim_set_values(&a_score, 0, 255);
|
||||
lv_anim_set_completed_cb(&a_score, anim_state_ready_cb);
|
||||
lv_anim_timeline_add(at_active, 0, &a_score);
|
||||
} else {
|
||||
lv_anim_set_completed_cb(&a_advice, anim_state_ready_cb);
|
||||
}
|
||||
lv_anim_timeline_add(at_active, 0, &a_advice);
|
||||
|
||||
// Eco flash
|
||||
lv_anim_t a_eco;
|
||||
lv_anim_init(&a_eco);
|
||||
lv_anim_set_early_apply(&a_eco, false);
|
||||
lv_anim_set_var(&a_eco, l_eco);
|
||||
lv_anim_set_path_cb(&a_eco, lv_anim_path_linear);
|
||||
lv_anim_set_duration(&a_eco, 1000);
|
||||
lv_anim_set_exec_cb(&a_eco, anim_text_color_mix_hero_sub);
|
||||
|
||||
lv_anim_set_values(&a_eco, 255, 0);
|
||||
lv_anim_timeline_add(at_active_rep, 0, &a_eco);
|
||||
|
||||
lv_anim_set_values(&a_eco, 0, 255);
|
||||
lv_anim_timeline_add(at_active_rep, 1000, &a_eco);
|
||||
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_ui_game_over(bool won) {
|
||||
setup_next_state();
|
||||
|
||||
// Widgets
|
||||
lv_obj_t *l_main = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_main, &s_hero, 0);
|
||||
lv_obj_center(l_main);
|
||||
lv_label_set_text_static(l_main, won ? "VICTORY" : "DEFEAT");
|
||||
lv_obj_set_style_text_color(l_main, won ? color_text_won : color_text_lost, 0);
|
||||
|
||||
lv_obj_t *l_subtitle = lv_label_create(o_active);
|
||||
lv_obj_add_style(l_subtitle, &s_subtitle, 0);
|
||||
lv_obj_center(l_subtitle);
|
||||
lv_label_set_text_static(l_subtitle, won ? "WELL PLAYED!" : "HARD LUCK...");
|
||||
|
||||
lv_obj_update_layout(o_active);
|
||||
lv_obj_set_y(
|
||||
l_subtitle,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
|
||||
// Animations
|
||||
if (won) {
|
||||
lv_anim_t a_fly;
|
||||
lv_anim_init(&a_fly);
|
||||
lv_anim_set_path_cb(&a_fly, lv_anim_path_ease_out);
|
||||
lv_anim_set_duration(&a_fly, 750);
|
||||
|
||||
// Main text from top-left
|
||||
// Y
|
||||
lv_anim_set_var(&a_fly, l_main);
|
||||
lv_anim_set_exec_cb(&a_fly, anim_y_cb);
|
||||
lv_anim_set_values(
|
||||
&a_fly,
|
||||
-(lv_obj_get_height(o_container) + lv_obj_get_height(l_main)) / 2, 0);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||
|
||||
// X
|
||||
lv_anim_set_exec_cb(&a_fly, anim_x_cb);
|
||||
lv_anim_set_values(
|
||||
&a_fly,
|
||||
-(lv_obj_get_width(o_container) + lv_obj_get_width(l_main)) / 2, 0);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||
|
||||
|
||||
// Subtitle from bottom-right
|
||||
// Y
|
||||
lv_anim_set_var(&a_fly, l_subtitle);
|
||||
lv_anim_set_exec_cb(&a_fly, anim_y_cb);
|
||||
lv_anim_set_values(
|
||||
&a_fly,
|
||||
(lv_obj_get_height(o_container) + lv_obj_get_height(l_subtitle)) / 2,
|
||||
(lv_obj_get_height(l_main) + lv_obj_get_height(l_subtitle)) / 2 + 5);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||
|
||||
// X
|
||||
lv_anim_set_exec_cb(&a_fly, anim_x_cb);
|
||||
lv_anim_set_values(
|
||||
&a_fly,
|
||||
(lv_obj_get_width(o_container) + lv_obj_get_width(l_subtitle)) / 2, 0);
|
||||
lv_anim_set_completed_cb(&a_fly, anim_state_ready_cb);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fly);
|
||||
} else {
|
||||
lv_anim_t a_fade_in;
|
||||
lv_anim_init(&a_fade_in);
|
||||
lv_anim_set_values(&a_fade_in, 0, 255);
|
||||
lv_anim_set_exec_cb(&a_fade_in, anim_opa_cb);
|
||||
lv_anim_set_path_cb(&a_fade_in, lv_anim_path_ease_in);
|
||||
lv_anim_set_duration(&a_fade_in, 1000);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_main);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
|
||||
lv_anim_set_var(&a_fade_in, l_subtitle);
|
||||
lv_anim_set_completed_cb(&a_fade_in, anim_state_ready_cb);
|
||||
lv_anim_timeline_add(at_active, 0, &a_fade_in);
|
||||
}
|
||||
|
||||
lv_anim_timeline_start(at_active);
|
||||
}
|
||||
|
||||
void val_lvgl_ui(lv_display_t *disp) {
|
||||
color_primary = lv_color_hex(0xff4655);
|
||||
color_secondary = lv_color_hex(0xf7518f);
|
||||
|
||||
color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
|
||||
color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 2);
|
||||
color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 1);
|
||||
color_text_won = lv_palette_lighten(LV_PALETTE_GREEN, 1);
|
||||
color_text_lost = lv_palette_darken(LV_PALETTE_RED, 4);
|
||||
|
||||
// init default theme
|
||||
lv_theme_default_init(
|
||||
disp, color_primary, color_secondary,
|
||||
true, // dark theme
|
||||
font_normal);
|
||||
// lv_sysmon_hide_performance(disp);
|
||||
lv_sysmon_hide_performance(disp);
|
||||
|
||||
lv_font_t *f_hero_emoji = lv_imgfont_create(120, imgfont_get_path, NULL);
|
||||
assert(f_hero_emoji);
|
||||
@@ -270,6 +740,7 @@ void val_lvgl_ui(lv_display_t *disp) {
|
||||
lv_obj_set_style_border_width(o_container, 0, 0);
|
||||
lv_obj_set_style_pad_all(o_container, 0, 0);
|
||||
lv_obj_set_size(o_container, lv_pct(100), lv_pct(100));
|
||||
lv_obj_set_scrollbar_mode(o_container, LV_SCROLLBAR_MODE_OFF);
|
||||
|
||||
// Settings button
|
||||
lv_obj_t *b_cfg = lv_button_create(lv_screen_active());
|
||||
|
@@ -2,6 +2,21 @@
|
||||
|
||||
#include "lvgl.h"
|
||||
|
||||
extern const char *val_ext_gamemodes[];
|
||||
#define VAL_EXT_GAMEMODES_SIZE 6
|
||||
|
||||
typedef enum val_eco_decision {
|
||||
ECO_BUY,
|
||||
ECO_SAVE,
|
||||
ECO_BONUS,
|
||||
ECO_MATCH_TEAM,
|
||||
} val_eco_decision_t;
|
||||
typedef enum val_won {
|
||||
ROUND_LOST,
|
||||
ROUND_WON,
|
||||
ROUND_NONE,
|
||||
} val_won_t;
|
||||
|
||||
LV_FONT_DECLARE(lv_font_tungsten_40)
|
||||
LV_FONT_DECLARE(lv_font_tungsten_180)
|
||||
|
||||
@@ -15,5 +30,12 @@ bool val_ui_state_ready();
|
||||
void val_ui_none();
|
||||
void val_ui_menu(bool was_idle);
|
||||
void val_ui_idle();
|
||||
void val_ui_queue_start(bool ms_not_comp);
|
||||
void val_ui_match_found(bool is_premier);
|
||||
void val_ui_pregame(bool is_split);
|
||||
void val_ui_game_generic(const char *gamemode);
|
||||
void val_ui_game_start();
|
||||
void val_ui_round_start(uint8_t score, uint8_t score_enemy, val_won_t won, val_eco_decision_t eco);
|
||||
void val_ui_game_over(bool won);
|
||||
|
||||
void val_lvgl_ui(lv_display_t *disp);
|
||||
|
@@ -101,7 +101,7 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
||||
ESP_LOGE(TAG, "Failed to grab LVGL lock");
|
||||
return;
|
||||
}
|
||||
if (buf[0] > ST_IDLE) {
|
||||
if (buf[0] > ST_GAME_OVER) {
|
||||
ESP_LOGW(TAG, "Unknown state %hhu", buf[0]);
|
||||
goto ret;
|
||||
}
|
||||
@@ -123,6 +123,51 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
|
||||
case ST_IDLE:
|
||||
val_ui_idle();
|
||||
break;
|
||||
case ST_QUEUE_START:
|
||||
if (bufsize < 2) {
|
||||
ESP_LOGE(TAG, "Invalid ST_QUEUE_START command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_queue_start((bool)buf[1]);
|
||||
break;
|
||||
case ST_MATCH_FOUND:
|
||||
if (bufsize < 2) {
|
||||
ESP_LOGE(TAG, "Invalid ST_MATCH_FOUND command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_match_found((bool)buf[1]);
|
||||
break;
|
||||
case ST_PREGAME:
|
||||
if (bufsize < 2) {
|
||||
ESP_LOGE(TAG, "Invalid ST_PREGAME command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_pregame((bool)buf[1]);
|
||||
break;
|
||||
case ST_GAME_GENERIC:
|
||||
if (bufsize < 2 || buf[1] > VAL_EXT_GAMEMODES_SIZE) {
|
||||
ESP_LOGE(TAG, "Invalid ST_PREGAME command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_game_generic(val_ext_gamemodes[buf[1]]);
|
||||
break;
|
||||
case ST_GAME_START:
|
||||
val_ui_game_start();
|
||||
break;
|
||||
case ST_ROUND_START:
|
||||
if (bufsize < 5 || buf[3] > ROUND_NONE || buf[4] > ECO_MATCH_TEAM) {
|
||||
ESP_LOGE(TAG, "Invalid ST_ROUND_START command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_round_start(buf[1], buf[2], buf[3], buf[4]);
|
||||
break;
|
||||
case ST_GAME_OVER:
|
||||
if (bufsize < 2) {
|
||||
ESP_LOGE(TAG, "Invalid ST_GAME_OVER command");
|
||||
goto ret;
|
||||
}
|
||||
val_ui_game_over((bool)buf[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
ret:
|
||||
|
@@ -8,7 +8,14 @@
|
||||
typedef enum val_state {
|
||||
ST_NONE = 0,
|
||||
ST_MENU,
|
||||
ST_IDLE
|
||||
ST_IDLE,
|
||||
ST_QUEUE_START,
|
||||
ST_MATCH_FOUND,
|
||||
ST_PREGAME,
|
||||
ST_GAME_GENERIC,
|
||||
ST_GAME_START,
|
||||
ST_ROUND_START,
|
||||
ST_GAME_OVER,
|
||||
} val_state_t;
|
||||
|
||||
void val_usb_init(void);
|
||||
|
@@ -21,7 +21,6 @@ CONFIG_ESP_WIFI_DPP_SUPPORT=y
|
||||
CONFIG_FREERTOS_HZ=1000
|
||||
CONFIG_TINYUSB_DEBUG_LEVEL=0
|
||||
CONFIG_TINYUSB_HID_COUNT=1
|
||||
CONFIG_LV_DEF_REFR_PERIOD=24
|
||||
CONFIG_LV_USE_LOG=y
|
||||
CONFIG_LV_LOG_PRINTF=y
|
||||
CONFIG_LV_FONT_MONTSERRAT_24=y
|
||||
|
Reference in New Issue
Block a user