fix Ep3 NTE target replacement function
This commit is contained in:
@@ -204,7 +204,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
}
|
||||
}
|
||||
|
||||
string cond_str = cond.str();
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("wrote condition %zd => %s", cond_index, cond_str.c_str());
|
||||
|
||||
if (!is_nte) {
|
||||
@@ -213,7 +213,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
|
||||
continue;
|
||||
}
|
||||
string cond_str = cond.str();
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("sorted conditions: [%zu] => %s", z, cond_str.c_str());
|
||||
}
|
||||
}
|
||||
@@ -1361,11 +1361,12 @@ bool Card::is_guard_item() const {
|
||||
}
|
||||
|
||||
bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto log = this->server()->log_stack(other_card
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(other_card
|
||||
? string_printf("unknown_80236554(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
|
||||
: string_printf("unknown_80236554(@%04hX #%04hX, null): ", this->get_card_ref(), this->get_card_id()));
|
||||
if (as) {
|
||||
string as_str = as->str();
|
||||
string as_str = as->str(s);
|
||||
log.debug("as = %s", as_str.c_str());
|
||||
} else {
|
||||
log.debug("as = null");
|
||||
@@ -1403,8 +1404,8 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
log.debug("last attack damage stats cleared");
|
||||
|
||||
if (other_card) {
|
||||
this->server()->card_special->apply_action_conditions(0x03, other_card, this->shared_from_this(), 0x20, as);
|
||||
this->server()->card_special->apply_action_conditions(0x17, other_card, this->shared_from_this(), 0x40, as);
|
||||
s->card_special->apply_action_conditions(0x03, other_card, this->shared_from_this(), 0x20, as);
|
||||
s->card_special->apply_action_conditions(0x17, other_card, this->shared_from_this(), 0x40, as);
|
||||
if (other_card->action_chain.check_flag(0x20000)) {
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
return ret;
|
||||
@@ -1417,8 +1418,9 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
}
|
||||
|
||||
void Card::unknown_802362D8(shared_ptr<Card> other_card) {
|
||||
auto s = this->server();
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->server()->player_states[client_id];
|
||||
auto ps = s->player_states[client_id];
|
||||
if (ps) {
|
||||
shared_ptr<Card> card = ps->get_sc_card();
|
||||
if (card) {
|
||||
|
||||
+4
-11
@@ -15,11 +15,7 @@ class PlayerState;
|
||||
|
||||
class Card : public std::enable_shared_from_this<Card> {
|
||||
public:
|
||||
Card(
|
||||
uint16_t card_id,
|
||||
uint16_t card_ref,
|
||||
uint16_t client_id,
|
||||
std::shared_ptr<Server> server);
|
||||
Card(uint16_t card_id, uint16_t card_ref, uint16_t client_id, std::shared_ptr<Server> server);
|
||||
void init();
|
||||
std::shared_ptr<Server> server();
|
||||
std::shared_ptr<const Server> server() const;
|
||||
@@ -47,8 +43,7 @@ public:
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06* cmd,
|
||||
size_t strike_number,
|
||||
int16_t* out_effective_damage);
|
||||
int16_t compute_defense_power_for_attacker_card(
|
||||
std::shared_ptr<const Card> attacker_card);
|
||||
int16_t compute_defense_power_for_attacker_card(std::shared_ptr<const Card> attacker_card);
|
||||
void destroy_set_card(std::shared_ptr<Card> attacker_card);
|
||||
int32_t error_code_for_move_to_location(const Location& loc) const;
|
||||
void execute_attack(std::shared_ptr<Card> attacker_card);
|
||||
@@ -73,12 +68,10 @@ public:
|
||||
void send_6xB4x4E_4C_4D_if_needed(bool always_send = false);
|
||||
void send_6xB4x4E_if_needed(bool always_send = false);
|
||||
void set_current_and_max_hp(int16_t hp);
|
||||
void set_current_hp(
|
||||
uint32_t new_hp, bool propagate_shared_hp = true, bool enforce_max_hp = true);
|
||||
void set_current_hp(uint32_t new_hp, bool propagate_shared_hp = true, bool enforce_max_hp = true);
|
||||
void update_stats_on_destruction();
|
||||
void clear_action_chain_and_metadata_and_most_flags();
|
||||
void compute_action_chain_results(
|
||||
bool apply_action_conditions, bool ignore_this_card_ap_tp);
|
||||
void compute_action_chain_results(bool apply_action_conditions, bool ignore_this_card_ap_tp);
|
||||
void unknown_802380C0();
|
||||
void unknown_80237F98(bool require_condition_20_or_21);
|
||||
void unknown_80237F88();
|
||||
|
||||
+16
-15
@@ -460,7 +460,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
auto log = s->log_stack(string_printf("apply_stat_deltas_to_card_from_condition_and_clear_cond(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
string cond_str = cond.str();
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("cond: %s", cond_str.c_str());
|
||||
|
||||
ConditionType cond_type = cond.type;
|
||||
@@ -706,7 +706,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
auto log = s->log_stack("compute_attack_env_stats: ");
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
string pa_str = pa.str();
|
||||
string pa_str = pa.str(s);
|
||||
log.debug("pa=%s, card=@%04hX #%04hX, dice_roll=%hhu, target=@%04hX, condition_giver=@%04hX", pa_str.c_str(), card->get_card_ref(), card->get_card_id(), dice_roll.value, target_card_ref, condition_giver_card_ref);
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
@@ -834,16 +834,16 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
size_t z = 0;
|
||||
|
||||
uint16_t z_ref = pa.attacker_card_ref;
|
||||
// Note: The (z < 9) conditions in these two loops are not present in the
|
||||
// Note: The (z < 8) conditions in these two loops are not present in the
|
||||
// original code.
|
||||
for (z = 0;
|
||||
((target_card_ref != z_ref) && (z < 9) && ((z_ref = pa.action_card_refs[z]) != 0xFFFF));
|
||||
((target_card_ref != z_ref) && (z < 8) && ((z_ref = pa.action_card_refs[z]) != 0xFFFF));
|
||||
z++) {
|
||||
}
|
||||
|
||||
ast.action_cards_ap = 0;
|
||||
ast.action_cards_tp = 0;
|
||||
for (; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
for (; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
auto ce = s->definition_for_card_ref(pa.action_card_refs[z]);
|
||||
if (ce) {
|
||||
if (ce->def.ap.type != CardDefinition::Stat::Type::MINUS_STAT) {
|
||||
@@ -1192,7 +1192,8 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
}
|
||||
|
||||
StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) const {
|
||||
auto log = this->server()->log_stack(string_printf("compute_stat_swap_type(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("compute_stat_swap_type(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
if (!card) {
|
||||
log.debug("card is missing");
|
||||
return StatSwapType::NONE;
|
||||
@@ -1203,7 +1204,7 @@ StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) co
|
||||
auto& cond = card->action_chain.conditions[cond_index];
|
||||
if (cond.type != ConditionType::NONE) {
|
||||
auto cond_log = log.sub(string_printf("(%zu) ", cond_index));
|
||||
string cond_str = cond.str();
|
||||
string cond_str = cond.str(s);
|
||||
cond_log.debug("%s", cond_str.c_str());
|
||||
if (!this->card_ref_has_ability_trap(cond)) {
|
||||
if (cond.type == ConditionType::UNKNOWN_75) {
|
||||
@@ -1775,7 +1776,7 @@ bool CardSpecial::execute_effect(
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("execute_effect(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
{
|
||||
string cond_str = cond.str();
|
||||
string cond_str = cond.str(s);
|
||||
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);
|
||||
}
|
||||
bool is_nte = s->options.is_nte();
|
||||
@@ -2899,9 +2900,9 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
break;
|
||||
case 0x04: // p04
|
||||
size_t z;
|
||||
for (z = 0; (z < 9) && (as.action_card_refs[z] != 0xFFFF) && (as.action_card_refs[z] != card_ref); z++) {
|
||||
for (z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF) && (as.action_card_refs[z] != card_ref); z++) {
|
||||
}
|
||||
for (; (z < 9) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
for (; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
auto result_card = s->card_for_set_card_ref(as.action_card_refs[z]);
|
||||
if (result_card) {
|
||||
ret.emplace_back(result_card);
|
||||
@@ -3938,7 +3939,7 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
{
|
||||
string as_str = as.str();
|
||||
string as_str = as.str(s);
|
||||
log.debug("when=%02hhX, 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);
|
||||
}
|
||||
@@ -4664,8 +4665,9 @@ vector<shared_ptr<const Card>> CardSpecial::filter_cards_by_range(
|
||||
}
|
||||
|
||||
void CardSpecial::unknown_8024AAB8(const ActionState& as) {
|
||||
auto log = this->server()->log_stack("unknown_8024AAB8: ");
|
||||
string as_str = as.str();
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack("unknown_8024AAB8: ");
|
||||
string as_str = as.str(s);
|
||||
log.debug("as=%s", as_str.c_str());
|
||||
|
||||
for (size_t z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
@@ -4697,8 +4699,7 @@ void CardSpecial::unknown_8024AAB8(const ActionState& as) {
|
||||
card_ref2 = this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x26);
|
||||
this->evaluate_and_apply_effects(0x34, card_ref2, as, card_ref1);
|
||||
for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) {
|
||||
uint16_t card_ref = this->send_6xB4x06_if_card_ref_invalid(
|
||||
as.action_card_refs[z], 0x27);
|
||||
uint16_t card_ref = this->send_6xB4x06_if_card_ref_invalid(as.action_card_refs[z], 0x27);
|
||||
if (card_ref == 0xFFFF) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
|
||||
void PlayerState::init() {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack("PlayerState::init: ");
|
||||
|
||||
if (s->player_states.at(this->client_id).get() != this) {
|
||||
// Note: The original code handles this, but we don't. This appears not to
|
||||
@@ -832,7 +833,7 @@ vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
uint8_t target_team_id) const {
|
||||
auto s = this->server();
|
||||
|
||||
auto log = this->server()->log_stack("get_all_cards_within_range: ");
|
||||
auto log = s->log_stack("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);
|
||||
|
||||
@@ -1754,22 +1755,33 @@ int16_t PlayerState::get_assist_turns_remaining() {
|
||||
|
||||
bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack("set_action_cards_for_action_state: ");
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (attacker_card) {
|
||||
log.debug("attacker card present");
|
||||
attacker_card->card_flags |= 0x100;
|
||||
}
|
||||
|
||||
auto action_type = s->ruler_server->get_pending_action_type(pa);
|
||||
if (action_type == ActionType::DEFENSE) {
|
||||
log.debug("action type is DEFENSE");
|
||||
} else if (action_type == ActionType::ATTACK) {
|
||||
log.debug("action type is ATTACK");
|
||||
} else {
|
||||
log.debug("action type is UNKNOWN");
|
||||
}
|
||||
if (!is_nte) {
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, 1);
|
||||
log.debug("(non-nte) subtracting action points");
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, true);
|
||||
}
|
||||
|
||||
if (action_type == ActionType::ATTACK) {
|
||||
auto card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (card) {
|
||||
card->loc.direction = pa.facing_direction;
|
||||
log.debug("set facing direction to %s", name_for_direction(card->loc.direction));
|
||||
|
||||
G_Unknown_Ep3_6xB4x4A cmd;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
@@ -1778,6 +1790,10 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
cmd.entry_count = 0;
|
||||
size_t z = 0;
|
||||
do {
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug("on action card ref %s", ref_str.c_str());
|
||||
}
|
||||
card->unknown_80237A90(pa, pa.action_card_refs[z]);
|
||||
card->unknown_802379BC(pa.action_card_refs[z]);
|
||||
if (!is_nte) {
|
||||
@@ -1811,6 +1827,10 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
|
||||
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
if (target_card) {
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.target_card_refs[z]);
|
||||
log.debug("on target card ref %s", ref_str.c_str());
|
||||
}
|
||||
target_card->unknown_802379DC(pa);
|
||||
if (!is_nte) {
|
||||
if (this->client_id == target_card->get_client_id()) {
|
||||
@@ -1833,9 +1853,14 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
}
|
||||
}
|
||||
if (is_nte) {
|
||||
log.debug("(nte) subtracting action points");
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, 1);
|
||||
}
|
||||
for (size_t z = 0; (z < pa.action_card_refs.size()) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug("discarding %s from hand", ref_str.c_str());
|
||||
}
|
||||
this->discard_ref_from_hand(pa.action_card_refs[z]);
|
||||
}
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
|
||||
@@ -6,22 +6,6 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
template <size_t Count>
|
||||
std::string string_for_refs(const parray<le_uint16_t, Count>& card_refs) {
|
||||
string ret = "[";
|
||||
for (size_t z = 0; z < Count; z++) {
|
||||
if (card_refs[z] != 0xFFFF) {
|
||||
ret += string_printf("%zu:@$%04X ", z, card_refs[z].load());
|
||||
}
|
||||
}
|
||||
if (!ret.empty()) {
|
||||
ret.back() = ']'; // Replace the ' ' from the last added item
|
||||
} else {
|
||||
ret.push_back(']');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Condition::Condition() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -77,10 +61,12 @@ void Condition::clear_FF() {
|
||||
this->unknown_a8 = 0xFF;
|
||||
}
|
||||
|
||||
std::string Condition::str() const {
|
||||
std::string Condition::str(shared_ptr<const Server> s) const {
|
||||
auto card_ref_str = s->debug_str_for_card_ref(this->card_ref);
|
||||
auto giver_ref_str = s->debug_str_for_card_ref(this->condition_giver_card_ref);
|
||||
return string_printf(
|
||||
"Condition[type=%s, turns=%hhu, a_arg=%hhd, dice=%hhu, flags=%02hhX, "
|
||||
"def_eff_index=%hhu, ref=@%04hX, value=%hd, giver_ref=@%04hX "
|
||||
"def_eff_index=%hhu, ref=%s, value=%hd, giver_ref=%s "
|
||||
"percent=%hhu value8=%hd order=%hu a8=%hu]",
|
||||
name_for_condition_type(this->type),
|
||||
this->remaining_turns,
|
||||
@@ -88,9 +74,9 @@ std::string Condition::str() const {
|
||||
this->dice_roll_value,
|
||||
this->flags,
|
||||
this->card_definition_effect_index,
|
||||
this->card_ref.load(),
|
||||
card_ref_str.c_str(),
|
||||
this->value.load(),
|
||||
this->condition_giver_card_ref.load(),
|
||||
giver_ref_str.c_str(),
|
||||
this->random_percent,
|
||||
this->value8,
|
||||
this->order,
|
||||
@@ -114,13 +100,15 @@ void EffectResult::clear() {
|
||||
this->dice_roll_value = 0;
|
||||
}
|
||||
|
||||
std::string EffectResult::str() const {
|
||||
std::string EffectResult::str(shared_ptr<const Server> s) const {
|
||||
string attacker_ref_str = s->debug_str_for_card_ref(this->attacker_card_ref);
|
||||
string target_ref_str = s->debug_str_for_card_ref(this->target_card_ref);
|
||||
return string_printf(
|
||||
"EffectResult[att_ref=@%04hX, target_ref=@%04hX, value=%hhd, "
|
||||
"EffectResult[att_ref=%s, target_ref=%s, value=%hhd, "
|
||||
"cur_hp=%hhd, ap=%hhd, tp=%hhd, flags=%02hhX, op=%hhd, "
|
||||
"cond_index=%hhu, dice=%hhu]",
|
||||
this->attacker_card_ref.load(),
|
||||
this->target_card_ref.load(),
|
||||
attacker_ref_str.c_str(),
|
||||
target_ref_str.c_str(),
|
||||
this->value,
|
||||
this->current_hp,
|
||||
this->ap,
|
||||
@@ -148,12 +136,13 @@ bool CardShortStatus::operator!=(const CardShortStatus& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string CardShortStatus::str() const {
|
||||
std::string CardShortStatus::str(shared_ptr<const Server> s) const {
|
||||
string loc_s = this->loc.str();
|
||||
string ref_str = s->debug_str_for_card_ref(this->card_ref);
|
||||
return string_printf(
|
||||
"CardShortStatus[ref=@%04hX, cur_hp=%hd, flags=%08" PRIX32 ", loc=%s, "
|
||||
"CardShortStatus[ref=%s, cur_hp=%hd, flags=%08" PRIX32 ", loc=%s, "
|
||||
"u1=%04hX, max_hp=%hhd, u2=%hhu]",
|
||||
this->card_ref.load(),
|
||||
ref_str.c_str(),
|
||||
this->current_hp.load(),
|
||||
this->card_flags.load(),
|
||||
loc_s.c_str(),
|
||||
@@ -195,23 +184,27 @@ void ActionState::clear() {
|
||||
this->original_attacker_card_ref = 0xFFFF;
|
||||
this->target_card_refs.clear(0xFFFF);
|
||||
this->action_card_refs.clear(0xFFFF);
|
||||
this->unused2 = 0xFFFF;
|
||||
}
|
||||
|
||||
std::string ActionState::str() const {
|
||||
string target_refs_s = string_for_refs(this->target_card_refs);
|
||||
string action_refs_s = string_for_refs(this->action_card_refs);
|
||||
std::string ActionState::str(shared_ptr<const Server> s) const {
|
||||
string attacker_ref_s = s->debug_str_for_card_ref(this->attacker_card_ref);
|
||||
string defense_ref_s = s->debug_str_for_card_ref(this->defense_card_ref);
|
||||
string original_attacker_ref_s = s->debug_str_for_card_ref(this->original_attacker_card_ref);
|
||||
string target_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
string action_refs_s = s->debug_str_for_card_refs(this->action_card_refs);
|
||||
return string_printf(
|
||||
"ActionState[client=%hu, u=%hhu, facing=%s, attacker_ref=@%04hX, "
|
||||
"def_ref=@%04hX, target_refs=%s, action_refs=%s, "
|
||||
"orig_attacker_ref=@%04hX]",
|
||||
"ActionState[client=%hu, u=%hhu, facing=%s, attacker_ref=%s, "
|
||||
"def_ref=%s, target_refs=%s, action_refs=%s, "
|
||||
"orig_attacker_ref=%s]",
|
||||
this->client_id.load(),
|
||||
this->unused,
|
||||
name_for_direction(this->facing_direction),
|
||||
this->attacker_card_ref.load(),
|
||||
this->defense_card_ref.load(),
|
||||
attacker_ref_s.c_str(),
|
||||
defense_ref_s.c_str(),
|
||||
target_refs_s.c_str(),
|
||||
action_refs_s.c_str(),
|
||||
this->original_attacker_card_ref.load());
|
||||
original_attacker_ref_s.c_str());
|
||||
}
|
||||
|
||||
ActionChain::ActionChain() {
|
||||
@@ -245,23 +238,24 @@ bool ActionChain::operator!=(const ActionChain& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionChain::str() const {
|
||||
string attack_action_card_refs_s = string_for_refs(this->attack_action_card_refs);
|
||||
string target_card_refs_s = string_for_refs(this->target_card_refs);
|
||||
std::string ActionChain::str(shared_ptr<const Server> s) const {
|
||||
string acting_card_ref_s = s->debug_str_for_card_ref(this->acting_card_ref);
|
||||
string unknown_card_ref_a3_s = s->debug_str_for_card_ref(this->unknown_card_ref_a3);
|
||||
string attack_action_card_refs_s = s->debug_str_for_card_refs(this->attack_action_card_refs);
|
||||
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
return string_printf(
|
||||
"ActionChain[eff_ap=%hhd, eff_tp=%hhd, ap_bonus=%hhd, damage=%hhd, "
|
||||
"acting_ref=@%04hX, unknown_ref_a3=@%04hX, "
|
||||
"attack_action_refs=%s, attack_action_ref_count=%hhu, "
|
||||
"medium=%s, target_ref_count=%hhu, subphase=%s, "
|
||||
"strikes=%hhu, damage_mult=%hhd, attack_num=%hhu, "
|
||||
"acting_ref=%s, unknown_ref_a3=%s, attack_action_refs=%s, "
|
||||
"attack_action_ref_count=%hhu, medium=%s, target_ref_count=%hhu, "
|
||||
"subphase=%s, strikes=%hhu, damage_mult=%hhd, attack_num=%hhu, "
|
||||
"tp_bonus=%hhd, phys_bonus_nte=%hhu, tech_bonus_nte=%hhu, card_ap=%hhd, "
|
||||
"card_tp=%hhd, flags=%08" PRIX32 ", target_refs=%s]",
|
||||
this->effective_ap,
|
||||
this->effective_tp,
|
||||
this->ap_effect_bonus,
|
||||
this->damage,
|
||||
this->acting_card_ref.load(),
|
||||
this->unknown_card_ref_a3.load(),
|
||||
acting_card_ref_s.c_str(),
|
||||
unknown_card_ref_a3_s.c_str(),
|
||||
attack_action_card_refs_s.c_str(),
|
||||
this->attack_action_card_ref_count,
|
||||
name_for_attack_medium(this->attack_medium),
|
||||
@@ -338,17 +332,17 @@ bool ActionChainWithConds::operator!=(const ActionChainWithConds& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionChainWithConds::str() const {
|
||||
std::string ActionChainWithConds::str(shared_ptr<const Server> s) const {
|
||||
string ret = "ActionChainWithConds[chain=";
|
||||
ret += this->chain.str();
|
||||
ret += this->chain.str(s);
|
||||
ret += ", conds=[";
|
||||
for (size_t z = 0; z < this->conditions.size(); z++) {
|
||||
if (this->conditions[z].type != ConditionType::NONE) {
|
||||
if (ret.back() != '=') {
|
||||
if (ret.back() != '[') {
|
||||
ret += ", ";
|
||||
}
|
||||
ret += string_printf("%zu:", z);
|
||||
ret += this->conditions[z].str();
|
||||
ret += this->conditions[z].str(s);
|
||||
}
|
||||
}
|
||||
ret += "]]";
|
||||
@@ -581,16 +575,17 @@ bool ActionMetadata::operator!=(const ActionMetadata& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionMetadata::str() const {
|
||||
string target_card_refs_s = string_for_refs(this->target_card_refs);
|
||||
string defense_card_refs_s = string_for_refs(this->defense_card_refs);
|
||||
string original_attacker_card_refs_s = string_for_refs(this->original_attacker_card_refs);
|
||||
std::string ActionMetadata::str(shared_ptr<const Server> s) const {
|
||||
string card_ref_s = s->debug_str_for_card_ref(this->card_ref);
|
||||
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
string defense_card_refs_s = s->debug_str_for_card_refs(this->defense_card_refs);
|
||||
string original_attacker_card_refs_s = s->debug_str_for_card_refs(this->original_attacker_card_refs);
|
||||
return string_printf(
|
||||
"ActionMetadata[ref=@%04hX, target_ref_count=%hhu, def_ref_count=%hhu, "
|
||||
"ActionMetadata[ref=%s, target_ref_count=%hhu, def_ref_count=%hhu, "
|
||||
"subphase=%s, def_power=%hhd, def_bonus=%hhd, "
|
||||
"att_bonus=%hhd, flags=%08" PRIX32 ", target_refs=%s, "
|
||||
"defense_refs=%s, original_attacker_refs=%s]",
|
||||
this->card_ref.load(),
|
||||
card_ref_s.c_str(),
|
||||
this->target_card_ref_count,
|
||||
this->defense_card_ref_count,
|
||||
name_for_action_subphase(this->action_subphase),
|
||||
@@ -679,20 +674,22 @@ HandAndEquipState::HandAndEquipState() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
std::string HandAndEquipState::str() const {
|
||||
string hand_card_refs_s = string_for_refs(this->hand_card_refs);
|
||||
string set_card_refs_s = string_for_refs(this->set_card_refs);
|
||||
string hand_card_refs2_s = string_for_refs(this->hand_card_refs2);
|
||||
string set_card_refs2_s = string_for_refs(this->set_card_refs2);
|
||||
std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
|
||||
string assist_card_ref_s = s->debug_str_for_card_ref(this->assist_card_ref);
|
||||
string assist_card_ref2_s = s->debug_str_for_card_ref(this->assist_card_ref2);
|
||||
string assist_card_id_s = s->debug_str_for_card_id(this->assist_card_id);
|
||||
string sc_card_ref_s = s->debug_str_for_card_ref(this->sc_card_ref);
|
||||
string hand_card_refs_s = s->debug_str_for_card_refs(this->hand_card_refs);
|
||||
string set_card_refs_s = s->debug_str_for_card_refs(this->set_card_refs);
|
||||
string hand_card_refs2_s = s->debug_str_for_card_refs(this->hand_card_refs2);
|
||||
string set_card_refs2_s = s->debug_str_for_card_refs(this->set_card_refs2);
|
||||
return string_printf(
|
||||
"HandAndEquipState[dice=[%hhu, %hhu], atk=%hhu, def=%hhu, atk2=%hhu, "
|
||||
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, "
|
||||
"assist_flags=%08" PRIX32 ", hand_refs=%s, "
|
||||
"assist_ref=@%04hX, set_refs=%s, sc_ref=@%04hX, "
|
||||
"hand_refs2=%s, set_refs2=%s, assist_ref2=@%04hX, "
|
||||
"assist_set_num=%hu, assist_card_id=#%04hX, "
|
||||
"assist_turns=%hhu, assit_dely=%hhu, atk_bonus=%hhu, "
|
||||
"def_bonus=%hhu, u2=[%hhu, %hhu]]",
|
||||
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, assist_flags=%08" PRIX32 ", "
|
||||
"hand_refs=%s, assist_ref=%s, set_refs=%s, sc_ref=%s, hand_refs2=%s, "
|
||||
"set_refs2=%s, assist_ref2=%s, assist_set_num=%hu, assist_card_id=%s, "
|
||||
"assist_turns=%hhu, assist_delay=%hhu, atk_bonus=%hhu, def_bonus=%hhu, "
|
||||
"u2=[%hhu, %hhu]]",
|
||||
this->dice_results[0],
|
||||
this->dice_results[1],
|
||||
this->atk_points,
|
||||
@@ -703,14 +700,14 @@ std::string HandAndEquipState::str() const {
|
||||
this->is_cpu_player,
|
||||
this->assist_flags.load(),
|
||||
hand_card_refs_s.c_str(),
|
||||
this->assist_card_ref.load(),
|
||||
assist_card_ref_s.c_str(),
|
||||
set_card_refs_s.c_str(),
|
||||
this->sc_card_ref.load(),
|
||||
sc_card_ref_s.c_str(),
|
||||
hand_card_refs2_s.c_str(),
|
||||
set_card_refs2_s.c_str(),
|
||||
this->assist_card_ref2.load(),
|
||||
assist_card_ref2_s.c_str(),
|
||||
this->assist_card_set_number.load(),
|
||||
this->assist_card_id.load(),
|
||||
assist_card_id_s.c_str(),
|
||||
this->assist_remaining_turns,
|
||||
this->assist_delay_turns,
|
||||
this->atk_bonuses,
|
||||
|
||||
@@ -35,7 +35,7 @@ struct Condition {
|
||||
void clear();
|
||||
void clear_FF();
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct EffectResult {
|
||||
@@ -55,9 +55,9 @@ struct EffectResult {
|
||||
bool operator==(const EffectResult& other) const;
|
||||
bool operator!=(const EffectResult& other) const;
|
||||
|
||||
std::string str() const;
|
||||
|
||||
void clear();
|
||||
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct CardShortStatus {
|
||||
@@ -77,7 +77,7 @@ struct CardShortStatus {
|
||||
void clear();
|
||||
void clear_FF();
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ActionState {
|
||||
@@ -87,7 +87,8 @@ struct ActionState {
|
||||
/* 04 */ le_uint16_t attacker_card_ref;
|
||||
/* 06 */ le_uint16_t defense_card_ref;
|
||||
/* 08 */ parray<le_uint16_t, 4 * 9> target_card_refs;
|
||||
/* 50 */ parray<le_uint16_t, 9> action_card_refs;
|
||||
/* 50 */ parray<le_uint16_t, 8> action_card_refs;
|
||||
/* 60 */ le_uint16_t unused2;
|
||||
/* 62 */ le_uint16_t original_attacker_card_ref;
|
||||
/* 64 */
|
||||
|
||||
@@ -97,7 +98,7 @@ struct ActionState {
|
||||
|
||||
void clear();
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ActionChain {
|
||||
@@ -133,7 +134,7 @@ struct ActionChain {
|
||||
void clear();
|
||||
void clear_FF();
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ActionChainWithConds {
|
||||
@@ -171,7 +172,7 @@ struct ActionChainWithConds {
|
||||
|
||||
uint8_t get_adjusted_move_ability_nte(uint8_t ability) const;
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct ActionChainWithCondsTrial {
|
||||
@@ -224,8 +225,6 @@ struct ActionMetadata {
|
||||
bool operator==(const ActionMetadata& other) const;
|
||||
bool operator!=(const ActionMetadata& other) const;
|
||||
|
||||
std::string str() const;
|
||||
|
||||
void clear();
|
||||
void clear_FF();
|
||||
|
||||
@@ -240,6 +239,8 @@ struct ActionMetadata {
|
||||
uint16_t defense_card_ref,
|
||||
std::shared_ptr<Card> card,
|
||||
uint16_t original_attacker_card_ref);
|
||||
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct HandAndEquipState {
|
||||
@@ -274,7 +275,7 @@ struct HandAndEquipState {
|
||||
void clear();
|
||||
void clear_FF();
|
||||
|
||||
std::string str() const;
|
||||
std::string str(std::shared_ptr<const Server> s) const;
|
||||
} __attribute__((packed));
|
||||
|
||||
struct PlayerBattleStats {
|
||||
|
||||
@@ -1441,8 +1441,7 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
|
||||
assist_cost_bias++;
|
||||
} else if (is_nte && (assist_effect == AssistEffect::DEFLATION)) {
|
||||
assist_cost_bias--;
|
||||
} else if ((assist_effect == AssistEffect::BATTLE_ROYALE) &&
|
||||
(pa.action_card_refs[0] == 0xFFFF)) {
|
||||
} else if ((assist_effect == AssistEffect::BATTLE_ROYALE) && (pa.action_card_refs[0] == 0xFFFF)) {
|
||||
total_cost = 0;
|
||||
final_cost = 0;
|
||||
}
|
||||
@@ -1470,9 +1469,9 @@ bool RulerServer::compute_effective_range_and_target_mode_for_attack(
|
||||
TargetMode* out_effective_target_mode,
|
||||
uint16_t* out_orig_card_ref) const {
|
||||
size_t z;
|
||||
for (z = 0; (z < 9) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
for (z = 0; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
}
|
||||
if (z >= 9) {
|
||||
if (z >= 8) {
|
||||
return false;
|
||||
}
|
||||
uint16_t card_ref = (z == 0) ? pa.attacker_card_ref : pa.action_card_refs[z - 1];
|
||||
@@ -1630,8 +1629,7 @@ bool RulerServer::defense_card_can_apply_to_attack(
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RulerServer::defense_card_matches_any_attack_card_top_color(
|
||||
const ActionState& pa) const {
|
||||
bool RulerServer::defense_card_matches_any_attack_card_top_color(const ActionState& pa) const {
|
||||
auto ce = this->definition_for_card_ref(pa.action_card_refs[0]);
|
||||
if (!ce) {
|
||||
throw runtime_error("defense card definition is missing");
|
||||
@@ -2274,7 +2272,7 @@ bool RulerServer::is_attack_valid(const ActionState& pa) {
|
||||
|
||||
size_t conditional_card_count = 0;
|
||||
size_t z;
|
||||
for (z = 0; z < 9; z++) {
|
||||
for (z = 0; z < 8; z++) {
|
||||
uint16_t right_card_ref = pa.action_card_refs[z];
|
||||
if (right_card_ref == 0xFFFF) {
|
||||
break;
|
||||
|
||||
+55
-6
@@ -160,6 +160,32 @@ const Server::StackLogger& Server::log() const {
|
||||
return *this->logger_stack.back();
|
||||
}
|
||||
|
||||
std::string Server::debug_str_for_card_ref(uint16_t card_ref) const {
|
||||
if (card_ref == 0xFFFF) {
|
||||
return "@FFFF";
|
||||
}
|
||||
auto ce = this->definition_for_card_ref(card_ref);
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode();
|
||||
return string_printf("@%04hX (#%04" PRIX32 " %s)", card_ref, ce->def.card_id.load(), name.c_str());
|
||||
} else {
|
||||
return string_printf("@%04hX (missing)", card_ref);
|
||||
}
|
||||
}
|
||||
|
||||
std::string Server::debug_str_for_card_id(uint16_t card_id) const {
|
||||
if (card_id == 0xFFFF) {
|
||||
return "#FFFF";
|
||||
}
|
||||
auto ce = this->definition_for_card_id(card_id);
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode();
|
||||
return string_printf("#%04hX (%s)", card_id, name.c_str());
|
||||
} else {
|
||||
return string_printf("#%04hX (missing)", card_id);
|
||||
}
|
||||
}
|
||||
|
||||
int8_t Server::get_winner_team_id() const {
|
||||
// Note: This function is not part of the original implementation.
|
||||
|
||||
@@ -946,44 +972,63 @@ void Server::end_action_phase() {
|
||||
}
|
||||
|
||||
bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
|
||||
auto log = this->log_stack("enqueue_attack_or_defense: ");
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string s = pa->str(this->shared_from_this());
|
||||
log.debug("input: %s", s.c_str());
|
||||
}
|
||||
|
||||
if (client_id >= 4) {
|
||||
this->ruler_server->error_code3 = -0x78;
|
||||
log.debug("failed: invalid client ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ps = this->player_states[client_id];
|
||||
if (!ps) {
|
||||
this->ruler_server->error_code3 = -0x72;
|
||||
log.debug("failed: player not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pa->action_card_refs[0] == 0xFFFF) {
|
||||
if (pa->defense_card_ref != 0xFFFF) {
|
||||
pa->action_card_refs[0] = pa->defense_card_ref;
|
||||
log.debug("moved defense card ref to action card ref 0");
|
||||
}
|
||||
} else {
|
||||
pa->defense_card_ref = pa->action_card_refs[0];
|
||||
log.debug("moved action card ref 0 to defense card ref");
|
||||
}
|
||||
|
||||
if (!this->ruler_server->is_attack_or_defense_valid(*pa)) {
|
||||
log.debug("failed: attack or defense not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t ally_atk_result = this->send_6xB4x33_remove_ally_atk_if_needed(*pa);
|
||||
if (ally_atk_result == 1) {
|
||||
log.debug("pending: need ally approval");
|
||||
return true;
|
||||
} else if (ally_atk_result == -1) {
|
||||
log.debug("failed: ally declined");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->num_pending_attacks >= 0x20) {
|
||||
this->ruler_server->error_code3 = -0x71;
|
||||
log.debug("failed: too many pending attacks");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t attack_index = this->num_pending_attacks++;
|
||||
this->pending_attacks[attack_index] = *pa;
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string pa_str = this->pending_attacks[attack_index].str(this->shared_from_this());
|
||||
log.debug("set pending attack %zu: %s", attack_index, pa_str.c_str());
|
||||
}
|
||||
ps->set_action_cards_for_action_state(*pa);
|
||||
log.debug("set action cards");
|
||||
auto card = this->card_for_set_card_ref(this->send_6xB4x06_if_card_ref_invalid(pa->attacker_card_ref, 1));
|
||||
if (card) {
|
||||
card->card_flags |= 0x400;
|
||||
@@ -2735,16 +2780,20 @@ void Server::unknown_8023EEF4() {
|
||||
auto card = this->attack_cards[this->unknown_a14];
|
||||
if (this->get_current_team_turn() == card->get_team_id()) {
|
||||
ActionState as = this->pending_attacks_with_cards[this->unknown_a14];
|
||||
log.debug("card @%04hX #%04hX can attack", card->get_card_ref(), card->get_card_id());
|
||||
string as_str = as.str();
|
||||
log.debug("as: %s", as_str.c_str());
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
log.debug("card @%04hX #%04hX can attack", card->get_card_ref(), card->get_card_id());
|
||||
string as_str = as.str(this->shared_from_this());
|
||||
log.debug("as: %s", as_str.c_str());
|
||||
}
|
||||
if (is_nte) {
|
||||
this->replace_targets_due_to_destruction_nte(&as);
|
||||
} else {
|
||||
this->replace_targets_due_to_destruction_or_conditions(&as);
|
||||
}
|
||||
as_str = as.str();
|
||||
log.debug("as after target replacement: %s", as_str.c_str());
|
||||
if (log.should_log(LogLevel::DEBUG)) {
|
||||
string as_str = as.str(this->shared_from_this());
|
||||
log.debug("as after target replacement: %s", as_str.c_str());
|
||||
}
|
||||
if (this->any_target_exists_for_attack(as)) {
|
||||
log.debug("as is valid");
|
||||
break;
|
||||
@@ -2856,7 +2905,7 @@ void Server::replace_targets_due_to_destruction_nte(ActionState* as) {
|
||||
if (!target_card) {
|
||||
break;
|
||||
}
|
||||
if ((target_card->card_flags & 2) ||
|
||||
if (!(target_card->card_flags & 2) ||
|
||||
(target_card->get_definition()->def.type != CardType::ITEM) ||
|
||||
attacker_card->action_chain.check_flag(0x02)) {
|
||||
continue;
|
||||
|
||||
@@ -99,6 +99,33 @@ public:
|
||||
StackLogger log_stack(const std::string& prefix) const;
|
||||
const StackLogger& log() const;
|
||||
|
||||
std::string debug_str_for_card_ref(uint16_t card_ref) const;
|
||||
std::string debug_str_for_card_id(uint16_t card_id) const;
|
||||
template <typename U16T>
|
||||
std::string debug_str_for_card_refs(const U16T* refs, size_t count) const {
|
||||
std::string ret = "[";
|
||||
for (size_t z = 0; z < count; z++) {
|
||||
if (refs[z] != 0xFFFF) {
|
||||
std::string ref_str = this->debug_str_for_card_ref(refs[z]);
|
||||
ret += string_printf("%zu:%s ", z, ref_str.c_str());
|
||||
}
|
||||
}
|
||||
if (ret.size() > 1) {
|
||||
ret.back() = ']'; // Replace the ' ' from the last added item
|
||||
} else {
|
||||
ret.push_back(']');
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
template <typename U16T>
|
||||
std::string debug_str_for_card_refs(const std::vector<U16T>& refs) const {
|
||||
return this->debug_str_for_card_refs(refs.data(), refs.size());
|
||||
}
|
||||
template <typename U16T, size_t Count>
|
||||
std::string debug_str_for_card_refs(const parray<U16T, Count>& refs) const {
|
||||
return this->debug_str_for_card_refs(refs.data(), refs.size());
|
||||
}
|
||||
|
||||
int8_t get_winner_team_id() const;
|
||||
|
||||
template <typename T>
|
||||
|
||||
Reference in New Issue
Block a user