merge Ep3 ServerBase and Server into one class
This commit is contained in:
+13
-31
@@ -1240,25 +1240,19 @@ static void server_command_enable_ep3_battle_debug_menu(
|
||||
if (l->episode != Episode::EP3) {
|
||||
throw logic_error("non-Ep3 client in Ep3 game");
|
||||
}
|
||||
auto base = l->ep3_server_base;
|
||||
if (!base) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
auto server = base->server;
|
||||
if (!server) {
|
||||
if (!l->ep3_server) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.empty()) {
|
||||
server->override_environment_number = stoul(encode_sjis(args), nullptr, 16);
|
||||
send_text_message_printf(l, "$C6Override environment\nnumber set to %02hhX", server->override_environment_number);
|
||||
} else if (server->override_environment_number == 0xFF) {
|
||||
server->override_environment_number = 0x1A;
|
||||
l->ep3_server->override_environment_number = stoul(encode_sjis(args), nullptr, 16);
|
||||
send_text_message_printf(l, "$C6Override environment\nnumber set to %02hhX", l->ep3_server->override_environment_number);
|
||||
} else if (l->ep3_server->override_environment_number == 0xFF) {
|
||||
l->ep3_server->override_environment_number = 0x1A;
|
||||
send_text_message(l, u"$C6Battle setup debug\nmenu enabled");
|
||||
} else {
|
||||
server->override_environment_number = 0xFF;
|
||||
l->ep3_server->override_environment_number = 0xFF;
|
||||
send_text_message(l, u"$C6Battle setup debug\nmenu disabled");
|
||||
}
|
||||
}
|
||||
@@ -1271,23 +1265,17 @@ static void server_command_ep3_infinite_time(
|
||||
if (l->episode != Episode::EP3) {
|
||||
throw logic_error("non-Ep3 client in Ep3 game");
|
||||
}
|
||||
auto base = l->ep3_server_base;
|
||||
if (!base) {
|
||||
if (!l->ep3_server) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
auto server = base->server;
|
||||
if (!server) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
if (server->setup_phase != Episode3::SetupPhase::REGISTRATION) {
|
||||
if (l->ep3_server->setup_phase != Episode3::SetupPhase::REGISTRATION) {
|
||||
send_text_message(c, u"$C6Battle is already\nin progress");
|
||||
return;
|
||||
}
|
||||
|
||||
base->behavior_flags ^= Episode3::BehaviorFlag::DISABLE_TIME_LIMITS;
|
||||
bool infinite_time_enabled = (base->behavior_flags & Episode3::BehaviorFlag::DISABLE_TIME_LIMITS);
|
||||
l->ep3_server->behavior_flags ^= Episode3::BehaviorFlag::DISABLE_TIME_LIMITS;
|
||||
bool infinite_time_enabled = (l->ep3_server->behavior_flags & Episode3::BehaviorFlag::DISABLE_TIME_LIMITS);
|
||||
send_text_message(l, infinite_time_enabled ? u"$C6Infinite time enabled" : u"$C6Infinite time disabled");
|
||||
}
|
||||
|
||||
@@ -1298,23 +1286,17 @@ static void server_command_surrender(
|
||||
if (l->episode != Episode::EP3) {
|
||||
throw logic_error("non-Ep3 client in Ep3 game");
|
||||
}
|
||||
auto base = l->ep3_server_base;
|
||||
if (!base) {
|
||||
if (!l->ep3_server) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
auto server = base->server;
|
||||
if (!server) {
|
||||
send_text_message(c, u"$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
if (server->setup_phase != Episode3::SetupPhase::MAIN_BATTLE) {
|
||||
if (l->ep3_server->setup_phase != Episode3::SetupPhase::MAIN_BATTLE) {
|
||||
send_text_message(c, u"$C6Battle has not\nyet started");
|
||||
return;
|
||||
}
|
||||
string name = encode_sjis(c->game_data.player()->disp.name);
|
||||
send_text_message_printf(l, "$C6%s has\nsurrendered", name.c_str());
|
||||
server->force_battle_result(c->lobby_client_id, false);
|
||||
l->ep3_server->force_battle_result(c->lobby_client_id, false);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -49,7 +49,7 @@ void Card::init() {
|
||||
this->max_hp = this->def_entry->def.hp.stat;
|
||||
this->current_hp = this->def_entry->def.hp.stat;
|
||||
if (this->sc_card_ref == this->card_ref) {
|
||||
int16_t rules_char_hp = this->server()->base()->map_and_rules1->rules.char_hp;
|
||||
int16_t rules_char_hp = this->server()->map_and_rules1->rules.char_hp;
|
||||
int16_t base_char_hp = (rules_char_hp == 0) ? 15 : rules_char_hp;
|
||||
int16_t hp = clamp<int16_t>(base_char_hp + this->def_entry->def.hp.stat, 1, 99);
|
||||
this->max_hp = hp;
|
||||
@@ -358,7 +358,7 @@ void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
}
|
||||
|
||||
if ((this->server()->base()->map_and_rules1->rules.hp_type == HPType::DEFEAT_TEAM) &&
|
||||
if ((this->server()->map_and_rules1->rules.hp_type == HPType::DEFEAT_TEAM) &&
|
||||
(this->player_state()->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);
|
||||
@@ -585,7 +585,7 @@ int32_t Card::move_to_location(const Location& loc) {
|
||||
}
|
||||
|
||||
void Card::propagate_shared_hp_if_needed() {
|
||||
if ((this->server()->base()->map_and_rules1->rules.hp_type == HPType::COMMON_HP) &&
|
||||
if ((this->server()->map_and_rules1->rules.hp_type == HPType::COMMON_HP) &&
|
||||
((this->def_entry->def.type == CardType::HUNTERS_SC) || (this->def_entry->def.type == CardType::ARKZ_SC))) {
|
||||
for (size_t other_client_id = 0; other_client_id < 4; other_client_id++) {
|
||||
auto other_ps = this->server()->player_states[other_client_id];
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
class PlayerState;
|
||||
|
||||
|
||||
+22
-22
@@ -832,7 +832,7 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
// the Gifoie card's ID (00D9) for compute_effective_range.
|
||||
// TODO: We should fix this so it doesn't rely on a fixed card definition.
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, 0x00D9, target_card_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, 0x00D9, target_card_loc, this->server()->map_and_rules1);
|
||||
auto card_refs_in_parry_range = target_ps->get_all_cards_within_range(
|
||||
range, target_card_loc, 0xFF);
|
||||
|
||||
@@ -1527,7 +1527,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
const AttackEnvStats& ast,
|
||||
const char* expr,
|
||||
DiceRoll& dice_roll) const {
|
||||
auto log = this->server()->base()->log.sub("evaluate_effect_expr: ");
|
||||
auto log = this->server()->log.sub("evaluate_effect_expr: ");
|
||||
log.debug("ast, expr=\"%s\", dice_roll=(client_id=%02hhX, a2=%02hhX, value=%02hhX, value_used_in_expr=%s, a5=%04hX)", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5);
|
||||
|
||||
// Note: This implementation is not based on the original code because the
|
||||
@@ -1618,7 +1618,7 @@ bool CardSpecial::execute_effect(
|
||||
ConditionType cond_type,
|
||||
uint32_t unknown_p7,
|
||||
uint16_t attacker_card_ref) {
|
||||
auto log = this->server()->base()->log.sub("execute_effect: ");
|
||||
auto log = this->server()->log.sub("execute_effect: ");
|
||||
{
|
||||
string cond_str = cond.str();
|
||||
log.debug("cond=%s, card=%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=%04hX", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, name_for_condition_type(cond_type), unknown_p7, attacker_card_ref);
|
||||
@@ -2496,7 +2496,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
const ActionState& as,
|
||||
int16_t p_target_type,
|
||||
bool apply_usability_filters) const {
|
||||
auto log = this->server()->base()->log.sub("get_targeted_cards_for_condition: ");
|
||||
auto log = this->server()->log.sub("get_targeted_cards_for_condition: ");
|
||||
log.debug("card_ref=%04hX, def_effect_index=%02hhX, setter_card_ref=%04hX, as, p_target_type=%hd, apply_usability_filters=%s", card_ref, def_effect_index, setter_card_ref, p_target_type, apply_usability_filters ? "true" : "false");
|
||||
|
||||
vector<shared_ptr<const Card>> ret;
|
||||
@@ -2570,7 +2570,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (ce && ps) {
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, ce->def.card_id, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
add_card_refs(ps->get_card_refs_within_range_from_all_players(range, card1_loc, CardType::ITEM));
|
||||
}
|
||||
}
|
||||
@@ -2610,7 +2610,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (ce && ps) {
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, ce->def.card_id, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
add_card_refs(ps->get_all_cards_within_range(range, card1_loc, card1->get_team_id()));
|
||||
}
|
||||
}
|
||||
@@ -2680,7 +2680,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// should fix this eventually.
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, card1->get_team_id());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -2706,7 +2706,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
log23.debug("effective range card ID is %04hX", range_card_id);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1, &log23);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1, &log23);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
log23.debug("%zu result card refs", result_card_refs.size());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
@@ -2783,7 +2783,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// TODO: Again with the Gifoie hardcoding...
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -2837,7 +2837,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// TODO: Yet another Gifoie hardcode location :(
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, card1->get_team_id());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -2864,7 +2864,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// TODO: Sigh. Gifoie again.
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -2960,7 +2960,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// Slay instead of Gifoie
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x009C, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -2989,7 +2989,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// TODO: Sigh. Gifoie. Sigh.
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -3027,7 +3027,7 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
// TODO: One more Gifoie here.
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, range_card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, card1->get_team_id());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
@@ -3448,7 +3448,7 @@ void CardSpecial::check_for_defense_interference(
|
||||
shared_ptr<Card> target_card,
|
||||
int16_t* inout_unknown_p4) {
|
||||
// Note: This check is not part of the original implementation.
|
||||
if (this->server()->base()->behavior_flags & BehaviorFlag::DISABLE_INTERFERENCE) {
|
||||
if (this->server()->behavior_flags & BehaviorFlag::DISABLE_INTERFERENCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3530,17 +3530,17 @@ void CardSpecial::unknown_8024C2B0(
|
||||
uint16_t sc_card_ref,
|
||||
bool apply_defense_condition_to_all_cards,
|
||||
uint16_t apply_defense_condition_to_card_ref) {
|
||||
auto debug_log = this->server()->base()->log.sub("unknown_8024C2B0: ");
|
||||
auto log = this->server()->log.sub("unknown_8024C2B0: ");
|
||||
{
|
||||
string as_str = as.str();
|
||||
debug_log.debug("when=%02" PRIX32 ", set_card_ref=%04hX, as=%s, sc_card_ref=%04hX, apply_defense_condition_to_all_cards=%s, apply_defense_condition_to_card_ref=%04hX",
|
||||
log.debug("when=%02" PRIX32 ", set_card_ref=%04hX, as=%s, sc_card_ref=%04hX, apply_defense_condition_to_all_cards=%s, apply_defense_condition_to_card_ref=%04hX",
|
||||
when, set_card_ref, as_str.c_str(), sc_card_ref, apply_defense_condition_to_all_cards ? "true" : "false", apply_defense_condition_to_card_ref);
|
||||
}
|
||||
|
||||
set_card_ref = this->send_6xB4x06_if_card_ref_invalid(set_card_ref, 1);
|
||||
auto ce = this->server()->definition_for_card_ref(set_card_ref);
|
||||
if (!ce) {
|
||||
debug_log.debug("ce missing");
|
||||
log.debug("ce missing");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3581,10 +3581,10 @@ void CardSpecial::unknown_8024C2B0(
|
||||
dice_roll.unknown_a2 = 3;
|
||||
dice_roll.value_used_in_expr = false;
|
||||
|
||||
debug_log.debug("inputs: dice_roll=%02hhX, random_percent=%hhu, unknown_v1=%s", dice_roll.value, random_percent, unknown_v1 ? "true" : "false");
|
||||
log.debug("inputs: dice_roll=%02hhX, random_percent=%hhu, unknown_v1=%s", dice_roll.value, random_percent, unknown_v1 ? "true" : "false");
|
||||
|
||||
for (size_t def_effect_index = 0; (def_effect_index < 3) && !unknown_v1 && (ce->def.effects[def_effect_index].type != ConditionType::NONE); def_effect_index++) {
|
||||
auto effect_log = debug_log.sub(string_printf("(effect:%zu) ", def_effect_index));
|
||||
auto effect_log = log.sub(string_printf("(effect:%zu) ", def_effect_index));
|
||||
const auto& card_effect = ce->def.effects[def_effect_index];
|
||||
string card_effect_str = card_effect.str();
|
||||
effect_log.debug("effect: %s", card_effect_str.c_str());
|
||||
@@ -4215,7 +4215,7 @@ vector<shared_ptr<const Card>> CardSpecial::filter_cards_by_range(
|
||||
// TODO: Remove hardcoded card ID here (Earthquake)
|
||||
uint16_t card_id = this->get_card_id_with_effective_range(card1, 0x00ED, card2);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->card_index, card_id, card1_loc, this->server()->map_and_rules1);
|
||||
auto card_refs_in_range = ps->get_card_refs_within_range_from_all_players(range, card1_loc, CardType::ITEM);
|
||||
|
||||
for (auto card : cards) {
|
||||
@@ -4431,7 +4431,7 @@ void CardSpecial::unknown_8024A9D8(const ActionState& pa, uint16_t action_card_r
|
||||
|
||||
void CardSpecial::check_for_attack_interference(shared_ptr<Card> unknown_p2) {
|
||||
// Note: This check is not part of the original implementation.
|
||||
if (this->server()->base()->behavior_flags & BehaviorFlag::DISABLE_INTERFERENCE) {
|
||||
if (this->server()->behavior_flags & BehaviorFlag::DISABLE_INTERFERENCE) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -273,4 +273,46 @@ void DeckState::shuffle() {
|
||||
}
|
||||
}
|
||||
|
||||
static const char* name_for_card_state(DeckState::CardState st) {
|
||||
switch (st) {
|
||||
case DeckState::CardState::DRAWABLE:
|
||||
return "DRAWABLE";
|
||||
case DeckState::CardState::STORY_CHARACTER:
|
||||
return "STORY_CHARACTER";
|
||||
case DeckState::CardState::IN_HAND:
|
||||
return "IN_HAND";
|
||||
case DeckState::CardState::IN_PLAY:
|
||||
return "IN_PLAY";
|
||||
case DeckState::CardState::DISCARDED:
|
||||
return "DISCARDED";
|
||||
case DeckState::CardState::INVALID:
|
||||
return "INVALID";
|
||||
default:
|
||||
return "__UNKNOWN__";
|
||||
}
|
||||
}
|
||||
|
||||
void DeckState::print(FILE* stream, std::shared_ptr<const CardIndex> card_index) const {
|
||||
fprintf(stream, "DeckState: client_id=%hhu draw_index=%hhu card_ref_base=%04hX shuffle=%s loop=%s\n",
|
||||
this->client_id, this->draw_index, this->card_ref_base, this->shuffle_enabled ? "true" : "false", this->loop_enabled ? "true" : "false");
|
||||
for (size_t z = 0; z < 31; z++) {
|
||||
const auto& e = this->entries[z];
|
||||
shared_ptr<const CardIndex::CardEntry> ce;
|
||||
if (card_index) {
|
||||
try {
|
||||
ce = card_index->definition_for_id(e.card_id);
|
||||
} catch (const out_of_range&) {
|
||||
}
|
||||
}
|
||||
if (ce) {
|
||||
string name = ce->def.en_name;
|
||||
fprintf(stream, " (%02zu) index=%02hhX ref=%04hX card_id=%04hX \"%s\" %s\n",
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, name.c_str(), name_for_card_state(e.state));
|
||||
} else {
|
||||
fprintf(stream, " (%02zu) index=%02hhX ref=%04hX card_id=%04hX %s\n",
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, name_for_card_state(e.state));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "../PSOEncryption.hh"
|
||||
#include "../Text.hh"
|
||||
#include "DataIndexes.hh"
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
@@ -93,6 +94,8 @@ public:
|
||||
void shuffle();
|
||||
void do_mulligan();
|
||||
|
||||
void print(FILE* stream, std::shared_ptr<const CardIndex> card_index = nullptr) const;
|
||||
|
||||
private:
|
||||
struct CardEntry {
|
||||
uint16_t card_id;
|
||||
|
||||
+199
-129
@@ -40,7 +40,9 @@ PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
unknown_a17(0) {}
|
||||
|
||||
void PlayerState::init() {
|
||||
if (this->server()->player_states[this->client_id].get() != this) {
|
||||
auto s = this->server();
|
||||
|
||||
if (s->player_states[this->client_id].get() != this) {
|
||||
// Note: The original code handles this, but we don't. This appears not to
|
||||
// ever happen, so we didn't bother implementing it.
|
||||
throw logic_error("replacing a player state object is not permitted");
|
||||
@@ -48,19 +50,19 @@ void PlayerState::init() {
|
||||
|
||||
this->deck_state.reset(new DeckState(
|
||||
this->client_id,
|
||||
this->server()->base()->deck_entries[client_id]->card_ids,
|
||||
this->server()->random_crypt));
|
||||
if (this->server()->base()->map_and_rules1->rules.disable_deck_shuffle) {
|
||||
s->deck_entries[client_id]->card_ids,
|
||||
s->random_crypt));
|
||||
if (s->map_and_rules1->rules.disable_deck_shuffle) {
|
||||
this->deck_state->disable_shuffle();
|
||||
}
|
||||
if (this->server()->base()->map_and_rules1->rules.disable_deck_loop) {
|
||||
if (s->map_and_rules1->rules.disable_deck_loop) {
|
||||
this->deck_state->disable_loop();
|
||||
}
|
||||
|
||||
this->sc_card_ref = this->deck_state->sc_card_ref();
|
||||
this->sc_card_id = this->server()->card_id_for_card_ref(this->sc_card_ref);
|
||||
this->team_id = this->server()->base()->deck_entries[this->client_id]->team_id;
|
||||
auto sc_ce = this->server()->definition_for_card_ref(this->sc_card_ref);
|
||||
this->sc_card_id = s->card_id_for_card_ref(this->sc_card_ref);
|
||||
this->team_id = s->deck_entries[this->client_id]->team_id;
|
||||
auto sc_ce = s->definition_for_card_ref(this->sc_card_ref);
|
||||
if (!sc_ce) {
|
||||
throw runtime_error("SC card definition is missing");
|
||||
}
|
||||
@@ -93,27 +95,27 @@ void PlayerState::init() {
|
||||
this->deck_state->sc_card_id(),
|
||||
this->sc_card_ref,
|
||||
this->client_id,
|
||||
this->server()));
|
||||
s));
|
||||
this->sc_card->init();
|
||||
this->draw_initial_hand();
|
||||
|
||||
this->server()->assist_server->hand_and_equip_states[this->client_id] = this->hand_and_equip;
|
||||
this->server()->assist_server->card_short_statuses[this->client_id] = this->card_short_statuses;
|
||||
this->server()->assist_server->deck_entries[this->client_id] = this->server()->base()->deck_entries[this->client_id];
|
||||
this->server()->assist_server->set_card_action_chains[this->client_id] = this->set_card_action_chains;
|
||||
this->server()->assist_server->set_card_action_metadatas[this->client_id] = this->set_card_action_metadatas;
|
||||
this->server()->ruler_server->register_player(
|
||||
s->assist_server->hand_and_equip_states[this->client_id] = this->hand_and_equip;
|
||||
s->assist_server->card_short_statuses[this->client_id] = this->card_short_statuses;
|
||||
s->assist_server->deck_entries[this->client_id] = s->deck_entries[this->client_id];
|
||||
s->assist_server->set_card_action_chains[this->client_id] = this->set_card_action_chains;
|
||||
s->assist_server->set_card_action_metadatas[this->client_id] = this->set_card_action_metadatas;
|
||||
s->ruler_server->register_player(
|
||||
this->client_id,
|
||||
this->hand_and_equip,
|
||||
this->card_short_statuses,
|
||||
this->server()->base()->deck_entries[this->client_id],
|
||||
s->deck_entries[this->client_id],
|
||||
this->set_card_action_chains,
|
||||
this->set_card_action_metadatas);
|
||||
this->server()->ruler_server->set_client_team_id(this->client_id, this->team_id);
|
||||
s->ruler_server->set_client_team_id(this->client_id, this->team_id);
|
||||
|
||||
this->server()->card_special->on_card_set(this->shared_from_this(), this->sc_card_ref);
|
||||
s->card_special->on_card_set(this->shared_from_this(), this->sc_card_ref);
|
||||
|
||||
this->god_whim_can_use_hidden_cards = (this->server()->base()->deck_entries[this->client_id]->god_whim_flag != 3);
|
||||
this->god_whim_can_use_hidden_cards = (s->deck_entries[this->client_id]->god_whim_flag != 3);
|
||||
}
|
||||
|
||||
shared_ptr<Server> PlayerState::server() {
|
||||
@@ -134,9 +136,10 @@ shared_ptr<const Server> PlayerState::server() const {
|
||||
|
||||
bool PlayerState::draw_cards_allowed() const {
|
||||
if (!(this->assist_flags & 0x80)) {
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
auto s = this->server();
|
||||
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++) {
|
||||
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::SKIP_DRAW) {
|
||||
return false;
|
||||
}
|
||||
@@ -149,9 +152,11 @@ bool PlayerState::draw_cards_allowed() const {
|
||||
|
||||
void PlayerState::apply_assist_card_effect_on_set(
|
||||
shared_ptr<PlayerState> setter_ps) {
|
||||
auto s = this->server();
|
||||
|
||||
uint16_t assist_card_id = this->set_assist_card_id;
|
||||
if (assist_card_id == 0xFFFF) {
|
||||
assist_card_id = this->server()->card_id_for_card_ref(this->card_refs[6]);
|
||||
assist_card_id = s->card_id_for_card_ref(this->card_refs[6]);
|
||||
}
|
||||
|
||||
auto assist_effect = assist_effect_number_for_card_id(assist_card_id);
|
||||
@@ -160,7 +165,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
this->assist_card_set_number = 0;
|
||||
}
|
||||
|
||||
if (this->server()->assist_server->should_block_assist_effects_for_client(this->client_id)) {
|
||||
if (s->assist_server->should_block_assist_effects_for_client(this->client_id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -213,7 +218,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
|
||||
size_t log_index;
|
||||
for (log_index = 0; log_index < 0x10; log_index++) {
|
||||
auto ce = this->server()->definition_for_card_ref(
|
||||
auto ce = s->definition_for_card_ref(
|
||||
this->discard_log_card_refs[log_index]);
|
||||
if (ce && ((ce->def.type == CardType::ITEM || ce->def.type == CardType::CREATURE))) {
|
||||
break;
|
||||
@@ -246,13 +251,13 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
|
||||
this->atk_points = min<uint8_t>(9, this->atk_points + (total_cost >> 1));
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
this->server()->send_6xB4x05();
|
||||
s->send_6xB4x05();
|
||||
break;
|
||||
}
|
||||
|
||||
case AssistEffect::MUSCULAR:
|
||||
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) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = other_ps->get_set_card(set_index);
|
||||
@@ -268,7 +273,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
|
||||
case AssistEffect::CHANGE_BODY:
|
||||
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) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = other_ps->get_set_card(set_index);
|
||||
@@ -291,7 +296,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
case AssistEffect::ASSIST_RETURN:
|
||||
if (this->card_refs[7] != 0xFFFF) {
|
||||
uint8_t client_id = client_id_for_card_ref(this->card_refs[7]);
|
||||
auto other_ps = this->server()->get_player_state(client_id);
|
||||
auto other_ps = s->get_player_state(client_id);
|
||||
if (other_ps.get() != this) {
|
||||
other_ps->deck_state->draw_card_by_ref(this->card_refs[7]);
|
||||
other_ps->set_card_from_hand(
|
||||
@@ -301,13 +306,13 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
break;
|
||||
|
||||
case AssistEffect::REQUIEM:
|
||||
this->server()->add_team_exp(this->team_id, this->num_destroyed_fcs << 1);
|
||||
this->server()->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
s->add_team_exp(this->team_id, this->num_destroyed_fcs << 1);
|
||||
s->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
|
||||
this->num_destroyed_fcs = 0;
|
||||
this->server()->team_num_cards_destroyed[this->team_id] = 0;
|
||||
s->team_num_cards_destroyed[this->team_id] = 0;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
const auto other_ps = this->server()->get_player_state(client_id);
|
||||
const auto other_ps = s->get_player_state(client_id);
|
||||
if (other_ps && (this->team_id == other_ps->get_team_id())) {
|
||||
auto card = other_ps->get_sc_card();
|
||||
if (card) {
|
||||
@@ -327,7 +332,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
|
||||
case AssistEffect::SLOW_TIME:
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
@@ -358,7 +363,7 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
|
||||
case AssistEffect::QUICK_TIME:
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
@@ -408,9 +413,11 @@ void PlayerState::apply_assist_card_effect_on_set(
|
||||
}
|
||||
|
||||
void PlayerState::apply_dice_effects() {
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
auto s = this->server();
|
||||
|
||||
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++) {
|
||||
auto eff = this->server()->assist_server->get_active_assist_by_index(z);
|
||||
auto eff = s->assist_server->get_active_assist_by_index(z);
|
||||
switch (eff) {
|
||||
case AssistEffect::DICE_FEVER:
|
||||
for (size_t die_index = 0; die_index < 2; die_index++) {
|
||||
@@ -455,7 +462,8 @@ uint16_t PlayerState::card_ref_for_hand_index(size_t hand_index) const {
|
||||
}
|
||||
|
||||
int16_t PlayerState::compute_attack_or_defense_atk_costs(const ActionState& pa) const {
|
||||
return this->server()->ruler_server->compute_attack_or_defense_costs(pa, 0, 0);
|
||||
auto s = this->server();
|
||||
return s->ruler_server->compute_attack_or_defense_costs(pa, 0, 0);
|
||||
}
|
||||
|
||||
void PlayerState::compute_total_set_cards_cost() {
|
||||
@@ -494,6 +502,8 @@ size_t PlayerState::count_set_refs() const {
|
||||
}
|
||||
|
||||
void PlayerState::discard_all_assist_cards_from_hand() {
|
||||
auto s = this->server();
|
||||
|
||||
parray<uint16_t, 6> temp_card_refs;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
temp_card_refs[hand_index] = this->card_refs[hand_index];
|
||||
@@ -501,7 +511,7 @@ void PlayerState::discard_all_assist_cards_from_hand() {
|
||||
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
uint16_t card_ref = temp_card_refs[hand_index];
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (ce && (ce->def.type == CardType::ASSIST)) {
|
||||
this->discard_ref_from_hand(card_ref);
|
||||
}
|
||||
@@ -511,6 +521,8 @@ void PlayerState::discard_all_assist_cards_from_hand() {
|
||||
}
|
||||
|
||||
void PlayerState::discard_all_attack_action_cards_from_hand() {
|
||||
auto s = this->server();
|
||||
|
||||
parray<uint16_t, 6> temp_card_refs;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
temp_card_refs[hand_index] = this->card_refs[hand_index];
|
||||
@@ -518,7 +530,7 @@ void PlayerState::discard_all_attack_action_cards_from_hand() {
|
||||
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
uint16_t card_ref = temp_card_refs[hand_index];
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (ce && (ce->def.type == CardType::ACTION) &&
|
||||
(ce->def.card_class() != CardClass::DEFENSE_ACTION)) {
|
||||
this->discard_ref_from_hand(card_ref);
|
||||
@@ -529,6 +541,8 @@ void PlayerState::discard_all_attack_action_cards_from_hand() {
|
||||
}
|
||||
|
||||
void PlayerState::discard_all_item_and_creature_cards_from_hand() {
|
||||
auto s = this->server();
|
||||
|
||||
parray<uint16_t, 6> temp_card_refs;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
temp_card_refs[hand_index] = this->card_refs[hand_index];
|
||||
@@ -536,7 +550,7 @@ void PlayerState::discard_all_item_and_creature_cards_from_hand() {
|
||||
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
uint16_t card_ref = temp_card_refs[hand_index];
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (ce && ((ce->def.type == CardType::ITEM) || (ce->def.type == CardType::CREATURE))) {
|
||||
this->discard_ref_from_hand(card_ref);
|
||||
}
|
||||
@@ -546,6 +560,8 @@ void PlayerState::discard_all_item_and_creature_cards_from_hand() {
|
||||
}
|
||||
|
||||
void PlayerState::discard_and_redraw_hand() {
|
||||
auto s = this->server();
|
||||
|
||||
while (this->card_refs[0] != 0xFFFF) {
|
||||
this->discard_ref_from_hand(this->card_refs[0]);
|
||||
}
|
||||
@@ -555,7 +571,7 @@ void PlayerState::discard_and_redraw_hand() {
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
cmd.unknown_a2.clear(0xFFFFFFFF);
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
|
||||
this->deck_state->restart();
|
||||
this->draw_hand();
|
||||
@@ -582,7 +598,8 @@ bool PlayerState::discard_card_or_add_to_draw_pile(
|
||||
void PlayerState::discard_random_hand_card() {
|
||||
size_t max = this->get_hand_size();
|
||||
if (max > 0) {
|
||||
this->discard_ref_from_hand(this->card_refs[this->server()->get_random(max)]);
|
||||
auto s = this->server();
|
||||
this->discard_ref_from_hand(this->card_refs[s->get_random(max)]);
|
||||
}
|
||||
this->move_null_hand_refs_to_end();
|
||||
}
|
||||
@@ -602,9 +619,11 @@ bool PlayerState::discard_ref_from_hand(uint16_t card_ref) {
|
||||
}
|
||||
|
||||
void PlayerState::discard_set_assist_card() {
|
||||
auto s = this->server();
|
||||
|
||||
this->set_assist_card_id = 0xFFFF;
|
||||
uint8_t client_id = client_id_for_card_ref(this->card_refs[6]);
|
||||
auto setter_ps = this->server()->get_player_state(client_id);
|
||||
auto setter_ps = s->get_player_state(client_id);
|
||||
if (setter_ps) {
|
||||
setter_ps->get_deck()->set_card_discarded(this->card_refs[6]);
|
||||
this->card_refs[6] = 0xFFFF;
|
||||
@@ -613,10 +632,10 @@ void PlayerState::discard_set_assist_card() {
|
||||
this->assist_remaining_turns = 0;
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
|
||||
this->server()->assist_server->populate_effects();
|
||||
s->assist_server->populate_effects();
|
||||
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
@@ -627,7 +646,7 @@ void PlayerState::discard_set_assist_card() {
|
||||
}
|
||||
}
|
||||
|
||||
this->server()->destroy_cards_with_zero_hp();
|
||||
s->destroy_cards_with_zero_hp();
|
||||
}
|
||||
|
||||
bool PlayerState::do_mulligan() {
|
||||
@@ -635,6 +654,8 @@ bool PlayerState::do_mulligan() {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
|
||||
this->num_mulligans_allowed--;
|
||||
while (this->card_refs[0] != 0xFFFF) {
|
||||
this->discard_ref_from_hand(this->card_refs[0]);
|
||||
@@ -645,7 +666,7 @@ bool PlayerState::do_mulligan() {
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
cmd.unknown_a2.clear(0xFFFFFFFF);
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
|
||||
this->deck_state->do_mulligan();
|
||||
this->draw_hand(5);
|
||||
@@ -655,10 +676,12 @@ bool PlayerState::do_mulligan() {
|
||||
}
|
||||
|
||||
void PlayerState::draw_hand(ssize_t override_count) {
|
||||
auto s = this->server();
|
||||
|
||||
ssize_t count = 5 - this->get_hand_size();
|
||||
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++) {
|
||||
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::RICH_PLUS) {
|
||||
count = 4 - this->get_hand_size();
|
||||
} else if (eff == AssistEffect::RICH) {
|
||||
@@ -678,7 +701,7 @@ void PlayerState::draw_hand(ssize_t override_count) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (this->server()->get_setup_phase() == SetupPhase::MAIN_BATTLE) {
|
||||
if (s->get_setup_phase() == SetupPhase::MAIN_BATTLE) {
|
||||
this->stats.num_cards_drawn++;
|
||||
}
|
||||
}
|
||||
@@ -702,7 +725,9 @@ int32_t PlayerState::error_code_for_client_setting_card(
|
||||
uint8_t card_index,
|
||||
const Location* loc,
|
||||
uint8_t assist_target_client_id) const {
|
||||
int32_t code = this->server()->ruler_server->error_code_for_client_setting_card(
|
||||
auto s = this->server();
|
||||
|
||||
int32_t code = s->ruler_server->error_code_for_client_setting_card(
|
||||
this->client_id, card_ref, loc, assist_target_client_id);
|
||||
if (code) {
|
||||
return code;
|
||||
@@ -716,7 +741,7 @@ int32_t PlayerState::error_code_for_client_setting_card(
|
||||
return -0x7D;
|
||||
}
|
||||
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (!ce) {
|
||||
return -0x7D;
|
||||
}
|
||||
@@ -731,7 +756,7 @@ int32_t PlayerState::error_code_for_client_setting_card(
|
||||
return -0x7E;
|
||||
}
|
||||
if ((ce->def.type == CardType::CREATURE) &&
|
||||
!this->server()->base()->map_and_rules1->tile_is_vacant(loc->x, loc->y)) {
|
||||
!s->map_and_rules1->tile_is_vacant(loc->x, loc->y)) {
|
||||
return -0x7A;
|
||||
}
|
||||
return 0;
|
||||
@@ -751,13 +776,15 @@ vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
uint8_t target_team_id) const {
|
||||
auto log = this->server()->base()->log.sub("get_all_cards_within_range: ");
|
||||
auto s = this->server();
|
||||
|
||||
auto log = s->log.sub("get_all_cards_within_range: ");
|
||||
string loc_str = loc.str();
|
||||
log.debug("loc=%s, target_team_id=%02hhX", loc_str.c_str(), target_team_id);
|
||||
|
||||
vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = this->server()->player_states[client_id];
|
||||
auto other_ps = s->player_states[client_id];
|
||||
if (other_ps &&
|
||||
((target_team_id == 0xFF) || (target_team_id == other_ps->get_team_id()))) {
|
||||
auto card_refs = get_card_refs_within_range(range, loc, *other_ps->card_short_statuses, &log);
|
||||
@@ -857,10 +884,11 @@ bool PlayerState::is_mulligan_allowed() const {
|
||||
}
|
||||
|
||||
bool PlayerState::is_team_turn() const {
|
||||
auto s = this->server();
|
||||
// Note: The original code checks if this->w_server is null before doing this.
|
||||
// We don't check because that should never happen, and server() will throw if
|
||||
// it does.
|
||||
return this->server()->get_current_team_turn() == this->team_id;
|
||||
return s->get_current_team_turn() == this->team_id;
|
||||
}
|
||||
|
||||
void PlayerState::log_discard(uint16_t card_ref, uint16_t reason) {
|
||||
@@ -874,33 +902,35 @@ void PlayerState::log_discard(uint16_t card_ref, uint16_t reason) {
|
||||
|
||||
bool PlayerState::move_card_to_location_by_card_index(
|
||||
size_t card_index, const Location& new_loc) {
|
||||
auto s = this->server();
|
||||
|
||||
shared_ptr<Card> card;
|
||||
if (card_index == 0) {
|
||||
card = this->sc_card;
|
||||
} else {
|
||||
if ((card_index < 7) || (card_index >= 15)) {
|
||||
this->server()->ruler_server->error_code2 = -0x78;
|
||||
s->ruler_server->error_code2 = -0x78;
|
||||
return false;
|
||||
}
|
||||
card = this->set_cards[card_index - 7];
|
||||
}
|
||||
if (!card) {
|
||||
this->server()->ruler_server->error_code2 = -0x78;
|
||||
s->ruler_server->error_code2 = -0x78;
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t code = card->error_code_for_move_to_location(new_loc);
|
||||
if (code) {
|
||||
this->server()->ruler_server->error_code2 = code;
|
||||
s->ruler_server->error_code2 = code;
|
||||
return false;
|
||||
}
|
||||
|
||||
card->move_to_location(new_loc);
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
this->send_6xB4x04_if_needed();
|
||||
this->server()->send_6xB4x05();
|
||||
this->server()->send_6xB4x39();
|
||||
this->server()->card_special->unknown_80244AA8(card);
|
||||
s->send_6xB4x05();
|
||||
s->send_6xB4x39();
|
||||
s->card_special->unknown_80244AA8(card);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -918,6 +948,8 @@ void PlayerState::move_null_hand_refs_to_end() {
|
||||
}
|
||||
|
||||
void PlayerState::on_cards_destroyed() {
|
||||
auto s = this->server();
|
||||
|
||||
// {card_ref: should_return_to_hand}
|
||||
unordered_multimap<uint16_t, bool> card_refs_map;
|
||||
|
||||
@@ -928,7 +960,7 @@ void PlayerState::on_cards_destroyed() {
|
||||
}
|
||||
|
||||
uint16_t card_ref = this->card_refs[z + 8];
|
||||
card_refs_map.emplace(card_ref, this->server()->card_special->should_return_card_ref_to_hand_on_destruction(this->card_refs[z + 8]));
|
||||
card_refs_map.emplace(card_ref, s->card_special->should_return_card_ref_to_hand_on_destruction(this->card_refs[z + 8]));
|
||||
|
||||
bool should_discard = true;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
@@ -988,16 +1020,18 @@ void PlayerState::on_cards_destroyed() {
|
||||
}
|
||||
|
||||
void PlayerState::replace_all_set_assists_with_random_assists() {
|
||||
auto s = this->server();
|
||||
|
||||
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 &&
|
||||
((other_ps->card_refs[6] != 0xFFFF) || (other_ps->set_assist_card_id != 0xFFFF))) {
|
||||
uint16_t card_id = 0x0130;
|
||||
while (card_id == 0x0130) { // God Whim
|
||||
size_t index = this->server()->get_random(ALL_ASSIST_CARD_IDS.size());
|
||||
size_t index = s->get_random(ALL_ASSIST_CARD_IDS.size());
|
||||
card_id = ALL_ASSIST_CARD_IDS[index];
|
||||
if (!this->god_whim_can_use_hidden_cards) {
|
||||
auto ce = this->server()->definition_for_card_id(card_id);
|
||||
auto ce = s->definition_for_card_id(card_id);
|
||||
if (!ce || ce->def.cannot_drop) {
|
||||
continue;
|
||||
}
|
||||
@@ -1009,7 +1043,9 @@ void PlayerState::replace_all_set_assists_with_random_assists() {
|
||||
}
|
||||
|
||||
bool PlayerState::replace_assist_card_by_id(uint16_t card_id) {
|
||||
auto ce = this->server()->definition_for_card_id(card_id);
|
||||
auto s = this->server();
|
||||
|
||||
auto ce = s->definition_for_card_id(card_id);
|
||||
if (!ce || (ce->def.type != CardType::ASSIST)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1017,12 +1053,12 @@ bool PlayerState::replace_assist_card_by_id(uint16_t card_id) {
|
||||
this->discard_set_assist_card();
|
||||
this->set_assist_card_id = card_id;
|
||||
this->assist_remaining_turns = ce->def.assist_turns;
|
||||
this->assist_card_set_number = this->server()->next_assist_card_set_number++;
|
||||
this->assist_card_set_number = s->next_assist_card_set_number++;
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
this->server()->assist_server->populate_effects();
|
||||
s->assist_server->populate_effects();
|
||||
|
||||
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) {
|
||||
uint32_t prev_assist_flags = other_ps->assist_flags;
|
||||
other_ps->set_assist_flags_from_assist_effects();
|
||||
@@ -1093,9 +1129,11 @@ bool PlayerState::return_set_card_to_hand1(uint16_t card_ref) {
|
||||
}
|
||||
|
||||
uint8_t PlayerState::roll_dice(size_t num_dice) {
|
||||
auto s = this->server();
|
||||
|
||||
uint8_t ret = 0;
|
||||
for (size_t z = 0; z < num_dice; z++) {
|
||||
this->dice_results[z] = this->server()->get_random(this->dice_max) + 1;
|
||||
this->dice_results[z] = s->get_random(this->dice_max) + 1;
|
||||
ret += this->dice_results[z];
|
||||
}
|
||||
|
||||
@@ -1116,6 +1154,8 @@ uint8_t PlayerState::roll_dice_with_effects(size_t num_dice) {
|
||||
}
|
||||
|
||||
void PlayerState::send_set_card_updates(bool always_send) {
|
||||
auto s = this->server();
|
||||
|
||||
uint16_t mask;
|
||||
if (!this->sc_card) {
|
||||
this->set_card_action_chains->at(0).clear();
|
||||
@@ -1137,19 +1177,21 @@ void PlayerState::send_set_card_updates(bool always_send) {
|
||||
}
|
||||
}
|
||||
|
||||
if (mask && !this->server()->get_should_copy_prev_states_to_current_states()) {
|
||||
if (mask && !s->get_should_copy_prev_states_to_current_states()) {
|
||||
G_ClearSetCardConditions_GC_Ep3_6xB4x4F cmd;
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.clear_mask = mask;
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerState::set_assist_flags_from_assist_effects() {
|
||||
auto s = this->server();
|
||||
|
||||
this->assist_flags &= 0xFFFFF88F;
|
||||
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::SIMPLE:
|
||||
this->assist_flags |= 0x10;
|
||||
break;
|
||||
@@ -1181,11 +1223,13 @@ bool PlayerState::set_card_from_hand(
|
||||
const Location* loc,
|
||||
uint8_t assist_target_client_id,
|
||||
bool skip_error_checks_and_atk_sub) {
|
||||
auto s = this->server();
|
||||
|
||||
if (!skip_error_checks_and_atk_sub) {
|
||||
int32_t code = this->error_code_for_client_setting_card(
|
||||
card_ref, card_index, loc, assist_target_client_id);
|
||||
if (code) {
|
||||
this->server()->ruler_server->error_code1 = code;
|
||||
s->ruler_server->error_code1 = code;
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
return false;
|
||||
}
|
||||
@@ -1198,24 +1242,24 @@ bool PlayerState::set_card_from_hand(
|
||||
}
|
||||
|
||||
if (!skip_error_checks_and_atk_sub) {
|
||||
int16_t cost = this->server()->ruler_server->set_cost_for_card(
|
||||
int16_t cost = s->ruler_server->set_cost_for_card(
|
||||
this->client_id, card_ref);
|
||||
this->subtract_atk_points(cost);
|
||||
}
|
||||
|
||||
this->deck_state->set_card_ref_in_play(card_ref);
|
||||
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (ce->def.type == CardType::ITEM || ce->def.type == CardType::CREATURE) {
|
||||
if ((card_index < 7) || (card_index >= 15)) {
|
||||
return 0;
|
||||
}
|
||||
this->card_refs[card_index + 1] = card_ref;
|
||||
this->set_cards[card_index - 7].reset(new Card(
|
||||
this->server()->card_id_for_card_ref(card_ref),
|
||||
s->card_id_for_card_ref(card_ref),
|
||||
card_ref,
|
||||
this->client_id,
|
||||
this->server()));
|
||||
s));
|
||||
auto new_card = this->set_cards[card_index - 7];
|
||||
new_card->init();
|
||||
|
||||
@@ -1230,7 +1274,7 @@ bool PlayerState::set_card_from_hand(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto target_ps = this->server()->player_states[assist_target_client_id];
|
||||
auto target_ps = s->player_states[assist_target_client_id];
|
||||
if (target_ps) {
|
||||
uint16_t prev_assist_card_ref = target_ps->card_refs[6];
|
||||
target_ps->discard_set_assist_card();
|
||||
@@ -1239,15 +1283,15 @@ bool PlayerState::set_card_from_hand(
|
||||
|
||||
target_ps->assist_remaining_turns = ce->def.assist_turns;
|
||||
target_ps->assist_delay_turns = 0;
|
||||
target_ps->assist_card_set_number = this->server()->next_assist_card_set_number++;
|
||||
target_ps->assist_card_set_number = s->next_assist_card_set_number++;
|
||||
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
target_ps->apply_assist_card_effect_on_set(this->shared_from_this());
|
||||
target_ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
this->server()->assist_server->populate_effects();
|
||||
s->assist_server->populate_effects();
|
||||
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
@@ -1263,26 +1307,28 @@ bool PlayerState::set_card_from_hand(
|
||||
this->stats.num_cards_set++;
|
||||
|
||||
this->compute_total_set_cards_cost();
|
||||
this->server()->card_special->on_card_set(this->shared_from_this(), card_ref);
|
||||
s->card_special->on_card_set(this->shared_from_this(), card_ref);
|
||||
if (ce->def.type == CardType::ASSIST) {
|
||||
this->server()->check_for_destroyed_cards_and_send_6xB4x05_6xB4x02();
|
||||
s->check_for_destroyed_cards_and_send_6xB4x05_6xB4x02();
|
||||
}
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
this->server()->send_6xB4x05();
|
||||
s->send_6xB4x05();
|
||||
|
||||
G_Unknown_GC_Ep3_6xB4x4A cmd;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
cmd.card_refs[0] = card_ref;
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.entry_count = 1;
|
||||
cmd.round_num = this->server()->get_round_num();
|
||||
this->server()->send(cmd);
|
||||
cmd.round_num = s->get_round_num();
|
||||
s->send(cmd);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerState::set_initial_location() {
|
||||
auto mr = this->server()->base()->map_and_rules1;
|
||||
auto s = this->server();
|
||||
|
||||
auto mr = s->map_and_rules1;
|
||||
|
||||
uint8_t num_team_players;
|
||||
if (this->team_id == 0) {
|
||||
@@ -1296,7 +1342,7 @@ void PlayerState::set_initial_location() {
|
||||
if (client_id == this->client_id) {
|
||||
break;
|
||||
}
|
||||
auto other_ps = this->server()->player_states[client_id];
|
||||
auto other_ps = s->player_states[client_id];
|
||||
if (other_ps && (this->team_id == other_ps->get_team_id())) {
|
||||
player_index_within_team++;
|
||||
}
|
||||
@@ -1333,11 +1379,12 @@ void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
|
||||
for (size_t warp_type = 0; warp_type < 5; warp_type++) {
|
||||
for (size_t warp_end = 0; warp_end < 2; warp_end++) {
|
||||
if ((s->warp_positions[warp_type][warp_end][0] == card->loc.x) &&
|
||||
(s->warp_positions[warp_type][warp_end][1] == card->loc.y)) {
|
||||
s->base()->map_and_rules1->set_occupied_bit_for_tile(
|
||||
s->map_and_rules1->set_occupied_bit_for_tile(
|
||||
s->warp_positions[warp_type][warp_end ^ 1][0],
|
||||
s->warp_positions[warp_type][warp_end ^ 1][1]);
|
||||
}
|
||||
@@ -1346,8 +1393,10 @@ void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(
|
||||
}
|
||||
|
||||
void PlayerState::set_map_occupied_bits_for_sc_and_creatures() {
|
||||
auto s = this->server();
|
||||
|
||||
if (this->sc_card && !(this->sc_card->card_flags & 2)) {
|
||||
this->server()->base()->map_and_rules1->set_occupied_bit_for_tile(
|
||||
s->map_and_rules1->set_occupied_bit_for_tile(
|
||||
this->sc_card->loc.x, this->sc_card->loc.y);
|
||||
this->set_map_occupied_bit_for_card_on_warp_tile(this->sc_card);
|
||||
}
|
||||
@@ -1356,7 +1405,7 @@ void PlayerState::set_map_occupied_bits_for_sc_and_creatures() {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->set_cards[set_index];
|
||||
if (card) {
|
||||
this->server()->base()->map_and_rules1->set_occupied_bit_for_tile(
|
||||
s->map_and_rules1->set_occupied_bit_for_tile(
|
||||
card->loc.x, card->loc.y);
|
||||
this->set_map_occupied_bit_for_card_on_warp_tile(card);
|
||||
}
|
||||
@@ -1370,8 +1419,10 @@ void PlayerState::subtract_def_points(uint8_t cost) {
|
||||
|
||||
bool PlayerState::subtract_or_check_atk_or_def_points_for_action(
|
||||
const ActionState& pa, bool deduct_points) {
|
||||
auto s = this->server();
|
||||
|
||||
int16_t cost = this->compute_attack_or_defense_atk_costs(pa);
|
||||
auto type = this->server()->ruler_server->get_pending_action_type(pa);
|
||||
auto type = s->ruler_server->get_pending_action_type(pa);
|
||||
|
||||
if ((type == ActionType::ATTACK) && (cost <= this->atk_points)) {
|
||||
if (deduct_points) {
|
||||
@@ -1396,6 +1447,8 @@ void PlayerState::subtract_atk_points(uint8_t cost) {
|
||||
|
||||
void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed(
|
||||
bool always_send) {
|
||||
auto s = this->server();
|
||||
|
||||
G_UpdateHand_GC_Ep3_6xB4x02 cmd;
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.state.dice_results = this->dice_results;
|
||||
@@ -1404,7 +1457,7 @@ void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed(
|
||||
cmd.state.atk_points2 = this->atk_points2;
|
||||
cmd.state.unknown_a1 = this->unknown_a14;
|
||||
cmd.state.total_set_cards_cost = this->total_set_cards_cost;
|
||||
cmd.state.is_cpu_player = this->server()->base()->presence_entries[this->client_id].is_cpu_player;
|
||||
cmd.state.is_cpu_player = s->presence_entries[this->client_id].is_cpu_player;
|
||||
cmd.state.assist_flags = this->assist_flags;
|
||||
for (size_t z = 0; z < 6; z++) {
|
||||
cmd.state.hand_card_refs[z] = this->card_refs[z];
|
||||
@@ -1427,16 +1480,18 @@ void PlayerState::update_hand_and_equip_state_and_send_6xB4x02_if_needed(
|
||||
cmd.state.def_bonuses = this->def_bonuses;
|
||||
if (always_send || memcmp(&this->hand_and_equip, &cmd.state, sizeof(this->hand_and_equip))) {
|
||||
*this->hand_and_equip = cmd.state;
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
}
|
||||
this->send_6xB4x04_if_needed(always_send);
|
||||
}
|
||||
|
||||
void PlayerState::set_random_assist_card_from_hand_for_free() {
|
||||
auto s = this->server();
|
||||
|
||||
vector<uint16_t> candidate_card_refs;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
uint16_t card_ref = this->card_refs[hand_index];
|
||||
auto ce = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
if (ce && (ce->def.type == CardType::ASSIST) &&
|
||||
(assist_effect_number_for_card_id(ce->def.card_id) != AssistEffect::SQUEEZE)) {
|
||||
candidate_card_refs.emplace_back(card_ref);
|
||||
@@ -1445,13 +1500,15 @@ void PlayerState::set_random_assist_card_from_hand_for_free() {
|
||||
|
||||
if (!candidate_card_refs.empty()) {
|
||||
this->discard_set_assist_card();
|
||||
size_t index = this->server()->get_random(candidate_card_refs.size());
|
||||
size_t index = s->get_random(candidate_card_refs.size());
|
||||
this->set_card_from_hand(
|
||||
candidate_card_refs[index], 15, nullptr, this->client_id, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerState::send_6xB4x04_if_needed(bool always_send) {
|
||||
auto s = this->server();
|
||||
|
||||
G_UpdateShortStatuses_GC_Ep3_6xB4x04 cmd;
|
||||
cmd.client_id = this->client_id;
|
||||
// Note: The original code calls memset to clear all the short status structs
|
||||
@@ -1490,8 +1547,8 @@ void PlayerState::send_6xB4x04_if_needed(bool always_send) {
|
||||
|
||||
if (always_send || (cmd.card_statuses != *this->card_short_statuses)) {
|
||||
*this->card_short_statuses = cmd.card_statuses;
|
||||
if (!this->server()->get_should_copy_prev_states_to_current_states()) {
|
||||
this->server()->send(cmd);
|
||||
if (!s->get_should_copy_prev_states_to_current_states()) {
|
||||
s->send(cmd);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1500,9 +1557,11 @@ vector<uint16_t> PlayerState::get_card_refs_within_range_from_all_players(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
CardType type) const {
|
||||
auto s = this->server();
|
||||
|
||||
vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = this->server()->player_states[client_id];
|
||||
auto other_ps = s->player_states[client_id];
|
||||
if (other_ps && ((other_ps->get_sc_card_type() == type) || (type == CardType::ITEM))) {
|
||||
auto card_refs = get_card_refs_within_range(range, loc, *other_ps->card_short_statuses);
|
||||
ret.insert(ret.end(), card_refs.begin(), card_refs.end());
|
||||
@@ -1545,14 +1604,16 @@ void PlayerState::unknown_80239528() {
|
||||
}
|
||||
|
||||
void PlayerState::handle_before_turn_assist_effects() {
|
||||
auto s = this->server();
|
||||
|
||||
if ((this->assist_delay_turns > 0) &&
|
||||
(--this->assist_delay_turns == 0)) {
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
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::BOMB:
|
||||
this->server()->execute_bomb_assist_effect();
|
||||
s->execute_bomb_assist_effect();
|
||||
break;
|
||||
case AssistEffect::ATK_DICE_2:
|
||||
// Note: This behavior doesn't match the card description. Is it
|
||||
@@ -1579,21 +1640,23 @@ int16_t PlayerState::get_assist_turns_remaining() {
|
||||
}
|
||||
|
||||
bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
auto attacker_card = this->server()->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
auto s = this->server();
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (attacker_card) {
|
||||
attacker_card->card_flags |= 0x100;
|
||||
}
|
||||
|
||||
auto action_type = this->server()->ruler_server->get_pending_action_type(pa);
|
||||
auto action_type = s->ruler_server->get_pending_action_type(pa);
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, 1);
|
||||
|
||||
if (action_type == ActionType::ATTACK) {
|
||||
G_Unknown_GC_Ep3_6xB4x4A cmd;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.round_num = this->server()->get_round_num();
|
||||
cmd.round_num = s->get_round_num();
|
||||
cmd.entry_count = 0;
|
||||
auto card = this->server()->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
auto card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (card) {
|
||||
card->loc.direction = pa.facing_direction;
|
||||
size_t z = 0;
|
||||
@@ -1604,7 +1667,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
cmd.card_refs[z] = pa.action_card_refs[z];
|
||||
cmd.entry_count++;
|
||||
}
|
||||
auto ce = this->server()->definition_for_card_ref(pa.action_card_refs[z]);
|
||||
auto ce = s->definition_for_card_ref(pa.action_card_refs[z]);
|
||||
if (ce) {
|
||||
auto card_class = ce->def.card_class();
|
||||
if ((card_class == CardClass::TECH) ||
|
||||
@@ -1622,7 +1685,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
z++;
|
||||
} while ((z < 8) && (pa.action_card_refs[z] != 0xFFFF));
|
||||
if (cmd.entry_count > 0) {
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1630,9 +1693,9 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
G_Unknown_GC_Ep3_6xB4x4A cmd;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
cmd.client_id = this->client_id;
|
||||
cmd.round_num = this->server()->get_round_num();
|
||||
cmd.round_num = s->get_round_num();
|
||||
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
|
||||
auto target_card = this->server()->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
if (target_card) {
|
||||
target_card->unknown_802379DC(pa);
|
||||
if (this->client_id == target_card->get_client_id()) {
|
||||
@@ -1645,7 +1708,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
}
|
||||
cmd.card_refs[0] = pa.defense_card_ref;
|
||||
cmd.entry_count = 1;
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
}
|
||||
for (size_t z = 0; (z < 4 * 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
this->discard_ref_from_hand(pa.action_card_refs[z]);
|
||||
@@ -1692,6 +1755,8 @@ void PlayerState::handle_homesick_assist_effect(shared_ptr<Card> card) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
|
||||
size_t set_index;
|
||||
for (set_index = 0; set_index < 8; set_index++) {
|
||||
if (this->set_cards[set_index] == card) {
|
||||
@@ -1701,9 +1766,9 @@ void PlayerState::handle_homesick_assist_effect(shared_ptr<Card> card) {
|
||||
|
||||
if (set_index < 8) {
|
||||
uint16_t card_ref = card->get_card_ref();
|
||||
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++) {
|
||||
if (this->server()->assist_server->get_active_assist_by_index(z) == AssistEffect::HOMESICK) {
|
||||
if (s->assist_server->get_active_assist_by_index(z) == AssistEffect::HOMESICK) {
|
||||
this->return_set_card_to_hand2(card_ref);
|
||||
this->log_discard(card_ref, 1);
|
||||
this->set_cards[set_index]->card_flags |= 2;
|
||||
@@ -1719,9 +1784,11 @@ void PlayerState::handle_homesick_assist_effect(shared_ptr<Card> card) {
|
||||
}
|
||||
|
||||
void PlayerState::apply_main_die_assist_effects(uint8_t* die_value) const {
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
auto s = this->server();
|
||||
|
||||
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::DICE_FEVER:
|
||||
*die_value = 5;
|
||||
break;
|
||||
@@ -1741,7 +1808,8 @@ void PlayerState::apply_main_die_assist_effects(uint8_t* die_value) const {
|
||||
}
|
||||
|
||||
void PlayerState::roll_main_dice() {
|
||||
const auto& rules = this->server()->base()->map_and_rules1->rules;
|
||||
auto s = this->server();
|
||||
const auto& rules = s->map_and_rules1->rules;
|
||||
|
||||
uint8_t min_dice = rules.min_dice;
|
||||
uint8_t max_dice = rules.max_dice;
|
||||
@@ -1765,8 +1833,8 @@ void PlayerState::roll_main_dice() {
|
||||
this->atk_points = min_dice;
|
||||
this->def_points = min_dice;
|
||||
} else {
|
||||
this->dice_results[0] = min_dice + this->server()->get_random(dice_range_width);
|
||||
this->dice_results[1] = min_dice + this->server()->get_random(dice_range_width);
|
||||
this->dice_results[0] = min_dice + s->get_random(dice_range_width);
|
||||
this->dice_results[1] = min_dice + s->get_random(dice_range_width);
|
||||
this->atk_points = this->dice_results[0];
|
||||
this->def_points = this->dice_results[1];
|
||||
}
|
||||
@@ -1788,7 +1856,7 @@ void PlayerState::roll_main_dice() {
|
||||
this->assist_flags |= 2;
|
||||
}
|
||||
|
||||
this->atk_points = this->atk_points + this->server()->card_special->client_has_atk_dice_boost_condition(this->client_id);
|
||||
this->atk_points = this->atk_points + s->card_special->client_has_atk_dice_boost_condition(this->client_id);
|
||||
|
||||
uint8_t atk_before_bonuses = this->atk_points;
|
||||
uint8_t def_before_bonuses = this->def_points;
|
||||
@@ -1798,8 +1866,8 @@ void PlayerState::roll_main_dice() {
|
||||
this->dice_results[0] = this->atk_points;
|
||||
this->dice_results[1] = this->def_points;
|
||||
|
||||
this->atk_points += this->server()->team_dice_boost[this->team_id];
|
||||
this->def_points += this->server()->team_dice_boost[this->team_id];
|
||||
this->atk_points += s->team_dice_boost[this->team_id];
|
||||
this->def_points += s->team_dice_boost[this->team_id];
|
||||
this->atk_points = clamp<uint8_t>(this->atk_points, 1, 9);
|
||||
this->def_points = clamp<uint8_t>(this->def_points, 1, 9);
|
||||
this->atk_bonuses = this->atk_points - atk_before_bonuses;
|
||||
@@ -1821,6 +1889,8 @@ void PlayerState::unknown_8023C110() {
|
||||
}
|
||||
|
||||
void PlayerState::compute_team_dice_boost_after_draw_phase() {
|
||||
auto s = this->server();
|
||||
|
||||
if (this->sc_card) {
|
||||
this->sc_card->unknown_80237F88();
|
||||
}
|
||||
@@ -1831,12 +1901,12 @@ void PlayerState::compute_team_dice_boost_after_draw_phase() {
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t current_team_turn = this->server()->get_current_team_turn();
|
||||
uint8_t dice_boost = this->server()->get_team_exp(current_team_turn) /
|
||||
(this->server()->team_client_count[current_team_turn] * 12);
|
||||
this->server()->card_special->adjust_dice_boost_if_team_has_condition_52(
|
||||
uint8_t current_team_turn = s->get_current_team_turn();
|
||||
uint8_t dice_boost = s->get_team_exp(current_team_turn) /
|
||||
(s->team_client_count[current_team_turn] * 12);
|
||||
s->card_special->adjust_dice_boost_if_team_has_condition_52(
|
||||
current_team_turn, &dice_boost, 0);
|
||||
this->server()->team_dice_boost[current_team_turn] = clamp<int16_t>(dice_boost, 0, 8);
|
||||
s->team_dice_boost[current_team_turn] = clamp<int16_t>(dice_boost, 0, 8);
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
|
||||
class PlayerState : public std::enable_shared_from_this<PlayerState> {
|
||||
|
||||
@@ -9,7 +9,6 @@
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
class ServerBase;
|
||||
class Server;
|
||||
class Card;
|
||||
|
||||
|
||||
+12
-10
@@ -903,21 +903,23 @@ 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.sub("check_usability_or_condition_apply: ");
|
||||
|
||||
if (static_cast<uint8_t>(attack_medium) & 0x80) {
|
||||
attack_medium = AttackMedium::UNKNOWN;
|
||||
}
|
||||
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply(client_id1=%02hhX, card_id1=%04hX, client_id2=%02hhX, card_id2=%04hX, card_id3=%04hX, def_effect_index=%02hhX, is_item_usability_check=%s, attack_medium=%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));
|
||||
log.debug("check_usability_or_condition_apply(client_id1=%02hhX, card_id1=%04hX, client_id2=%02hhX, card_id2=%04hX, card_id3=%04hX, def_effect_index=%02hhX, is_item_usability_check=%s, attack_medium=%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 ce1 = this->definition_for_card_id(card_id1);
|
||||
auto ce2 = this->definition_for_card_id(card_id2);
|
||||
auto ce3 = this->definition_for_card_id(card_id3);
|
||||
if (!ce1) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: ce1 missing");
|
||||
log.debug("check_usability_or_condition_apply: ce1 missing");
|
||||
return false;
|
||||
}
|
||||
if ((ce1->def.type == CardType::ITEM) && this->card_id_is_boss_sc(card_id2)) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: ce1 is item and card_id2 is boss sc");
|
||||
log.debug("check_usability_or_condition_apply: ce1 is item and card_id2 is boss sc");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -926,12 +928,12 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
criterion_code = ce1->def.usable_criterion;
|
||||
} else {
|
||||
if (def_effect_index > 2) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: invalid def_effect_index");
|
||||
log.debug("check_usability_or_condition_apply: invalid def_effect_index");
|
||||
return false;
|
||||
}
|
||||
criterion_code = ce1->def.effects[def_effect_index].apply_criterion;
|
||||
}
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: criterion_code=%s", name_for_criterion_code(criterion_code));
|
||||
log.debug("check_usability_or_condition_apply: criterion_code=%s", name_for_criterion_code(criterion_code));
|
||||
|
||||
// For item usability checks, prevent criteria that depend on player
|
||||
// positioning/team setup
|
||||
@@ -942,7 +944,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
(criterion_code == CriterionCode::UNKNOWN_07) ||
|
||||
(criterion_code == CriterionCode::NOT_SC) ||
|
||||
(criterion_code == CriterionCode::SC))) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: criterion is forbidden");
|
||||
log.debug("check_usability_or_condition_apply: criterion is forbidden");
|
||||
criterion_code = CriterionCode::NONE;
|
||||
}
|
||||
|
||||
@@ -992,12 +994,12 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
break;
|
||||
case CriterionCode::UNKNOWN_07:
|
||||
// Like NOT_SC, but for ce3 instead of ce2
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: ce3 type is %s", ce3 ? name_for_card_type(ce3->def.type) : "missing");
|
||||
log.debug("check_usability_or_condition_apply: UNKNOWN_07: ce3 type is %s", ce3 ? name_for_card_type(ce3->def.type) : "missing");
|
||||
if (!ce3 || ((ce3->def.type != CardType::HUNTERS_SC) && (ce3->def.type != CardType::ARKZ_SC))) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: returned %s", ret ? "true" : "false");
|
||||
log.debug("check_usability_or_condition_apply: UNKNOWN_07: returned %s", ret ? "true" : "false");
|
||||
return ret;
|
||||
}
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: did not pass");
|
||||
log.debug("check_usability_or_condition_apply: UNKNOWN_07: did not pass");
|
||||
break;
|
||||
case CriterionCode::NOT_SC:
|
||||
if (!ce2 || ((ce2->def.type != CardType::HUNTERS_SC) && (ce2->def.type != CardType::ARKZ_SC))) {
|
||||
@@ -1318,7 +1320,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
}
|
||||
}
|
||||
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: default return (false)");
|
||||
log.debug("check_usability_or_condition_apply: default return (false)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+102
-149
@@ -14,18 +14,17 @@ namespace Episode3 {
|
||||
static const char* VERSION_SIGNATURE =
|
||||
"newserv Ep3 based on [V1][FINAL2.0] 03/09/13 15:30 by K.Toya";
|
||||
|
||||
ServerBase::PresenceEntry::PresenceEntry() {
|
||||
Server::PresenceEntry::PresenceEntry() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
void ServerBase::PresenceEntry::clear() {
|
||||
void Server::PresenceEntry::clear() {
|
||||
this->player_present = 0;
|
||||
this->deck_valid = 0;
|
||||
this->is_cpu_player = 0;
|
||||
}
|
||||
|
||||
ServerBase::ServerBase(
|
||||
shared_ptr<Lobby> lobby,
|
||||
Server::Server(shared_ptr<Lobby> lobby,
|
||||
shared_ptr<const CardIndex> card_index,
|
||||
shared_ptr<const MapIndex> map_index,
|
||||
uint32_t behavior_flags,
|
||||
@@ -37,34 +36,8 @@ ServerBase::ServerBase(
|
||||
behavior_flags(behavior_flags),
|
||||
log(lobby->log.prefix + "[Ep3::Server] ", lobby->log.min_level),
|
||||
random_crypt(random_crypt),
|
||||
last_chosen_map(map_if_tournament),
|
||||
is_tournament(!!map_if_tournament),
|
||||
last_chosen_map(map_if_tournament) {}
|
||||
|
||||
void ServerBase::init() {
|
||||
this->reset();
|
||||
}
|
||||
|
||||
void ServerBase::reset() {
|
||||
this->map_and_rules1.reset(new MapAndRulesState());
|
||||
this->map_and_rules2.reset(new MapAndRulesState());
|
||||
this->num_clients_present = 0;
|
||||
this->overlay_state.clear();
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
this->presence_entries[z].clear();
|
||||
this->deck_entries[z].reset(new DeckEntry());
|
||||
this->name_entries[z].clear();
|
||||
this->name_entries_valid[z] = false;
|
||||
}
|
||||
this->recreate_server();
|
||||
}
|
||||
|
||||
void ServerBase::recreate_server() {
|
||||
this->server.reset(new Server(this->shared_from_this()));
|
||||
this->server->init();
|
||||
}
|
||||
|
||||
Server::Server(shared_ptr<ServerBase> base)
|
||||
: w_base(base),
|
||||
tournament_match_result_sent(false),
|
||||
override_environment_number(0xFF),
|
||||
battle_finished(false),
|
||||
@@ -80,7 +53,6 @@ Server::Server(shared_ptr<ServerBase> base)
|
||||
num_pending_attacks(0),
|
||||
client_done_enqueuing_attacks(false),
|
||||
player_ready_to_end_phase(false),
|
||||
random_crypt(base->random_crypt),
|
||||
unknown_a10(0),
|
||||
overall_time_expired(false),
|
||||
battle_start_usecs(0),
|
||||
@@ -98,7 +70,6 @@ Server::Server(shared_ptr<ServerBase> base)
|
||||
team_num_ally_fcs_destroyed(0),
|
||||
team_num_cards_destroyed(0),
|
||||
hard_reset_flag(false),
|
||||
tournament_flag(base->is_tournament ? 1 : 0),
|
||||
num_trap_tiles_of_type(0),
|
||||
chosen_trap_tile_index_of_type(0),
|
||||
has_done_pb(0),
|
||||
@@ -106,6 +77,17 @@ Server::Server(shared_ptr<ServerBase> base)
|
||||
prev_num_6xB4x06_commands_sent(0) {}
|
||||
|
||||
void Server::init() {
|
||||
this->map_and_rules1.reset(new MapAndRulesState());
|
||||
this->map_and_rules2.reset(new MapAndRulesState());
|
||||
this->num_clients_present = 0;
|
||||
this->overlay_state.clear();
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
this->presence_entries[z].clear();
|
||||
this->deck_entries[z].reset(new DeckEntry());
|
||||
this->name_entries[z].clear();
|
||||
this->name_entries_valid[z] = false;
|
||||
}
|
||||
|
||||
this->card_special.reset(new CardSpecial(this->shared_from_this()));
|
||||
|
||||
// Note: The original implementation calls the default PSOV2Encryption
|
||||
@@ -122,28 +104,11 @@ void Server::init() {
|
||||
|
||||
this->assist_server.reset(new AssistServer(this->shared_from_this()));
|
||||
this->ruler_server.reset(new RulerServer(this->shared_from_this()));
|
||||
this->ruler_server->link_objects(
|
||||
this->base()->map_and_rules1, this->state_flags, this->assist_server);
|
||||
this->ruler_server->link_objects(this->map_and_rules1, this->state_flags, this->assist_server);
|
||||
|
||||
this->send_6xB4x46();
|
||||
}
|
||||
|
||||
shared_ptr<ServerBase> Server::base() {
|
||||
auto s = this->w_base.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server base is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const ServerBase> Server::base() const {
|
||||
auto s = this->w_base.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server base is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
int8_t Server::get_winner_team_id() const {
|
||||
// Note: This function is not part of the original implementation.
|
||||
|
||||
@@ -181,13 +146,13 @@ int8_t Server::get_winner_team_id() const {
|
||||
|
||||
void Server::send(const void* data, size_t size) const {
|
||||
// Note: This function is (obviously) not part of the original implementation.
|
||||
auto l = this->base()->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
string masked_data;
|
||||
if (!(this->base()->behavior_flags & BehaviorFlag::DISABLE_MASKING)) {
|
||||
if (!(this->behavior_flags & BehaviorFlag::DISABLE_MASKING)) {
|
||||
if (size >= 8) {
|
||||
masked_data.assign(reinterpret_cast<const char*>(data), size);
|
||||
uint8_t mask_key = (random_object<uint32_t>() % 0xFF) + 1;
|
||||
@@ -214,14 +179,14 @@ void Server::send(const void* data, size_t size) const {
|
||||
void Server::send_6xB4x46() const {
|
||||
// Note: This function is not part of the original implementation; it was
|
||||
// factored out from its callsites in this file and the strings were changed.
|
||||
auto l = this->base()->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
G_ServerVersionStrings_GC_Ep3_6xB4x46 cmd46;
|
||||
cmd46.version_signature = VERSION_SIGNATURE;
|
||||
cmd46.date_str1 = format_time(this->base()->card_index->definitions_mtime() * 1000000);
|
||||
cmd46.date_str1 = format_time(this->card_index->definitions_mtime() * 1000000);
|
||||
cmd46.date_str2 = string_printf("Lobby/%08" PRIX32, l->lobby_id);
|
||||
this->send(cmd46);
|
||||
}
|
||||
@@ -248,9 +213,8 @@ void Server::send_commands_for_joining_spectator(Channel& c, bool is_trial) cons
|
||||
}
|
||||
}
|
||||
|
||||
auto map = this->base()->last_chosen_map;
|
||||
if (map) {
|
||||
string data = this->prepare_6xB6x41_map_definition(map, is_trial);
|
||||
if (this->last_chosen_map) {
|
||||
string data = this->prepare_6xB6x41_map_definition(this->last_chosen_map, is_trial);
|
||||
c.send(0x6C, 0x00, data);
|
||||
}
|
||||
|
||||
@@ -263,19 +227,9 @@ void Server::send_commands_for_joining_spectator(Channel& c, bool is_trial) cons
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void Server::log_debug(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
if (l && (this->base()->behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
this->base()->log.info_v(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_debug_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
if (l && (this->base()->behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
auto l = this->lobby.lock();
|
||||
if (l && (this->behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::string buf = string_vprintf(fmt, va);
|
||||
@@ -286,7 +240,7 @@ __attribute__((format(printf, 2, 3))) void Server::send_debug_message_printf(con
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_info_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->base()->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (l) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
@@ -299,19 +253,21 @@ __attribute__((format(printf, 2, 3))) void Server::send_info_message_printf(cons
|
||||
|
||||
void Server::send_debug_command_received_message(
|
||||
uint8_t client_id, uint8_t subsubcommand, const char* description) const {
|
||||
this->log_debug("%hhu/CAx%02hhX %s", client_id, subsubcommand, description);
|
||||
this->log.debug("%hhu/CAx%02hhX %s", client_id, subsubcommand, description);
|
||||
this->send_debug_message_printf("$C5%hhu/CAx%02hhX %s", client_id, subsubcommand, description);
|
||||
}
|
||||
|
||||
void Server::send_debug_command_received_message(uint8_t subsubcommand, const char* description) const {
|
||||
this->log_debug("*/CAx%02hhX %s", subsubcommand, description);
|
||||
this->log.debug("*/CAx%02hhX %s", subsubcommand, description);
|
||||
this->send_debug_message_printf("$C5*/CAx%02hhX %s", subsubcommand, description);
|
||||
}
|
||||
|
||||
void Server::send_debug_message_if_error_code_nonzero(
|
||||
uint8_t client_id, int32_t error_code) const {
|
||||
if (error_code != 0) {
|
||||
this->send_debug_message_printf("Client %hhu error\nCode: -0x%zX", client_id, static_cast<ssize_t>(-error_code));
|
||||
if (error_code < 0) {
|
||||
this->send_debug_message_printf("$C4%hhu/ERROR -0x%zX", client_id, static_cast<ssize_t>(-error_code));
|
||||
} else if (error_code > 0) {
|
||||
this->send_debug_message_printf("$C4%hhu/ERROR 0x%zX", client_id, static_cast<ssize_t>(error_code));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -374,7 +330,7 @@ void Server::draw_phase_before() {
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_ref(uint16_t card_ref) const {
|
||||
try {
|
||||
return this->base()->card_index->definition_for_id(this->card_id_for_card_ref(card_ref));
|
||||
return this->card_index->definition_for_id(this->card_id_for_card_ref(card_ref));
|
||||
} catch (const out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -455,7 +411,7 @@ bool Server::card_ref_is_empty_or_has_valid_card_id(uint16_t card_ref) const {
|
||||
|
||||
bool Server::check_for_battle_end() {
|
||||
bool ret = false;
|
||||
if (this->base()->map_and_rules1->rules.hp_type == HPType::DEFEAT_TEAM) {
|
||||
if (this->map_and_rules1->rules.hp_type == HPType::DEFEAT_TEAM) {
|
||||
bool teams_defeated[2] = {true, true};
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->player_states[client_id];
|
||||
@@ -551,7 +507,7 @@ void Server::check_for_destroyed_cards_and_send_6xB4x05_6xB4x02() {
|
||||
|
||||
bool Server::check_presence_entry(uint8_t client_id) const {
|
||||
return (client_id < 4)
|
||||
? this->base()->presence_entries[client_id].player_present
|
||||
? this->presence_entries[client_id].player_present
|
||||
: false;
|
||||
}
|
||||
|
||||
@@ -569,7 +525,7 @@ void Server::clear_player_flags_after_dice_phase() {
|
||||
void Server::compute_all_map_occupied_bits() {
|
||||
for (size_t y = 0; y < 0x10; y++) {
|
||||
for (size_t x = 0; x < 0x10; x++) {
|
||||
this->base()->map_and_rules1->clear_occupied_bit_for_tile(x, y);
|
||||
this->map_and_rules1->clear_occupied_bit_for_tile(x, y);
|
||||
}
|
||||
}
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
@@ -602,7 +558,7 @@ void Server::copy_player_states_to_prev_states() {
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_id(uint16_t card_id) const {
|
||||
try {
|
||||
return this->base()->card_index->definition_for_id(card_id);
|
||||
return this->card_index->definition_for_id(card_id);
|
||||
} catch (const out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -628,8 +584,8 @@ void Server::destroy_cards_with_zero_hp() {
|
||||
}
|
||||
|
||||
void Server::determine_first_team_turn() {
|
||||
this->team_client_count[0] = this->base()->map_and_rules1->num_team0_players;
|
||||
this->team_client_count[1] = this->base()->map_and_rules1->num_players - this->team_client_count[0];
|
||||
this->team_client_count[0] = this->map_and_rules1->num_team0_players;
|
||||
this->team_client_count[1] = this->map_and_rules1->num_players - this->team_client_count[0];
|
||||
this->first_team_turn = 0xFF;
|
||||
while (this->first_team_turn == 0xFF) {
|
||||
uint8_t results[2] = {0, 0};
|
||||
@@ -709,11 +665,11 @@ void Server::draw_phase_after() {
|
||||
this->round_num++;
|
||||
|
||||
if (this->current_team_turn1 == this->first_team_turn) {
|
||||
if (this->base()->map_and_rules1->rules.overall_time_limit > 0) {
|
||||
if (this->map_and_rules1->rules.overall_time_limit > 0) {
|
||||
// Battle time limits are specified in increments of 5 minutes.
|
||||
// Note: This part is not based on the original code because the timing
|
||||
// facilities used are different.
|
||||
uint64_t limit_5mins = this->base()->map_and_rules1->rules.overall_time_limit;
|
||||
uint64_t limit_5mins = this->map_and_rules1->rules.overall_time_limit;
|
||||
uint64_t end_usecs = this->battle_start_usecs + (limit_5mins * 300 * 1000 * 1000);
|
||||
if (now() >= end_usecs) {
|
||||
this->overall_time_expired = true;
|
||||
@@ -1042,7 +998,7 @@ void Server::action_phase_before() {
|
||||
G_SetPlayerNames_GC_Ep3_6xB4x1C Server::prepare_6xB4x1C_names_update() const {
|
||||
G_SetPlayerNames_GC_Ep3_6xB4x1C cmd;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
cmd.entries[z] = this->base()->name_entries[z];
|
||||
cmd.entries[z] = this->name_entries[z];
|
||||
}
|
||||
return cmd;
|
||||
}
|
||||
@@ -1117,7 +1073,7 @@ G_UpdateDecks_GC_Ep3_6xB4x07 Server::prepare_6xB4x07_decks_update() const {
|
||||
cmd07.entries[z].team_id = 0xFFFFFFFF;
|
||||
} else {
|
||||
cmd07.entries_present[z] = 1;
|
||||
cmd07.entries[z] = *this->base()->deck_entries[z];
|
||||
cmd07.entries[z] = *this->deck_entries[z];
|
||||
}
|
||||
}
|
||||
return cmd07;
|
||||
@@ -1126,9 +1082,9 @@ G_UpdateDecks_GC_Ep3_6xB4x07 Server::prepare_6xB4x07_decks_update() const {
|
||||
void Server::send_all_state_updates() {
|
||||
this->send(this->prepare_6xB4x07_decks_update());
|
||||
|
||||
G_UpdateMap_GC_Ep3_6xB4x05 cmd05;
|
||||
cmd05.state = *this->base()->map_and_rules1;
|
||||
this->send(cmd05);
|
||||
G_UpdateMap_GC_Ep3_6xB4x05 cmd;
|
||||
cmd.state = *this->map_and_rules1;
|
||||
this->send(cmd);
|
||||
|
||||
this->send_6xB4x02_for_all_players_if_needed();
|
||||
}
|
||||
@@ -1185,7 +1141,7 @@ void Server::set_client_id_ready_to_advance_phase(uint8_t client_id) {
|
||||
ps->assist_flags |= 1;
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
if (this->battle_phase == BattlePhase::DICE) {
|
||||
if (!(ps->assist_flags & 0x8000) || this->base()->map_and_rules1->rules.disable_dice_boost) {
|
||||
if (!(ps->assist_flags & 0x8000) || this->map_and_rules1->rules.disable_dice_boost) {
|
||||
ps->assist_flags &= 0xFFFF7FFF;
|
||||
ps->roll_main_dice();
|
||||
if ((ps->get_atk_points() < 3) && (ps->get_def_points() < 3)) {
|
||||
@@ -1265,8 +1221,8 @@ void Server::set_phase_after() {
|
||||
switch (this->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::SHUFFLE_ALL:
|
||||
case AssistEffect::SHUFFLE_GROUP:
|
||||
if (!this->base()->map_and_rules1->rules.disable_deck_shuffle &&
|
||||
!this->base()->map_and_rules1->rules.disable_deck_loop) {
|
||||
if (!this->map_and_rules1->rules.disable_deck_shuffle &&
|
||||
!this->map_and_rules1->rules.disable_deck_loop) {
|
||||
ps->discard_and_redraw_hand();
|
||||
}
|
||||
break;
|
||||
@@ -1321,7 +1277,7 @@ void Server::move_phase_before() {
|
||||
}
|
||||
|
||||
void Server::set_player_deck_valid(uint8_t client_id) {
|
||||
this->base()->presence_entries[client_id].deck_valid = true;
|
||||
this->presence_entries[client_id].deck_valid = true;
|
||||
}
|
||||
|
||||
void Server::setup_and_start_battle() {
|
||||
@@ -1332,14 +1288,14 @@ void Server::setup_and_start_battle() {
|
||||
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (!this->check_presence_entry(z)) {
|
||||
this->base()->name_entries[z].clear();
|
||||
this->name_entries[z].clear();
|
||||
} else {
|
||||
this->player_states[z].reset(new PlayerState(z, this->shared_from_this()));
|
||||
this->player_states[z]->init();
|
||||
}
|
||||
}
|
||||
|
||||
if (this->base()->map_and_rules1->rules.hp_type == HPType::COMMON_HP) {
|
||||
if (this->map_and_rules1->rules.hp_type == HPType::COMMON_HP) {
|
||||
int16_t team_hp[2] = {99, 99};
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
@@ -1367,7 +1323,7 @@ void Server::setup_and_start_battle() {
|
||||
}
|
||||
}
|
||||
|
||||
this->base()->map_and_rules1->start_facing_directions = 0;
|
||||
this->map_and_rules1->start_facing_directions = 0;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
@@ -1380,8 +1336,8 @@ void Server::setup_and_start_battle() {
|
||||
|
||||
for (size_t y = 0; y < 0x10; y++) {
|
||||
for (size_t x = 0; x < 0x10; x++) {
|
||||
if (this->base()->map_and_rules1->map.tiles[y][x] > 1) {
|
||||
this->base()->map_and_rules1->map.tiles[y][x] = 1;
|
||||
if (this->map_and_rules1->map.tiles[y][x] > 1) {
|
||||
this->map_and_rules1->map.tiles[y][x] = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1395,7 +1351,7 @@ void Server::setup_and_start_battle() {
|
||||
|
||||
for (size_t y = 0; y < 0x10; y++) {
|
||||
for (size_t x = 0; x < 0x10; x++) {
|
||||
uint8_t tile_spec = this->base()->overlay_state.tiles[y][x];
|
||||
uint8_t tile_spec = this->overlay_state.tiles[y][x];
|
||||
uint8_t tile_type = tile_spec & 0xF0;
|
||||
uint8_t tile_subtype = tile_spec & 0x0F;
|
||||
if (tile_type == 0x30) {
|
||||
@@ -1407,7 +1363,7 @@ void Server::setup_and_start_battle() {
|
||||
this->warp_positions[tile_subtype][1][1] = y;
|
||||
}
|
||||
} else if ((tile_type == 0x10) || (tile_type == 0x20) || (tile_type == 0x50)) {
|
||||
this->base()->map_and_rules1->map.tiles[y][x] = 0;
|
||||
this->map_and_rules1->map.tiles[y][x] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1418,7 +1374,7 @@ void Server::setup_and_start_battle() {
|
||||
size_t num_trap_tiles = 0;
|
||||
for (size_t y = 0; y < 0x10; y++) {
|
||||
for (size_t x = 0; x < 0x10; x++) {
|
||||
if ((this->base()->overlay_state.tiles[y][x] == (trap_type | 0x40)) &&
|
||||
if ((this->overlay_state.tiles[y][x] == (trap_type | 0x40)) &&
|
||||
(num_trap_tiles < 8)) {
|
||||
this->trap_tile_locs[trap_type][num_trap_tiles][0] = x;
|
||||
this->trap_tile_locs[trap_type][num_trap_tiles][1] = y;
|
||||
@@ -1450,7 +1406,7 @@ void Server::setup_and_start_battle() {
|
||||
this->send_6xB4x50_trap_tile_locations();
|
||||
|
||||
G_UpdateMap_GC_Ep3_6xB4x05 cmd05;
|
||||
cmd05.state = *this->base()->map_and_rules1;
|
||||
cmd05.state = *this->map_and_rules1;
|
||||
cmd05.unknown_a1 = 1;
|
||||
this->send(cmd05);
|
||||
|
||||
@@ -1474,7 +1430,7 @@ void Server::update_battle_state_flags_and_send_6xB4x03_if_needed(
|
||||
cmd.state.team_dice_boost[0] = this->team_dice_boost[0];
|
||||
cmd.state.team_dice_boost[1] = this->team_dice_boost[1];
|
||||
cmd.state.first_team_turn = this->first_team_turn;
|
||||
cmd.state.tournament_flag = this->tournament_flag;
|
||||
cmd.state.tournament_flag = this->is_tournament ? 1 : 0;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
@@ -1496,13 +1452,13 @@ bool Server::update_registration_phase() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->base()->map_and_rules1->num_players == 0) {
|
||||
if (this->map_and_rules1->num_players == 0) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_NUM_PLAYERS;
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->base()->map_and_rules1->num_players != this->base()->num_clients_present) {
|
||||
if (this->map_and_rules1->num_players != this->num_clients_present) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_PLAYERS;
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
@@ -1510,12 +1466,12 @@ bool Server::update_registration_phase() {
|
||||
|
||||
size_t num_team0_registered_players = 0;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (this->base()->deck_entries[z]->team_id == 0) {
|
||||
if (this->deck_entries[z]->team_id == 0) {
|
||||
num_team0_registered_players++;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_team0_registered_players != this->base()->map_and_rules1->num_team0_players) {
|
||||
if (num_team0_registered_players != this->map_and_rules1->num_team0_players) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_DECKS;
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
@@ -1573,7 +1529,7 @@ void Server::on_server_data_input(const string& data) {
|
||||
|
||||
(this->*handler)(unmasked_data);
|
||||
|
||||
if (this->hard_reset_flag && (this->base())) {
|
||||
if (this->hard_reset_flag) {
|
||||
// In the original implementation, this command recreates the server object.
|
||||
// This is possible because the dispatch function is not part of the server
|
||||
// object in the original implementation; however, in our implementation, it
|
||||
@@ -1851,31 +1807,30 @@ void Server::handle_CAx13_update_map_during_setup(const string& data) {
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "UPDATE MAP");
|
||||
|
||||
auto b = this->base();
|
||||
if (!this->battle_in_progress &&
|
||||
(this->setup_phase == SetupPhase::REGISTRATION) &&
|
||||
(b->map_and_rules1->num_players == 0) &&
|
||||
(this->map_and_rules1->num_players == 0) &&
|
||||
(this->registration_phase != RegistrationPhase::REGISTERED) &&
|
||||
(this->registration_phase != RegistrationPhase::BATTLE_STARTED)) {
|
||||
*b->map_and_rules1 = in_cmd.map_and_rules_state;
|
||||
*b->map_and_rules2 = in_cmd.map_and_rules_state;
|
||||
*this->map_and_rules1 = in_cmd.map_and_rules_state;
|
||||
*this->map_and_rules2 = in_cmd.map_and_rules_state;
|
||||
if (this->override_environment_number != 0xFF) {
|
||||
b->map_and_rules1->environment_number = this->override_environment_number;
|
||||
b->map_and_rules2->environment_number = this->override_environment_number;
|
||||
this->map_and_rules1->environment_number = this->override_environment_number;
|
||||
this->map_and_rules2->environment_number = this->override_environment_number;
|
||||
this->override_environment_number = 0xFF;
|
||||
}
|
||||
b->overlay_state = in_cmd.overlay_state;
|
||||
if (b->behavior_flags & BehaviorFlag::DISABLE_TIME_LIMITS) {
|
||||
b->map_and_rules1->rules.overall_time_limit = 0;
|
||||
b->map_and_rules1->rules.phase_time_limit = 0;
|
||||
b->map_and_rules2->rules.overall_time_limit = 0;
|
||||
b->map_and_rules2->rules.phase_time_limit = 0;
|
||||
this->overlay_state = in_cmd.overlay_state;
|
||||
if (this->behavior_flags & BehaviorFlag::DISABLE_TIME_LIMITS) {
|
||||
this->map_and_rules1->rules.overall_time_limit = 0;
|
||||
this->map_and_rules1->rules.phase_time_limit = 0;
|
||||
this->map_and_rules2->rules.overall_time_limit = 0;
|
||||
this->map_and_rules2->rules.phase_time_limit = 0;
|
||||
}
|
||||
if (b->map_and_rules1->rules.check_invalid_fields()) {
|
||||
b->map_and_rules1->rules.check_and_reset_invalid_fields();
|
||||
if (this->map_and_rules1->rules.check_invalid_fields()) {
|
||||
this->map_and_rules1->rules.check_and_reset_invalid_fields();
|
||||
}
|
||||
if (b->map_and_rules1->num_players_per_team == 0) {
|
||||
b->map_and_rules1->num_players_per_team = b->map_and_rules1->num_players >> 1;
|
||||
if (this->map_and_rules1->num_players_per_team == 0) {
|
||||
this->map_and_rules1->num_players_per_team = this->map_and_rules1->num_players >> 1;
|
||||
}
|
||||
this->update_registration_phase();
|
||||
}
|
||||
@@ -1895,31 +1850,31 @@ void Server::handle_CAx14_update_deck_during_setup(const string& data) {
|
||||
}
|
||||
DeckEntry entry = in_cmd.entry;
|
||||
int32_t verify_error = 0;
|
||||
if (!(this->base()->behavior_flags & BehaviorFlag::SKIP_DECK_VERIFY)) {
|
||||
if (!(this->behavior_flags & BehaviorFlag::SKIP_DECK_VERIFY)) {
|
||||
// Note: Sega's original implementation doesn't use the card counts here
|
||||
if (this->base()->behavior_flags & BehaviorFlag::IGNORE_CARD_COUNTS) {
|
||||
if (this->behavior_flags & BehaviorFlag::IGNORE_CARD_COUNTS) {
|
||||
verify_error = this->ruler_server->verify_deck(entry.card_ids);
|
||||
} else {
|
||||
verify_error = this->ruler_server->verify_deck(entry.card_ids,
|
||||
&this->base()->client_card_counts[in_cmd.client_id]);
|
||||
&this->client_card_counts[in_cmd.client_id]);
|
||||
}
|
||||
}
|
||||
if (verify_error) {
|
||||
throw runtime_error(string_printf("invalid deck: -0x%" PRIX32, verify_error));
|
||||
}
|
||||
if (!(this->base()->behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
|
||||
if (!(this->behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
|
||||
this->ruler_server->replace_D1_D2_rarity_cards_with_Attack(entry.card_ids);
|
||||
}
|
||||
*this->base()->deck_entries[in_cmd.client_id] = in_cmd.entry;
|
||||
this->base()->presence_entries[in_cmd.client_id].player_present = true;
|
||||
this->base()->presence_entries[in_cmd.client_id].is_cpu_player = in_cmd.is_cpu_player;
|
||||
*this->deck_entries[in_cmd.client_id] = in_cmd.entry;
|
||||
this->presence_entries[in_cmd.client_id].player_present = true;
|
||||
this->presence_entries[in_cmd.client_id].is_cpu_player = in_cmd.is_cpu_player;
|
||||
this->set_player_deck_valid(in_cmd.client_id);
|
||||
}
|
||||
|
||||
this->base()->num_clients_present = 0;
|
||||
this->num_clients_present = 0;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (this->check_presence_entry(z)) {
|
||||
this->base()->num_clients_present++;
|
||||
this->num_clients_present++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1941,13 +1896,13 @@ void Server::handle_CAx1B_update_player_name(const string& data) {
|
||||
in_cmd.entry.client_id, in_cmd.header.subsubcommand, "UPDATE NAME");
|
||||
|
||||
if (!this->is_registration_complete() && (in_cmd.entry.client_id < 4)) {
|
||||
this->base()->name_entries[in_cmd.entry.client_id] = in_cmd.entry;
|
||||
this->base()->name_entries_valid[in_cmd.entry.client_id] = false;
|
||||
this->name_entries[in_cmd.entry.client_id] = in_cmd.entry;
|
||||
this->name_entries_valid[in_cmd.entry.client_id] = false;
|
||||
}
|
||||
|
||||
G_SetPlayerNames_GC_Ep3_6xB4x1C out_cmd;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
out_cmd.entries[z] = this->base()->name_entries[z];
|
||||
out_cmd.entries[z] = this->name_entries[z];
|
||||
}
|
||||
this->send(out_cmd);
|
||||
}
|
||||
@@ -1962,16 +1917,16 @@ void Server::handle_CAx1D_start_battle(const string& data) {
|
||||
G_RejectBattleStartRequest_GC_Ep3_6xB4x53 out_cmd;
|
||||
out_cmd.setup_phase = this->setup_phase;
|
||||
out_cmd.registration_phase = this->registration_phase;
|
||||
out_cmd.state = *this->base()->map_and_rules1;
|
||||
out_cmd.state = *this->map_and_rules1;
|
||||
this->send(out_cmd);
|
||||
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
this->base()->deck_entries[z]->clear();
|
||||
this->base()->presence_entries[z].clear();
|
||||
this->deck_entries[z]->clear();
|
||||
this->presence_entries[z].clear();
|
||||
}
|
||||
this->battle_in_progress = false;
|
||||
} else {
|
||||
auto l = this->base()->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
}
|
||||
@@ -2163,12 +2118,12 @@ void Server::handle_CAx40_map_list_request(const string& data) {
|
||||
this->send_debug_command_received_message(
|
||||
in_cmd.header.subsubcommand, "MAP LIST");
|
||||
|
||||
auto l = this->base()->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
const auto& list_data = this->base()->map_index->get_compressed_list(l->count_clients());
|
||||
const auto& list_data = this->map_index->get_compressed_list(l->count_clients());
|
||||
|
||||
StringWriter w;
|
||||
uint32_t subcommand_size = (list_data.size() + sizeof(G_MapList_GC_Ep3_6xB6x40) + 3) & (~3);
|
||||
@@ -2191,15 +2146,13 @@ void Server::handle_CAx41_map_request(const string& data) {
|
||||
this->send_debug_command_received_message(
|
||||
cmd.header.subsubcommand, "MAP DATA");
|
||||
|
||||
auto base = this->base();
|
||||
auto l = base->lobby.lock();
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
base->last_chosen_map = base->map_index->definition_for_number(cmd.map_number);
|
||||
auto out_cmd = this->prepare_6xB6x41_map_definition(
|
||||
base->last_chosen_map, l->flags & Lobby::Flag::IS_EP3_TRIAL);
|
||||
this->last_chosen_map = this->map_index->definition_for_number(cmd.map_number);
|
||||
auto out_cmd = this->prepare_6xB6x41_map_definition(this->last_chosen_map, l->flags & Lobby::Flag::IS_EP3_TRIAL);
|
||||
send_command(l, 0x6C, 0x00, out_cmd);
|
||||
for (auto watcher_l : l->watcher_lobbies) {
|
||||
send_command_if_not_loading(watcher_l, 0x6C, 0x00, out_cmd);
|
||||
@@ -2233,7 +2186,7 @@ void Server::handle_CAx49_card_counts(const string& data) {
|
||||
|
||||
// Note: Sega's implmentation completely ignores this command. This
|
||||
// implementation is not based on the original code.
|
||||
auto& dest_counts = this->base()->client_card_counts[in_cmd.header.sender_client_id];
|
||||
auto& dest_counts = this->client_card_counts[in_cmd.header.sender_client_id];
|
||||
dest_counts = in_cmd.card_id_to_count;
|
||||
decrypt_trivial_gci_data(dest_counts.data(), dest_counts.bytes(), in_cmd.basis);
|
||||
}
|
||||
@@ -2675,7 +2628,7 @@ void Server::send_6xB4x39() const {
|
||||
void Server::send_6xB4x05() {
|
||||
this->compute_all_map_occupied_bits();
|
||||
G_UpdateMap_GC_Ep3_6xB4x05 cmd;
|
||||
cmd.state = *this->base()->map_and_rules1;
|
||||
cmd.state = *this->map_and_rules1;
|
||||
this->send(cmd);
|
||||
}
|
||||
|
||||
|
||||
+54
-68
@@ -32,75 +32,39 @@ namespace Episode3 {
|
||||
*
|
||||
* There are likely undiscovered bugs in this code, some originally written by
|
||||
* Sega, but more written by me as I manually transcribed and updated this code.
|
||||
*
|
||||
* Class ownership levels (classes may only contain weak_ptrs, not shared_ptrs,
|
||||
* to classes at the same or higher level):
|
||||
* - Server
|
||||
* - - RulerServer
|
||||
* - - - AssistServer
|
||||
* - - - CardSpecial
|
||||
* - - - - StateFlags
|
||||
* - - - - DeckEntry
|
||||
* - - - - PlayerState
|
||||
* - - - - - Card
|
||||
* - - - - - - CardShortStatus
|
||||
* - - - - - - DeckState
|
||||
* - - - - - - HandAndEquipState
|
||||
* - - - - - - MapAndRulesState / OverlayState
|
||||
* - - - - - - - Everything within DataIndexes
|
||||
*/
|
||||
|
||||
// Class ownership levels (classes may only contain weak_ptrs, not shared_ptrs,
|
||||
// to classes at the same or higher level):
|
||||
// - ServerBase
|
||||
// - - Server
|
||||
// - - - RulerServer
|
||||
// - - - - AssistServer
|
||||
// - - - - CardSpecial
|
||||
// - - - - - StateFlags
|
||||
// - - - - - DeckEntry
|
||||
// - - - - - PlayerState
|
||||
// - - - - - - Card
|
||||
// - - - - - - - CardShortStatus
|
||||
// - - - - - - - DeckState
|
||||
// - - - - - - - HandAndEquipState
|
||||
// - - - - - - - MapAndRulesState / OverlayState
|
||||
// - - - - - - - - Everything within DataIndexes
|
||||
|
||||
class Server;
|
||||
|
||||
class ServerBase : public std::enable_shared_from_this<ServerBase> {
|
||||
class Server : public std::enable_shared_from_this<Server> {
|
||||
// In the original code, there is a TCardServerBase class and a TCardServer
|
||||
// class, with the former containing some basic parts of the game state and
|
||||
// a pointer to the latter. It seems these two classes exist (instead of one
|
||||
// big class) so that the force reset command could be implemented; however,
|
||||
// it appears that that command is never sent by the client, so we combine
|
||||
// the two classes into one in our implementation.
|
||||
public:
|
||||
ServerBase(
|
||||
std::shared_ptr<Lobby> lobby,
|
||||
Server(std::shared_ptr<Lobby> lobby,
|
||||
std::shared_ptr<const CardIndex> card_index,
|
||||
std::shared_ptr<const MapIndex> map_index,
|
||||
uint32_t behavior_flags,
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt,
|
||||
std::shared_ptr<const MapIndex::MapEntry> map_if_tournament);
|
||||
void init();
|
||||
void reset();
|
||||
void recreate_server();
|
||||
|
||||
struct PresenceEntry {
|
||||
uint8_t player_present;
|
||||
uint8_t deck_valid;
|
||||
uint8_t is_cpu_player;
|
||||
PresenceEntry();
|
||||
void clear();
|
||||
} __attribute__((packed));
|
||||
|
||||
std::weak_ptr<Lobby> lobby;
|
||||
std::shared_ptr<const CardIndex> card_index;
|
||||
std::shared_ptr<const MapIndex> map_index;
|
||||
uint32_t behavior_flags;
|
||||
PrefixedLogger log;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
bool is_tournament;
|
||||
std::shared_ptr<const MapIndex::MapEntry> last_chosen_map;
|
||||
|
||||
std::shared_ptr<MapAndRulesState> map_and_rules1;
|
||||
std::shared_ptr<MapAndRulesState> map_and_rules2;
|
||||
std::shared_ptr<DeckEntry> deck_entries[4];
|
||||
std::shared_ptr<Server> server;
|
||||
parray<PresenceEntry, 4> presence_entries;
|
||||
uint8_t num_clients_present;
|
||||
parray<NameEntry, 4> name_entries;
|
||||
parray<uint8_t, 4> name_entries_valid;
|
||||
OverlayState overlay_state;
|
||||
parray<parray<uint8_t, 0x2F0>, 4> client_card_counts;
|
||||
};
|
||||
|
||||
class Server : public std::enable_shared_from_this<Server> {
|
||||
public:
|
||||
explicit Server(std::shared_ptr<ServerBase> base);
|
||||
void init();
|
||||
std::shared_ptr<ServerBase> base();
|
||||
std::shared_ptr<const ServerBase> base() const;
|
||||
|
||||
int8_t get_winner_team_id() const;
|
||||
|
||||
@@ -122,8 +86,6 @@ public:
|
||||
|
||||
void send_commands_for_joining_spectator(Channel& ch, bool is_trial) const;
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void log_debug(const char* fmt, ...) const;
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void send_debug_message_printf(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3))) void send_info_message_printf(const char* fmt, ...) const;
|
||||
void send_debug_command_received_message(
|
||||
@@ -244,12 +206,38 @@ private:
|
||||
typedef void (Server::*handler_t)(const std::string&);
|
||||
static const std::unordered_map<uint8_t, handler_t> subcommand_handlers;
|
||||
|
||||
std::weak_ptr<ServerBase> w_base;
|
||||
|
||||
public:
|
||||
bool tournament_match_result_sent; // Not part of original implementation
|
||||
uint8_t override_environment_number; // Not part of original implementation
|
||||
// These fields are not part of the original implementation
|
||||
std::weak_ptr<Lobby> lobby;
|
||||
std::shared_ptr<const CardIndex> card_index;
|
||||
std::shared_ptr<const MapIndex> map_index;
|
||||
uint32_t behavior_flags;
|
||||
PrefixedLogger log;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
std::shared_ptr<const MapIndex::MapEntry> last_chosen_map;
|
||||
bool is_tournament;
|
||||
bool tournament_match_result_sent;
|
||||
uint8_t override_environment_number;
|
||||
|
||||
// These fields were originally contained in the TCardServerBase object
|
||||
struct PresenceEntry {
|
||||
uint8_t player_present;
|
||||
uint8_t deck_valid;
|
||||
uint8_t is_cpu_player;
|
||||
PresenceEntry();
|
||||
void clear();
|
||||
} __attribute__((packed));
|
||||
std::shared_ptr<MapAndRulesState> map_and_rules1;
|
||||
std::shared_ptr<MapAndRulesState> map_and_rules2;
|
||||
std::shared_ptr<DeckEntry> deck_entries[4];
|
||||
parray<PresenceEntry, 4> presence_entries;
|
||||
uint8_t num_clients_present;
|
||||
parray<NameEntry, 4> name_entries;
|
||||
parray<uint8_t, 4> name_entries_valid;
|
||||
OverlayState overlay_state;
|
||||
parray<parray<uint8_t, 0x2F0>, 4> client_card_counts;
|
||||
|
||||
// These fields were originally contained in the TCardServer object
|
||||
uint32_t battle_finished;
|
||||
uint32_t battle_in_progress;
|
||||
uint32_t round_num;
|
||||
@@ -264,7 +252,6 @@ public:
|
||||
uint32_t num_pending_attacks;
|
||||
parray<uint8_t, 4> client_done_enqueuing_attacks;
|
||||
parray<uint8_t, 4> player_ready_to_end_phase;
|
||||
std::shared_ptr<PSOLFGEncryption> random_crypt;
|
||||
uint32_t unknown_a10;
|
||||
uint32_t overall_time_expired;
|
||||
// Note: In the original implementation, this is a uint32_t and is measured in
|
||||
@@ -292,7 +279,6 @@ public:
|
||||
parray<uint32_t, 2> team_num_ally_fcs_destroyed;
|
||||
parray<uint32_t, 2> team_num_cards_destroyed;
|
||||
uint32_t hard_reset_flag;
|
||||
uint8_t tournament_flag;
|
||||
parray<uint8_t, 5> num_trap_tiles_of_type;
|
||||
parray<uint8_t, 5> chosen_trap_tile_index_of_type;
|
||||
parray<parray<parray<uint8_t, 2>, 8>, 5> trap_tile_locs;
|
||||
|
||||
+1
-1
@@ -90,7 +90,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
// Types 2 and 3 may be distinguished by the presence of the battle_record
|
||||
// field - in replay games, it will be present; in watcher games it will be
|
||||
// absent.
|
||||
std::shared_ptr<Episode3::ServerBase> ep3_server_base; // Only used in primary games
|
||||
std::shared_ptr<Episode3::Server> ep3_server; // Only used in primary games
|
||||
std::weak_ptr<Lobby> watched_lobby; // Only used in watcher games
|
||||
std::unordered_set<shared_ptr<Lobby>> watcher_lobbies; // Only used in primary games
|
||||
std::shared_ptr<Episode3::BattleRecord> battle_record; // Not used in watcher games
|
||||
|
||||
+11
-11
@@ -1279,22 +1279,22 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
throw runtime_error("unknown Episode 3 server data request");
|
||||
}
|
||||
|
||||
if (!l->ep3_server_base || l->ep3_server_base->server->battle_finished) {
|
||||
if (!l->ep3_server_base) {
|
||||
if (!l->ep3_server || l->ep3_server->battle_finished) {
|
||||
if (!l->ep3_server) {
|
||||
l->log.info("Creating Episode 3 server state");
|
||||
} else {
|
||||
l->log.info("Recreating Episode 3 server state");
|
||||
}
|
||||
auto tourn = l->tournament_match ? l->tournament_match->tournament.lock() : nullptr;
|
||||
bool is_trial = (l->flags & Lobby::Flag::IS_EP3_TRIAL);
|
||||
l->ep3_server_base = make_shared<Episode3::ServerBase>(
|
||||
l->ep3_server = make_shared<Episode3::Server>(
|
||||
l,
|
||||
is_trial ? s->ep3_card_index_trial : s->ep3_card_index,
|
||||
s->ep3_map_index,
|
||||
s->ep3_behavior_flags,
|
||||
l->random_crypt,
|
||||
tourn ? tourn->get_map() : nullptr);
|
||||
l->ep3_server_base->init();
|
||||
l->ep3_server->init();
|
||||
|
||||
if (s->ep3_behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES) {
|
||||
for (size_t z = 0; z < l->max_clients; z++) {
|
||||
@@ -1327,11 +1327,11 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
send_text_message(l, u"$C6Recording enabled");
|
||||
}
|
||||
}
|
||||
l->ep3_server_base->server->on_server_data_input(data);
|
||||
l->ep3_server->on_server_data_input(data);
|
||||
if (l->tournament_match &&
|
||||
l->ep3_server_base->server->setup_phase == Episode3::SetupPhase::BATTLE_ENDED &&
|
||||
!l->ep3_server_base->server->tournament_match_result_sent) {
|
||||
int8_t winner_team_id = l->ep3_server_base->server->get_winner_team_id();
|
||||
l->ep3_server->setup_phase == Episode3::SetupPhase::BATTLE_ENDED &&
|
||||
!l->ep3_server->tournament_match_result_sent) {
|
||||
int8_t winner_team_id = l->ep3_server->get_winner_team_id();
|
||||
if (winner_team_id == -1) {
|
||||
throw runtime_error("match complete, but winner team not specified");
|
||||
}
|
||||
@@ -1349,7 +1349,7 @@ static void on_CA_Ep3(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
send_ep3_tournament_match_result(s, l, l->tournament_match);
|
||||
|
||||
on_tournament_bracket_updated(s, tourn);
|
||||
l->ep3_server_base->server->tournament_match_result_sent = true;
|
||||
l->ep3_server->tournament_match_result_sent = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3534,8 +3534,8 @@ static void on_6F(shared_ptr<ServerState> s, shared_ptr<Client> c,
|
||||
auto watched_lobby = l->watched_lobby.lock();
|
||||
if (l->battle_player && (l->flags & Lobby::Flag::START_BATTLE_PLAYER_IMMEDIATELY)) {
|
||||
l->battle_player->start();
|
||||
} else if (watched_lobby && watched_lobby->ep3_server_base) {
|
||||
watched_lobby->ep3_server_base->server->send_commands_for_joining_spectator(
|
||||
} else if (watched_lobby && watched_lobby->ep3_server) {
|
||||
watched_lobby->ep3_server->send_commands_for_joining_spectator(
|
||||
c->channel, c->flags & Client::Flag::IS_EP3_TRIAL_EDITION);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,7 @@ static void forward_subcommand(shared_ptr<Lobby> l, shared_ptr<Client> c,
|
||||
// battle, forward everything to watcher lobbies.
|
||||
if (size &&
|
||||
(watcher_subcommands.count(*reinterpret_cast<const uint8_t*>(data) ||
|
||||
(l->ep3_server_base &&
|
||||
l->ep3_server_base->server->setup_phase != Episode3::SetupPhase::REGISTRATION)))) {
|
||||
(l->ep3_server && l->ep3_server->setup_phase != Episode3::SetupPhase::REGISTRATION)))) {
|
||||
for (const auto& watcher_lobby : l->watcher_lobbies) {
|
||||
forward_subcommand(watcher_lobby, c, command, flag, data, size);
|
||||
}
|
||||
|
||||
+3
-3
@@ -2472,9 +2472,9 @@ void send_ep3_game_details(shared_ptr<Client> c, shared_ptr<Lobby> l) {
|
||||
flag = 0x04;
|
||||
|
||||
} else if (primary_lobby &&
|
||||
primary_lobby->ep3_server_base &&
|
||||
primary_lobby->ep3_server_base->server->get_setup_phase() != Episode3::SetupPhase::REGISTRATION) {
|
||||
cmd.rules = primary_lobby->ep3_server_base->map_and_rules1->rules;
|
||||
primary_lobby->ep3_server &&
|
||||
primary_lobby->ep3_server->get_setup_phase() != Episode3::SetupPhase::REGISTRATION) {
|
||||
cmd.rules = primary_lobby->ep3_server->map_and_rules1->rules;
|
||||
flag = 0x01;
|
||||
|
||||
} else {
|
||||
|
||||
@@ -10418,10 +10418,8 @@ I 32209 2023-09-08 23:41:07 - [Commands] Sending to C-7 (Tali) (version=GC comma
|
||||
0000 | C9 00 14 00 B4 04 00 00 1E 00 00 00 00 00 00 78 | x
|
||||
0010 | 85 00 00 00 |
|
||||
I 32209 2023-09-08 23:41:07 - [Commands] Sending to C-7 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 38 00 00 00 00 00 00 00 00 00 43 6C 69 65 | 8 Clie
|
||||
0010 | 6E 74 20 33 20 65 72 72 6F 72 0A 43 6F 64 65 3A | nt 3 error Code:
|
||||
0020 | 20 2D 30 78 46 46 46 46 46 46 46 46 46 46 46 46 | -0xFFFFFFFFFFFF
|
||||
0030 | 46 46 37 42 00 00 00 00 | FF7B
|
||||
0000 | B0 00 20 00 00 00 00 00 00 00 00 00 09 43 34 33 | C43
|
||||
0010 | 2F 45 52 52 4F 52 20 30 78 38 35 00 00 00 00 00 | /ERROR 0x85
|
||||
I 32209 2023-09-08 23:41:07 - [Commands] Received from C-7 (Tali) (version=GC command=CA flag=00)
|
||||
0000 | CA 00 20 00 B3 07 01 00 0D 00 00 03 00 00 00 7C | |
|
||||
0010 | 00 00 00 00 03 00 03 00 E8 80 B4 6A 59 80 10 31 | jY 1
|
||||
@@ -16945,10 +16943,8 @@ I 32209 2023-09-08 23:41:38 - [Commands] Sending to C-7 (Tali) (version=GC comma
|
||||
0000 | C9 00 14 00 B4 04 00 00 1E 00 00 00 00 00 00 F0 |
|
||||
0010 | 80 00 00 00 |
|
||||
I 32209 2023-09-08 23:41:38 - [Commands] Sending to C-7 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 38 00 00 00 00 00 00 00 00 00 43 6C 69 65 | 8 Clie
|
||||
0010 | 6E 74 20 33 20 65 72 72 6F 72 0A 43 6F 64 65 3A | nt 3 error Code:
|
||||
0020 | 20 2D 30 78 46 46 46 46 46 46 46 46 46 46 46 46 | -0xFFFFFFFFFFFF
|
||||
0030 | 46 46 38 30 00 00 00 00 | FF80
|
||||
0000 | B0 00 20 00 00 00 00 00 00 00 00 00 09 43 34 33 | C43
|
||||
0010 | 2F 45 52 52 4F 52 20 30 78 38 30 00 00 00 00 00 | /ERROR 0x80
|
||||
I 32209 2023-09-08 23:41:40 - [Commands] Received from C-7 (Tali) (version=GC command=CA flag=00)
|
||||
0000 | CA 00 18 00 B3 05 02 00 28 00 00 80 00 00 00 F4 | (
|
||||
0010 | 00 00 00 00 00 03 AB 00 |
|
||||
@@ -30827,10 +30823,8 @@ I 32209 2023-09-08 23:42:52 - [Commands] Sending to C-7 (Tali) (version=GC comma
|
||||
0000 | C9 00 14 00 B4 04 00 00 1E 00 00 00 00 00 01 E4 |
|
||||
0010 | 87 00 00 00 |
|
||||
I 32209 2023-09-08 23:42:52 - [Commands] Sending to C-7 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 38 00 00 00 00 00 00 00 00 00 43 6C 69 65 | 8 Clie
|
||||
0010 | 6E 74 20 32 20 65 72 72 6F 72 0A 43 6F 64 65 3A | nt 2 error Code:
|
||||
0020 | 20 2D 30 78 46 46 46 46 46 46 46 46 46 46 46 46 | -0xFFFFFFFFFFFF
|
||||
0030 | 46 46 37 39 00 00 00 00 | FF79
|
||||
0000 | B0 00 20 00 00 00 00 00 00 00 00 00 09 43 34 32 | C42
|
||||
0010 | 2F 45 52 52 4F 52 20 30 78 38 37 00 00 00 00 00 | /ERROR 0x87
|
||||
I 32209 2023-09-08 23:42:53 - [Commands] Received from C-7 (Tali) (version=GC command=CA flag=00)
|
||||
0000 | CA 00 1C 00 B3 06 00 00 10 00 00 00 00 00 01 E8 |
|
||||
0010 | 00 00 00 00 02 00 00 00 01 02 00 00 |
|
||||
@@ -38877,10 +38871,8 @@ I 32209 2023-09-08 23:43:22 - [Commands] Sending to C-7 (Tali) (version=GC comma
|
||||
0000 | C9 00 14 00 B4 04 00 00 1E 00 00 00 00 00 02 64 | d
|
||||
0010 | 80 00 00 00 |
|
||||
I 32209 2023-09-08 23:43:22 - [Commands] Sending to C-7 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 38 00 00 00 00 00 00 00 00 00 43 6C 69 65 | 8 Clie
|
||||
0010 | 6E 74 20 33 20 65 72 72 6F 72 0A 43 6F 64 65 3A | nt 3 error Code:
|
||||
0020 | 20 2D 30 78 46 46 46 46 46 46 46 46 46 46 46 46 | -0xFFFFFFFFFFFF
|
||||
0030 | 46 46 38 30 00 00 00 00 | FF80
|
||||
0000 | B0 00 20 00 00 00 00 00 00 00 00 00 09 43 34 33 | C43
|
||||
0010 | 2F 45 52 52 4F 52 20 30 78 38 30 00 00 00 00 00 | /ERROR 0x80
|
||||
I 32209 2023-09-08 23:43:23 - [Commands] Received from C-7 (Tali) (version=GC command=CA flag=00)
|
||||
0000 | CA 00 18 00 B3 05 AC 00 28 00 00 80 00 00 02 68 | ( h
|
||||
0010 | 00 00 00 00 00 02 07 20 |
|
||||
@@ -48676,10 +48668,8 @@ I 32209 2023-09-08 23:44:05 - [Commands] Sending to C-7 (Tali) (version=GC comma
|
||||
0000 | C9 00 14 00 B4 04 00 00 1E 00 00 00 00 00 03 1C |
|
||||
0010 | 80 00 00 00 |
|
||||
I 32209 2023-09-08 23:44:05 - [Commands] Sending to C-7 (Tali) (version=GC command=B0 flag=00)
|
||||
0000 | B0 00 38 00 00 00 00 00 00 00 00 00 43 6C 69 65 | 8 Clie
|
||||
0010 | 6E 74 20 33 20 65 72 72 6F 72 0A 43 6F 64 65 3A | nt 3 error Code:
|
||||
0020 | 20 2D 30 78 46 46 46 46 46 46 46 46 46 46 46 46 | -0xFFFFFFFFFFFF
|
||||
0030 | 46 46 38 30 00 00 00 00 | FF80
|
||||
0000 | B0 00 20 00 00 00 00 00 00 00 00 00 09 43 34 33 | C43
|
||||
0010 | 2F 45 52 52 4F 52 20 30 78 38 30 00 00 00 00 00 | /ERROR 0x80
|
||||
I 32209 2023-09-08 23:44:06 - [Commands] Received from C-7 (Tali) (version=GC command=CA flag=00)
|
||||
0000 | CA 00 18 00 B3 05 AC 00 28 00 00 80 00 00 03 20 | (
|
||||
0010 | 00 00 00 00 00 02 12 E0 |
|
||||
|
||||
Reference in New Issue
Block a user