firmware+controller: Add round start state
This commit is contained in:
		@@ -2,7 +2,7 @@
 | 
				
			|||||||
import logging
 | 
					import logging
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import valconomy
 | 
					import valconomy
 | 
				
			||||||
from valconomy import ValorantPlayerInfo, RiotPlayerInfo
 | 
					from valconomy import ValorantPlayerInfo, RiotPlayerInfo, EconomyDecision
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def main():
 | 
					def main():
 | 
				
			||||||
  logging.basicConfig(
 | 
					  logging.basicConfig(
 | 
				
			||||||
@@ -26,6 +26,18 @@ def main():
 | 
				
			|||||||
    h.game_start(None)
 | 
					    h.game_start(None)
 | 
				
			||||||
    h.game_over(None, False)
 | 
					    h.game_over(None, False)
 | 
				
			||||||
    h.game_over(None, True)
 | 
					    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()
 | 
					    h.service()
 | 
				
			||||||
  finally:
 | 
					  finally:
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -340,8 +340,24 @@ class HIDValconomyHandler(ValconomyHandler):
 | 
				
			|||||||
  def game_start(self, info: RiotPlayerInfo):
 | 
					  def game_start(self, info: RiotPlayerInfo):
 | 
				
			||||||
    self._enq(7)
 | 
					    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):
 | 
					  def game_over(self, info: RiotPlayerInfo, won: bool):
 | 
				
			||||||
    self._enq(8, 1 if won else 0, fmt='B')
 | 
					    self._enq(9, 1 if won else 0, fmt='B')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class GameState(Enum):
 | 
					class GameState(Enum):
 | 
				
			||||||
  NONE = 0
 | 
					  NONE = 0
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
#include "ui.h"
 | 
					#include "ui.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static const char* M_VAL_TIME = "VAL TIME?";
 | 
					 | 
				
			||||||
const char *val_ext_gamemodes[] = {
 | 
					const char *val_ext_gamemodes[] = {
 | 
				
			||||||
  "TDM",
 | 
					  "TDM",
 | 
				
			||||||
  "DEATHMATCH",
 | 
					  "DEATHMATCH",
 | 
				
			||||||
@@ -12,10 +11,25 @@ const char *val_ext_gamemodes[] = {
 | 
				
			|||||||
  "GAME",
 | 
					  "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 const lv_font_t *font_normal = &lv_font_montserrat_24;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static lv_color_t color_primary, color_secondary;
 | 
					static lv_color_t color_primary, color_secondary;
 | 
				
			||||||
static lv_color_t color_text_hero, color_text_subtitle, color_text_victory;
 | 
					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_style_t s_hero, s_subtitle;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -509,6 +523,105 @@ void val_ui_game_start() {
 | 
				
			|||||||
  state_ready = true;
 | 
					  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) {
 | 
					void val_ui_game_over(bool won) {
 | 
				
			||||||
  setup_next_state();
 | 
					  setup_next_state();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -517,7 +630,7 @@ void val_ui_game_over(bool won) {
 | 
				
			|||||||
  lv_obj_add_style(l_main, &s_hero, 0);
 | 
					  lv_obj_add_style(l_main, &s_hero, 0);
 | 
				
			||||||
  lv_obj_center(l_main);
 | 
					  lv_obj_center(l_main);
 | 
				
			||||||
  lv_label_set_text_static(l_main, won ? "VICTORY" : "DEFEAT");
 | 
					  lv_label_set_text_static(l_main, won ? "VICTORY" : "DEFEAT");
 | 
				
			||||||
  if (won) lv_obj_set_style_text_color(l_main, color_text_victory, 0);
 | 
					  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_t *l_subtitle = lv_label_create(o_active);
 | 
				
			||||||
  lv_obj_add_style(l_subtitle, &s_subtitle, 0);
 | 
					  lv_obj_add_style(l_subtitle, &s_subtitle, 0);
 | 
				
			||||||
@@ -553,7 +666,7 @@ void val_ui_game_over(bool won) {
 | 
				
			|||||||
    lv_anim_timeline_add(at_active, 0, &a_fly);
 | 
					    lv_anim_timeline_add(at_active, 0, &a_fly);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Subtitle from bottom right
 | 
					    // Subtitle from bottom-right
 | 
				
			||||||
    // Y
 | 
					    // Y
 | 
				
			||||||
    lv_anim_set_var(&a_fly, l_subtitle);
 | 
					    lv_anim_set_var(&a_fly, l_subtitle);
 | 
				
			||||||
    lv_anim_set_exec_cb(&a_fly, anim_y_cb);
 | 
					    lv_anim_set_exec_cb(&a_fly, anim_y_cb);
 | 
				
			||||||
@@ -595,7 +708,8 @@ void val_lvgl_ui(lv_display_t *disp) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
 | 
					  color_text_hero = lv_palette_lighten(LV_PALETTE_GREY, 2);
 | 
				
			||||||
  color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 1);
 | 
					  color_text_subtitle = lv_palette_darken(LV_PALETTE_GREY, 1);
 | 
				
			||||||
  color_text_victory = lv_palette_lighten(LV_PALETTE_GREEN, 1);
 | 
					  color_text_won = lv_palette_lighten(LV_PALETTE_GREEN, 1);
 | 
				
			||||||
 | 
					  color_text_lost = lv_palette_darken(LV_PALETTE_RED, 4);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  // init default theme
 | 
					  // init default theme
 | 
				
			||||||
  lv_theme_default_init(
 | 
					  lv_theme_default_init(
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,6 +5,18 @@
 | 
				
			|||||||
extern const char *val_ext_gamemodes[];
 | 
					extern const char *val_ext_gamemodes[];
 | 
				
			||||||
#define VAL_EXT_GAMEMODES_SIZE 6
 | 
					#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_40)
 | 
				
			||||||
LV_FONT_DECLARE(lv_font_tungsten_180)
 | 
					LV_FONT_DECLARE(lv_font_tungsten_180)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -23,6 +35,7 @@ void val_ui_match_found(bool is_premier);
 | 
				
			|||||||
void val_ui_pregame(bool is_split);
 | 
					void val_ui_pregame(bool is_split);
 | 
				
			||||||
void val_ui_game_generic(const char *gamemode);
 | 
					void val_ui_game_generic(const char *gamemode);
 | 
				
			||||||
void val_ui_game_start();
 | 
					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_ui_game_over(bool won);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void val_lvgl_ui(lv_display_t *disp);
 | 
					void val_lvgl_ui(lv_display_t *disp);
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -154,6 +154,13 @@ void tud_hid_set_report_cb(uint8_t instance, uint8_t report_id, hid_report_type_
 | 
				
			|||||||
  case ST_GAME_START:
 | 
					  case ST_GAME_START:
 | 
				
			||||||
    val_ui_game_start();
 | 
					    val_ui_game_start();
 | 
				
			||||||
    break;
 | 
					    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:
 | 
					  case ST_GAME_OVER:
 | 
				
			||||||
    if (bufsize < 2) {
 | 
					    if (bufsize < 2) {
 | 
				
			||||||
      ESP_LOGE(TAG, "Invalid ST_GAME_OVER command");
 | 
					      ESP_LOGE(TAG, "Invalid ST_GAME_OVER command");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,6 +14,7 @@ typedef enum val_state {
 | 
				
			|||||||
  ST_PREGAME,
 | 
					  ST_PREGAME,
 | 
				
			||||||
  ST_GAME_GENERIC,
 | 
					  ST_GAME_GENERIC,
 | 
				
			||||||
  ST_GAME_START,
 | 
					  ST_GAME_START,
 | 
				
			||||||
 | 
					  ST_ROUND_START,
 | 
				
			||||||
  ST_GAME_OVER,
 | 
					  ST_GAME_OVER,
 | 
				
			||||||
} val_state_t;
 | 
					} val_state_t;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user