From ab1f68152014668ceca80d06785c1f14c1649aa4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martti=20Rannanj=C3=A4rvi?= Date: Tue, 30 Jul 2024 02:02:24 +0300 Subject: [PATCH] game: Add tournament fight statistics --- src/game/protos/fight_stats.h | 5 ++++ src/game/scenes/arena.c | 27 +++++++++++++++++++++- src/game/scenes/vs.c | 43 +++++++++++++++++++++++++++++++---- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/src/game/protos/fight_stats.h b/src/game/protos/fight_stats.h index cd6e03a5a..8d36a6e83 100644 --- a/src/game/protos/fight_stats.h +++ b/src/game/protos/fight_stats.h @@ -6,6 +6,11 @@ typedef struct fight_stats_t { int bonuses; int repair_cost; int profit; + + unsigned hits_landed[2]; + float average_damage[2]; + unsigned total_attacks[2]; + unsigned hit_miss_ratio[2]; } fight_stats; #endif // FIGHT_STATS_H diff --git a/src/game/scenes/arena.c b/src/game/scenes/arena.c index 541c7852e..183bb016d 100644 --- a/src/game/scenes/arena.c +++ b/src/game/scenes/arena.c @@ -260,6 +260,9 @@ void arena_end(scene *sc) { game_state_set_next(gs, next_id); } else if(is_singleplayer(sc) || is_tournament(sc)) { game_player *p1 = game_state_get_player(gs, 0); + game_player *p2 = game_state_get_player(gs, 1); + har *p1_har = object_get_userdata(game_player_get_har(p1)); + har *p2_har = object_get_userdata(game_player_get_har(p2)); fight_stats->bonuses = game_player_get_score(p1)->score / 1000; fight_stats->profit = fight_stats->bonuses + fight_stats->winnings - fight_stats->repair_cost; // TODO Selling parts here is not implemented @@ -268,6 +271,22 @@ void arena_end(scene *sc) { } else { p1->pilot->money += fight_stats->profit; } + + if(fight_stats->hits_landed[0] != 0) { + fight_stats->average_damage[0] = + (float)(p2_har->health_max - p2_har->health) / (float)fight_stats->hits_landed[0]; + } + if(fight_stats->total_attacks[0] != 0) { + fight_stats->hit_miss_ratio[0] = 100 * fight_stats->hits_landed[0] / fight_stats->total_attacks[0]; + } + if(fight_stats->hits_landed[1] != 0) { + fight_stats->average_damage[1] = + (float)(p1_har->health_max - p1_har->health) / (float)fight_stats->hits_landed[1]; + } + if(fight_stats->total_attacks[1] != 0) { + fight_stats->hit_miss_ratio[1] = 100 * fight_stats->hits_landed[1] / fight_stats->total_attacks[1]; + } + game_state_set_next(gs, SCENE_NEWSROOM); } else if(is_twoplayer(sc)) { game_state_set_next(gs, SCENE_MELEE); @@ -354,6 +373,8 @@ void arena_har_take_hit_hook(int hittee, af_move *move, scene *scene) { if(is_netplay(scene) && scene->gs->role == ROLE_CLIENT) { return; // netplay clients do not keep score } + fight_stats *fight_stats = &scene->gs->fight_stats; + fight_stats->hits_landed[abs(hittee - 1)]++; if(hittee == 1) { score = game_player_get_score(game_state_get_player(scene->gs, 0)); @@ -533,7 +554,6 @@ void arena_har_defeat_hook(int player_id, scene *scene) { object *loser = game_player_get_har(player_loser); har *winner_har = object_get_userdata(winner); fight_stats *fight_stats = &gs->fight_stats; - memset(fight_stats, 0, sizeof(*fight_stats)); // XXX need a smarter way to detect if a player is networked or local if(player_winner->ctrl->type != CTRL_TYPE_NETWORK && player_loser->ctrl->type == CTRL_TYPE_NETWORK) { scene_youwin_anim_start(scene->gs); @@ -610,6 +630,7 @@ void arena_maybe_turn_har(int player_id, scene *scene) { void arena_har_hook(har_event event, void *data) { scene *scene = data; + fight_stats *fight_stats = &scene->gs->fight_stats; int other_player_id = abs(event.player_id - 1); arena_local *arena = scene_get_userdata(scene); chr_score *score = game_player_get_score(game_state_get_player(scene->gs, event.player_id)); @@ -635,6 +656,7 @@ void arena_har_hook(har_event event, void *data) { arena_har_hit_wall_hook(event.player_id, event.wall, scene); break; case HAR_EVENT_ATTACK: + fight_stats->total_attacks[event.player_id]++; if(object_is_airborne(obj_har1)) { har1->air_attacked = 1; DEBUG("AIR ATTACK %u", event.player_id); @@ -1190,6 +1212,9 @@ int arena_create(scene *scene) { // Load up settings setting = settings_get(); + fight_stats *fight_stats = &scene->gs->fight_stats; + memset(fight_stats, 0, sizeof(*fight_stats)); + // Initialize Demo if(is_demoplay(scene)) { game_state_init_demo(scene->gs); diff --git a/src/game/scenes/vs.c b/src/game/scenes/vs.c index 303fee914..f639f2ed2 100644 --- a/src/game/scenes/vs.c +++ b/src/game/scenes/vs.c @@ -288,31 +288,66 @@ void vs_render(scene *scene) { font_render_wrapped(&font_small, "Hmph. you'd think this remake would've been done by now, huh?", 59, 165, 220, COLOR_YELLOW); + fight_stats *fight_stats = &scene->gs->fight_stats; char text[32]; char money[16]; font_render_wrapped(&font_small, "FINANCIAL REPORT", 190, 6, 100, COLOR_GREEN); font_render(&font_small, "WINNINGS:", 190, 16, COLOR_DARK_GREEN); - score_format(scene->gs->fight_stats.winnings, money, sizeof(money)); + score_format(fight_stats->winnings, money, sizeof(money)); snprintf(text, sizeof(text), "$ %sK", money); font_render(&font_small, text, 250, 16, COLOR_GREEN); font_render(&font_small, "BONUSES:", 196, 24, COLOR_DARK_GREEN); - score_format(scene->gs->fight_stats.bonuses, money, sizeof(money)); + score_format(fight_stats->bonuses, money, sizeof(money)); snprintf(text, sizeof(text), "$ %sK", money); font_render(&font_small, text, 250, 24, COLOR_GREEN); font_render(&font_small, "REPAIR COST:", 172, 32, COLOR_DARK_GREEN); - score_format(scene->gs->fight_stats.repair_cost, money, sizeof(money)); + score_format(fight_stats->repair_cost, money, sizeof(money)); snprintf(text, sizeof(text), "$ %sK", money); font_render(&font_small, text, 250, 32, COLOR_GREEN); font_render(&font_small, "PROFIT:", 202, 40, COLOR_DARK_GREEN); - score_format(scene->gs->fight_stats.profit, money, sizeof(money)); + score_format(fight_stats->profit, money, sizeof(money)); snprintf(text, sizeof(text), "$ %sK", money); font_render(&font_small, text, 250, 40, COLOR_GREEN); font_render_wrapped(&font_small, "FIGHT STATISTICS", 210, 60, 60, COLOR_GREEN); + + font_render(&font_small, "HITS LANDED:", 202, 79, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u", fight_stats->hits_landed[0]); + font_render(&font_small, text, 276, 79, COLOR_GREEN); + + font_render(&font_small, "AVERAGE DAMAGE:", 184, 86, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%.1f", fight_stats->average_damage[0]); + font_render(&font_small, text, 276, 86, COLOR_GREEN); + + font_render(&font_small, "FAILED ATTACKS:", 184, 93, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u", fight_stats->total_attacks[0] - fight_stats->hits_landed[0]); + font_render(&font_small, text, 276, 93, COLOR_GREEN); + + font_render(&font_small, "HIT/MISS RATIO:", 184, 100, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u%%", fight_stats->hit_miss_ratio[0]); + font_render(&font_small, text, 276, 100, COLOR_GREEN); + + font_render(&font_small, "OPPONENT", 210, 108, COLOR_GREEN); + + font_render(&font_small, "HITS LANDED:", 202, 115, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u", fight_stats->hits_landed[1]); + font_render(&font_small, text, 276, 115, COLOR_GREEN); + + font_render(&font_small, "AVERAGE DAMAGE:", 184, 123, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%.1f", fight_stats->average_damage[1]); + font_render(&font_small, text, 276, 123, COLOR_GREEN); + + font_render(&font_small, "FAILED ATTACKS:", 184, 130, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u", fight_stats->total_attacks[1] - fight_stats->hits_landed[1]); + font_render(&font_small, text, 276, 130, COLOR_GREEN); + + font_render(&font_small, "HIT/MISS RATIO:", 184, 137, COLOR_DARK_GREEN); + snprintf(text, sizeof(text), "%u%%", fight_stats->hit_miss_ratio[1]); + font_render(&font_small, text, 276, 137, COLOR_GREEN); } else { font_render_wrapped(&font_small, lang_get(749 + (11 * player1->pilot->pilot_id) + player2->pilot->pilot_id), 59, 160, 150, COLOR_YELLOW);