Ep3 NTE battles checkpoint 2
This commit is contained in:
+52
-46
@@ -6230,16 +6230,16 @@ struct G_UpdateActionChainAndMetadata_Ep3_6xB4x0A {
|
||||
|
||||
// 6xB3x0B / CAx0B: Redraw initial hand (immediately before battle)
|
||||
|
||||
struct G_RedrawInitialHand_Ep3_6xB3x0B_CAx0B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_RedrawInitialHand_Ep3_6xB3x0B_CAx0B) / 4, 0, 0x0B, 0, 0, 0, 0, 0};
|
||||
struct G_RedrawInitialHand_Ep3_CAx0B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_RedrawInitialHand_Ep3_CAx0B) / 4, 0, 0x0B, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
parray<uint8_t, 2> unused2;
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x0C / CAx0C: End initial redraw phase
|
||||
|
||||
struct G_EndInitialRedrawPhase_Ep3_6xB3x0C_CAx0C {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndInitialRedrawPhase_Ep3_6xB3x0C_CAx0C) / 4, 0, 0x0C, 0, 0, 0, 0, 0};
|
||||
struct G_EndInitialRedrawPhase_Ep3_CAx0C {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndInitialRedrawPhase_Ep3_CAx0C) / 4, 0, 0x0C, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
parray<uint8_t, 2> unused2;
|
||||
} __packed__;
|
||||
@@ -6249,24 +6249,24 @@ struct G_EndInitialRedrawPhase_Ep3_6xB3x0C_CAx0C {
|
||||
// current phase. This command isn't used for ending the attack or defense
|
||||
// phases; for those phases, CAx12 and CAx28 are used instead.
|
||||
|
||||
struct G_EndNonAttackPhase_Ep3_6xB3x0D_CAx0D {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndNonAttackPhase_Ep3_6xB3x0D_CAx0D) / 4, 0, 0x0D, 0, 0, 0, 0, 0};
|
||||
struct G_EndNonAttackPhase_Ep3_CAx0D {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndNonAttackPhase_Ep3_CAx0D) / 4, 0, 0x0D, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
parray<le_uint16_t, 5> unused2;
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x0E / CAx0E: Discard card from hand
|
||||
|
||||
struct G_DiscardCardFromHand_Ep3_6xB3x0E_CAx0E {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_DiscardCardFromHand_Ep3_6xB3x0E_CAx0E) / 4, 0, 0x0E, 0, 0, 0, 0, 0};
|
||||
struct G_DiscardCardFromHand_Ep3_CAx0E {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_DiscardCardFromHand_Ep3_CAx0E) / 4, 0, 0x0E, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
le_uint16_t card_ref = 0xFFFF;
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x0F / CAx0F: Set card from hand
|
||||
|
||||
struct G_SetCardFromHand_Ep3_6xB3x0F_CAx0F {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetCardFromHand_Ep3_6xB3x0F_CAx0F) / 4, 0, 0x0F, 0, 0, 0, 0, 0};
|
||||
struct G_SetCardFromHand_Ep3_CAx0F {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetCardFromHand_Ep3_CAx0F) / 4, 0, 0x0F, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
le_uint16_t card_ref = 0xFFFF;
|
||||
le_uint16_t set_index = 0;
|
||||
@@ -6276,8 +6276,8 @@ struct G_SetCardFromHand_Ep3_6xB3x0F_CAx0F {
|
||||
|
||||
// 6xB3x10 / CAx10: Move field character
|
||||
|
||||
struct G_MoveFieldCharacter_Ep3_6xB3x10_CAx10 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MoveFieldCharacter_Ep3_6xB3x10_CAx10) / 4, 0, 0x10, 0, 0, 0, 0, 0};
|
||||
struct G_MoveFieldCharacter_Ep3_CAx10 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MoveFieldCharacter_Ep3_CAx10) / 4, 0, 0x10, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
le_uint16_t set_index = 0;
|
||||
Episode3::Location loc;
|
||||
@@ -6289,8 +6289,8 @@ struct G_MoveFieldCharacter_Ep3_6xB3x10_CAx10 {
|
||||
// sent once for each attack (even if it includes multiple cards); in the
|
||||
// defense case, this command is sent once for each defense card.
|
||||
|
||||
struct G_EnqueueAttackOrDefense_Ep3_6xB3x11_CAx11 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EnqueueAttackOrDefense_Ep3_6xB3x11_CAx11) / 4, 0, 0x11, 0, 0, 0, 0, 0};
|
||||
struct G_EnqueueAttackOrDefense_Ep3_CAx11 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EnqueueAttackOrDefense_Ep3_CAx11) / 4, 0, 0x11, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
parray<uint8_t, 2> unused2;
|
||||
Episode3::ActionState entry;
|
||||
@@ -6300,24 +6300,30 @@ struct G_EnqueueAttackOrDefense_Ep3_6xB3x11_CAx11 {
|
||||
// This command informs the server that the client is done playing attacks in
|
||||
// the current round. (In the defense phase, CAx28 is used instead.)
|
||||
|
||||
struct G_EndAttackList_Ep3_6xB3x12_CAx12 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndAttackList_Ep3_6xB3x12_CAx12) / 4, 0, 0x12, 0, 0, 0, 0, 0};
|
||||
struct G_EndAttackList_Ep3_CAx12 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndAttackList_Ep3_CAx12) / 4, 0, 0x12, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
parray<uint8_t, 2> unused2;
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x13 / CAx13: Set map state during setup
|
||||
|
||||
struct G_SetMapState_Ep3_6xB3x13_CAx13 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetMapState_Ep3_6xB3x13_CAx13) / 4, 0, 0x13, 0, 0, 0, 0, 0};
|
||||
struct G_SetMapState_Ep3NTE_CAx13 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetMapState_Ep3NTE_CAx13) / 4, 0, 0x13, 0, 0, 0, 0, 0};
|
||||
Episode3::MapAndRulesStateTrial map_and_rules_state;
|
||||
Episode3::OverlayState overlay_state;
|
||||
} __packed__;
|
||||
|
||||
struct G_SetMapState_Ep3_CAx13 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetMapState_Ep3_CAx13) / 4, 0, 0x13, 0, 0, 0, 0, 0};
|
||||
Episode3::MapAndRulesState map_and_rules_state;
|
||||
Episode3::OverlayState overlay_state;
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x14 / CAx14: Set player deck during setup
|
||||
|
||||
struct G_SetPlayerDeck_Ep3_6xB3x14_CAx14 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetPlayerDeck_Ep3_6xB3x14_CAx14) / 4, 0, 0x14, 0, 0, 0, 0, 0};
|
||||
struct G_SetPlayerDeck_Ep3_CAx14 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetPlayerDeck_Ep3_CAx14) / 4, 0, 0x14, 0, 0, 0, 0, 0};
|
||||
le_uint16_t client_id = 0;
|
||||
uint8_t is_cpu_player = 0;
|
||||
uint8_t unused2 = 0;
|
||||
@@ -6327,8 +6333,8 @@ struct G_SetPlayerDeck_Ep3_6xB3x14_CAx14 {
|
||||
// 6xB3x15 / CAx15: Hard-reset server state
|
||||
// This command appears to be completely unused; the client never sends it.
|
||||
|
||||
struct G_HardResetServerState_Ep3_6xB3x15_CAx15 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_HardResetServerState_Ep3_6xB3x15_CAx15) / 4, 0, 0x15, 0, 0, 0, 0, 0};
|
||||
struct G_HardResetServerState_Ep3_CAx15 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_HardResetServerState_Ep3_CAx15) / 4, 0, 0x15, 0, 0, 0, 0, 0};
|
||||
// No arguments
|
||||
} __packed__;
|
||||
|
||||
@@ -6356,8 +6362,8 @@ struct G_ForceDisconnect_Ep3_6xB5x1A {
|
||||
// Curiously, this command can be used during a non-setup phase; the server
|
||||
// should ignore the command's contents but still send a 6xB4x1C in response.
|
||||
|
||||
struct G_SetPlayerName_Ep3_6xB3x1B_CAx1B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetPlayerName_Ep3_6xB3x1B_CAx1B) / 4, 0, 0x1B, 0, 0, 0, 0, 0};
|
||||
struct G_SetPlayerName_Ep3_CAx1B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_SetPlayerName_Ep3_CAx1B) / 4, 0, 0x1B, 0, 0, 0, 0, 0};
|
||||
Episode3::NameEntry entry;
|
||||
} __packed__;
|
||||
|
||||
@@ -6373,8 +6379,8 @@ struct G_SetPlayerNames_Ep3_6xB4x1C {
|
||||
// response to this command) that includes RegistrationPhase::BATTLE_STARTED and
|
||||
// a SetupPhase value other than REGISTRATION.
|
||||
|
||||
struct G_StartBattle_Ep3_6xB3x1D_CAx1D {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_StartBattle_Ep3_6xB3x1D_CAx1D) / 4, 0, 0x1D, 0, 0, 0, 0, 0};
|
||||
struct G_StartBattle_Ep3_CAx1D {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_StartBattle_Ep3_CAx1D) / 4, 0, 0x1D, 0, 0, 0, 0, 0};
|
||||
} __packed__;
|
||||
|
||||
// 6xB4x1E: Action result
|
||||
@@ -6412,8 +6418,8 @@ struct G_Unknown_Ep3_6xB5x20 {
|
||||
|
||||
// 6xB3x21 / CAx21: End battle
|
||||
|
||||
struct G_EndBattle_Ep3_6xB3x21_CAx21 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndBattle_Ep3_6xB3x21_CAx21) / 4, 0, 0x21, 0, 0, 0, 0, 0};
|
||||
struct G_EndBattle_Ep3_CAx21 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndBattle_Ep3_CAx21) / 4, 0, 0x21, 0, 0, 0, 0, 0};
|
||||
le_uint32_t unused2 = 0;
|
||||
} __packed__;
|
||||
|
||||
@@ -6455,8 +6461,8 @@ struct G_Unknown_Ep3_6xB5x27 {
|
||||
// This command informs the server that the client is done playing defense
|
||||
// cards. (In the attack phase, CAx12 is used instead.)
|
||||
|
||||
struct G_EndDefenseList_Ep3_6xB3x28_CAx28 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndDefenseList_Ep3_6xB3x28_CAx28) / 4, 0, 0x28, 0, 0, 0, 0, 0};
|
||||
struct G_EndDefenseList_Ep3_CAx28 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndDefenseList_Ep3_CAx28) / 4, 0, 0x28, 0, 0, 0, 0, 0};
|
||||
uint8_t unused1 = 0;
|
||||
uint8_t client_id = 0;
|
||||
parray<uint8_t, 2> unused2;
|
||||
@@ -6488,8 +6494,8 @@ struct G_Unknown_Ep3_6xB4x2A {
|
||||
// It seems Sega's servers completely ignored this command. The command name is
|
||||
// based on a debug message found nearby.
|
||||
|
||||
struct G_ExecLegacyCard_Ep3_6xB3x2B_CAx2B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_ExecLegacyCard_Ep3_6xB3x2B_CAx2B) / 4, 0, 0x2B, 0, 0, 0, 0, 0};
|
||||
struct G_ExecLegacyCard_Ep3_CAx2B {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_ExecLegacyCard_Ep3_CAx2B) / 4, 0, 0x2B, 0, 0, 0, 0, 0};
|
||||
le_uint16_t unused2 = 0;
|
||||
parray<uint8_t, 2> unused3;
|
||||
} __packed__;
|
||||
@@ -6592,8 +6598,8 @@ struct G_SubtractAllyATKPoints_Ep3_6xB4x33 {
|
||||
|
||||
// 6xB3x34 / CAx34: Photon blast request
|
||||
|
||||
struct G_PhotonBlastRequest_Ep3_6xB3x34_CAx34 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_PhotonBlastRequest_Ep3_6xB3x34_CAx34) / 4, 0, 0x34, 0, 0, 0, 0, 0};
|
||||
struct G_PhotonBlastRequest_Ep3_CAx34 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_PhotonBlastRequest_Ep3_CAx34) / 4, 0, 0x34, 0, 0, 0, 0, 0};
|
||||
uint8_t ally_client_id = 0;
|
||||
uint8_t reason = 0;
|
||||
le_uint16_t card_ref = 0xFFFF;
|
||||
@@ -6624,8 +6630,8 @@ struct G_RecreatePlayer_Ep3_6xB5x36 {
|
||||
|
||||
// 6xB3x37 / CAx37: Ready to advance from starting rolls phase
|
||||
|
||||
struct G_AdvanceFromStartingRollsPhase_Ep3_6xB3x37_CAx37 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_AdvanceFromStartingRollsPhase_Ep3_6xB3x37_CAx37) / 4, 0, 0x37, 0, 0, 0, 0, 0};
|
||||
struct G_AdvanceFromStartingRollsPhase_Ep3_CAx37 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_AdvanceFromStartingRollsPhase_Ep3_CAx37) / 4, 0, 0x37, 0, 0, 0, 0, 0};
|
||||
uint8_t client_id = 0;
|
||||
parray<uint8_t, 3> unused2;
|
||||
} __packed__;
|
||||
@@ -6661,8 +6667,8 @@ struct G_UpdateAllPlayerStatistics_Ep3_6xB4x39 {
|
||||
// It seems Sega's servers completely ignored this command and used server-side
|
||||
// timing instead. newserv does the same.
|
||||
|
||||
struct G_OverallTimeLimitExpired_Ep3_6xB3x3A_CAx3A {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_OverallTimeLimitExpired_Ep3_6xB3x3A_CAx3A) / 4, 0, 0x3A, 0, 0, 0, 0, 0};
|
||||
struct G_OverallTimeLimitExpired_Ep3_CAx3A {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_OverallTimeLimitExpired_Ep3_CAx3A) / 4, 0, 0x3A, 0, 0, 0, 0, 0};
|
||||
} __packed__;
|
||||
|
||||
// 6xB4x3B: Load current environment
|
||||
@@ -6748,16 +6754,16 @@ struct G_OpenBlockingMenu_Ep3_6xB5x3F {
|
||||
// 6xB3x40 / CAx40: Request map list
|
||||
// The server should respond with a 6xB6x40 command.
|
||||
|
||||
struct G_MapListRequest_Ep3_6xB3x40_CAx40 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MapListRequest_Ep3_6xB3x40_CAx40) / 4, 0, 0x40, 0, 0, 0, 0, 0};
|
||||
struct G_MapListRequest_Ep3_CAx40 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MapListRequest_Ep3_CAx40) / 4, 0, 0x40, 0, 0, 0, 0, 0};
|
||||
} __packed__;
|
||||
|
||||
// 6xB3x41 / CAx41: Request map data
|
||||
// The server should respond with a 6xB6x41 command containing the definition of
|
||||
// the specified map.
|
||||
|
||||
struct G_MapDataRequest_Ep3_6xB3x41_CAx41 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MapDataRequest_Ep3_6xB3x41_CAx41) / 4, 0, 0x41, 0, 0, 0, 0, 0};
|
||||
struct G_MapDataRequest_Ep3_CAx41 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_MapDataRequest_Ep3_CAx41) / 4, 0, 0x41, 0, 0, 0, 0, 0};
|
||||
le_uint32_t map_number = 0;
|
||||
} __packed__;
|
||||
|
||||
@@ -6865,8 +6871,8 @@ struct G_SetSpectatorCARDLevel_Ep3_6xB5x47 {
|
||||
|
||||
// 6xB3x48 / CAx48: End turn
|
||||
|
||||
struct G_EndTurn_Ep3_6xB3x48_CAx48 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndTurn_Ep3_6xB3x48_CAx48) / 4, 0, 0x48, 0, 0, 0, 0, 0};
|
||||
struct G_EndTurn_Ep3_CAx48 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_EndTurn_Ep3_CAx48) / 4, 0, 0x48, 0, 0, 0, 0, 0};
|
||||
uint8_t client_id = 0;
|
||||
parray<uint8_t, 3> unused2;
|
||||
} __packed__;
|
||||
@@ -6883,8 +6889,8 @@ struct G_EndTurn_Ep3_6xB3x48_CAx48 {
|
||||
// that callsite to implement one of the deck validity checks.
|
||||
// Episode 3 Trial Edition does not send this command.
|
||||
|
||||
struct G_CardCounts_Ep3_6xB3x49_CAx49 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_CardCounts_Ep3_6xB3x49_CAx49) / 4, 0, 0x49, 0, 0, 0, 0, 0};
|
||||
struct G_CardCounts_Ep3_CAx49 {
|
||||
G_CardServerDataCommandHeader header = {0xB3, sizeof(G_CardCounts_Ep3_CAx49) / 4, 0, 0x49, 0, 0, 0, 0, 0};
|
||||
uint8_t basis = 0;
|
||||
parray<uint8_t, 3> unused;
|
||||
// This is encrypted with the trivial algorithm (see decrypt_trivial_gci_data)
|
||||
|
||||
+122
-86
@@ -122,14 +122,16 @@ ssize_t Card::apply_abnormal_condition(
|
||||
int16_t value,
|
||||
int8_t dice_roll_value,
|
||||
int8_t random_percent) {
|
||||
auto log = this->server()->log_stack(string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
ssize_t existing_cond_index;
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
const auto& cond = this->action_chain.conditions[z];
|
||||
if (cond.type == eff.type) {
|
||||
existing_cond_index = z;
|
||||
if (eff.type == ConditionType::MV_BONUS ||
|
||||
if ((!is_trial && eff.type == ConditionType::MV_BONUS) ||
|
||||
((cond.card_definition_effect_index == def_effect_index) &&
|
||||
(cond.card_ref == target_card_ref))) {
|
||||
break;
|
||||
@@ -165,7 +167,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
log.debug("MV_BONUS combines => existing_cond_value = %hd", existing_cond_value);
|
||||
}
|
||||
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
s->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
cond.type = eff.type;
|
||||
cond.card_ref = target_card_ref;
|
||||
cond.condition_giver_card_ref = sc_card_ref;
|
||||
@@ -205,14 +207,15 @@ ssize_t Card::apply_abnormal_condition(
|
||||
string cond_str = cond.str();
|
||||
log.debug("wrote condition %zd => %s", cond_index, cond_str.c_str());
|
||||
|
||||
this->server()->card_special->update_condition_orders(this->shared_from_this());
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
|
||||
continue;
|
||||
if (!is_trial) {
|
||||
s->card_special->update_condition_orders(this->shared_from_this());
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
|
||||
continue;
|
||||
}
|
||||
string cond_str = cond.str();
|
||||
log.debug("sorted conditions: [%zu] => %s", z, cond_str.c_str());
|
||||
}
|
||||
string cond_str = cond.str();
|
||||
log.debug("sorted conditions: [%zu] => %s", z, cond_str.c_str());
|
||||
}
|
||||
|
||||
return cond_index;
|
||||
@@ -368,25 +371,27 @@ int16_t Card::compute_defense_power_for_attacker_card(
|
||||
}
|
||||
|
||||
void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
auto s = this->server();
|
||||
auto ps = this->player_state();
|
||||
|
||||
this->current_hp = 0;
|
||||
if (!(this->card_flags & 2)) {
|
||||
if (!this->server()->ruler_server->card_ref_or_any_set_card_has_condition_46(this->card_ref)) {
|
||||
this->server()->card_special->on_card_destroyed(
|
||||
if (!s->ruler_server->card_ref_or_any_set_card_has_condition_46(this->card_ref)) {
|
||||
s->card_special->on_card_destroyed(
|
||||
attacker_card, this->shared_from_this());
|
||||
|
||||
this->card_flags = this->card_flags | 2;
|
||||
this->update_stats_on_destruction();
|
||||
this->player_state()->stats.num_owned_cards_destroyed++;
|
||||
ps->stats.num_owned_cards_destroyed++;
|
||||
|
||||
if (attacker_card && (attacker_card->team_id != this->team_id)) {
|
||||
attacker_card->player_state()->stats.num_opponent_cards_destroyed++;
|
||||
this->server()->add_team_exp(this->team_id ^ 1, 3);
|
||||
s->add_team_exp(this->team_id ^ 1, 3);
|
||||
}
|
||||
|
||||
if ((this->sc_card_type == CardType::HUNTERS_SC) && (this->def_entry->def.type == CardType::ITEM)) {
|
||||
auto sc_card = this->player_state()->get_sc_card();
|
||||
if (!(sc_card->card_flags & 2) &&
|
||||
!sc_card->get_attack_condition_value(ConditionType::ELUDE, 0xFFFF, 0xFF, 0xFFFF, nullptr)) {
|
||||
auto sc_card = ps->get_sc_card();
|
||||
if (!(sc_card->card_flags & 2) && !sc_card->get_condition_value(ConditionType::ELUDE)) {
|
||||
int16_t hp = sc_card->get_current_hp();
|
||||
sc_card->set_current_hp(hp - 1);
|
||||
sc_card->player_state()->stats.sc_damage_taken++;
|
||||
@@ -396,7 +401,7 @@ void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
cmd.effect.attacker_card_ref = attacker_card->card_ref;
|
||||
cmd.effect.target_card_ref = sc_card->card_ref;
|
||||
cmd.effect.value = 1;
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
}
|
||||
if (sc_card->get_current_hp() < 1) {
|
||||
sc_card->destroy_set_card(attacker_card);
|
||||
@@ -404,10 +409,10 @@ void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->server()->map_and_rules->rules.hp_type == HPType::DEFEAT_TEAM) &&
|
||||
(this->player_state()->get_sc_card().get() == this)) {
|
||||
if ((s->map_and_rules->rules.hp_type == HPType::DEFEAT_TEAM) &&
|
||||
(ps->get_sc_card().get() == this)) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->player_state()->get_set_card(set_index);
|
||||
auto card = ps->get_set_card(set_index);
|
||||
if (card) {
|
||||
card->card_flags |= 2;
|
||||
}
|
||||
@@ -415,27 +420,27 @@ void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
if (!this->server()->player_states[client_id]) {
|
||||
if (!s->player_states[client_id]) {
|
||||
continue;
|
||||
}
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(client_id);
|
||||
size_t num_assists = s->assist_server->compute_num_assist_effects_for_client(client_id);
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
auto eff = this->server()->assist_server->get_active_assist_by_index(z);
|
||||
auto eff = s->assist_server->get_active_assist_by_index(z);
|
||||
if (eff == AssistEffect::HOMESICK) {
|
||||
if (client_id == this->client_id) {
|
||||
this->player_state()->return_set_card_to_hand2(this->card_ref);
|
||||
ps->return_set_card_to_hand2(this->card_ref);
|
||||
}
|
||||
} else if (eff == AssistEffect::INHERITANCE) {
|
||||
uint8_t other_team_id = this->server()->player_states[client_id]->get_team_id();
|
||||
uint8_t this_team_id = this->player_state()->get_team_id();
|
||||
uint8_t other_team_id = s->player_states[client_id]->get_team_id();
|
||||
uint8_t this_team_id = ps->get_team_id();
|
||||
if (this_team_id == other_team_id) {
|
||||
this->server()->add_team_exp(team_id, this->max_hp);
|
||||
s->add_team_exp(team_id, this->max_hp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else if (this->w_destroyer_sc_card.expired() && attacker_card) {
|
||||
} else if (!this->w_destroyer_sc_card.lock() && attacker_card) {
|
||||
this->w_destroyer_sc_card = attacker_card->player_state()->get_sc_card();
|
||||
}
|
||||
}
|
||||
@@ -560,14 +565,27 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
}
|
||||
|
||||
bool Card::get_attack_condition_value(
|
||||
bool Card::get_condition_value(
|
||||
ConditionType cond_type,
|
||||
uint16_t card_ref,
|
||||
uint8_t def_effect_index,
|
||||
uint16_t value,
|
||||
uint16_t* out_value) const {
|
||||
return this->action_chain.get_condition_value(
|
||||
cond_type, card_ref, def_effect_index, value, out_value);
|
||||
return this->action_chain.get_condition_value(cond_type, card_ref, def_effect_index, value, out_value);
|
||||
}
|
||||
|
||||
Condition* Card::find_condition(ConditionType cond_type) {
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
auto& cond = this->action_chain.conditions[z];
|
||||
if (cond.type == cond_type) {
|
||||
return &cond;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const Condition* Card::find_condition(ConditionType cond_type) const {
|
||||
return const_cast<Card*>(this)->find_condition(cond_type);
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Card::get_definition() const {
|
||||
@@ -808,10 +826,12 @@ void Card::clear_action_chain_and_metadata_and_most_flags() {
|
||||
this->action_metadata.card_ref = this->card_ref;
|
||||
}
|
||||
|
||||
void Card::compute_action_chain_results(
|
||||
bool apply_action_conditions, bool ignore_this_card_ap_tp) {
|
||||
auto log = this->server()->log_stack(string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
this->action_chain.compute_attack_medium(this->server());
|
||||
void Card::compute_action_chain_results(bool apply_action_conditions, bool ignore_this_card_ap_tp) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
this->action_chain.compute_attack_medium(s);
|
||||
this->action_chain.chain.strike_count = 1;
|
||||
this->action_chain.chain.ap_effect_bonus = 0;
|
||||
this->action_chain.chain.tp_effect_bonus = 0;
|
||||
@@ -824,16 +844,19 @@ void Card::compute_action_chain_results(
|
||||
|
||||
int16_t card_ap;
|
||||
int16_t card_tp;
|
||||
auto stat_swap_type = this->server()->card_special->compute_stat_swap_type(this->shared_from_this());
|
||||
auto stat_swap_type = is_trial ? StatSwapType::NONE : s->card_special->compute_stat_swap_type(this->shared_from_this());
|
||||
log.debug("stat_swap_type = %zu (0=none, 1=a/t, 2=a/h)", static_cast<size_t>(stat_swap_type));
|
||||
this->server()->card_special->get_effective_ap_tp(
|
||||
stat_swap_type, &card_ap, &card_tp, this->get_current_hp(), this->ap, this->tp);
|
||||
s->card_special->get_effective_ap_tp(stat_swap_type, &card_ap, &card_tp, this->get_current_hp(), this->ap, this->tp);
|
||||
log.debug("card_ap = %hd, card_tp = %hd", card_ap, card_tp);
|
||||
|
||||
int16_t effective_ap = card_ap;
|
||||
int16_t effective_tp = card_tp;
|
||||
int16_t effective_ap = this->ap;
|
||||
int16_t effective_tp = this->tp;
|
||||
|
||||
// This option doesn't exist in NTE
|
||||
ignore_this_card_ap_tp &= !is_trial;
|
||||
|
||||
for (size_t z = 0; (!ignore_this_card_ap_tp && (z < 8) && (z < this->action_chain.chain.attack_action_card_ref_count)); z++) {
|
||||
auto ce = this->server()->definition_for_card_ref(this->action_chain.chain.attack_action_card_refs[z]);
|
||||
auto ce = s->definition_for_card_ref(this->action_chain.chain.attack_action_card_refs[z]);
|
||||
if (ce) {
|
||||
effective_ap += ce->def.ap.stat;
|
||||
effective_tp += ce->def.tp.stat;
|
||||
@@ -842,11 +865,12 @@ void Card::compute_action_chain_results(
|
||||
}
|
||||
|
||||
// Add AP/TP from MAG items to SC's AP/TP
|
||||
auto ps = this->player_state();
|
||||
if (this->def_entry->def.is_sc()) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->player_state()->get_set_card(set_index);
|
||||
auto card = ps->get_set_card(set_index);
|
||||
if ((card && (card->def_entry->def.card_class() == CardClass::MAG_ITEM)) && !(card->card_flags & 2)) {
|
||||
this->server()->card_special->get_effective_ap_tp(
|
||||
s->card_special->get_effective_ap_tp(
|
||||
stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp);
|
||||
effective_ap += card_ap;
|
||||
effective_tp += card_tp;
|
||||
@@ -857,7 +881,7 @@ void Card::compute_action_chain_results(
|
||||
}
|
||||
|
||||
if ((this->def_entry->def.type == CardType::ITEM) && this->sc_def_entry) {
|
||||
auto sc_card = this->player_state()->get_sc_card();
|
||||
auto sc_card = ps->get_sc_card();
|
||||
sc_card->compute_action_chain_results(apply_action_conditions, true);
|
||||
effective_ap += sc_card->action_chain.chain.effective_ap + sc_card->action_chain.chain.ap_effect_bonus;
|
||||
effective_tp += sc_card->action_chain.chain.effective_tp + sc_card->action_chain.chain.tp_effect_bonus;
|
||||
@@ -866,50 +890,58 @@ void Card::compute_action_chain_results(
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x10)) {
|
||||
this->action_chain.chain.effective_ap = min<int16_t>(effective_ap, 99);
|
||||
this->action_chain.chain.effective_ap = is_trial ? effective_ap : min<int16_t>(effective_ap, 99);
|
||||
log.debug("set chain effective_ap = %hd", this->action_chain.chain.effective_ap);
|
||||
}
|
||||
if (!this->action_chain.check_flag(0x20)) {
|
||||
this->action_chain.chain.effective_tp = min<int16_t>(effective_tp, 99);
|
||||
this->action_chain.chain.effective_tp = is_trial ? effective_tp : min<int16_t>(effective_tp, 99);
|
||||
log.debug("set chain effective_tp = %hd", this->action_chain.chain.effective_tp);
|
||||
}
|
||||
|
||||
if (apply_action_conditions) {
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, this->shared_from_this(), this->shared_from_this(), 1, nullptr);
|
||||
auto this_sh = this->shared_from_this();
|
||||
s->card_special->apply_action_conditions(3, this_sh, this_sh, 1, nullptr);
|
||||
log.debug("applied action conditions (1)");
|
||||
} else {
|
||||
log.debug("skipped applying action conditions (1)");
|
||||
}
|
||||
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
size_t num_assists = s->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
switch (this->server()->assist_server->get_active_assist_by_index(z)) {
|
||||
switch (s->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::POWERLESS_RAIN:
|
||||
if (this->card_type_is_sc_or_creature() &&
|
||||
if (!is_trial &&
|
||||
this->card_type_is_sc_or_creature() &&
|
||||
(this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
|
||||
this->action_chain.chain.ap_effect_bonus -= 2;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::BRAVE_WIND:
|
||||
if (this->card_type_is_sc_or_creature() &&
|
||||
if (!is_trial &&
|
||||
this->card_type_is_sc_or_creature() &&
|
||||
(this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
|
||||
this->action_chain.chain.ap_effect_bonus += 2;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::INFLUENCE:
|
||||
if (this->card_type_is_sc_or_creature()) {
|
||||
int16_t count = this->player_state()->count_set_refs();
|
||||
if (!is_trial &&
|
||||
this->card_type_is_sc_or_creature()) {
|
||||
int16_t count = ps->count_set_refs();
|
||||
this->action_chain.chain.ap_effect_bonus += (count >> 1);
|
||||
}
|
||||
break;
|
||||
case AssistEffect::AP_ABSORPTION:
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::TECH) {
|
||||
if (!is_trial && (this->action_chain.chain.attack_medium == AttackMedium::TECH)) {
|
||||
this->action_chain.chain.tp_effect_bonus += 2;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::FIX:
|
||||
if (is_trial && !this->def_entry->def.is_sc()) {
|
||||
this->action_chain.chain.ap_effect_bonus = 2 - this->action_chain.chain.card_ap;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::TECH_FIELD:
|
||||
if (this->card_type_is_sc_or_creature()) {
|
||||
if (is_trial ? this->def_entry->def.is_sc() : this->card_type_is_sc_or_creature()) {
|
||||
this->action_chain.chain.tp_effect_bonus += 2;
|
||||
}
|
||||
break;
|
||||
@@ -962,7 +994,7 @@ void Card::compute_action_chain_results(
|
||||
if (this->def_entry->def.is_sc()) {
|
||||
size_t num_scs_in_range = 0;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = this->server()->get_player_state(client_id);
|
||||
auto other_ps = s->get_player_state(client_id);
|
||||
if (!other_ps || (client_id == this->client_id) || (other_ps->get_team_id() != this->team_id)) {
|
||||
continue;
|
||||
}
|
||||
@@ -980,8 +1012,8 @@ void Card::compute_action_chain_results(
|
||||
break;
|
||||
case AssistEffect::VENGEANCE:
|
||||
if (!this->def_entry->def.is_sc()) {
|
||||
this->action_chain.chain.ap_effect_bonus +=
|
||||
(this->server()->team_num_ally_fcs_destroyed[this->team_id] / 3);
|
||||
size_t denom = is_trial ? 2 : 3;
|
||||
this->action_chain.chain.ap_effect_bonus += (s->team_num_ally_fcs_destroyed[this->team_id] / denom);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -999,42 +1031,46 @@ void Card::compute_action_chain_results(
|
||||
} else {
|
||||
log.debug("(unknown attack medium) damage = 0");
|
||||
}
|
||||
this->action_chain.chain.damage = min<int16_t>(
|
||||
damage * this->action_chain.chain.damage_multiplier, 99);
|
||||
|
||||
this->action_chain.chain.damage = is_trial
|
||||
? (damage * this->action_chain.chain.damage_multiplier)
|
||||
: min<int16_t>(damage * this->action_chain.chain.damage_multiplier, 99);
|
||||
log.debug("overall chain damage = %hd (base) * %hhd (mult) = %hhd", damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
|
||||
|
||||
if (apply_action_conditions) {
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
0x03, this->shared_from_this(), this->shared_from_this(), 2, nullptr);
|
||||
auto this_sh = this->shared_from_this();
|
||||
s->card_special->apply_action_conditions(0x03, this_sh, this_sh, 2, nullptr);
|
||||
log.debug("applied action conditions (2)");
|
||||
if (this->action_chain.check_flag(0x100)) {
|
||||
if (!is_trial && this->action_chain.check_flag(0x100)) {
|
||||
this->action_chain.chain.damage = min<int16_t>(this->action_chain.chain.damage + 5, 99);
|
||||
log.debug("(has flag 0x100) chain damage = %hhd", this->action_chain.chain.damage);
|
||||
}
|
||||
} else {
|
||||
log.debug("applied action conditions (2)");
|
||||
log.debug("skipped applying action conditions (2)");
|
||||
}
|
||||
|
||||
num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->get_client_id());
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
switch (this->server()->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::AP_ABSORPTION:
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
this->action_chain.chain.damage = 0;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::SILENT_COLOSSEUM:
|
||||
if (this->action_chain.chain.damage >= 7) {
|
||||
this->action_chain.chain.damage = 0;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::FIX:
|
||||
if (!this->def_entry->def.is_sc()) {
|
||||
this->action_chain.chain.damage = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (!is_trial) {
|
||||
num_assists = s->assist_server->compute_num_assist_effects_for_client(this->get_client_id());
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
switch (s->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::AP_ABSORPTION:
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
this->action_chain.chain.damage = 0;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::SILENT_COLOSSEUM:
|
||||
if (this->action_chain.chain.damage >= 7) {
|
||||
this->action_chain.chain.damage = 0;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::FIX:
|
||||
if (!this->def_entry->def.is_sc()) {
|
||||
this->action_chain.chain.damage = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,12 +51,14 @@ public:
|
||||
void destroy_set_card(std::shared_ptr<Card> attacker_card);
|
||||
int32_t error_code_for_move_to_location(const Location& loc) const;
|
||||
void execute_attack(std::shared_ptr<Card> attacker_card);
|
||||
bool get_attack_condition_value(
|
||||
bool get_condition_value(
|
||||
ConditionType cond_type,
|
||||
uint16_t card_ref,
|
||||
uint8_t def_effect_index,
|
||||
uint16_t value,
|
||||
uint16_t* out_value) const;
|
||||
uint16_t card_ref = 0xFFFF,
|
||||
uint8_t def_effect_index = 0xFF,
|
||||
uint16_t value = 0xFFFF,
|
||||
uint16_t* out_value = nullptr) const;
|
||||
Condition* find_condition(ConditionType cond_type);
|
||||
const Condition* find_condition(ConditionType cond_type) const;
|
||||
std::shared_ptr<const CardIndex::CardEntry> get_definition() const;
|
||||
uint16_t get_card_ref() const;
|
||||
uint16_t get_card_id() const;
|
||||
|
||||
+560
-409
File diff suppressed because it is too large
Load Diff
@@ -341,10 +341,15 @@ const char* name_for_direction(Direction d) {
|
||||
}
|
||||
}
|
||||
|
||||
bool card_class_is_tech_like(CardClass cc) {
|
||||
return (cc == CardClass::TECH) ||
|
||||
(cc == CardClass::PHOTON_BLAST) ||
|
||||
(cc == CardClass::BOSS_TECH);
|
||||
bool card_class_is_tech_like(CardClass cc, bool is_trial) {
|
||||
// NTE does not consider BOSS_TECH to be a tech-like card class, but that's
|
||||
// probably because that card class just doesn't exist on NTE. Still, we
|
||||
// handle
|
||||
if (is_trial) {
|
||||
return (cc == CardClass::TECH) || (cc == CardClass::PHOTON_BLAST);
|
||||
} else {
|
||||
return (cc == CardClass::TECH) || (cc == CardClass::PHOTON_BLAST) || (cc == CardClass::BOSS_TECH);
|
||||
}
|
||||
}
|
||||
|
||||
static const unordered_map<string, const char*> description_for_expr_token({
|
||||
@@ -745,8 +750,14 @@ string CardDefinition::Effect::str_for_arg(const string& arg) {
|
||||
} catch (const out_of_range&) {
|
||||
return arg + " (Req. condition: unknown)";
|
||||
}
|
||||
case 'o':
|
||||
return arg + " (Req. prev effect conditions passed)";
|
||||
case 'o': {
|
||||
const char* suffix = ((value / 10) == 1) ? " on opponent card" : " on self";
|
||||
if (value == 0) {
|
||||
return string_printf("%s (Req. any previous effect%s)", arg.c_str(), suffix);
|
||||
} else {
|
||||
return string_printf("%s (Req. effect %zu passed%s)", arg.c_str(), static_cast<size_t>(value % 10), suffix);
|
||||
}
|
||||
}
|
||||
case 'p':
|
||||
try {
|
||||
return string_printf("%s (Target: %s)", arg.c_str(), description_for_p_target.at(value));
|
||||
@@ -1456,7 +1467,7 @@ RulesTrial::RulesTrial(const Rules& r)
|
||||
phase_time_limit(r.phase_time_limit),
|
||||
allowed_cards(r.allowed_cards),
|
||||
atk_dice_max(r.max_dice),
|
||||
def_dice_max(r.max_dice),
|
||||
def_dice_max(r.def_dice_range ? (r.def_dice_range & 0x0F) : r.max_dice),
|
||||
disable_deck_shuffle(r.disable_deck_shuffle),
|
||||
disable_deck_loop(r.disable_deck_loop),
|
||||
char_hp(r.char_hp),
|
||||
|
||||
@@ -164,7 +164,7 @@ enum class CardClass : uint16_t {
|
||||
};
|
||||
|
||||
const char* name_for_card_class(CardClass cc);
|
||||
bool card_class_is_tech_like(CardClass cc);
|
||||
bool card_class_is_tech_like(CardClass cc, bool is_trial);
|
||||
|
||||
enum class TargetMode : uint8_t {
|
||||
NONE = 0x00, // Used for defense cards, mags, shields, etc.
|
||||
@@ -300,7 +300,7 @@ enum class ConditionType : uint8_t {
|
||||
UNKNOWN_75 = 0x75,
|
||||
REFLECT = 0x76, // Generate reverse attack
|
||||
UNKNOWN_77 = 0x77,
|
||||
ANY = 0x78, // Not a real condition; used as a wildcard in search functions
|
||||
ANY = 0x78, // Not a real condition; used as a wildcard in search functions. Has value 0x64 on NTE
|
||||
UNKNOWN_79 = 0x79,
|
||||
UNKNOWN_7A = 0x7A,
|
||||
UNKNOWN_7B = 0x7B,
|
||||
@@ -984,7 +984,7 @@ struct RulesTrial {
|
||||
/* 00 */ uint8_t overall_time_limit = 0;
|
||||
/* 01 */ uint8_t phase_time_limit = 0;
|
||||
/* 02 */ AllowedCards allowed_cards = AllowedCards::ALL;
|
||||
/* 03 */ uint8_t atk_dice_max = 1; // TODO: Are these actually maxes? Look at the dice roll function
|
||||
/* 03 */ uint8_t atk_dice_max = 6;
|
||||
/* 04 */ uint8_t def_dice_max = 6;
|
||||
/* 05 */ uint8_t disable_deck_shuffle = 0;
|
||||
/* 06 */ uint8_t disable_deck_loop = 0;
|
||||
|
||||
+47
-11
@@ -93,7 +93,7 @@ void PlayerState::init() {
|
||||
this->draw_initial_hand();
|
||||
if (s->options.is_trial()) {
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
// TODO: NTE calls 80243310(1) here
|
||||
this->send_set_card_updates(true);
|
||||
}
|
||||
|
||||
s->assist_server->hand_and_equip_states[this->client_id] = this->hand_and_equip;
|
||||
@@ -1167,25 +1167,29 @@ uint8_t PlayerState::roll_dice_with_effects(size_t num_dice) {
|
||||
|
||||
void PlayerState::send_set_card_updates(bool always_send) {
|
||||
auto s = this->server();
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
uint16_t mask;
|
||||
if (!this->sc_card) {
|
||||
uint16_t mask = 0;
|
||||
if (this->sc_card) {
|
||||
this->sc_card->send_6xB4x4E_4C_4D_if_needed(always_send);
|
||||
} else if (is_trial) {
|
||||
this->send_6xB4x0A_for_set_card(0);
|
||||
} else {
|
||||
this->set_card_action_chains->at(0).clear();
|
||||
this->set_card_action_metadatas->at(0).clear();
|
||||
mask = 1;
|
||||
} else {
|
||||
this->sc_card->send_6xB4x4E_4C_4D_if_needed(always_send);
|
||||
mask = 0;
|
||||
mask |= 1;
|
||||
}
|
||||
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->set_cards[set_index];
|
||||
if (!card) {
|
||||
if (card) {
|
||||
card->send_6xB4x4E_4C_4D_if_needed(always_send);
|
||||
} else if (is_trial) {
|
||||
this->send_6xB4x0A_for_set_card(set_index + 1);
|
||||
} else {
|
||||
mask |= 1 << (set_index + 1);
|
||||
this->set_card_action_chains->at(set_index + 1).clear();
|
||||
this->set_card_action_metadatas->at(set_index + 1).clear();
|
||||
} else {
|
||||
card->send_6xB4x4E_4C_4D_if_needed(always_send);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1773,7 +1777,7 @@ void PlayerState::unknown_8023C174() {
|
||||
AssistFlag::ELIGIBLE_FOR_DICE_BOOST);
|
||||
this->set_assist_flags_from_assist_effects();
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed(0);
|
||||
this->send_set_card_updates(0);
|
||||
this->send_set_card_updates();
|
||||
}
|
||||
|
||||
void PlayerState::handle_homesick_assist_effect_from_bomb(shared_ptr<Card> card) {
|
||||
@@ -1960,4 +1964,36 @@ void PlayerState::compute_team_dice_bonus_after_draw_phase() {
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
void PlayerState::send_6xB4x0A_for_set_card(size_t set_index) {
|
||||
if (set_index >= 9) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
|
||||
// The original code (in NTE) calls memcmp here, but then ignores the results
|
||||
// and always copies the chain and metadata.
|
||||
// this->set_card_action_chains->at(set_index) == this->unknown_a12;
|
||||
// this->set_card_action_metadatas->at(set_index) == this->unknown_a13;
|
||||
this->set_card_action_chains->at(set_index) = this->unknown_a12;
|
||||
this->set_card_action_metadatas->at(set_index) = this->unknown_a13;
|
||||
|
||||
if (s->options.is_trial()) {
|
||||
G_UpdateActionChainAndMetadata_Ep3NTE_6xB4x0A cmd;
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.index = set_index;
|
||||
cmd.chain = this->unknown_a12;
|
||||
cmd.metadata = this->unknown_a13;
|
||||
s->send(cmd);
|
||||
|
||||
} else {
|
||||
G_UpdateActionChainAndMetadata_Ep3_6xB4x0A cmd;
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.index = set_index;
|
||||
cmd.chain = this->unknown_a12;
|
||||
cmd.metadata = this->unknown_a13;
|
||||
s->send(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -138,6 +138,7 @@ public:
|
||||
void roll_main_dice();
|
||||
void unknown_8023C110();
|
||||
void compute_team_dice_bonus_after_draw_phase();
|
||||
void send_6xB4x0A_for_set_card(size_t set_index);
|
||||
|
||||
private:
|
||||
std::weak_ptr<Server> w_server;
|
||||
|
||||
@@ -439,7 +439,7 @@ void ActionChainWithConds::compute_attack_medium(shared_ptr<Server> server) {
|
||||
if (!ce) {
|
||||
continue;
|
||||
}
|
||||
if (card_class_is_tech_like(ce->def.card_class())) {
|
||||
if (card_class_is_tech_like(ce->def.card_class(), server->options.is_trial())) {
|
||||
this->chain.attack_medium = AttackMedium::TECH;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,9 +636,11 @@ bool RulerServer::card_ref_has_free_maneuver(uint16_t card_ref) const {
|
||||
}
|
||||
|
||||
bool RulerServer::card_ref_is_aerial(uint16_t card_ref) const {
|
||||
const auto* stat = this->short_status_for_card_ref(card_ref);
|
||||
if (!stat || !this->card_exists_by_status(*stat)) {
|
||||
return false;
|
||||
if (!this->server()->options.is_trial()) {
|
||||
const auto* stat = this->short_status_for_card_ref(card_ref);
|
||||
if (!stat || !this->card_exists_by_status(*stat)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t client_id = client_id_for_card_ref(card_ref);
|
||||
@@ -905,7 +907,8 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
uint8_t def_effect_index,
|
||||
bool is_item_usability_check,
|
||||
AttackMedium attack_medium) const {
|
||||
auto log = this->server()->log_stack(string_printf("check_usability_or_condition_apply(%02hhX, #%04hX, %02hhX, #%04hX, #%04hX, %02hhX, %s, %s): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", name_for_attack_medium(attack_medium)));
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("check_usability_or_condition_apply(%02hhX, #%04hX, %02hhX, #%04hX, #%04hX, %02hhX, %s, %s): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", name_for_attack_medium(attack_medium)));
|
||||
|
||||
if (static_cast<uint8_t>(attack_medium) & 0x80) {
|
||||
attack_medium = AttackMedium::UNKNOWN;
|
||||
@@ -918,7 +921,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
log.debug("ce1 missing");
|
||||
return false;
|
||||
}
|
||||
if ((ce1->def.type == CardType::ITEM) && this->card_id_is_boss_sc(card_id2)) {
|
||||
if (!s->options.is_trial() && (ce1->def.type == CardType::ITEM) && this->card_id_is_boss_sc(card_id2)) {
|
||||
log.debug("ce1 is item and card_id2 is boss sc");
|
||||
return false;
|
||||
}
|
||||
@@ -954,8 +957,8 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
// creature card is usable, the two client IDs should be the same or the
|
||||
// second should not be given, so we'd return true if the criterion passes. If
|
||||
// neither of these cases apply, we should return false as a failsafe even if
|
||||
// the criterion passes.
|
||||
bool ret = (!(def_effect_index & 0x80) || (client_id1 == client_id2)) || (client_id2 == 0xFF);
|
||||
// the criterion passes. NTE did not have such a check.
|
||||
bool ret = s->options.is_trial() || (!(def_effect_index & 0x80) || (client_id1 == client_id2)) || (client_id2 == 0xFF);
|
||||
switch (criterion_code) {
|
||||
case CriterionCode::NONE:
|
||||
return ret;
|
||||
@@ -1371,13 +1374,14 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
|
||||
tech_cost_bias = -1;
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
for (size_t z = 0; pa.action_card_refs[z] != 0xFFFF; z++) {
|
||||
auto ce = this->definition_for_card_ref(pa.action_card_refs[z]);
|
||||
if (has_mighty_knuckle || !ce || (ce->def.type != CardType::ACTION)) {
|
||||
return 99;
|
||||
}
|
||||
total_cost += (ce->def.self_cost + cost_bias);
|
||||
if (card_class_is_tech_like(ce->def.card_class())) {
|
||||
if (card_class_is_tech_like(ce->def.card_class(), s->options.is_trial())) {
|
||||
total_cost += tech_cost_bias;
|
||||
}
|
||||
total_ally_cost += ce->def.ally_cost;
|
||||
@@ -2520,13 +2524,14 @@ void RulerServer::replace_D1_D2_rank_cards_with_Attack(
|
||||
}
|
||||
|
||||
AttackMedium RulerServer::get_attack_medium(const ActionState& pa) const {
|
||||
bool is_trial = this->server()->options.is_trial();
|
||||
for (size_t z = 0; z < 8; z++) {
|
||||
uint16_t card_ref = pa.action_card_refs[z];
|
||||
if (card_ref == 0xFFFF) {
|
||||
return AttackMedium::PHYSICAL;
|
||||
}
|
||||
auto ce = this->definition_for_card_ref(card_ref);
|
||||
if (ce && card_class_is_tech_like(ce->def.card_class())) {
|
||||
if (ce && card_class_is_tech_like(ce->def.card_class(), is_trial)) {
|
||||
return AttackMedium::TECH;
|
||||
}
|
||||
}
|
||||
|
||||
+34
-26
@@ -822,7 +822,6 @@ void Server::draw_phase_after() {
|
||||
}
|
||||
if (no_winner_specified) {
|
||||
if (this->options.is_trial()) {
|
||||
// TODO: This looks like an incomplete version of compute_losing_team_id_and_add_winner_flags; reconcile this
|
||||
throw runtime_error("unimplemented NTE condition");
|
||||
} else {
|
||||
this->compute_losing_team_id_and_add_winner_flags(0);
|
||||
@@ -1705,7 +1704,7 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
|
||||
}
|
||||
|
||||
void Server::handle_CAx0B_mulligan_hand(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_RedrawInitialHand_Ep3_6xB3x0B_CAx0B>(data);
|
||||
const auto& in_cmd = check_size_t<G_RedrawInitialHand_Ep3_CAx0B>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "REDRAW");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1738,7 +1737,7 @@ void Server::handle_CAx0B_mulligan_hand(shared_ptr<Client>, const string& data)
|
||||
}
|
||||
|
||||
void Server::handle_CAx0C_end_mulligan_phase(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndInitialRedrawPhase_Ep3_6xB3x0C_CAx0C>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndInitialRedrawPhase_Ep3_CAx0C>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "SETUP ADV 2");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1796,7 +1795,7 @@ void Server::handle_CAx0C_end_mulligan_phase(shared_ptr<Client>, const string& d
|
||||
}
|
||||
|
||||
void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndNonAttackPhase_Ep3_6xB3x0D_CAx0D>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndNonAttackPhase_Ep3_CAx0D>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END PHASE");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
@@ -1816,7 +1815,7 @@ void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string&
|
||||
}
|
||||
|
||||
void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_DiscardCardFromHand_Ep3_6xB3x0E_CAx0E>(data);
|
||||
const auto& in_cmd = check_size_t<G_DiscardCardFromHand_Ep3_CAx0E>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "DISCARD");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1856,7 +1855,7 @@ void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const strin
|
||||
}
|
||||
|
||||
void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetCardFromHand_Ep3_6xB3x0F_CAx0F>(data);
|
||||
const auto& in_cmd = check_size_t<G_SetCardFromHand_Ep3_CAx0F>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "SET FC");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
@@ -1898,7 +1897,7 @@ void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& d
|
||||
}
|
||||
|
||||
void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_MoveFieldCharacter_Ep3_6xB3x10_CAx10>(data);
|
||||
const auto& in_cmd = check_size_t<G_MoveFieldCharacter_Ep3_CAx10>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "MOVE");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1936,7 +1935,7 @@ void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string&
|
||||
}
|
||||
|
||||
void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EnqueueAttackOrDefense_Ep3_6xB3x11_CAx11>(data);
|
||||
const auto& in_cmd = check_size_t<G_EnqueueAttackOrDefense_Ep3_CAx11>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "ENQUEUE ACT");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1972,7 +1971,7 @@ void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const st
|
||||
}
|
||||
|
||||
void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndAttackList_Ep3_6xB3x12_CAx12>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndAttackList_Ep3_CAx12>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "END ATK LIST");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1994,8 +1993,9 @@ void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
|
||||
}
|
||||
|
||||
void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetMapState_Ep3_6xB3x13_CAx13>(data);
|
||||
template <typename CmdT>
|
||||
void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<CmdT>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "UPDATE MAP");
|
||||
|
||||
@@ -2036,8 +2036,16 @@ void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client>, const stri
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client> c, const string& data) {
|
||||
if (this->options.is_trial()) {
|
||||
this->handle_CAx13_update_map_during_setup_t<G_SetMapState_Ep3NTE_CAx13>(c, data);
|
||||
} else {
|
||||
this->handle_CAx13_update_map_during_setup_t<G_SetMapState_Ep3_CAx13>(c, data);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerDeck_Ep3_6xB3x14_CAx14>(data);
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerDeck_Ep3_CAx14>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "UPDATE DECK");
|
||||
|
||||
@@ -2062,7 +2070,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
|
||||
if (verify_error) {
|
||||
throw runtime_error(string_printf("invalid deck: -0x%" PRIX32, verify_error));
|
||||
}
|
||||
if (!(this->options.behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
|
||||
if (!this->options.is_trial() && !(this->options.behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
|
||||
this->ruler_server->replace_D1_D2_rank_cards_with_Attack(entry.card_ids);
|
||||
}
|
||||
*this->deck_entries[in_cmd.client_id] = in_cmd.entry;
|
||||
@@ -2084,7 +2092,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
|
||||
}
|
||||
|
||||
void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_HardResetServerState_Ep3_6xB3x15_CAx15>(data);
|
||||
const auto& in_cmd = check_size_t<G_HardResetServerState_Ep3_CAx15>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "HARD RESET");
|
||||
|
||||
@@ -2102,7 +2110,7 @@ void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, con
|
||||
}
|
||||
|
||||
void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerName_Ep3_6xB3x1B_CAx1B>(data);
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerName_Ep3_CAx1B>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.entry.client_id, in_cmd.header.subsubcommand, "UPDATE NAME");
|
||||
|
||||
@@ -2134,7 +2142,7 @@ void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& d
|
||||
}
|
||||
|
||||
void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_StartBattle_Ep3_6xB3x1D_CAx1D>(data);
|
||||
const auto& in_cmd = check_size_t<G_StartBattle_Ep3_CAx1D>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "START BATTLE");
|
||||
|
||||
@@ -2171,7 +2179,7 @@ void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
|
||||
void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndBattle_Ep3_6xB3x21_CAx21>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndBattle_Ep3_CAx21>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "END BATTLE");
|
||||
if (this->setup_phase == SetupPhase::BATTLE_ENDED) {
|
||||
@@ -2186,7 +2194,7 @@ void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
|
||||
void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndDefenseList_Ep3_6xB3x28_CAx28>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndDefenseList_Ep3_CAx28>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "END DEF LIST");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -2239,13 +2247,13 @@ void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& dat
|
||||
}
|
||||
|
||||
void Server::handle_CAx2B_legacy_set_card(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_ExecLegacyCard_Ep3_6xB3x2B_CAx2B>(data);
|
||||
const auto& in_cmd = check_size_t<G_ExecLegacyCard_Ep3_CAx2B>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "EXEC LEGACY");
|
||||
// Sega's original implementation does nothing here, so we do nothing as well.
|
||||
}
|
||||
|
||||
void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_PhotonBlastRequest_Ep3_6xB3x34_CAx34>(data);
|
||||
const auto& in_cmd = check_size_t<G_PhotonBlastRequest_Ep3_CAx34>(data);
|
||||
|
||||
uint8_t card_ref_client_id = client_id_for_card_ref(in_cmd.card_ref);
|
||||
this->send_debug_command_received_message(
|
||||
@@ -2322,7 +2330,7 @@ void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const str
|
||||
}
|
||||
|
||||
void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_AdvanceFromStartingRollsPhase_Ep3_6xB3x37_CAx37>(data);
|
||||
const auto& in_cmd = check_size_t<G_AdvanceFromStartingRollsPhase_Ep3_CAx37>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "SETUP ADV 1");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -2352,14 +2360,14 @@ void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared
|
||||
}
|
||||
|
||||
void Server::handle_CAx3A_time_limit_expired(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_OverallTimeLimitExpired_Ep3_6xB3x3A_CAx3A>(data);
|
||||
const auto& in_cmd = check_size_t<G_OverallTimeLimitExpired_Ep3_CAx3A>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "TIME EXPIRED");
|
||||
// We don't need to do anything here because the overall time limit is tracked
|
||||
// server-side instead.
|
||||
}
|
||||
|
||||
void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_MapListRequest_Ep3_6xB3x40_CAx40>(data);
|
||||
const auto& in_cmd = check_size_t<G_MapListRequest_Ep3_CAx40>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "MAP LIST");
|
||||
|
||||
@@ -2431,7 +2439,7 @@ void Server::send_6xB6x41_to_all_clients() const {
|
||||
}
|
||||
|
||||
void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
|
||||
const auto& cmd = check_size_t<G_MapDataRequest_Ep3_6xB3x41_CAx41>(data);
|
||||
const auto& cmd = check_size_t<G_MapDataRequest_Ep3_CAx41>(data);
|
||||
this->send_debug_command_received_message(
|
||||
cmd.header.subsubcommand, "MAP DATA");
|
||||
|
||||
@@ -2440,7 +2448,7 @@ void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
|
||||
void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndTurn_Ep3_6xB3x48_CAx48>(data);
|
||||
const auto& in_cmd = check_size_t<G_EndTurn_Ep3_CAx48>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.client_id, in_cmd.header.subsubcommand, "END TURN");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -2458,7 +2466,7 @@ void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
|
||||
void Server::handle_CAx49_card_counts(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_CardCounts_Ep3_6xB3x49_CAx49>(data);
|
||||
const auto& in_cmd = check_size_t<G_CardCounts_Ep3_CAx49>(data);
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.sender_client_id, in_cmd.header.subsubcommand, "CARD COUNTS");
|
||||
|
||||
|
||||
@@ -195,6 +195,8 @@ public:
|
||||
void handle_CAx10_move_fc_to_location(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx11_enqueue_attack_or_defense(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx12_end_attack_list(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
template <typename CmdT>
|
||||
void handle_CAx13_update_map_during_setup_t(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx13_update_map_during_setup(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx14_update_deck_during_setup(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx15_unused_hard_reset_server_state(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
|
||||
Reference in New Issue
Block a user