implement spectator count view in primary game

This commit is contained in:
Martin Michelsen
2022-12-12 21:55:11 -08:00
parent 391a70f68d
commit 0d7f69eb66
6 changed files with 82 additions and 8 deletions
+16 -6
View File
@@ -5615,15 +5615,25 @@ struct G_TournamentMatchResult_GC_Ep3_6xB4x51 {
ptext<char, 0x20> meseta_reward_text;
} __packed__;
// 6xB4x52: Unknown
// 6xB4x52: Set game metadata
struct G_Unknown_GC_Ep3_6xB4x52 {
G_CardBattleCommandHeader header = {0xB4, sizeof(G_Unknown_GC_Ep3_6xB4x52) / 4, 0, 0x52, 0, 0, 0};
struct G_SetGameMetadata_GC_Ep3_6xB4x52 {
G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetGameMetadata_GC_Ep3_6xB4x52) / 4, 0, 0x52, 0, 0, 0};
le_uint16_t unknown_a1 = 0; // Clamped to [0, 999] by the client
le_uint16_t unknown_a2 = 0; // Clamped to [0, 999] by the client
// If num_spectators is nonzero, an icon appears in the middle of the screen
// during battle when the details view is enabled (by pressing Z). However,
// the number of people visible in the icon doesn't match the actual number of
// spectators. Specifically:
// 0 = no icon
// 1 = icon with a single spectator (green)
// 2-4 = icon with 3 spectators (blue)
// 5-10 = icon with 5 spectators (yellow)
// 11-29 = icon with 8 spectators (purple)
// 30+ = icon with 12 spectators (red)
le_uint16_t num_spectators = 0; // Clamped to [0, 999] by the client
le_uint16_t unused = 0;
le_uint16_t size = 0; // Number of used bytes in data (clamped to 0xFF)
parray<uint8_t, 0x100> data;
le_uint16_t size = 0; // Number of used bytes in unknown_a2 (clamped to 0xFF)
parray<uint8_t, 0x100> unknown_a2;
} __packed__;
// 6xB4x53: Reject battle start request
+25 -1
View File
@@ -132,6 +132,18 @@ void Lobby::add_client(shared_ptr<Client> c) {
c->game_data.player()->inventory,
c->game_data.player()->disp.to_dcpcv3());
}
// Send spectator count notifications if needed
if (this->is_game() && (this->flags & Lobby::Flag::EPISODE_3_ONLY)) {
if (this->flags & Lobby::Flag::IS_SPECTATOR_TEAM) {
auto watched_l = this->watched_lobby.lock();
if (watched_l) {
send_ep3_update_spectator_count(watched_l);
}
} else {
send_ep3_update_spectator_count(this->shared_from_this());
}
}
}
void Lobby::remove_client(shared_ptr<Client> c) {
@@ -154,10 +166,22 @@ void Lobby::remove_client(shared_ptr<Client> c) {
this->reassign_leader_on_client_departure(c->lobby_client_id);
// If the lobby ios recording a battle record, add the player leave event
// If the lobby is recording a battle record, add the player leave event
if (this->battle_record) {
this->battle_record->delete_player(c->lobby_client_id);
}
// If the lobby is Episode 3, update the appropriate spectator counts
if (this->is_game() && (this->flags & Lobby::Flag::EPISODE_3_ONLY)) {
if (this->flags & Lobby::Flag::IS_SPECTATOR_TEAM) {
auto watched_l = this->watched_lobby.lock();
if (watched_l) {
send_ep3_update_spectator_count(watched_l);
}
} else {
send_ep3_update_spectator_count(this->shared_from_this());
}
}
}
void Lobby::move_client_to_lobby(shared_ptr<Lobby> dest_lobby,
+1 -1
View File
@@ -20,7 +20,7 @@
#include "Episode3/BattleRecord.hh"
#include "Episode3/Server.hh"
struct Lobby {
struct Lobby : public std::enable_shared_from_this<Lobby> {
enum Flag {
GAME = 0x00000001,
EPISODE_3_ONLY = 0x00000002,
+19
View File
@@ -2284,6 +2284,25 @@ void send_ep3_tournament_match_result(
// the player 1000000 and never charge for anything.
cmd.meseta_amount = 100;
cmd.meseta_reward_text = "You got %s meseta!";
if (!(tourn->get_data_index()->behavior_flags & Episode3::BehaviorFlag::DISABLE_MASKING)) {
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
set_mask_for_ep3_game_command(&cmd, sizeof(cmd), mask_key);
}
send_command_t(l, 0xC9, 0x00, cmd);
}
void send_ep3_update_spectator_count(shared_ptr<Lobby> l) {
G_SetGameMetadata_GC_Ep3_6xB4x52 cmd;
for (auto watcher_l : l->watcher_lobbies) {
for (auto c : watcher_l->clients) {
if (c) {
cmd.num_spectators++;
}
}
}
// TODO: Make s available here so we can apply masking if needed (perhaps by
// adding a weak_ptr in Lobby... it'd be dumb to require s to be passed in to
// this function just to check a behavior flag)
send_command_t(l, 0xC9, 0x00, cmd);
}
+2
View File
@@ -339,6 +339,8 @@ void send_ep3_tournament_details(
void send_ep3_game_details(
std::shared_ptr<Client> c, std::shared_ptr<Lobby> l);
void send_ep3_update_spectator_count(std::shared_ptr<Lobby> l);
// Pass mask_key = 0 to unmask the command
void set_mask_for_ep3_game_command(void* vdata, size_t size, uint8_t mask_key);
+19
View File
@@ -2805,6 +2805,25 @@ I 13136 2022-11-27 21:06:44 - [Lobby/15] Created lobby
[PlayerInventory] 3 (00010003): 030000 (Monomate x4)
[PlayerInventory] 4 (00010004): 030100 (Monofluid x4)
I 13136 2022-11-27 21:06:44 - [Commands] Sending to C-6 (Tali) (version=GC command=64 flag=01)
0000 | C9 00 14 01 B4 44 00 00 52 00 00 00 00 00 00 00 | D R
0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0030 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0040 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0050 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0060 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0070 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0080 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0090 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00A0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00B0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00C0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00D0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00E0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
00F0 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0100 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0110 | 00 00 00 00 |
I 13136 2022-11-27 21:06:44 - [Commands] Sending to C-6 (Tali) (version=GC command=64 flag=01)
0000 | 64 01 84 11 00 00 00 00 00 00 00 00 00 00 00 00 | d
0010 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |
0020 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |