fix chained action card conditions not applying
This commit is contained in:
+104
-15
@@ -107,6 +107,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
int16_t value,
|
||||
int8_t dice_roll_value,
|
||||
int8_t random_percent) {
|
||||
auto log = this->server()->log_stack(string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
|
||||
|
||||
ssize_t existing_cond_index;
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
@@ -132,9 +133,13 @@ ssize_t Card::apply_abnormal_condition(
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.debug("existing_cond_index < 0 (new condition) => cond_index = %zd", cond_index);
|
||||
} else {
|
||||
log.debug("existing_cond_index = %zd (existing condition)", existing_cond_index);
|
||||
}
|
||||
|
||||
if (cond_index < 0) {
|
||||
log.debug("no space for condition");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -142,10 +147,10 @@ ssize_t Card::apply_abnormal_condition(
|
||||
auto& cond = this->action_chain.conditions[cond_index];
|
||||
if ((eff.type == ConditionType::MV_BONUS) && (cond.type == ConditionType::MV_BONUS)) {
|
||||
existing_cond_value = clamp<int16_t>(cond.value, -99, 99);
|
||||
log.debug("MV_BONUS combines => existing_cond_value = %hd", existing_cond_value);
|
||||
}
|
||||
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(
|
||||
cond, this->shared_from_this());
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
cond.type = eff.type;
|
||||
cond.card_ref = target_card_ref;
|
||||
cond.condition_giver_card_ref = sc_card_ref;
|
||||
@@ -178,7 +183,19 @@ ssize_t Card::apply_abnormal_condition(
|
||||
cond.remaining_turns = atoi(&eff.arg1[1]);
|
||||
}
|
||||
|
||||
string cond_str = cond.str();
|
||||
log.debug("wrote condition %zd => %s", cond_index, cond_str.c_str());
|
||||
|
||||
this->server()->card_special->update_condition_orders(this->shared_from_this());
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.conditions.size(); z++) {
|
||||
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
|
||||
continue;
|
||||
}
|
||||
string cond_str = cond.str();
|
||||
log.debug("sorted conditions: [%zu] => %s", z, cond_str.c_str());
|
||||
}
|
||||
|
||||
return cond_index;
|
||||
}
|
||||
|
||||
@@ -227,9 +244,12 @@ void Card::commit_attack(
|
||||
G_ApplyConditionEffect_GC_Ep3_6xB4x06* cmd,
|
||||
size_t strike_number,
|
||||
int16_t* out_effective_damage) {
|
||||
auto log = this->server()->log_stack(string_printf("commit_attack(@%04hX #%04hX, @%04hX #%04hX => %hd (str%zu)): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id(), damage, strike_number));
|
||||
|
||||
int16_t effective_damage = damage;
|
||||
this->server()->card_special->adjust_attack_damage_due_to_conditions(
|
||||
this->shared_from_this(), &effective_damage, attacker_card->get_card_ref());
|
||||
log.debug("adjusted damage = %hd", effective_damage);
|
||||
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
@@ -247,29 +267,36 @@ void Card::commit_attack(
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("after assists = %hd", effective_damage);
|
||||
|
||||
if (this->action_metadata.check_flag(0x10)) {
|
||||
effective_damage = 0;
|
||||
log.debug("flag 0x10 => effective damage = %hd", effective_damage);
|
||||
}
|
||||
|
||||
auto attacker_ps = attacker_card->player_state();
|
||||
attacker_ps->stats.damage_given += effective_damage;
|
||||
this->player_state()->stats.damage_taken += effective_damage;
|
||||
log.debug("updated stats");
|
||||
|
||||
this->current_hp = clamp<int16_t>(
|
||||
this->current_hp - effective_damage, 0, this->max_hp);
|
||||
this->current_hp = clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
|
||||
log.debug("hp set to %hd", this->current_hp);
|
||||
|
||||
if ((effective_damage > 0) &&
|
||||
(attacker_ps->stats.max_attack_damage < effective_damage)) {
|
||||
attacker_ps->stats.max_attack_damage = effective_damage;
|
||||
log.debug("attacker new max damage %hd", effective_damage);
|
||||
}
|
||||
|
||||
this->last_attack_final_damage = effective_damage;
|
||||
log.debug("last attack final damage = %hd", effective_damage);
|
||||
if (effective_damage > 0) {
|
||||
this->card_flags = this->card_flags | 4;
|
||||
log.debug("set flag 4");
|
||||
}
|
||||
if (this->current_hp < 1) {
|
||||
this->destroy_set_card(attacker_card);
|
||||
log.debug("card destroyed");
|
||||
}
|
||||
|
||||
G_ApplyConditionEffect_GC_Ep3_6xB4x06 cmd_to_send;
|
||||
@@ -420,12 +447,18 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto log = this->server()->log_stack(string_printf("execute_attack(@%04X #%04X, @%04X #%04X): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id()));
|
||||
|
||||
this->card_flags = this->card_flags & 0xFFFFFFF3;
|
||||
int16_t attack_ap = this->action_metadata.attack_bonus;
|
||||
int16_t attack_tp = 0;
|
||||
int16_t defense_power = this->compute_defense_power_for_attacker_card(attacker_card);
|
||||
log.debug("ap=%hd, tp=%hd, defense=%hd", attack_ap, attack_tp, defense_power);
|
||||
if ((attack_ap == 0) && !this->action_metadata.check_flag(0x20)) {
|
||||
log.debug("ap == 0 and flag 0x20 not set");
|
||||
return;
|
||||
} else {
|
||||
log.debug("ap != 0 or flag 0x20 set; continuing...");
|
||||
}
|
||||
|
||||
G_ApplyConditionEffect_GC_Ep3_6xB4x06 cmd;
|
||||
@@ -447,12 +480,15 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
uint16_t attacker_card_ref = attacker_card->get_card_ref();
|
||||
this->server()->card_special->compute_attack_ap(
|
||||
this->shared_from_this(), &attack_ap, attacker_card_ref);
|
||||
log.debug("computed ap %hd", attack_ap);
|
||||
this->apply_ap_adjust_assists_to_attack(attacker_card, &attack_ap, &defense_power);
|
||||
log.debug("assist adjusts ap=%hd, defense=%hd", attack_ap, defense_power);
|
||||
int16_t raw_damage = attack_ap - defense_power;
|
||||
// Note: The original code uses attack_tp here, even though it is always
|
||||
// zero at this point
|
||||
int16_t preliminary_damage = max<int16_t>(raw_damage, 0) - attack_tp;
|
||||
this->last_attack_preliminary_damage = preliminary_damage;
|
||||
log.debug("raw_damage=%hd, preliminary_damange=%hd", raw_damage, preliminary_damage);
|
||||
uint16_t targeted_card_ref = this->get_card_ref();
|
||||
|
||||
uint32_t unknown_a9 = 0;
|
||||
@@ -460,15 +496,20 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
targeted_card_ref, 1, 0, attacker_card_ref, 0xFFFF, 0, &unknown_a9, 0xFF, 0, 0xFFFF);
|
||||
if (!target) {
|
||||
target = this->shared_from_this();
|
||||
log.debug("target is not replaced");
|
||||
} else {
|
||||
log.debug("target replaced with @%04hX #%04hX", target->get_card_ref(), target->get_card_id());
|
||||
}
|
||||
if (unknown_a9 != 0) {
|
||||
preliminary_damage = 0;
|
||||
log.debug("a9 nonzero; preliminary_damage = 0");
|
||||
}
|
||||
|
||||
if (!(this->card_flags & 2) &&
|
||||
(!attacker_card || !(attacker_card->card_flags & 2))) {
|
||||
this->server()->card_special->check_for_defense_interference(
|
||||
attacker_card, this->shared_from_this(), &preliminary_damage);
|
||||
log.debug("checked for defense interference");
|
||||
}
|
||||
|
||||
cmd.effect.current_hp = min<int16_t>(attack_ap, 99);
|
||||
@@ -476,6 +517,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
cmd.effect.tp = attack_tp;
|
||||
this->player_state()->stats.num_attacks_taken++;
|
||||
if (!(target->card_flags & 2)) {
|
||||
log.debug("flag 2 not set");
|
||||
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
|
||||
int16_t final_effective_damage = 0;
|
||||
target->commit_attack(
|
||||
@@ -487,9 +529,11 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
0, this->current_defense_power - final_effective_damage);
|
||||
}
|
||||
} else {
|
||||
log.debug("flag 2 set; committing zero-damage attack");
|
||||
target->commit_attack(0, attacker_card, &cmd, 0, nullptr);
|
||||
}
|
||||
if (this != target.get()) {
|
||||
log.debug("target was replaced; committing zero-damage attack on original card");
|
||||
this->commit_attack(0, attacker_card, &cmd, 0, nullptr);
|
||||
}
|
||||
|
||||
@@ -515,6 +559,10 @@ uint16_t Card::get_card_ref() const {
|
||||
return this->card_ref;
|
||||
}
|
||||
|
||||
uint16_t Card::get_card_id() const {
|
||||
return this->get_definition()->def.card_id;
|
||||
}
|
||||
|
||||
uint8_t Card::get_client_id() const {
|
||||
return this->client_id;
|
||||
}
|
||||
@@ -724,24 +772,34 @@ void Card::clear_action_chain_and_metadata_and_most_flags() {
|
||||
|
||||
void Card::compute_action_chain_results(
|
||||
bool apply_action_conditions, bool ignore_this_card_ap_tp) {
|
||||
auto log = this->server()->log_stack(string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
this->action_chain.compute_attack_medium(this->server());
|
||||
this->action_chain.chain.strike_count = 1;
|
||||
this->action_chain.chain.ap_effect_bonus = 0;
|
||||
this->action_chain.chain.tp_effect_bonus = 0;
|
||||
|
||||
log.debug("(initial) medium=%s, strike_count=%hhu, ap_effect_bonus=%hhd, tp_effect_bonus=%hhd",
|
||||
name_for_attack_medium(this->action_chain.chain.attack_medium),
|
||||
this->action_chain.chain.strike_count,
|
||||
this->action_chain.chain.ap_effect_bonus,
|
||||
this->action_chain.chain.tp_effect_bonus);
|
||||
|
||||
int16_t card_ap;
|
||||
int16_t card_tp;
|
||||
auto stat_swap_type = this->server()->card_special->compute_stat_swap_type(this->shared_from_this());
|
||||
log.debug("stat_swap_type = %zu (0=none, 1=a/t, 2=a/h)", static_cast<size_t>(stat_swap_type));
|
||||
this->server()->card_special->get_effective_ap_tp(
|
||||
stat_swap_type, &card_ap, &card_tp, this->get_current_hp(), this->ap, this->tp);
|
||||
log.debug("card_ap = %hd, card_tp = %hd", card_ap, card_tp);
|
||||
|
||||
int16_t effective_tp = card_tp;
|
||||
int16_t effective_ap = card_ap;
|
||||
int16_t effective_tp = card_tp;
|
||||
for (size_t z = 0; (!ignore_this_card_ap_tp && (z < 8) && (z < this->action_chain.chain.attack_action_card_ref_count)); z++) {
|
||||
auto ce = this->server()->definition_for_card_ref(this->action_chain.chain.attack_action_card_refs[z]);
|
||||
if (ce) {
|
||||
effective_ap += ce->def.ap.stat;
|
||||
effective_tp += ce->def.tp.stat;
|
||||
log.debug("(action card @%04hX) updated effective_ap = %hd, effective_tp = %hd", this->action_chain.chain.attack_action_card_refs[z].load(), effective_ap, effective_tp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -754,6 +812,8 @@ void Card::compute_action_chain_results(
|
||||
stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp);
|
||||
effective_ap += card_ap;
|
||||
effective_tp += card_tp;
|
||||
log.debug("(mag card set_index %zu @%04hX) updated effective_ap = %hd, effective_tp = %hd",
|
||||
set_index, card->get_card_ref(), effective_ap, effective_tp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -763,18 +823,25 @@ void Card::compute_action_chain_results(
|
||||
sc_card->compute_action_chain_results(apply_action_conditions, true);
|
||||
effective_ap += sc_card->action_chain.chain.effective_ap + sc_card->action_chain.chain.ap_effect_bonus;
|
||||
effective_tp += sc_card->action_chain.chain.effective_tp + sc_card->action_chain.chain.tp_effect_bonus;
|
||||
log.debug("(item is attacking; adding SC stats) updated effective_ap = %hd, effective_tp = %hd",
|
||||
effective_ap, effective_tp);
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x10)) {
|
||||
this->action_chain.chain.effective_ap = min<int16_t>(effective_ap, 99);
|
||||
log.debug("set chain effective_ap = %hd", this->action_chain.chain.effective_ap);
|
||||
}
|
||||
if (!this->action_chain.check_flag(0x20)) {
|
||||
this->action_chain.chain.effective_tp = min<int16_t>(effective_tp, 99);
|
||||
log.debug("set chain effective_tp = %hd", this->action_chain.chain.effective_tp);
|
||||
}
|
||||
|
||||
if (apply_action_conditions) {
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, this->shared_from_this(), this->shared_from_this(), 1, nullptr);
|
||||
log.debug("applied action conditions (1)");
|
||||
} else {
|
||||
log.debug("skipped applying action conditions (1)");
|
||||
}
|
||||
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
@@ -887,18 +954,27 @@ void Card::compute_action_chain_results(
|
||||
int16_t damage = 0;
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::TECH) {
|
||||
damage = this->action_chain.chain.effective_tp + this->action_chain.chain.tp_effect_bonus;
|
||||
log.debug("(tech) damage = %hhd (eff) + %hhd (bonus) = %hd", this->action_chain.chain.effective_tp, this->action_chain.chain.tp_effect_bonus, damage);
|
||||
} else if (this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
damage = this->action_chain.chain.effective_ap + this->action_chain.chain.ap_effect_bonus;
|
||||
log.debug("(physical) damage = %hhd (eff) + %hhd (bonus) = %hd", this->action_chain.chain.effective_ap, this->action_chain.chain.ap_effect_bonus, damage);
|
||||
} else {
|
||||
log.debug("(unknown attack medium) damage = 0");
|
||||
}
|
||||
this->action_chain.chain.damage = min<int16_t>(
|
||||
damage * this->action_chain.chain.damage_multiplier, 99);
|
||||
log.debug("overall chain damage = %hd (base) * %hhd (mult) = %hhd", damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
|
||||
|
||||
if (apply_action_conditions) {
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, this->shared_from_this(), this->shared_from_this(), 2, nullptr);
|
||||
0x03, this->shared_from_this(), this->shared_from_this(), 2, nullptr);
|
||||
log.debug("applied action conditions (2)");
|
||||
if (this->action_chain.check_flag(0x100)) {
|
||||
this->action_chain.chain.damage = min<int16_t>(this->action_chain.chain.damage + 5, 99);
|
||||
log.debug("(has flag 0x100) chain damage = %hhd", this->action_chain.chain.damage);
|
||||
}
|
||||
} else {
|
||||
log.debug("applied action conditions (2)");
|
||||
}
|
||||
|
||||
num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->get_client_id());
|
||||
@@ -983,6 +1059,7 @@ void Card::unknown_80235B10() {
|
||||
}
|
||||
|
||||
void Card::unknown_80236374(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto log = this->server()->log_stack(string_printf("unknown_80236374(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
|
||||
auto check_card = [&](shared_ptr<Card> card) -> void {
|
||||
if (card) {
|
||||
if (!card->unknown_80236554(other_card, as)) {
|
||||
@@ -1112,6 +1189,16 @@ 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
|
||||
? 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();
|
||||
log.debug("as = %s", as_str.c_str());
|
||||
} else {
|
||||
log.debug("as = null");
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
int16_t attack_bonus = 0;
|
||||
@@ -1121,6 +1208,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
if (other_card->action_chain.chain.target_card_refs[z] == this->get_card_ref()) {
|
||||
attack_bonus = other_card->action_chain.chain.damage;
|
||||
ret = true;
|
||||
log.debug("attack_bonus = %hd (matched other_card->action_chain.chain.target_card_refs)", attack_bonus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1128,6 +1216,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
for (size_t z = 0; (z < 4 * 9) && (as->target_card_refs[z] != 0xFFFF); z++) {
|
||||
if (as->target_card_refs[z] == this->get_card_ref()) {
|
||||
attack_bonus = other_card->action_chain.chain.damage;
|
||||
log.debug("attack_bonus = %hd (matched as->target_card_refs)", attack_bonus);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@@ -1136,23 +1225,22 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
}
|
||||
|
||||
this->action_metadata.attack_bonus = max<int16_t>(attack_bonus, 0);
|
||||
log.debug("attack_bonus = %hhd", this->action_metadata.attack_bonus);
|
||||
this->last_attack_preliminary_damage = 0;
|
||||
this->last_attack_final_damage = 0;
|
||||
log.debug("last attack damage stats cleared");
|
||||
|
||||
if (other_card) {
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, other_card, this->shared_from_this(), 0x20, as);
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
0x17, other_card, this->shared_from_this(), 0x40, as);
|
||||
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);
|
||||
if (other_card->action_chain.check_flag(0x20000)) {
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (!(this->card_flags & 2)) {
|
||||
return ret;
|
||||
if (this->card_flags & 2) {
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
}
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1174,8 +1262,9 @@ void Card::unknown_802362D8(shared_ptr<Card> other_card) {
|
||||
}
|
||||
}
|
||||
|
||||
void Card::unknown_80237734() {
|
||||
if (!this->action_chain.unknown_8024DEC4()) {
|
||||
void Card::apply_attack_result() {
|
||||
auto log = this->server()->log_stack(string_printf("apply_attack_result(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
if (!this->action_chain.can_apply_attack()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user