diff --git a/src/CommandFormats.hh b/src/CommandFormats.hh index 2d47a1e8..48ca9c6a 100644 --- a/src/CommandFormats.hh +++ b/src/CommandFormats.hh @@ -6055,79 +6055,89 @@ struct G_SetMesetaSlotPrizeResult_BB_6xE3 { // 6xB4x02: Update hand and equips struct G_UpdateHand_GC_Ep3_6xB4x02 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateHand_GC_Ep3_6xB4x02) / 4, 0, 0x02, 0, 0, 0}; - le_uint16_t client_id = 0; - le_uint16_t unused = 0; - Episode3::HandAndEquipState state; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateHand_GC_Ep3_6xB4x02) / 4, 0, 0x02, 0, 0, 0}; + /* 08 */ le_uint16_t client_id = 0; + /* 0A */ le_uint16_t unused = 0; + /* 0C */ Episode3::HandAndEquipState state; + /* 60 */ } __packed__; // 6xB4x03: Set state flags struct G_SetStateFlags_GC_Ep3_6xB4x03 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetStateFlags_GC_Ep3_6xB4x03) / 4, 0, 0x03, 0, 0, 0}; - Episode3::StateFlags state; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetStateFlags_GC_Ep3_6xB4x03) / 4, 0, 0x03, 0, 0, 0}; + /* 08 */ Episode3::StateFlags state; + /* 20 */ } __packed__; // 6xB4x04: Update SC/FC short statuses struct G_UpdateShortStatuses_GC_Ep3_6xB4x04 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateShortStatuses_GC_Ep3_6xB4x04) / 4, 0, 0x04, 0, 0, 0}; - le_uint16_t client_id = 0; - le_uint16_t unused = 0; + /* 0000 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateShortStatuses_GC_Ep3_6xB4x04) / 4, 0, 0x04, 0, 0, 0}; + /* 0008 */ le_uint16_t client_id = 0; + /* 000A */ le_uint16_t unused = 0; // The slots in this array have heterogeneous meanings. Specifically: // [0] is the SC card status // [1] through [6] are hand cards // [7] through [14] are set FC cards (items/creatures) // [15] is the set assist card - parray card_statuses; + /* 000C */ parray card_statuses; + /* 010C */ } __packed__; // 6xB4x05: Update map state +// TODO: This structure is different on Ep3 NTE because the Rules structure is +// shorter. Define an appropriate structure for this. struct G_UpdateMap_GC_Ep3_6xB4x05 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateMap_GC_Ep3_6xB4x05) / 4, 0, 0x05, 0, 0, 0}; - Episode3::MapAndRulesState state; - uint8_t start_battle = 0; - parray unused; + /* 0000 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateMap_GC_Ep3_6xB4x05) / 4, 0, 0x05, 0, 0, 0}; + /* 0008 */ Episode3::MapAndRulesState state; + /* 0140 */ uint8_t start_battle = 0; + /* 0141 */ parray unused; + /* 0144 */ } __packed__; // 6xB4x06: Apply condition effect struct G_ApplyConditionEffect_GC_Ep3_6xB4x06 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_ApplyConditionEffect_GC_Ep3_6xB4x06) / 4, 0, 0x06, 0, 0, 0}; - Episode3::EffectResult effect; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_ApplyConditionEffect_GC_Ep3_6xB4x06) / 4, 0, 0x06, 0, 0, 0}; + /* 08 */ Episode3::EffectResult effect; + /* 14 */ } __packed__; // 6xB4x07: Set battle decks struct G_UpdateDecks_GC_Ep3_6xB4x07 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateDecks_GC_Ep3_6xB4x07) / 4, 0, 0x07, 0, 0, 0}; - parray entries_present; - parray entries; + /* 0000 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateDecks_GC_Ep3_6xB4x07) / 4, 0, 0x07, 0, 0, 0}; + /* 0008 */ parray entries_present; + /* 000C */ parray entries; + /* 016C */ } __packed__; // 6xB4x09: Set action state struct G_SetActionState_GC_Ep3_6xB4x09 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetActionState_GC_Ep3_6xB4x09) / 4, 0, 0x09, 0, 0, 0}; - le_uint16_t client_id = 0; - parray unknown_a1; - Episode3::ActionState state; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetActionState_GC_Ep3_6xB4x09) / 4, 0, 0x09, 0, 0, 0}; + /* 08 */ le_uint16_t client_id = 0; + /* 0A */ parray unknown_a1; + /* 0C */ Episode3::ActionState state; + /* 70 */ } __packed__; // 6xB4x0A: Update action chain and metadata // This command seems to be unused; Sega's server implementation never sends it. struct G_UpdateActionChainAndMetadata_GC_Ep3_6xB4x0A { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateActionChainAndMetadata_GC_Ep3_6xB4x0A) / 4, 0, 0x0A, 0, 0, 0}; - le_uint16_t client_id = 0; + /* 0000 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateActionChainAndMetadata_GC_Ep3_6xB4x0A) / 4, 0, 0x0A, 0, 0, 0}; + /* 0008 */ le_uint16_t client_id = 0; // set_index must be 0xFF, or be in the range [0, 9]. If it's 0xFF, all nine // chains and metadatas are cleared for the client; otherwise, the provided // chain and metadata are copied into the slot specified by set_index. - int8_t set_index = 0; - uint8_t unused = 0; - Episode3::ActionChainWithConds chain; - Episode3::ActionMetadata metadata; + /* 000A */ int8_t set_index = 0; + /* 000B */ uint8_t unused = 0; + /* 000C */ Episode3::ActionChainWithConds chain; + /* 010C */ Episode3::ActionMetadata metadata; + /* 0180 */ } __packed__; // 6xB3x0B / CAx0B: Redraw initial hand (immediately before battle) @@ -6282,11 +6292,12 @@ struct G_StartBattle_GC_Ep3_6xB3x1D_CAx1D { // 6xB4x1E: Action result struct G_ActionResult_GC_Ep3_6xB4x1E { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_ActionResult_GC_Ep3_6xB4x1E) / 4, 0, 0x1E, 0, 0, 0}; - be_uint32_t sequence_num = 0; - uint8_t error_code = 0; - uint8_t response_phase = 0; - parray unused; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_ActionResult_GC_Ep3_6xB4x1E) / 4, 0, 0x1E, 0, 0, 0}; + /* 08 */ be_uint32_t sequence_num = 0; + /* 0C */ uint8_t error_code = 0; + /* 0D */ uint8_t response_phase = 0; + /* 0E */ parray unused; + /* 10 */ } __packed__; // 6xB4x1F: Set context token @@ -6368,10 +6379,11 @@ struct G_EndDefenseList_GC_Ep3_6xB3x28_CAx28 { // sends this. struct G_SetActionState_GC_Ep3_6xB4x29 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetActionState_GC_Ep3_6xB4x29) / 4, 0, 0x29, 0, 0, 0}; - uint8_t unknown_a1 = 0; - parray unknown_a2; - Episode3::ActionState state; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetActionState_GC_Ep3_6xB4x29) / 4, 0, 0x29, 0, 0, 0}; + /* 08 */ uint8_t unknown_a1 = 0; + /* 09 */ parray unknown_a2; + /* 0C */ Episode3::ActionState state; + /* 70 */ } __packed__; // 6xB4x2A: Unknown @@ -6397,12 +6409,13 @@ struct G_ExecLegacyCard_GC_Ep3_6xB3x2B_CAx2B { // 6xB4x2C: Unknown struct G_Unknown_GC_Ep3_6xB4x2C { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_Unknown_GC_Ep3_6xB4x2C) / 4, 0, 0x2C, 0, 0, 0}; - uint8_t change_type = 0; - uint8_t client_id = 0; - parray card_refs; - Episode3::Location loc; - parray unknown_a2; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_Unknown_GC_Ep3_6xB4x2C) / 4, 0, 0x2C, 0, 0, 0}; + /* 08 */ uint8_t change_type = 0; + /* 09 */ uint8_t client_id = 0; + /* 0A */ parray card_refs; + /* 10 */ Episode3::Location loc; + /* 14 */ parray unknown_a2; + /* 1C */ } __packed__; // 6xB5x2D: Unknown @@ -6482,10 +6495,11 @@ struct G_MoveSharedMenuCursor_GC_Ep3_6xB5x32 { // 6xB4x33: Subtract ally ATK points (e.g. for photon blast) struct G_SubtractAllyATKPoints_GC_Ep3_6xB4x33 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_SubtractAllyATKPoints_GC_Ep3_6xB4x33) / 4, 0, 0x33, 0, 0, 0}; - uint8_t client_id = 0; - uint8_t ally_cost = 0; - le_uint16_t card_ref = 0xFFFF; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_SubtractAllyATKPoints_GC_Ep3_6xB4x33) / 4, 0, 0x33, 0, 0, 0}; + /* 08 */ uint8_t client_id = 0; + /* 09 */ uint8_t ally_cost = 0; + /* 0A */ le_uint16_t card_ref = 0xFFFF; + /* 0C */ } __packed__; // 6xB3x34 / CAx34: Photon blast request @@ -6500,10 +6514,11 @@ struct G_PhotonBlastRequest_GC_Ep3_6xB3x34_CAx34 { // 6xB4x35: Update photon blast status struct G_PhotonBlastStatus_GC_Ep3_6xB4x35 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_PhotonBlastStatus_GC_Ep3_6xB4x35) / 4, 0, 0x35, 0, 0, 0}; - uint8_t client_id = 0; - uint8_t accepted = 0; - le_uint16_t card_ref = 0xFFFF; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_PhotonBlastStatus_GC_Ep3_6xB4x35) / 4, 0, 0x35, 0, 0, 0}; + /* 08 */ uint8_t client_id = 0; + /* 09 */ uint8_t accepted = 0; + /* 0A */ le_uint16_t card_ref = 0xFFFF; + /* 0C */ } __packed__; // 6xB5x36: Recreate player @@ -6541,10 +6556,13 @@ struct G_CardCountsRequest_GC_Ep3_6xB5x38 { } __packed__; // 6xB4x39: Update all player statistics +// TODO: This command is different on Ep3 NTE because the PlayerBattleStats +// structure is different. Document the format here. struct G_UpdateAllPlayerStatistics_GC_Ep3_6xB4x39 { - G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateAllPlayerStatistics_GC_Ep3_6xB4x39) / 4, 0, 0x39, 0, 0, 0}; - parray stats; + /* 00 */ G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateAllPlayerStatistics_GC_Ep3_6xB4x39) / 4, 0, 0x39, 0, 0, 0}; + /* 08 */ parray stats; + /* A8 */ } __packed__; // 6xB3x3A / CAx3A: Overall time limit expired @@ -6771,6 +6789,7 @@ struct G_EndTurn_GC_Ep3_6xB3x48_CAx48 { // pointer to the card counts array, but Sega's implementation always passes // null there, which skips the owned card count check. newserv uses this data at // that callsite to implement one of the deck validity checks. +// Episode 3 Trial Edition does not send this command. struct G_CardCounts_GC_Ep3_6xB3x49_CAx49 { G_CardServerDataCommandHeader header = {0xB3, sizeof(G_CardCounts_GC_Ep3_6xB3x49_CAx49) / 4, 0, 0x49, 0, 0, 0, 0, 0}; @@ -6782,6 +6801,7 @@ struct G_CardCounts_GC_Ep3_6xB3x49_CAx49 { } __packed__; // 6xB4x4A: Unknown +// This command is not valid on Episode 3 Trial Edition. // TODO: Document this from Episode 3 client/server disassembly struct G_Unknown_GC_Ep3_6xB4x4A { @@ -6796,6 +6816,7 @@ struct G_Unknown_GC_Ep3_6xB4x4A { } __packed__; // 6xB4x4B: Set EX result values +// This command is not valid on Episode 3 Trial Edition. // This command specifies how much EX the player should get based on the // difference between their level and the levels of the players they defeated or // were defeated by. (For multi-player opponent teams, the average of the @@ -6828,6 +6849,7 @@ struct G_SetEXResultValues_GC_Ep3_6xB4x4B { } __packed__; // 6xB4x4C: Update action chain +// This command is not valid on Episode 3 Trial Edition. struct G_UpdateActionChain_GC_Ep3_6xB4x4C { G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateActionChain_GC_Ep3_6xB4x4C) / 4, 0, 0x4C, 0, 0, 0}; @@ -6838,6 +6860,7 @@ struct G_UpdateActionChain_GC_Ep3_6xB4x4C { } __packed__; // 6xB4x4D: Update action metadata +// This command is not valid on Episode 3 Trial Edition. struct G_UpdateActionMetadata_GC_Ep3_6xB4x4D { G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateActionMetadata_GC_Ep3_6xB4x4D) / 4, 0, 0x4D, 0, 0, 0}; @@ -6848,6 +6871,7 @@ struct G_UpdateActionMetadata_GC_Ep3_6xB4x4D { } __packed__; // 6xB4x4E: Update card conditions +// This command is not valid on Episode 3 Trial Edition. struct G_UpdateCardConditions_GC_Ep3_6xB4x4E { G_CardBattleCommandHeader header = {0xB4, sizeof(G_UpdateCardConditions_GC_Ep3_6xB4x4E) / 4, 0, 0x4E, 0, 0, 0}; @@ -6858,6 +6882,7 @@ struct G_UpdateCardConditions_GC_Ep3_6xB4x4E { } __packed__; // 6xB4x4F: Clear set card conditions +// This command is not valid on Episode 3 Trial Edition. struct G_ClearSetCardConditions_GC_Ep3_6xB4x4F { G_CardBattleCommandHeader header = {0xB4, sizeof(G_ClearSetCardConditions_GC_Ep3_6xB4x4F) / 4, 0, 0x4F, 0, 0, 0}; @@ -6871,6 +6896,7 @@ struct G_ClearSetCardConditions_GC_Ep3_6xB4x4F { } __packed__; // 6xB4x50: Set trap tile locations +// This command is not valid on Episode 3 Trial Edition. struct G_SetTrapTileLocations_GC_Ep3_6xB4x50 { G_CardBattleCommandHeader header = {0xB4, sizeof(G_SetTrapTileLocations_GC_Ep3_6xB4x50) / 4, 0, 0x50, 0, 0, 0}; @@ -6882,6 +6908,7 @@ struct G_SetTrapTileLocations_GC_Ep3_6xB4x50 { } __packed__; // 6xB4x51: Tournament match result +// This command is not valid on Episode 3 Trial Edition. // This is sent as soon as the battle result is determined (before the battle // results screen). If the client is in tournament mode (tournament_flag is 1 in // the StateFlags struct), then it will use this information to show the @@ -6910,6 +6937,7 @@ struct G_TournamentMatchResult_GC_Ep3_6xB4x51 { } __packed__; // 6xB4x52: Set game metadata +// This command is not valid on Episode 3 Trial Edition. // This is sent to all players in a game and all attached spectator teams when // any player joins or leaves any spectator team watching the same game. @@ -6941,6 +6969,7 @@ struct G_SetGameMetadata_GC_Ep3_6xB4x52 { } __packed__; // 6xB4x53: Reject battle start request +// This command is not valid on Episode 3 Trial Edition. // This is sent in response to a CAx1D command if setup isn't complete (e.g. if // some names/decks are missing or invalid). Under normal operation, this should // never happen. diff --git a/src/Episode3/DeckState.hh b/src/Episode3/DeckState.hh index 710f5ec3..8d9ddc21 100644 --- a/src/Episode3/DeckState.hh +++ b/src/Episode3/DeckState.hh @@ -11,27 +11,29 @@ namespace Episode3 { struct NameEntry { - parray name; - uint8_t client_id; - uint8_t present; - uint8_t is_cpu_player; - uint8_t unused; + /* 00 */ parray name; + /* 10 */ uint8_t client_id; + /* 11 */ uint8_t present; + /* 12 */ uint8_t is_cpu_player; + /* 13 */ uint8_t unused; + /* 14 */ NameEntry(); void clear(); } __attribute__((packed)); struct DeckEntry { - pstring name; - le_uint32_t team_id; - parray card_ids; + /* 00 */ pstring name; + /* 10 */ le_uint32_t team_id; + /* 14 */ parray card_ids; // If the following flag is not set to 3, then the God Whim assist effect can // use cards that are hidden from the player during deck building. The client // always sets this to 3, and it's not clear why this even exists. - uint8_t god_whim_flag; - uint8_t unused1; - le_uint16_t player_level; - parray unused2; + /* 52 */ uint8_t god_whim_flag; + /* 53 */ uint8_t unused1; + /* 54 */ le_uint16_t player_level; + /* 56 */ parray unused2; + /* 58 */ DeckEntry(); void clear(); diff --git a/src/Episode3/MapState.hh b/src/Episode3/MapState.hh index 1845f7cc..a4e1bafd 100644 --- a/src/Episode3/MapState.hh +++ b/src/Episode3/MapState.hh @@ -10,10 +10,11 @@ namespace Episode3 { struct MapState { - le_uint16_t width; - le_uint16_t height; - parray, 0x10> tiles; - parray, 2> start_tile_definitions; + /* 0000 */ le_uint16_t width; + /* 0002 */ le_uint16_t height; + /* 0004 */ parray, 0x10> tiles; + /* 0104 */ parray, 2> start_tile_definitions; + /* 0110 */ MapState(); void clear(); @@ -22,18 +23,19 @@ struct MapState { } __attribute__((packed)); struct MapAndRulesState { - MapState map; - uint8_t num_players; - uint8_t unused1; - uint8_t environment_number; - uint8_t num_players_per_team; - uint8_t num_team0_players; - uint8_t unused2; - le_uint16_t start_facing_directions; - uint32_t unused3; - le_uint32_t map_number; - uint32_t unused4; - Rules rules; + /* 0000 */ MapState map; + /* 0110 */ uint8_t num_players; + /* 0111 */ uint8_t unused1; + /* 0112 */ uint8_t environment_number; + /* 0113 */ uint8_t num_players_per_team; + /* 0114 */ uint8_t num_team0_players; + /* 0115 */ uint8_t unused2; + /* 0116 */ le_uint16_t start_facing_directions; + /* 0118 */ uint32_t unused3; + /* 011C */ le_uint32_t map_number; + /* 0120 */ uint32_t unused4; + /* 0124 */ Rules rules; + /* 0138 */ MapAndRulesState(); void clear(); diff --git a/src/Episode3/PlayerStateSubordinates.hh b/src/Episode3/PlayerStateSubordinates.hh index 8d409108..6c752644 100644 --- a/src/Episode3/PlayerStateSubordinates.hh +++ b/src/Episode3/PlayerStateSubordinates.hh @@ -13,19 +13,20 @@ class Server; class Card; struct Condition { - ConditionType type; - uint8_t remaining_turns; - int8_t a_arg_value; - uint8_t dice_roll_value; - uint8_t flags; - uint8_t card_definition_effect_index; - le_uint16_t card_ref; - le_int16_t value; - le_uint16_t condition_giver_card_ref; - uint8_t random_percent; - int8_t value8; - uint8_t order; - uint8_t unknown_a8; + /* 00 */ ConditionType type; + /* 01 */ uint8_t remaining_turns; + /* 02 */ int8_t a_arg_value; + /* 03 */ uint8_t dice_roll_value; + /* 04 */ uint8_t flags; + /* 05 */ uint8_t card_definition_effect_index; + /* 06 */ le_uint16_t card_ref; + /* 08 */ le_int16_t value; + /* 0A */ le_uint16_t condition_giver_card_ref; + /* 0C */ uint8_t random_percent; + /* 0D */ int8_t value8; + /* 0E */ uint8_t order; + /* 0F */ uint8_t unknown_a8; + /* 10 */ Condition(); bool operator==(const Condition& other) const; @@ -38,16 +39,17 @@ struct Condition { } __attribute__((packed)); struct EffectResult { - le_uint16_t attacker_card_ref; - le_uint16_t target_card_ref; - int8_t value; - int8_t current_hp; - int8_t ap; - int8_t tp; - uint8_t flags; - int8_t operation; // May be a negative condition number - uint8_t condition_index; - uint8_t dice_roll_value; + /* 00 */ le_uint16_t attacker_card_ref; + /* 02 */ le_uint16_t target_card_ref; + /* 04 */ int8_t value; + /* 05 */ int8_t current_hp; + /* 06 */ int8_t ap; + /* 07 */ int8_t tp; + /* 08 */ uint8_t flags; + /* 09 */ int8_t operation; // May be a negative condition number + /* 0A */ uint8_t condition_index; + /* 0B */ uint8_t dice_roll_value; + /* 0C */ EffectResult(); bool operator==(const EffectResult& other) const; @@ -59,13 +61,14 @@ struct EffectResult { } __attribute__((packed)); struct CardShortStatus { - le_uint16_t card_ref; - le_uint16_t current_hp; - le_uint32_t card_flags; - Location loc; - le_uint16_t unused1; - int8_t max_hp; - uint8_t unused2; + /* 00 */ le_uint16_t card_ref; + /* 02 */ le_uint16_t current_hp; + /* 04 */ le_uint32_t card_flags; + /* 08 */ Location loc; + /* 0C */ le_uint16_t unused1; + /* 0E */ int8_t max_hp; + /* 0F */ uint8_t unused2; + /* 10 */ CardShortStatus(); bool operator==(const CardShortStatus& other) const; @@ -78,14 +81,15 @@ struct CardShortStatus { } __attribute__((packed)); struct ActionState { - le_uint16_t client_id; - uint8_t unused; - Direction facing_direction; - le_uint16_t attacker_card_ref; - le_uint16_t defense_card_ref; - parray target_card_refs; - parray action_card_refs; - le_uint16_t original_attacker_card_ref; + /* 00 */ le_uint16_t client_id; + /* 02 */ uint8_t unused; + /* 03 */ Direction facing_direction; + /* 04 */ le_uint16_t attacker_card_ref; + /* 06 */ le_uint16_t defense_card_ref; + /* 08 */ parray target_card_refs; + /* 50 */ parray action_card_refs; + /* 62 */ le_uint16_t original_attacker_card_ref; + /* 64 */ ActionState(); bool operator==(const ActionState& other) const; @@ -97,27 +101,28 @@ struct ActionState { } __attribute__((packed)); struct ActionChain { - int8_t effective_ap; - int8_t effective_tp; - int8_t ap_effect_bonus; - int8_t damage; - le_uint16_t acting_card_ref; - le_uint16_t unknown_card_ref_a3; - parray attack_action_card_refs; - uint8_t attack_action_card_ref_count; - AttackMedium attack_medium; - uint8_t target_card_ref_count; - ActionSubphase action_subphase; - uint8_t strike_count; - int8_t damage_multiplier; - uint8_t attack_number; - int8_t tp_effect_bonus; - uint8_t unused1; - uint8_t unused2; - int8_t card_ap; - int8_t card_tp; - le_uint32_t flags; - parray target_card_refs; + /* 00 */ int8_t effective_ap; + /* 01 */ int8_t effective_tp; + /* 02 */ int8_t ap_effect_bonus; + /* 03 */ int8_t damage; + /* 04 */ le_uint16_t acting_card_ref; + /* 06 */ le_uint16_t unknown_card_ref_a3; + /* 08 */ parray attack_action_card_refs; + /* 18 */ uint8_t attack_action_card_ref_count; + /* 19 */ AttackMedium attack_medium; + /* 1A */ uint8_t target_card_ref_count; + /* 1B */ ActionSubphase action_subphase; + /* 1C */ uint8_t strike_count; + /* 1D */ int8_t damage_multiplier; + /* 1E */ uint8_t attack_number; + /* 1F */ int8_t tp_effect_bonus; + /* 20 */ uint8_t unused1; + /* 21 */ uint8_t unused2; + /* 22 */ int8_t card_ap; + /* 23 */ int8_t card_tp; + /* 24 */ le_uint32_t flags; + /* 28 */ parray target_card_refs; + /* 70 */ ActionChain(); bool operator==(const ActionChain& other) const; @@ -130,8 +135,9 @@ struct ActionChain { } __attribute__((packed)); struct ActionChainWithConds { - ActionChain chain; - parray conditions; + /* 0000 */ ActionChain chain; + /* 0070 */ parray conditions; + /* 0100 */ ActionChainWithConds(); bool operator==(const ActionChainWithConds& other) const; @@ -165,17 +171,18 @@ struct ActionChainWithConds { } __attribute__((packed)); struct ActionMetadata { - le_uint16_t card_ref; - uint8_t target_card_ref_count; - uint8_t defense_card_ref_count; - ActionSubphase action_subphase; - int8_t defense_power; - int8_t defense_bonus; - int8_t attack_bonus; - le_uint32_t flags; - parray target_card_refs; - parray defense_card_refs; - parray original_attacker_card_refs; + /* 00 */ le_uint16_t card_ref; + /* 02 */ uint8_t target_card_ref_count; + /* 03 */ uint8_t defense_card_ref_count; + /* 04 */ ActionSubphase action_subphase; + /* 05 */ int8_t defense_power; + /* 06 */ int8_t defense_bonus; + /* 07 */ int8_t attack_bonus; + /* 08 */ le_uint32_t flags; + /* 0C */ parray target_card_refs; + /* 54 */ parray defense_card_refs; + /* 64 */ parray original_attacker_card_refs; + /* 74 */ ActionMetadata(); bool operator==(const ActionMetadata& other) const; @@ -200,28 +207,29 @@ struct ActionMetadata { } __attribute__((packed)); struct HandAndEquipState { - parray dice_results; - uint8_t atk_points; - uint8_t def_points; - uint8_t atk_points2; // TODO: rename this to something more appropriate - uint8_t unknown_a1; - uint8_t total_set_cards_cost; - uint8_t is_cpu_player; - le_uint32_t assist_flags; - parray hand_card_refs; - le_uint16_t assist_card_ref; - parray set_card_refs; - le_uint16_t sc_card_ref; - parray hand_card_refs2; - parray set_card_refs2; - le_uint16_t assist_card_ref2; - le_uint16_t assist_card_set_number; - le_uint16_t assist_card_id; - uint8_t assist_remaining_turns; - uint8_t assist_delay_turns; - uint8_t atk_bonuses; - uint8_t def_bonuses; - parray unused2; + /* 00 */ parray dice_results; + /* 02 */ uint8_t atk_points; + /* 03 */ uint8_t def_points; + /* 04 */ uint8_t atk_points2; // TODO: rename this to something more appropriate + /* 05 */ uint8_t unknown_a1; + /* 06 */ uint8_t total_set_cards_cost; + /* 07 */ uint8_t is_cpu_player; + /* 08 */ le_uint32_t assist_flags; + /* 0C */ parray hand_card_refs; + /* 18 */ le_uint16_t assist_card_ref; + /* 1A */ parray set_card_refs; + /* 2A */ le_uint16_t sc_card_ref; + /* 2C */ parray hand_card_refs2; + /* 38 */ parray set_card_refs2; + /* 48 */ le_uint16_t assist_card_ref2; + /* 4A */ le_uint16_t assist_card_set_number; + /* 4C */ le_uint16_t assist_card_id; + /* 4E */ uint8_t assist_remaining_turns; + /* 4F */ uint8_t assist_delay_turns; + /* 50 */ uint8_t atk_bonuses; + /* 51 */ uint8_t def_bonuses; + /* 52 */ parray unused2; + /* 54 */ HandAndEquipState(); bool operator==(const HandAndEquipState& other) const; @@ -234,26 +242,27 @@ struct HandAndEquipState { } __attribute__((packed)); struct PlayerBattleStats { - le_uint16_t damage_given; - le_uint16_t damage_taken; - le_uint16_t num_opponent_cards_destroyed; - le_uint16_t num_owned_cards_destroyed; - le_uint16_t total_move_distance; - le_uint16_t num_cards_set; - le_uint16_t num_item_or_creature_cards_set; - le_uint16_t num_attack_actions_set; - le_uint16_t num_tech_cards_set; - le_uint16_t num_assist_cards_set; - le_uint16_t defense_actions_set_on_self; - le_uint16_t defense_actions_set_on_ally; - le_uint16_t num_cards_drawn; - le_uint16_t max_attack_damage; - le_uint16_t max_attack_combo_size; - le_uint16_t num_attacks_given; - le_uint16_t num_attacks_taken; - le_uint16_t sc_damage_taken; - le_uint16_t action_card_negated_damage; - le_uint16_t unused; + /* 00 */ le_uint16_t damage_given; + /* 02 */ le_uint16_t damage_taken; + /* 04 */ le_uint16_t num_opponent_cards_destroyed; + /* 06 */ le_uint16_t num_owned_cards_destroyed; + /* 08 */ le_uint16_t total_move_distance; + /* 0A */ le_uint16_t num_cards_set; + /* 0C */ le_uint16_t num_item_or_creature_cards_set; + /* 0E */ le_uint16_t num_attack_actions_set; + /* 10 */ le_uint16_t num_tech_cards_set; + /* 12 */ le_uint16_t num_assist_cards_set; + /* 14 */ le_uint16_t defense_actions_set_on_self; + /* 16 */ le_uint16_t defense_actions_set_on_ally; + /* 18 */ le_uint16_t num_cards_drawn; + /* 1A */ le_uint16_t max_attack_damage; + /* 1C */ le_uint16_t max_attack_combo_size; + /* 1E */ le_uint16_t num_attacks_given; + /* 20 */ le_uint16_t num_attacks_taken; + /* 22 */ le_uint16_t sc_damage_taken; + /* 24 */ le_uint16_t action_card_negated_damage; + /* 26 */ le_uint16_t unused; + /* 28 */ PlayerBattleStats(); void clear();