Ep3 NTE checkpoint 5
This commit is contained in:
+271
-128
@@ -221,31 +221,62 @@ ssize_t Card::apply_abnormal_condition(
|
||||
return cond_index;
|
||||
}
|
||||
|
||||
void Card::apply_ap_adjust_assists_to_attack(
|
||||
void Card::apply_ap_and_tp_adjust_assists_to_attack(
|
||||
shared_ptr<const Card> attacker_card,
|
||||
int16_t* inout_attacker_ap,
|
||||
int16_t* in_defense_power) const {
|
||||
int16_t* in_defense_power,
|
||||
int16_t* inout_attacker_tp) const {
|
||||
auto s = this->server();
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
uint8_t client_id = attacker_card->get_client_id();
|
||||
size_t num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(client_id);
|
||||
size_t num_assists = s->assist_server->compute_num_assist_effects_for_client(client_id);
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
auto eff = this->server()->assist_server->get_active_assist_by_index(z);
|
||||
if ((eff == AssistEffect::FIX) &&
|
||||
attacker_card &&
|
||||
(attacker_card->def_entry->def.type != CardType::HUNTERS_SC) &&
|
||||
(attacker_card->def_entry->def.type != CardType::ARKZ_SC)) {
|
||||
*inout_attacker_ap = 2;
|
||||
} else if ((eff == AssistEffect::SILENT_COLOSSEUM) &&
|
||||
(*inout_attacker_ap - *in_defense_power >= 7)) {
|
||||
*inout_attacker_ap = 0;
|
||||
switch (s->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::POWERLESS_RAIN:
|
||||
if (is_trial) {
|
||||
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap - 2, 0);
|
||||
}
|
||||
break;
|
||||
case AssistEffect::BRAVE_WIND:
|
||||
if (is_trial) {
|
||||
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap + 2, 0);
|
||||
}
|
||||
break;
|
||||
case AssistEffect::SILENT_COLOSSEUM:
|
||||
if (*inout_attacker_ap - *in_defense_power >= 7) {
|
||||
*inout_attacker_ap = 0;
|
||||
}
|
||||
break;
|
||||
case AssistEffect::INFLUENCE:
|
||||
if (is_trial) {
|
||||
*inout_attacker_ap += attacker_card->player_state()->count_set_cards_for_env_stats_nte();
|
||||
}
|
||||
break;
|
||||
case AssistEffect::FIX:
|
||||
if (!is_trial && attacker_card && !attacker_card->def_entry->def.is_sc()) {
|
||||
*inout_attacker_ap = 2;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
num_assists = this->server()->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
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);
|
||||
if ((eff == AssistEffect::AP_ABSORPTION) &&
|
||||
(attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
|
||||
*inout_attacker_ap = 0;
|
||||
auto eff = s->assist_server->get_active_assist_by_index(z);
|
||||
if (eff == AssistEffect::AP_ABSORPTION) {
|
||||
if (is_trial) {
|
||||
if (attacker_card->action_chain.chain.attack_medium == AttackMedium::TECH) {
|
||||
*inout_attacker_ap = *inout_attacker_ap + 2;
|
||||
} else if (attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
*inout_attacker_tp = *inout_attacker_ap;
|
||||
*inout_attacker_ap = 0;
|
||||
}
|
||||
} else if (attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
*inout_attacker_ap = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -266,26 +297,30 @@ void Card::commit_attack(
|
||||
G_ApplyConditionEffect_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));
|
||||
auto s = this->server();
|
||||
auto log = s->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));
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
int16_t effective_damage = damage;
|
||||
this->server()->card_special->adjust_attack_damage_due_to_conditions(
|
||||
s->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);
|
||||
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::RANSOM) &&
|
||||
(attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
|
||||
uint8_t team_id = this->player_state()->get_team_id();
|
||||
int16_t exp_amount = clamp<int16_t>(this->server()->team_exp[team_id], 0, effective_damage);
|
||||
this->server()->team_exp[team_id] -= exp_amount;
|
||||
int16_t exp_amount = clamp<int16_t>(s->team_exp[team_id], 0, effective_damage);
|
||||
s->team_exp[team_id] -= exp_amount;
|
||||
effective_damage -= exp_amount;
|
||||
this->server()->compute_team_dice_bonus(team_id);
|
||||
this->server()->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
if (cmd) {
|
||||
cmd->effect.ap += exp_amount;
|
||||
if (!is_trial) {
|
||||
s->compute_team_dice_bonus(team_id);
|
||||
s->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
if (cmd) {
|
||||
cmd->effect.ap += exp_amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -329,12 +364,11 @@ void Card::commit_attack(
|
||||
cmd_to_send.effect.attacker_card_ref = attacker_card->card_ref;
|
||||
cmd_to_send.effect.target_card_ref = this->card_ref;
|
||||
cmd_to_send.effect.value = effective_damage;
|
||||
this->server()->send(cmd_to_send);
|
||||
s->send(cmd_to_send);
|
||||
|
||||
this->propagate_shared_hp_if_needed();
|
||||
|
||||
if ((this->def_entry->def.type == CardType::HUNTERS_SC) ||
|
||||
(this->def_entry->def.type == CardType::ARKZ_SC)) {
|
||||
if (!is_trial && this->def_entry->def.is_sc()) {
|
||||
this->player_state()->stats.sc_damage_taken += effective_damage;
|
||||
}
|
||||
|
||||
@@ -343,8 +377,7 @@ void Card::commit_attack(
|
||||
}
|
||||
}
|
||||
|
||||
int16_t Card::compute_defense_power_for_attacker_card(
|
||||
shared_ptr<const Card> attacker_card) {
|
||||
int16_t Card::compute_defense_power_for_attacker_card(shared_ptr<const Card> attacker_card) {
|
||||
if (!attacker_card) {
|
||||
return 0;
|
||||
}
|
||||
@@ -352,21 +385,19 @@ int16_t Card::compute_defense_power_for_attacker_card(
|
||||
this->action_metadata.defense_power = 0;
|
||||
this->action_metadata.defense_bonus = 0;
|
||||
|
||||
auto s = this->server();
|
||||
for (size_t z = 0; z < this->action_metadata.defense_card_ref_count; z++) {
|
||||
if (attacker_card->card_ref != this->action_metadata.original_attacker_card_refs[z]) {
|
||||
continue;
|
||||
}
|
||||
auto ce = this->server()->definition_for_card_ref(
|
||||
this->action_metadata.defense_card_refs[z]);
|
||||
auto ce = s->definition_for_card_ref(this->action_metadata.defense_card_refs[z]);
|
||||
if (ce) {
|
||||
this->action_metadata.defense_power += ce->def.hp.stat;
|
||||
}
|
||||
}
|
||||
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, attacker_card, this->shared_from_this(), 0x08, nullptr);
|
||||
this->server()->card_special->apply_action_conditions(
|
||||
3, attacker_card, this->shared_from_this(), 0x10, nullptr);
|
||||
s->card_special->apply_action_conditions(3, attacker_card, this->shared_from_this(), 0x08, nullptr);
|
||||
s->card_special->apply_action_conditions(3, attacker_card, this->shared_from_this(), 0x10, nullptr);
|
||||
return this->action_metadata.defense_power + this->action_metadata.defense_bonus;
|
||||
}
|
||||
|
||||
@@ -475,14 +506,16 @@ 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()));
|
||||
auto s = this->server();
|
||||
auto log = s->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()));
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
this->card_flags = this->card_flags & 0xFFFFFFF3;
|
||||
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)) {
|
||||
int16_t defense_power = is_trial ? 0 : this->compute_defense_power_for_attacker_card(attacker_card);
|
||||
log.debug("ap=%hd, tp=%hd", attack_ap, attack_tp);
|
||||
if (!is_trial && (attack_ap == 0) && !this->action_metadata.check_flag(0x20)) {
|
||||
log.debug("ap == 0 and flag 0x20 not set");
|
||||
return;
|
||||
} else {
|
||||
@@ -494,6 +527,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
cmd.effect.attacker_card_ref = attacker_card->card_ref;
|
||||
cmd.effect.target_card_ref = this->card_ref;
|
||||
if (attacker_card->action_chain.chain.attack_medium == AttackMedium::UNKNOWN_03) {
|
||||
// Probably Resta
|
||||
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
|
||||
this->current_hp = min<int16_t>(
|
||||
this->current_hp + attacker_card->action_chain.chain.effective_tp,
|
||||
@@ -502,70 +536,82 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
this->propagate_shared_hp_if_needed();
|
||||
cmd.effect.tp = attacker_card->action_chain.chain.effective_tp;
|
||||
cmd.effect.value = -cmd.effect.tp;
|
||||
this->server()->send(cmd);
|
||||
s->send(cmd);
|
||||
|
||||
} else {
|
||||
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);
|
||||
|
||||
if (!is_trial) {
|
||||
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 (is_trial) {
|
||||
attacker_card->compute_action_chain_results(true, false);
|
||||
attack_ap = attacker_card->action_chain.chain.damage;
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::TECH) {
|
||||
attack_ap += this->action_chain.chain.tech_attack_bonus_nte;
|
||||
} else if (this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
attack_ap += this->action_chain.chain.physical_attack_bonus_nte;
|
||||
}
|
||||
}
|
||||
|
||||
s->card_special->compute_attack_ap(this->shared_from_this(), &attack_ap, attacker_card->get_card_ref());
|
||||
log.debug("computed ap %hd", attack_ap);
|
||||
this->apply_ap_adjust_assists_to_attack(attacker_card, &attack_ap, &defense_power);
|
||||
this->apply_ap_and_tp_adjust_assists_to_attack(attacker_card, &attack_ap, &defense_power, &attack_tp);
|
||||
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;
|
||||
auto target = this->server()->card_special->compute_replaced_target_based_on_conditions(
|
||||
targeted_card_ref, 1, 0, attacker_card_ref, 0xFFFF, 0, &unknown_a9, 0xFF, 0, 0xFFFF);
|
||||
auto target = s->card_special->compute_replaced_target_based_on_conditions(
|
||||
this->get_card_ref(), 1, 0, attacker_card->get_card_ref(), 0xFFFF, 0, &unknown_a9, 0xFF, nullptr, 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 (!is_trial) {
|
||||
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))) {
|
||||
s->card_special->check_for_defense_interference(attacker_card, this->shared_from_this(), &preliminary_damage);
|
||||
log.debug("checked for defense interference");
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
cmd.effect.ap = min<int16_t>(defense_power, 99);
|
||||
cmd.effect.current_hp = is_trial ? attack_ap : min<int16_t>(attack_ap, 99);
|
||||
cmd.effect.ap = is_trial ? defense_power : min<int16_t>(defense_power, 99);
|
||||
cmd.effect.tp = attack_tp;
|
||||
this->player_state()->stats.num_attacks_taken++;
|
||||
|
||||
auto ps = this->player_state();
|
||||
ps->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(
|
||||
preliminary_damage, attacker_card, &cmd, strike_num, &final_effective_damage);
|
||||
// TODO: Is this the right interpretation? The original code does some
|
||||
// fancy bitwise magic that I didn't bother to decipher, because this
|
||||
// interpretation makes sense based on how the game works.
|
||||
this->player_state()->stats.action_card_negated_damage += max<int16_t>(
|
||||
0, this->current_defense_power - final_effective_damage);
|
||||
target->commit_attack(preliminary_damage, attacker_card, &cmd, strike_num, &final_effective_damage);
|
||||
ps->stats.action_card_negated_damage += max<int16_t>(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()) {
|
||||
|
||||
if (!is_trial && (this != target.get())) {
|
||||
log.debug("target was replaced; committing zero-damage attack on original card");
|
||||
this->commit_attack(0, attacker_card, &cmd, 0, nullptr);
|
||||
}
|
||||
|
||||
this->server()->send_6xB4x39();
|
||||
s->send_6xB4x39();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1110,30 +1156,29 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
}
|
||||
|
||||
void Card::unknown_802380C0() {
|
||||
bool is_trial = this->server()->options.is_trial();
|
||||
this->card_flags &= 0xFFFFF7FB;
|
||||
this->action_metadata.clear_flags(0x30);
|
||||
this->action_chain.clear_flags(0x140);
|
||||
this->action_metadata.clear_flags(is_trial ? 0x10 : 0x30);
|
||||
this->action_chain.clear_flags(is_trial ? 0x40 : 0x140);
|
||||
this->unknown_80237F98(0);
|
||||
}
|
||||
|
||||
void Card::unknown_80237F98(bool require_condition_20_or_21) {
|
||||
auto s = this->server();
|
||||
|
||||
bool should_send_updates = false;
|
||||
for (ssize_t z = 8; z >= 0; z--) {
|
||||
if (this->action_chain.conditions[z].type != ConditionType::NONE) {
|
||||
if (!require_condition_20_or_21 ||
|
||||
this->server()->card_special->condition_has_when_20_or_21(
|
||||
this->action_chain.conditions[z])) {
|
||||
s->card_special->condition_has_when_20_or_21(this->action_chain.conditions[z])) {
|
||||
ActionState as;
|
||||
auto& cond = this->action_chain.conditions[z];
|
||||
if (!this->server()->card_special->is_card_targeted_by_condition(
|
||||
cond, as, this->shared_from_this())) {
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(
|
||||
cond, this->shared_from_this());
|
||||
if (!s->card_special->is_card_targeted_by_condition(cond, as, this->shared_from_this())) {
|
||||
s->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
should_send_updates = true;
|
||||
} else if (this->action_chain.conditions[z].remaining_turns == 0) {
|
||||
if (--this->action_chain.conditions[z].a_arg_value < 1) {
|
||||
this->server()->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(
|
||||
cond, this->shared_from_this());
|
||||
s->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
should_send_updates = true;
|
||||
}
|
||||
}
|
||||
@@ -1142,7 +1187,9 @@ void Card::unknown_80237F98(bool require_condition_20_or_21) {
|
||||
}
|
||||
|
||||
this->compute_action_chain_results(1, false);
|
||||
this->unknown_80236554(nullptr, nullptr);
|
||||
if (!s->options.is_trial()) {
|
||||
this->unknown_80236554(nullptr, nullptr);
|
||||
}
|
||||
if (should_send_updates) {
|
||||
this->send_6xB4x4E_4C_4D_if_needed();
|
||||
}
|
||||
@@ -1387,64 +1434,160 @@ void Card::unknown_802362D8(shared_ptr<Card> other_card) {
|
||||
}
|
||||
|
||||
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()));
|
||||
auto s = this->server();
|
||||
auto ps = this->player_state();
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
auto log = s->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;
|
||||
}
|
||||
|
||||
if (this->player_state()->stats.max_attack_combo_size < this->action_chain.chain.attack_action_card_ref_count) {
|
||||
this->player_state()->stats.max_attack_combo_size = this->action_chain.chain.attack_action_card_ref_count;
|
||||
}
|
||||
|
||||
ActionState as;
|
||||
as.attacker_card_ref = this->get_card_ref();
|
||||
as.target_card_refs = this->action_chain.chain.target_card_refs;
|
||||
this->server()->replace_targets_due_to_destruction_or_conditions(&as);
|
||||
this->action_chain.chain.target_card_refs = as.target_card_refs;
|
||||
this->action_chain.chain.target_card_ref_count = 0;
|
||||
for (size_t z = 0; z < 4 * 9; z++) {
|
||||
if (this->action_chain.chain.target_card_refs[z] != 0xFFFF) {
|
||||
this->action_chain.chain.target_card_ref_count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
shared_ptr<Card> card = this->server()->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (card) {
|
||||
card->current_defense_power = card->action_metadata.attack_bonus;
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
this->server()->card_special->unknown_8024A6DC(this->shared_from_this(), card);
|
||||
if (is_trial) {
|
||||
if (this->action_chain.check_flag(0x02)) {
|
||||
auto first_target_card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[0]);
|
||||
if (first_target_card) {
|
||||
auto first_target_ps = first_target_card->player_state();
|
||||
if (first_target_ps->count_set_cards() == 0) {
|
||||
this->action_chain.clear_target_card_refs();
|
||||
this->action_chain.chain.target_card_refs[0] = first_target_ps->get_sc_card_ref();
|
||||
this->action_chain.chain.target_card_ref_count = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ActionChainWithConds temp_chain = this->action_chain;
|
||||
temp_chain.chain.target_card_ref_count = 0;
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
auto target_card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (!target_card) {
|
||||
continue;
|
||||
}
|
||||
if (!(target_card->card_flags & 2)) {
|
||||
temp_chain.chain.target_card_refs[temp_chain.chain.target_card_ref_count] = target_card->get_card_ref();
|
||||
temp_chain.chain.target_card_ref_count++;
|
||||
} else if ((target_card->get_definition()->def.type == CardType::ITEM) && !this->action_chain.check_flag(0x02)) {
|
||||
auto target_ps = target_card->player_state();
|
||||
shared_ptr<Card> candidate_card;
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto set_card = target_ps->get_set_card(set_index);
|
||||
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2) && set_card->is_guard_item()) {
|
||||
candidate_card = set_card;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!candidate_card) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto set_card = target_ps->get_set_card(set_index);
|
||||
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2)) {
|
||||
candidate_card = set_card;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (candidate_card) {
|
||||
temp_chain.chain.target_card_refs[temp_chain.chain.target_card_ref_count] = candidate_card->get_card_ref();
|
||||
temp_chain.chain.target_card_ref_count++;
|
||||
} else {
|
||||
auto target_sc = target_ps->get_sc_card();
|
||||
if (!(target_sc->card_flags & 2)) {
|
||||
temp_chain.chain.target_card_refs[temp_chain.chain.target_card_ref_count] = candidate_card->get_card_ref();
|
||||
temp_chain.chain.target_card_ref_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->action_chain.chain.target_card_ref_count = 0;
|
||||
for (size_t z = 0; z < temp_chain.chain.target_card_ref_count; z++) {
|
||||
this->action_chain.add_target_card_ref(temp_chain.chain.target_card_refs[z]);
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
s->card_special->unknown_8024945C(this->shared_from_this(), nullptr);
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
auto target_card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (target_card && !this->action_chain.check_flag(0x40)) {
|
||||
s->card_special->unknown_8024A6DC(this->shared_from_this(), target_card);
|
||||
}
|
||||
}
|
||||
|
||||
this->compute_action_chain_results(true, false);
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
s->card_special->unknown_8024997C(this->shared_from_this());
|
||||
}
|
||||
|
||||
this->compute_action_chain_results(true, false);
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
auto target_card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (target_card) {
|
||||
target_card->execute_attack(this->shared_from_this());
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (ps->stats.max_attack_combo_size < this->action_chain.chain.attack_action_card_ref_count) {
|
||||
ps->stats.max_attack_combo_size = this->action_chain.chain.attack_action_card_ref_count;
|
||||
}
|
||||
|
||||
ActionState as;
|
||||
as.attacker_card_ref = this->get_card_ref();
|
||||
as.target_card_refs = this->action_chain.chain.target_card_refs;
|
||||
s->replace_targets_due_to_destruction_or_conditions(&as);
|
||||
this->action_chain.chain.target_card_refs = as.target_card_refs;
|
||||
this->action_chain.chain.target_card_ref_count = 0;
|
||||
for (size_t z = 0; z < 4 * 9; z++) {
|
||||
if (this->action_chain.chain.target_card_refs[z] != 0xFFFF) {
|
||||
this->action_chain.chain.target_card_ref_count++;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
shared_ptr<Card> card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (card) {
|
||||
card->current_defense_power = card->action_metadata.attack_bonus;
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
s->card_special->unknown_8024A6DC(this->shared_from_this(), card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->compute_action_chain_results(1, 0);
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
s->card_special->unknown_8024997C(this->shared_from_this());
|
||||
}
|
||||
if (!(this->card_flags & 2)) {
|
||||
this->compute_action_chain_results(1, 0);
|
||||
s->card_special->check_for_attack_interference(this->shared_from_this());
|
||||
}
|
||||
this->compute_action_chain_results(1, 0);
|
||||
this->unknown_80236374(this->shared_from_this(), nullptr);
|
||||
this->unknown_802362D8(this->shared_from_this());
|
||||
}
|
||||
|
||||
this->compute_action_chain_results(1, 0);
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
this->server()->card_special->unknown_8024997C(this->shared_from_this());
|
||||
s->card_special->unknown_8024A394(this->shared_from_this());
|
||||
}
|
||||
if (!(this->card_flags & 2)) {
|
||||
this->compute_action_chain_results(1, 0);
|
||||
this->server()->card_special->check_for_attack_interference(this->shared_from_this());
|
||||
}
|
||||
this->compute_action_chain_results(1, 0);
|
||||
this->unknown_80236374(this->shared_from_this(), nullptr);
|
||||
this->unknown_802362D8(this->shared_from_this());
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
this->server()->card_special->unknown_8024A394(this->shared_from_this());
|
||||
}
|
||||
this->player_state()->stats.num_attacks_given++;
|
||||
ps->stats.num_attacks_given++;
|
||||
|
||||
this->action_chain.clear_flags(8);
|
||||
this->action_chain.set_flags(4);
|
||||
this->card_flags |= 0x200;
|
||||
this->action_chain.clear_target_card_refs();
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->server()->player_states[client_id];
|
||||
if (ps) {
|
||||
ps->unknown_8023C110();
|
||||
if (!is_trial) {
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = s->player_states[client_id];
|
||||
if (ps) {
|
||||
ps->unknown_8023C110();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->send_6xB4x4E_4C_4D_if_needed();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,10 +34,11 @@ public:
|
||||
int16_t value,
|
||||
int8_t dice_roll_value,
|
||||
int8_t random_percent);
|
||||
void apply_ap_adjust_assists_to_attack(
|
||||
void apply_ap_and_tp_adjust_assists_to_attack(
|
||||
std::shared_ptr<const Card> attacker_card,
|
||||
int16_t* inout_attacker_ap,
|
||||
int16_t* in_defense_power) const;
|
||||
int16_t* in_defense_power,
|
||||
int16_t* inout_attacker_tp) const;
|
||||
bool card_type_is_sc_or_creature() const;
|
||||
bool check_card_flag(uint32_t flags) const;
|
||||
void commit_attack(
|
||||
|
||||
+50
-42
@@ -150,7 +150,10 @@ shared_ptr<const Server> CardSpecial::server() const {
|
||||
|
||||
void CardSpecial::adjust_attack_damage_due_to_conditions(
|
||||
shared_ptr<const Card> target_card, int16_t* inout_damage, uint16_t attacker_card_ref) {
|
||||
shared_ptr<const Card> attacker_card = this->server()->card_for_set_card_ref(attacker_card_ref);
|
||||
auto s = this->server();
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
shared_ptr<const Card> attacker_card = s->card_for_set_card_ref(attacker_card_ref);
|
||||
auto attack_medium = attacker_card ? attacker_card->action_chain.chain.attack_medium : AttackMedium::UNKNOWN;
|
||||
|
||||
for (size_t z = 0; z < 9; z++) {
|
||||
@@ -158,11 +161,11 @@ void CardSpecial::adjust_attack_damage_due_to_conditions(
|
||||
if (cond.type == ConditionType::NONE) {
|
||||
continue;
|
||||
}
|
||||
if (this->card_ref_has_ability_trap(cond)) {
|
||||
if (!is_trial && this->card_ref_has_ability_trap(cond)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
if (!s->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
cond.card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
@@ -173,7 +176,7 @@ void CardSpecial::adjust_attack_damage_due_to_conditions(
|
||||
|
||||
switch (cond.type) {
|
||||
case ConditionType::WEAK_HIT_BLOCK:
|
||||
if (*inout_damage <= cond.value) {
|
||||
if (!is_trial && (*inout_damage <= cond.value)) {
|
||||
*inout_damage = 0;
|
||||
}
|
||||
break;
|
||||
@@ -182,30 +185,31 @@ void CardSpecial::adjust_attack_damage_due_to_conditions(
|
||||
auto target_ps = target_card->player_state();
|
||||
if (target_ps) {
|
||||
uint8_t target_team_id = target_ps->get_team_id();
|
||||
int16_t exp_deduction = this->server()->team_exp[target_team_id];
|
||||
int16_t exp_deduction = s->team_exp[target_team_id];
|
||||
if (exp_deduction < *inout_damage) {
|
||||
*inout_damage = *inout_damage - exp_deduction;
|
||||
this->server()->team_exp[target_team_id] = 0;
|
||||
s->team_exp[target_team_id] = 0;
|
||||
} else {
|
||||
this->server()->team_exp[target_team_id] = exp_deduction - *inout_damage;
|
||||
s->team_exp[target_team_id] = exp_deduction - *inout_damage;
|
||||
exp_deduction = *inout_damage;
|
||||
*inout_damage = 0;
|
||||
}
|
||||
this->send_6xB4x06_for_exp_change(
|
||||
target_card, attacker_card_ref, -exp_deduction, true);
|
||||
if (!is_trial) {
|
||||
this->send_6xB4x06_for_exp_change(target_card, attacker_card_ref, -exp_deduction, true);
|
||||
}
|
||||
this->compute_team_dice_bonus(target_team_id);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case ConditionType::UNKNOWN_73:
|
||||
if (cond.value <= *inout_damage) {
|
||||
if (!is_trial && (cond.value <= *inout_damage)) {
|
||||
*inout_damage = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case ConditionType::HALFGUARD:
|
||||
if (cond.value <= *inout_damage) {
|
||||
if (!is_trial && (cond.value <= *inout_damage)) {
|
||||
*inout_damage /= 2;
|
||||
}
|
||||
break;
|
||||
@@ -635,7 +639,10 @@ void CardSpecial::compute_attack_ap(
|
||||
shared_ptr<const Card> target_card,
|
||||
int16_t* out_value,
|
||||
uint16_t attacker_card_ref) {
|
||||
auto attacker_card = this->server()->card_for_set_card_ref(attacker_card_ref);
|
||||
auto s = this->server();
|
||||
auto is_trial = s->options.is_trial();
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(attacker_card_ref);
|
||||
AttackMedium attacker_sc_attack_medium = attacker_card
|
||||
? attacker_card->action_chain.chain.attack_medium
|
||||
: AttackMedium::UNKNOWN;
|
||||
@@ -648,8 +655,8 @@ void CardSpecial::compute_attack_ap(
|
||||
for (size_t cond_index = 0; cond_index < 9; cond_index++) {
|
||||
auto& cond = card->action_chain.conditions[cond_index];
|
||||
if (cond.type == ConditionType::NONE ||
|
||||
this->card_ref_has_ability_trap(cond) ||
|
||||
!this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
(!is_trial && this->card_ref_has_ability_trap(cond)) ||
|
||||
!s->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
card->action_chain.conditions[cond_index].card_ref,
|
||||
target_card->get_card_ref(),
|
||||
attacker_card_ref,
|
||||
@@ -669,7 +676,7 @@ void CardSpecial::compute_attack_ap(
|
||||
};
|
||||
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->server()->get_player_state(client_id);
|
||||
auto ps = s->get_player_state(client_id);
|
||||
if (ps) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
check_card(ps->get_set_card(set_index));
|
||||
@@ -678,11 +685,13 @@ void CardSpecial::compute_attack_ap(
|
||||
}
|
||||
}
|
||||
|
||||
if (attacker_card && attacker_card->get_condition_value(ConditionType::UNKNOWN_7D)) {
|
||||
*out_value = *out_value * 1.5f;
|
||||
}
|
||||
if (target_card && target_card->get_condition_value(ConditionType::UNKNOWN_7D)) {
|
||||
*out_value = 0;
|
||||
if (!is_trial) {
|
||||
if (attacker_card && attacker_card->get_condition_value(ConditionType::UNKNOWN_7D)) {
|
||||
*out_value = *out_value * 1.5f;
|
||||
}
|
||||
if (target_card && target_card->get_condition_value(ConditionType::UNKNOWN_7D)) {
|
||||
*out_value = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -694,6 +703,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
uint16_t condition_giver_card_ref) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack("compute_attack_env_stats: ");
|
||||
bool is_trial = s->options.is_trial();
|
||||
|
||||
string pa_str = pa.str();
|
||||
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);
|
||||
@@ -712,7 +722,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
|
||||
auto ps = card->player_state();
|
||||
log.debug("base ps = %hhu", ps->client_id);
|
||||
ast.num_set_cards = ps->count_set_cards();
|
||||
ast.num_set_cards = is_trial ? ps->count_set_cards_for_env_stats_nte() : ps->count_set_cards();
|
||||
auto condition_giver_card = s->card_for_set_card_ref(condition_giver_card_ref);
|
||||
auto target_card = s->card_for_set_card_ref(target_card_ref);
|
||||
if (!target_card) {
|
||||
@@ -723,7 +733,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto other_ps = s->get_player_state(z);
|
||||
if (other_ps) {
|
||||
ps_num_set_cards += other_ps->count_set_cards();
|
||||
ps_num_set_cards += is_trial ? other_ps->count_set_cards_for_env_stats_nte() : other_ps->count_set_cards();
|
||||
}
|
||||
}
|
||||
ast.total_num_set_cards = ps_num_set_cards;
|
||||
@@ -738,9 +748,9 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
auto other_ps = s->get_player_state(z);
|
||||
if (other_ps) {
|
||||
if (target_card_team_id == other_ps->get_team_id()) {
|
||||
target_team_num_set_cards += other_ps->count_set_cards();
|
||||
target_team_num_set_cards += is_trial ? other_ps->count_set_cards_for_env_stats_nte() : other_ps->count_set_cards();
|
||||
} else {
|
||||
non_target_team_num_set_cards += other_ps->count_set_cards();
|
||||
non_target_team_num_set_cards += is_trial ? other_ps->count_set_cards_for_env_stats_nte() : other_ps->count_set_cards();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -769,7 +779,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
}
|
||||
ast.num_item_or_creature_cards_in_hand = num_item_or_creature_cards_in_hand;
|
||||
|
||||
if (s->options.is_trial()) {
|
||||
if (is_trial) {
|
||||
ast.num_destroyed_ally_fcs = s->team_num_cards_destroyed[ps->get_team_id()] - card->num_ally_fcs_destroyed_at_set_time;
|
||||
} else {
|
||||
ast.num_destroyed_ally_fcs = card->num_destroyed_ally_fcs;
|
||||
@@ -4785,8 +4795,8 @@ void CardSpecial::action_phase_before_for_card(shared_ptr<Card> unknown_p2) {
|
||||
}
|
||||
}
|
||||
|
||||
void CardSpecial::unknown_8024945C(shared_ptr<Card> unknown_p2, const ActionState& existing_as) {
|
||||
this->apply_effects_on_phase_change_t<0x0A, 0x0A>(unknown_p2, this->server()->options.is_trial() ? nullptr : &existing_as);
|
||||
void CardSpecial::unknown_8024945C(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
|
||||
this->apply_effects_on_phase_change_t<0x0A, 0x0A>(unknown_p2, this->server()->options.is_trial() ? nullptr : existing_as);
|
||||
}
|
||||
|
||||
void CardSpecial::unknown_8024966C(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
|
||||
@@ -4937,7 +4947,8 @@ void CardSpecial::check_for_attack_interference(shared_ptr<Card> unknown_p2) {
|
||||
|
||||
template <uint8_t When1, uint8_t When2, uint8_t When3, uint8_t When4>
|
||||
void CardSpecial::unknown_t2(shared_ptr<Card> unknown_p2) {
|
||||
auto log = this->server()->log_stack(string_printf("unknown_t2<%02hhX, %02hhX, %02hhX, %02hhX>(@%04hX #%04hX): ", When1, When2, When3, When4, unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(string_printf("unknown_t2<%02hhX, %02hhX, %02hhX, %02hhX>(@%04hX #%04hX): ", When1, When2, When3, When4, unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
|
||||
ActionState as = this->create_attack_state_from_card_action_chain(unknown_p2);
|
||||
|
||||
@@ -4948,25 +4959,23 @@ void CardSpecial::unknown_t2(shared_ptr<Card> unknown_p2) {
|
||||
}
|
||||
|
||||
auto defender_card = unknown_p2;
|
||||
if (unknown_p2->get_definition() &&
|
||||
(unknown_p2->get_definition()->def.type == CardType::ITEM) &&
|
||||
sc_card) {
|
||||
if (unknown_p2->get_definition() && (unknown_p2->get_definition()->def.type == CardType::ITEM) && sc_card) {
|
||||
defender_card = sc_card;
|
||||
}
|
||||
|
||||
this->apply_defense_conditions(as, When1, unknown_p2, 4);
|
||||
this->apply_defense_conditions(as, When2, unknown_p2, 4);
|
||||
uint8_t apply_defense_conditions_flags = s->options.is_trial() ? 0x1F : 0x04;
|
||||
this->apply_defense_conditions(as, When1, unknown_p2, apply_defense_conditions_flags);
|
||||
this->apply_defense_conditions(as, When2, unknown_p2, apply_defense_conditions_flags);
|
||||
if (defender_card) {
|
||||
this->apply_defense_conditions(as, When3, defender_card, 4);
|
||||
this->apply_defense_conditions(as, When3, defender_card, apply_defense_conditions_flags);
|
||||
}
|
||||
|
||||
for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) {
|
||||
auto set_card = this->server()->card_for_set_card_ref(as.target_card_refs[z]);
|
||||
auto set_card = s->card_for_set_card_ref(as.target_card_refs[z]);
|
||||
if (set_card) {
|
||||
ActionState target_as = this->create_defense_state_for_card_pair_action_chains(
|
||||
unknown_p2, set_card);
|
||||
this->apply_defense_conditions(target_as, When1, set_card, 4);
|
||||
this->apply_defense_conditions(target_as, When4, set_card, 4);
|
||||
ActionState target_as = this->create_defense_state_for_card_pair_action_chains(unknown_p2, set_card);
|
||||
this->apply_defense_conditions(target_as, When1, set_card, apply_defense_conditions_flags);
|
||||
this->apply_defense_conditions(target_as, When4, set_card, apply_defense_conditions_flags);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4980,7 +4989,7 @@ void CardSpecial::unknown_t2(shared_ptr<Card> unknown_p2) {
|
||||
this->evaluate_and_apply_effects(When2, as.action_card_refs[z], as, unknown_p2->get_card_ref());
|
||||
}
|
||||
for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) {
|
||||
auto set_card = this->server()->card_for_set_card_ref(as.target_card_refs[z]);
|
||||
auto set_card = s->card_for_set_card_ref(as.target_card_refs[z]);
|
||||
if (set_card) {
|
||||
ActionState target_as = this->create_defense_state_for_card_pair_action_chains(unknown_p2, set_card);
|
||||
this->evaluate_and_apply_effects(When1, set_card->get_card_ref(), target_as, unknown_p2->get_card_ref());
|
||||
@@ -5031,8 +5040,7 @@ bool CardSpecial::client_has_atk_dice_boost_condition(uint8_t client_id) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void CardSpecial::unknown_8024A6DC(
|
||||
shared_ptr<Card> unknown_p2, shared_ptr<Card> unknown_p3) {
|
||||
void CardSpecial::unknown_8024A6DC(shared_ptr<Card> unknown_p2, shared_ptr<Card> unknown_p3) {
|
||||
ActionState as = this->create_defense_state_for_card_pair_action_chains(
|
||||
unknown_p2, unknown_p3);
|
||||
for (size_t z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
|
||||
@@ -319,7 +319,7 @@ public:
|
||||
void apply_effects_on_phase_change_t(std::shared_ptr<Card> unknown_p2, const ActionState* existing_as = nullptr);
|
||||
void draw_phase_before_for_card(std::shared_ptr<Card> unknown_p2);
|
||||
void action_phase_before_for_card(std::shared_ptr<Card> unknown_p2);
|
||||
void unknown_8024945C(std::shared_ptr<Card> unknown_p2, const ActionState& existing_as);
|
||||
void unknown_8024945C(std::shared_ptr<Card> unknown_p2, const ActionState* existing_as);
|
||||
void unknown_8024966C(std::shared_ptr<Card> unknown_p2, const ActionState* existing_as);
|
||||
static std::shared_ptr<Card> sc_card_for_card(std::shared_ptr<Card> unknown_p2);
|
||||
void unknown_8024A9D8(const ActionState& pa, uint16_t action_card_ref);
|
||||
|
||||
+14
-12
@@ -511,20 +511,22 @@ void PlayerState::compute_total_set_cards_cost() {
|
||||
}
|
||||
}
|
||||
|
||||
size_t PlayerState::count_set_cards_for_env_stats_nte() const {
|
||||
size_t ret = 0;
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
if (this->card_refs[8 + set_index] != 0xFFFF) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t PlayerState::count_set_cards() const {
|
||||
size_t ret = 0;
|
||||
if (this->server()->options.is_trial()) {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
if (this->card_refs[8 + set_index] != 0xFFFF) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->set_cards[set_index];
|
||||
if (card && !(card->card_flags & 2)) {
|
||||
ret++;
|
||||
}
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = this->set_cards[set_index];
|
||||
if (card && !(card->card_flags & 2)) {
|
||||
ret++;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -53,6 +53,7 @@ public:
|
||||
uint16_t card_ref_for_hand_index(size_t hand_index) const;
|
||||
int16_t compute_attack_or_defense_atk_costs(const ActionState& pa) const;
|
||||
void compute_total_set_cards_cost();
|
||||
size_t count_set_cards_for_env_stats_nte() const;
|
||||
size_t count_set_cards() const;
|
||||
size_t count_set_refs() const;
|
||||
void discard_all_assist_cards_from_hand();
|
||||
|
||||
@@ -234,8 +234,8 @@ bool ActionChain::operator==(const ActionChain& other) const {
|
||||
(this->damage_multiplier == other.damage_multiplier) &&
|
||||
(this->attack_number == other.attack_number) &&
|
||||
(this->tp_effect_bonus == other.tp_effect_bonus) &&
|
||||
(this->unused1 == other.unused1) &&
|
||||
(this->unused2 == other.unused2) &&
|
||||
(this->physical_attack_bonus_nte == other.physical_attack_bonus_nte) &&
|
||||
(this->tech_attack_bonus_nte == other.tech_attack_bonus_nte) &&
|
||||
(this->card_ap == other.card_ap) &&
|
||||
(this->card_tp == other.card_tp) &&
|
||||
(this->flags == other.flags) &&
|
||||
@@ -254,7 +254,7 @@ std::string ActionChain::str() const {
|
||||
"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, u1=%hhu, u2=%hhu, card_ap=%hhd, "
|
||||
"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,
|
||||
@@ -271,8 +271,8 @@ std::string ActionChain::str() const {
|
||||
this->damage_multiplier,
|
||||
this->attack_number,
|
||||
this->tp_effect_bonus,
|
||||
this->unused1,
|
||||
this->unused2,
|
||||
this->physical_attack_bonus_nte,
|
||||
this->tech_attack_bonus_nte,
|
||||
this->card_ap,
|
||||
this->card_tp,
|
||||
this->flags.load(),
|
||||
@@ -294,8 +294,8 @@ void ActionChain::clear() {
|
||||
this->damage_multiplier = 1;
|
||||
this->attack_number = 0xFF;
|
||||
this->tp_effect_bonus = 0;
|
||||
this->unused1 = 0;
|
||||
this->unused2 = 0;
|
||||
this->physical_attack_bonus_nte = 0;
|
||||
this->tech_attack_bonus_nte = 0;
|
||||
this->card_ap = 0;
|
||||
this->card_tp = 0;
|
||||
this->flags = 0;
|
||||
@@ -319,8 +319,8 @@ void ActionChain::clear_FF() {
|
||||
this->damage_multiplier = -1;
|
||||
this->attack_number = 0xFF;
|
||||
this->tp_effect_bonus = -1;
|
||||
this->unused1 = 0xFF;
|
||||
this->unused2 = 0xFF;
|
||||
this->physical_attack_bonus_nte = 0xFF;
|
||||
this->tech_attack_bonus_nte = 0xFF;
|
||||
this->card_ap = -1;
|
||||
this->card_tp = -1;
|
||||
this->flags = 0xFFFFFFFF;
|
||||
@@ -393,8 +393,8 @@ void ActionChainWithConds::reset() {
|
||||
this->chain.effective_tp = 0;
|
||||
this->chain.ap_effect_bonus = 0;
|
||||
this->chain.tp_effect_bonus = 0;
|
||||
this->chain.unused1 = 0;
|
||||
this->chain.unused2 = 0;
|
||||
this->chain.physical_attack_bonus_nte = 0;
|
||||
this->chain.tech_attack_bonus_nte = 0;
|
||||
this->chain.damage = 0;
|
||||
this->chain.strike_count = 1;
|
||||
this->chain.damage_multiplier = 1;
|
||||
@@ -525,8 +525,8 @@ ActionChainWithCondsTrial::ActionChainWithCondsTrial(const ActionChainWithConds&
|
||||
damage_multiplier(src.chain.damage_multiplier),
|
||||
attack_number(src.chain.attack_number),
|
||||
tp_effect_bonus(src.chain.tp_effect_bonus),
|
||||
unused1(src.chain.unused1),
|
||||
unused2(src.chain.unused2),
|
||||
physical_attack_bonus_nte(src.chain.physical_attack_bonus_nte),
|
||||
tech_attack_bonus_nte(src.chain.tech_attack_bonus_nte),
|
||||
card_ap(src.chain.card_ap),
|
||||
card_tp(src.chain.card_tp),
|
||||
flags(src.chain.flags),
|
||||
@@ -550,8 +550,8 @@ ActionChainWithCondsTrial::operator ActionChainWithConds() const {
|
||||
ret.chain.damage_multiplier = this->damage_multiplier;
|
||||
ret.chain.attack_number = this->attack_number;
|
||||
ret.chain.tp_effect_bonus = this->tp_effect_bonus;
|
||||
ret.chain.unused1 = this->unused1;
|
||||
ret.chain.unused2 = this->unused2;
|
||||
ret.chain.physical_attack_bonus_nte = this->physical_attack_bonus_nte;
|
||||
ret.chain.tech_attack_bonus_nte = this->tech_attack_bonus_nte;
|
||||
ret.chain.card_ap = this->card_ap;
|
||||
ret.chain.card_tp = this->card_tp;
|
||||
ret.chain.flags = this->flags;
|
||||
|
||||
@@ -118,8 +118,8 @@ struct ActionChain {
|
||||
/* 1D */ int8_t damage_multiplier;
|
||||
/* 1E */ uint8_t attack_number;
|
||||
/* 1F */ int8_t tp_effect_bonus;
|
||||
/* 20 */ uint8_t unused1;
|
||||
/* 21 */ uint8_t unused2;
|
||||
/* 20 */ int8_t physical_attack_bonus_nte;
|
||||
/* 21 */ int8_t tech_attack_bonus_nte;
|
||||
/* 22 */ int8_t card_ap;
|
||||
/* 23 */ int8_t card_tp;
|
||||
/* 24 */ le_uint32_t flags;
|
||||
@@ -190,8 +190,8 @@ struct ActionChainWithCondsTrial {
|
||||
/* 001D */ int8_t damage_multiplier;
|
||||
/* 001E */ uint8_t attack_number;
|
||||
/* 001F */ int8_t tp_effect_bonus;
|
||||
/* 0020 */ uint8_t unused1;
|
||||
/* 0021 */ uint8_t unused2;
|
||||
/* 0020 */ int8_t physical_attack_bonus_nte;
|
||||
/* 0021 */ int8_t tech_attack_bonus_nte;
|
||||
/* 0022 */ int8_t card_ap;
|
||||
/* 0023 */ int8_t card_tp;
|
||||
/* 0024 */ le_uint32_t flags;
|
||||
|
||||
+73
-58
@@ -853,11 +853,7 @@ void Server::draw_phase_after() {
|
||||
}
|
||||
}
|
||||
if (no_winner_specified) {
|
||||
if (this->options.is_trial()) {
|
||||
throw runtime_error("unimplemented NTE condition");
|
||||
} else {
|
||||
this->compute_losing_team_id_and_add_winner_flags(0);
|
||||
}
|
||||
this->compute_losing_team_id_and_add_winner_flags(0);
|
||||
}
|
||||
this->round_num--;
|
||||
this->set_battle_ended();
|
||||
@@ -2578,55 +2574,60 @@ void Server::handle_CAx49_card_counts(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
|
||||
void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
ps->assist_flags &= ~(AssistFlag::HAS_WON_BATTLE |
|
||||
AssistFlag::WINNER_DECIDED_BY_DEFEAT |
|
||||
AssistFlag::BATTLE_DID_NOT_END_DUE_TO_TIME_LIMIT);
|
||||
bool is_trial = this->options.is_trial();
|
||||
|
||||
if (!is_trial) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
ps->assist_flags &= ~(AssistFlag::HAS_WON_BATTLE |
|
||||
AssistFlag::WINNER_DECIDED_BY_DEFEAT |
|
||||
AssistFlag::BATTLE_DID_NOT_END_DUE_TO_TIME_LIMIT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t flags_to_add = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_DEFEAT;
|
||||
uint32_t winner_flags = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_DEFEAT;
|
||||
|
||||
// First, check which team has more dead SCs
|
||||
int8_t losing_team_id = -1;
|
||||
uint32_t team_counts[2] = {0, 0};
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
}
|
||||
auto sc_card = ps->get_sc_card();
|
||||
if (sc_card && (sc_card->card_flags & 2)) {
|
||||
team_counts[ps->get_team_id()]++;
|
||||
}
|
||||
}
|
||||
if (team_counts[1] < team_counts[0]) {
|
||||
losing_team_id = 0;
|
||||
} else if (team_counts[0] < team_counts[1]) {
|
||||
losing_team_id = 1;
|
||||
}
|
||||
array<uint32_t, 2> team_counts = {0, 0};
|
||||
|
||||
// If the SC counts match, break ties by remaining SC HP
|
||||
if (losing_team_id == -1) {
|
||||
team_counts[0] = 0;
|
||||
team_counts[1] = 0;
|
||||
if (!is_trial) {
|
||||
// First, check which team has more dead SCs
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
}
|
||||
auto sc_card = ps->get_sc_card();
|
||||
if (sc_card) {
|
||||
team_counts[ps->get_team_id()] += sc_card->get_current_hp();
|
||||
auto sc_card = ps->get_sc_card();
|
||||
if (sc_card && (sc_card->card_flags & 2)) {
|
||||
team_counts.at(ps->get_team_id())++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (team_counts[0] < team_counts[1]) {
|
||||
if (team_counts[1] < team_counts[0]) {
|
||||
losing_team_id = 0;
|
||||
} else if (team_counts[1] < team_counts[0]) {
|
||||
} else if (team_counts[0] < team_counts[1]) {
|
||||
losing_team_id = 1;
|
||||
}
|
||||
|
||||
// If the SC counts match, break ties by remaining SC HP
|
||||
if (losing_team_id == -1) {
|
||||
team_counts[0] = 0;
|
||||
team_counts[1] = 0;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
auto sc_card = ps->get_sc_card();
|
||||
if (sc_card) {
|
||||
team_counts.at(ps->get_team_id()) += sc_card->get_current_hp();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (team_counts[0] < team_counts[1]) {
|
||||
losing_team_id = 0;
|
||||
} else if (team_counts[1] < team_counts[0]) {
|
||||
losing_team_id = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If still tied, break ties by number of opponent cards destroyed
|
||||
@@ -2636,9 +2637,8 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
team_counts.at(ps->get_team_id()) += ps->stats.num_opponent_cards_destroyed;
|
||||
}
|
||||
team_counts[ps->get_team_id()] += ps->stats.num_opponent_cards_destroyed;
|
||||
}
|
||||
if (team_counts[0] < team_counts[1]) {
|
||||
losing_team_id = 0;
|
||||
@@ -2654,9 +2654,8 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
team_counts.at(ps->get_team_id()) += ps->stats.damage_given;
|
||||
}
|
||||
team_counts[ps->get_team_id()] += ps->stats.damage_given;
|
||||
}
|
||||
if (team_counts[0] < team_counts[1]) {
|
||||
losing_team_id = 0;
|
||||
@@ -2673,9 +2672,8 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
team_counts.at(ps->get_team_id()) += ps->roll_dice(1);
|
||||
}
|
||||
team_counts[ps->get_team_id()] += ps->roll_dice(1);
|
||||
}
|
||||
team_counts[0] *= this->team_client_count[1];
|
||||
team_counts[1] *= this->team_client_count[0];
|
||||
@@ -2685,18 +2683,19 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
losing_team_id = 1;
|
||||
}
|
||||
}
|
||||
flags_to_add = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_RANDOM;
|
||||
winner_flags = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_RANDOM;
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (!ps) {
|
||||
continue;
|
||||
if (losing_team_id != ps->get_team_id()) {
|
||||
ps->assist_flags |= winner_flags;
|
||||
}
|
||||
if (!is_trial || (losing_team_id != ps->get_team_id())) {
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
}
|
||||
if (losing_team_id != ps->get_team_id()) {
|
||||
ps->assist_flags |= flags_to_add;
|
||||
}
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2769,7 +2768,7 @@ void Server::unknown_8023EEF4() {
|
||||
this->attack_cards[this->unknown_a14]->compute_action_chain_results(1, 0);
|
||||
this->attack_cards[this->unknown_a14]->unknown_80236374(this->attack_cards[this->unknown_a14], &as);
|
||||
if (!this->attack_cards[this->unknown_a14]->action_chain.check_flag(0x40)) {
|
||||
this->card_special->unknown_8024945C(this->attack_cards[this->unknown_a14], as);
|
||||
this->card_special->unknown_8024945C(this->attack_cards[this->unknown_a14], &as);
|
||||
}
|
||||
this->attack_cards[this->unknown_a14]->compute_action_chain_results(1, 0);
|
||||
this->attack_cards[this->unknown_a14]->unknown_80236374(this->attack_cards[this->unknown_a14], &as);
|
||||
@@ -3038,16 +3037,32 @@ void Server::unknown_8023EE48() {
|
||||
}
|
||||
|
||||
void Server::unknown_8023EE80() {
|
||||
auto log = this->log_stack("unknown_8023EE80: ");
|
||||
bool is_trial = this->options.is_trial();
|
||||
|
||||
if (this->unknown_a14 < this->num_pending_attacks_with_cards) {
|
||||
log.debug("applying first attack result");
|
||||
this->attack_cards[this->unknown_a14]->apply_attack_result();
|
||||
if (is_trial) {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
ps->unknown_8023C110();
|
||||
}
|
||||
}
|
||||
}
|
||||
this->unknown_a14++;
|
||||
}
|
||||
|
||||
this->check_for_battle_end();
|
||||
this->copy_player_states_to_prev_states();
|
||||
this->unknown_8023EEF4();
|
||||
this->send_set_card_updates_and_6xB4x04_if_needed();
|
||||
|
||||
if (is_trial) {
|
||||
this->unknown_8023EEF4();
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
this->send_6xB4x02_for_all_players_if_needed();
|
||||
} else {
|
||||
this->copy_player_states_to_prev_states();
|
||||
this->unknown_8023EEF4();
|
||||
this->send_set_card_updates_and_6xB4x04_if_needed();
|
||||
}
|
||||
}
|
||||
|
||||
void Server::unknown_802402F4() {
|
||||
|
||||
Reference in New Issue
Block a user