fix some bugs introduced by Ep3 NTE work

This commit is contained in:
Martin Michelsen
2024-02-09 00:06:05 -08:00
parent 47533e1a5f
commit fcc274ce3e
8 changed files with 48 additions and 52 deletions
+17 -16
View File
@@ -540,12 +540,9 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
} else { } else {
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) { 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);
attacker_card->compute_action_chain_results(true, false); attacker_card->compute_action_chain_results(true, false);
attack_ap = attacker_card->action_chain.chain.damage; attack_ap = attacker_card->action_chain.chain.damage;
if (this->action_chain.chain.attack_medium == AttackMedium::TECH) { if (this->action_chain.chain.attack_medium == AttackMedium::TECH) {
@@ -922,15 +919,19 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
this->action_chain.chain.ap_effect_bonus, this->action_chain.chain.ap_effect_bonus,
this->action_chain.chain.tp_effect_bonus); this->action_chain.chain.tp_effect_bonus);
int16_t card_ap; int16_t effective_ap;
int16_t card_tp; int16_t effective_tp;
auto stat_swap_type = is_trial ? StatSwapType::NONE : s->card_special->compute_stat_swap_type(this->shared_from_this()); StatSwapType stat_swap_type;
log.debug("stat_swap_type = %zu (0=none, 1=a/t, 2=a/h)", static_cast<size_t>(stat_swap_type)); if (is_trial) {
s->card_special->get_effective_ap_tp(stat_swap_type, &card_ap, &card_tp, this->get_current_hp(), this->ap, this->tp); effective_ap = this->ap;
log.debug("card_ap = %hd, card_tp = %hd", card_ap, card_tp); effective_tp = this->tp;
stat_swap_type = StatSwapType::NONE;
int16_t effective_ap = this->ap; } else {
int16_t effective_tp = this->tp; stat_swap_type = s->card_special->compute_stat_swap_type(this->shared_from_this());
log.debug("stat_swap_type = %zu (0=none, 1=a/t, 2=a/h)", static_cast<size_t>(stat_swap_type));
s->card_special->get_effective_ap_tp(stat_swap_type, &effective_ap, &effective_tp, this->get_current_hp(), this->ap, this->tp);
log.debug("effective_ap = %hd, effective_tp = %hd", effective_ap, effective_tp);
}
// This option doesn't exist in NTE // This option doesn't exist in NTE
ignore_this_card_ap_tp &= !is_trial; ignore_this_card_ap_tp &= !is_trial;
@@ -950,6 +951,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
for (size_t set_index = 0; set_index < 8; set_index++) { for (size_t set_index = 0; set_index < 8; set_index++) {
auto card = ps->get_set_card(set_index); auto card = ps->get_set_card(set_index);
if ((card && (card->def_entry->def.card_class() == CardClass::MAG_ITEM)) && !(card->card_flags & 2)) { if ((card && (card->def_entry->def.card_class() == CardClass::MAG_ITEM)) && !(card->card_flags & 2)) {
int16_t card_ap, card_tp;
s->card_special->get_effective_ap_tp( s->card_special->get_effective_ap_tp(
stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp); stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp);
effective_ap += card_ap; effective_ap += card_ap;
@@ -1004,8 +1006,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
} }
break; break;
case AssistEffect::INFLUENCE: case AssistEffect::INFLUENCE:
if (!is_trial && if (!is_trial && this->card_type_is_sc_or_creature()) {
this->card_type_is_sc_or_creature()) {
int16_t count = ps->count_set_refs(); int16_t count = ps->count_set_refs();
this->action_chain.chain.ap_effect_bonus += (count >> 1); this->action_chain.chain.ap_effect_bonus += (count >> 1);
} }
+20 -17
View File
@@ -364,7 +364,7 @@ bool CardSpecial::apply_defense_condition(
} }
} }
if ((when == 0x04) && (flags & 4) && (defender_cond->type == ConditionType::ACID)) { if ((when == 0x04) && (flags & 4) && !defender_has_ability_trap && (defender_cond->type == ConditionType::ACID)) {
int16_t hp = defender_card->get_current_hp(); int16_t hp = defender_card->get_current_hp();
if (hp > 0) { if (hp > 0) {
this->send_6xB4x06_for_stat_delta(defender_card, defender_cond->card_ref, 0x20, -1, 0, 1); this->send_6xB4x06_for_stat_delta(defender_card, defender_cond->card_ref, 0x20, -1, 0, 1);
@@ -458,12 +458,13 @@ bool CardSpecial::apply_stat_deltas_to_all_cards_from_all_conditions_with_card_r
bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condition& cond, shared_ptr<Card> card) { bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condition& cond, shared_ptr<Card> card) {
auto s = this->server(); auto s = this->server();
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())); 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_trial = s->options.is_trial();
string cond_str = cond.str(); string cond_str = cond.str();
log.debug("cond: %s", cond_str.c_str()); log.debug("cond: %s", cond_str.c_str());
ConditionType cond_type = cond.type; ConditionType cond_type = cond.type;
// Note: NTE does not clamp the value here. int16_t cond_value = is_trial ? cond.value.load() : clamp<int16_t>(cond.value, -99, 99);
int16_t cond_value = clamp<int16_t>(cond.value, -99, 99);
uint8_t cond_flags = cond.flags; uint8_t cond_flags = cond.flags;
uint16_t cond_card_ref = card->get_card_ref(); uint16_t cond_card_ref = card->get_card_ref();
cond.clear(); cond.clear();
@@ -474,7 +475,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
int16_t ap = clamp<int16_t>(card->ap, -99, 99); int16_t ap = clamp<int16_t>(card->ap, -99, 99);
int16_t tp = clamp<int16_t>(card->tp, -99, 99); int16_t tp = clamp<int16_t>(card->tp, -99, 99);
log.debug("A_T_SWAP_0C: swapping AP (%hd) and TP (%hd)", ap, tp); log.debug("A_T_SWAP_0C: swapping AP (%hd) and TP (%hd)", ap, tp);
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, tp - ap, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, tp - ap, 0, 0);
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, ap - tp, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, ap - tp, 0, 0);
} }
@@ -490,7 +491,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
int16_t hp = clamp<int16_t>(card->get_current_hp(), -99, 99); int16_t hp = clamp<int16_t>(card->get_current_hp(), -99, 99);
if (hp != ap) { if (hp != ap) {
log.debug("A_H_SWAP: swapping AP (%hd) and HP (%hd)", ap, hp); log.debug("A_H_SWAP: swapping AP (%hd) and HP (%hd)", ap, hp);
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, hp - ap, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, hp - ap, 0, 0);
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x20, ap - hp, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x20, ap - hp, 0, 0);
} }
@@ -509,9 +510,9 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
// Note: In NTE, this case behaves intuitively, but in non-NTE, it seems // Note: In NTE, this case behaves intuitively, but in non-NTE, it seems
// that find_condition was changed to always return null. Perhaps this // that find_condition was changed to always return null. Perhaps this
// was an accident, or perhaps not, but we implement both behaviors. // was an accident, or perhaps not, but we implement both behaviors.
Condition* other_cond = s->options.is_trial() ? card->find_condition(ConditionType::AP_OVERRIDE) : nullptr; Condition* other_cond = is_trial ? card->find_condition(ConditionType::AP_OVERRIDE) : nullptr;
if (!other_cond) { if (!other_cond) {
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0);
} }
card->ap = max<int16_t>(card->ap - cond_value, 0); card->ap = max<int16_t>(card->ap - cond_value, 0);
@@ -526,9 +527,9 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
case ConditionType::TP_OVERRIDE: case ConditionType::TP_OVERRIDE:
if (cond_flags & 2) { if (cond_flags & 2) {
// See note in the AP_OVERRIDE case about why non-NTE always uses null. // See note in the AP_OVERRIDE case about why non-NTE always uses null.
Condition* other_cond = s->options.is_trial() ? card->find_condition(ConditionType::TP_OVERRIDE) : nullptr; Condition* other_cond = is_trial ? card->find_condition(ConditionType::TP_OVERRIDE) : nullptr;
if (!other_cond) { if (!other_cond) {
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0);
} }
card->tp = max<int16_t>(card->tp - cond_value, 0); card->tp = max<int16_t>(card->tp - cond_value, 0);
@@ -542,7 +543,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
break; break;
case ConditionType::MISC_AP_BONUSES: case ConditionType::MISC_AP_BONUSES:
if (cond_flags & 2) { if (cond_flags & 2) {
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0);
} }
card->ap = max<int16_t>(card->ap - cond_value, 0); card->ap = max<int16_t>(card->ap - cond_value, 0);
@@ -553,7 +554,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
break; break;
case ConditionType::MISC_TP_BONUSES: case ConditionType::MISC_TP_BONUSES:
if (cond_flags & 2) { if (cond_flags & 2) {
if (!s->options.is_trial()) { if (!is_trial) {
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0); this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0);
} }
card->tp = max<int16_t>(card->tp - cond_value, 0); card->tp = max<int16_t>(card->tp - cond_value, 0);
@@ -563,7 +564,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
} }
break; break;
case ConditionType::AP_SILENCE: case ConditionType::AP_SILENCE:
if (!s->options.is_trial()) { if (is_trial) {
goto trial_unimplemented; goto trial_unimplemented;
} }
if (cond_flags & 2) { if (cond_flags & 2) {
@@ -575,7 +576,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
} }
break; break;
case ConditionType::TP_SILENCE: case ConditionType::TP_SILENCE:
if (!s->options.is_trial()) { if (is_trial) {
goto trial_unimplemented; goto trial_unimplemented;
} }
if (cond_flags & 2) { if (cond_flags & 2) {
@@ -3934,13 +3935,15 @@ void CardSpecial::evaluate_and_apply_effects(
uint16_t apply_defense_condition_to_card_ref) { uint16_t apply_defense_condition_to_card_ref) {
auto s = this->server(); auto s = this->server();
auto log = s->log_stack(string_printf("evaluate_and_apply_effects(%02hhX, @%04hX, @%04hX): ", when, set_card_ref, sc_card_ref)); auto log = s->log_stack(string_printf("evaluate_and_apply_effects(%02hhX, @%04hX, @%04hX): ", when, set_card_ref, sc_card_ref));
bool is_trial = s->options.is_trial();
{ {
string as_str = as.str(); string as_str = as.str();
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", 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); 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);
} }
if (!s->options.is_trial()) { if (!is_trial) {
set_card_ref = this->send_6xB4x06_if_card_ref_invalid(set_card_ref, 1); set_card_ref = this->send_6xB4x06_if_card_ref_invalid(set_card_ref, 1);
} }
@@ -3950,7 +3953,7 @@ void CardSpecial::evaluate_and_apply_effects(
return; return;
} }
if (s->options.is_trial()) { if (is_trial) {
auto set_card = s->card_for_set_card_ref(set_card_ref); auto set_card = s->card_for_set_card_ref(set_card_ref);
if ((set_card != nullptr) && set_card->get_condition_value(ConditionType::ABILITY_TRAP)) { if ((set_card != nullptr) && set_card->get_condition_value(ConditionType::ABILITY_TRAP)) {
return; return;
@@ -4017,7 +4020,7 @@ void CardSpecial::evaluate_and_apply_effects(
string refs_str = refs_str_for_cards_vector(targeted_cards); string refs_str = refs_str_for_cards_vector(targeted_cards);
effect_log.debug("targeted_cards=[%s]", refs_str.c_str()); effect_log.debug("targeted_cards=[%s]", refs_str.c_str());
bool all_targets_matched = false; bool all_targets_matched = false;
if (!s->options.is_trial() && if (!is_trial &&
!targeted_cards.empty() && !targeted_cards.empty() &&
((card_effect.type == ConditionType::UNKNOWN_64) || ((card_effect.type == ConditionType::UNKNOWN_64) ||
(card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) || (card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) ||
@@ -4101,7 +4104,7 @@ void CardSpecial::evaluate_and_apply_effects(
cmd.effect.flags = 0x04; cmd.effect.flags = 0x04;
cmd.effect.attacker_card_ref = this->send_6xB4x06_if_card_ref_invalid(as_attacker_card_ref, 0x14); cmd.effect.attacker_card_ref = this->send_6xB4x06_if_card_ref_invalid(as_attacker_card_ref, 0x14);
cmd.effect.target_card_ref = target_card->get_card_ref(); cmd.effect.target_card_ref = target_card->get_card_ref();
cmd.effect.value = s->options.is_trial() ? 0 : target_card->action_chain.conditions[applied_cond_index].remaining_turns; cmd.effect.value = is_trial ? 0 : target_card->action_chain.conditions[applied_cond_index].remaining_turns;
cmd.effect.operation = static_cast<int8_t>(card_effect.type); cmd.effect.operation = static_cast<int8_t>(card_effect.type);
s->send(cmd); s->send(cmd);
+1 -2
View File
@@ -343,8 +343,7 @@ const char* name_for_direction(Direction d) {
bool card_class_is_tech_like(CardClass cc, bool is_trial) { bool card_class_is_tech_like(CardClass cc, bool is_trial) {
// NTE does not consider BOSS_TECH to be a tech-like card class, but that's // NTE does not consider BOSS_TECH to be a tech-like card class, but that's
// probably because that card class just doesn't exist on NTE. Still, we // probably because that card class just doesn't exist on NTE.
// handle
if (is_trial) { if (is_trial) {
return (cc == CardClass::TECH) || (cc == CardClass::PHOTON_BLAST); return (cc == CardClass::TECH) || (cc == CardClass::PHOTON_BLAST);
} else { } else {
+2 -2
View File
@@ -1186,9 +1186,9 @@ struct MapDefinition { // .mnmd format; also the format of (decompressed) quests
// 10 = blocked by rock (as if the corresponding map_tiles value was 00) // 10 = blocked by rock (as if the corresponding map_tiles value was 00)
// 20 = blocked by fence (as if the corresponding map_tiles value was 00) // 20 = blocked by fence (as if the corresponding map_tiles value was 00)
// 30-34 = teleporters (2 of each value may be present) // 30-34 = teleporters (2 of each value may be present)
// 40-44 = traps (one of each type is chosen at random to be a real trap at
// battle start time)
// 40-4F = traps on NTE // 40-4F = traps on NTE
// 40-44 = traps on non-NTE (one of each type is chosen at random to be a real
// trap at battle start time)
// 50 = blocked by metal box (appears as improperly-z-buffered teal cube in // 50 = blocked by metal box (appears as improperly-z-buffered teal cube in
// preview; behaves like 10 and 20 in game) // preview; behaves like 10 and 20 in game)
// The assist cards that each trap type can contain are: // The assist cards that each trap type can contain are:
+4 -10
View File
@@ -635,7 +635,7 @@ bool PlayerState::discard_card_or_add_to_draw_pile(uint16_t card_ref, bool add_t
card->update_stats_on_destruction(); card->update_stats_on_destruction();
this->set_cards[set_index].reset(); this->set_cards[set_index].reset();
} else { } else {
this->set_cards[set_index]->card_flags |= 2; card->card_flags |= 2;
} }
} }
if (add_to_draw_pile) { if (add_to_draw_pile) {
@@ -852,12 +852,7 @@ uint8_t PlayerState::get_atk_points() const {
return this->atk_points; return this->atk_points;
} }
uint8_t PlayerState::get_atk_points_nte() const { void PlayerState::get_short_status_for_card_index_in_hand(size_t hand_index, CardShortStatus* stat) const {
return min<uint8_t>(this->atk_points2_max, this->atk_points);
}
void PlayerState::get_short_status_for_card_index_in_hand(
size_t hand_index, CardShortStatus* stat) const {
stat->card_ref = this->card_refs[hand_index - 1]; stat->card_ref = this->card_refs[hand_index - 1];
} }
@@ -1269,6 +1264,7 @@ void PlayerState::send_set_card_updates(bool always_send) {
} }
} }
// mask will always be 0 here if is_trial is true
if (mask && !s->get_should_copy_prev_states_to_current_states()) { if (mask && !s->get_should_copy_prev_states_to_current_states()) {
G_ClearSetCardConditions_Ep3_6xB4x4F cmd; G_ClearSetCardConditions_Ep3_6xB4x4F cmd;
cmd.client_id = this->client_id; cmd.client_id = this->client_id;
@@ -1792,9 +1788,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
auto ce = s->definition_for_card_ref(pa.action_card_refs[z]); auto ce = s->definition_for_card_ref(pa.action_card_refs[z]);
if (ce) { if (ce) {
auto card_class = ce->def.card_class(); auto card_class = ce->def.card_class();
if ((card_class == CardClass::TECH) || if (card_class_is_tech_like(card_class, is_trial)) {
(card_class == CardClass::PHOTON_BLAST) ||
(card_class == CardClass::BOSS_TECH)) {
this->stats.num_tech_cards_set++; this->stats.num_tech_cards_set++;
} }
if ((card_class == CardClass::ATTACK_ACTION) || if ((card_class == CardClass::ATTACK_ACTION) ||
-1
View File
@@ -77,7 +77,6 @@ public:
const Location& loc, const Location& loc,
uint8_t target_team_id) const; uint8_t target_team_id) const;
uint8_t get_atk_points() const; uint8_t get_atk_points() const;
uint8_t get_atk_points_nte() const;
void get_short_status_for_card_index_in_hand(size_t hand_index, CardShortStatus* stat) const; void get_short_status_for_card_index_in_hand(size_t hand_index, CardShortStatus* stat) const;
std::shared_ptr<DeckState> get_deck(); std::shared_ptr<DeckState> get_deck();
uint8_t get_def_points() const; uint8_t get_def_points() const;
+1 -1
View File
@@ -196,7 +196,7 @@ struct ActionChainWithCondsTrial {
/* 0023 */ int8_t card_tp; /* 0023 */ int8_t card_tp;
/* 0024 */ le_uint32_t flags; /* 0024 */ le_uint32_t flags;
// The only difference between this structure and ActionChainWithConds is that // The only difference between this structure and ActionChainWithConds is that
// these two fields have changed orders. // these two fields are in the opposite order.
/* 0028 */ parray<Condition, 9> conditions; /* 0028 */ parray<Condition, 9> conditions;
/* 00B8 */ parray<le_uint16_t, 4 * 9> target_card_refs; /* 00B8 */ parray<le_uint16_t, 4 * 9> target_card_refs;
/* 0100 */ /* 0100 */
+3 -3
View File
@@ -1437,9 +1437,9 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
size_t num_assists = this->assist_server->compute_num_assist_effects_for_client(pa.client_id); size_t num_assists = this->assist_server->compute_num_assist_effects_for_client(pa.client_id);
for (size_t w = 0; w < num_assists; w++) { for (size_t w = 0; w < num_assists; w++) {
auto assist_effect = this->assist_server->get_active_assist_by_index(w); auto assist_effect = this->assist_server->get_active_assist_by_index(w);
if (!is_trial && (assist_effect == AssistEffect::INFLATION)) { if (is_trial && (assist_effect == AssistEffect::INFLATION)) {
assist_cost_bias++; assist_cost_bias++;
} else if (!is_trial && (assist_effect == AssistEffect::DEFLATION)) { } else if (is_trial && (assist_effect == AssistEffect::DEFLATION)) {
assist_cost_bias--; assist_cost_bias--;
} else if ((assist_effect == AssistEffect::BATTLE_ROYALE) && } else if ((assist_effect == AssistEffect::BATTLE_ROYALE) &&
(pa.action_card_refs[0] == 0xFFFF)) { (pa.action_card_refs[0] == 0xFFFF)) {
@@ -1720,7 +1720,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
} }
// Check for assists that can only be set on yourself // Check for assists that can only be set on yourself
auto eff = assist_effect_number_for_card_id(ce->def.card_id, this->server()->options.is_trial()); auto eff = assist_effect_number_for_card_id(ce->def.card_id, is_trial);
if (((eff == AssistEffect::LEGACY) || (!is_trial && (eff == AssistEffect::EXCHANGE))) && if (((eff == AssistEffect::LEGACY) || (!is_trial && (eff == AssistEffect::EXCHANGE))) &&
(assist_target_client_id != 0xFF) && (assist_target_client_id != 0xFF) &&
(assist_target_client_id != client_id_for_card_ref(card_ref))) { (assist_target_client_id != client_id_for_card_ref(card_ref))) {