From fcc274ce3ea804d991690c8a28e0be5345b9bc06 Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Fri, 9 Feb 2024 00:06:05 -0800 Subject: [PATCH] fix some bugs introduced by Ep3 NTE work --- src/Episode3/Card.cc | 33 +++++++++++----------- src/Episode3/CardSpecial.cc | 37 +++++++++++++------------ src/Episode3/DataIndexes.cc | 3 +- src/Episode3/DataIndexes.hh | 4 +-- src/Episode3/PlayerState.cc | 14 +++------- src/Episode3/PlayerState.hh | 1 - src/Episode3/PlayerStateSubordinates.hh | 2 +- src/Episode3/RulerServer.cc | 6 ++-- 8 files changed, 48 insertions(+), 52 deletions(-) diff --git a/src/Episode3/Card.cc b/src/Episode3/Card.cc index 648acddf..e38ab654 100644 --- a/src/Episode3/Card.cc +++ b/src/Episode3/Card.cc @@ -540,12 +540,9 @@ void Card::execute_attack(shared_ptr attacker_card) { } 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) { + 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); attack_ap = attacker_card->action_chain.chain.damage; 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.tp_effect_bonus); - int16_t card_ap; - int16_t card_tp; - auto stat_swap_type = is_trial ? StatSwapType::NONE : 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(stat_swap_type)); - s->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_ap = this->ap; - int16_t effective_tp = this->tp; + int16_t effective_ap; + int16_t effective_tp; + StatSwapType stat_swap_type; + if (is_trial) { + effective_ap = this->ap; + effective_tp = this->tp; + stat_swap_type = StatSwapType::NONE; + } else { + 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(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 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++) { auto card = ps->get_set_card(set_index); 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( stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp); effective_ap += card_ap; @@ -1004,8 +1006,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor } break; case AssistEffect::INFLUENCE: - if (!is_trial && - this->card_type_is_sc_or_creature()) { + if (!is_trial && this->card_type_is_sc_or_creature()) { int16_t count = ps->count_set_refs(); this->action_chain.chain.ap_effect_bonus += (count >> 1); } diff --git a/src/Episode3/CardSpecial.cc b/src/Episode3/CardSpecial.cc index c93f101e..59f45ec2 100644 --- a/src/Episode3/CardSpecial.cc +++ b/src/Episode3/CardSpecial.cc @@ -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(); if (hp > 0) { 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) { 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())); + bool is_trial = s->options.is_trial(); + string cond_str = cond.str(); log.debug("cond: %s", cond_str.c_str()); ConditionType cond_type = cond.type; - // Note: NTE does not clamp the value here. - int16_t cond_value = clamp(cond.value, -99, 99); + int16_t cond_value = is_trial ? cond.value.load() : clamp(cond.value, -99, 99); uint8_t cond_flags = cond.flags; uint16_t cond_card_ref = card->get_card_ref(); cond.clear(); @@ -474,7 +475,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit int16_t ap = clamp(card->ap, -99, 99); int16_t tp = clamp(card->tp, -99, 99); 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, 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(card->get_current_hp(), -99, 99); if (hp != ap) { 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, 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 // that find_condition was changed to always return null. Perhaps this // 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 (!s->options.is_trial()) { + if (!is_trial) { this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0); } card->ap = max(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: if (cond_flags & 2) { // 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 (!s->options.is_trial()) { + if (!is_trial) { this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0); } card->tp = max(card->tp - cond_value, 0); @@ -542,7 +543,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit break; case ConditionType::MISC_AP_BONUSES: 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); } card->ap = max(card->ap - cond_value, 0); @@ -553,7 +554,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit break; case ConditionType::MISC_TP_BONUSES: 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); } card->tp = max(card->tp - cond_value, 0); @@ -563,7 +564,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit } break; case ConditionType::AP_SILENCE: - if (!s->options.is_trial()) { + if (is_trial) { goto trial_unimplemented; } if (cond_flags & 2) { @@ -575,7 +576,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit } break; case ConditionType::TP_SILENCE: - if (!s->options.is_trial()) { + if (is_trial) { goto trial_unimplemented; } if (cond_flags & 2) { @@ -3934,13 +3935,15 @@ void CardSpecial::evaluate_and_apply_effects( uint16_t apply_defense_condition_to_card_ref) { 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)); + bool is_trial = s->options.is_trial(); + { 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", 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); } @@ -3950,7 +3953,7 @@ void CardSpecial::evaluate_and_apply_effects( return; } - if (s->options.is_trial()) { + if (is_trial) { auto set_card = s->card_for_set_card_ref(set_card_ref); if ((set_card != nullptr) && set_card->get_condition_value(ConditionType::ABILITY_TRAP)) { return; @@ -4017,7 +4020,7 @@ void CardSpecial::evaluate_and_apply_effects( string refs_str = refs_str_for_cards_vector(targeted_cards); effect_log.debug("targeted_cards=[%s]", refs_str.c_str()); bool all_targets_matched = false; - if (!s->options.is_trial() && + if (!is_trial && !targeted_cards.empty() && ((card_effect.type == ConditionType::UNKNOWN_64) || (card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) || @@ -4101,7 +4104,7 @@ void CardSpecial::evaluate_and_apply_effects( cmd.effect.flags = 0x04; 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.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(card_effect.type); s->send(cmd); diff --git a/src/Episode3/DataIndexes.cc b/src/Episode3/DataIndexes.cc index 720c69c9..e6a900ce 100644 --- a/src/Episode3/DataIndexes.cc +++ b/src/Episode3/DataIndexes.cc @@ -343,8 +343,7 @@ const char* name_for_direction(Direction d) { 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 - // probably because that card class just doesn't exist on NTE. Still, we - // handle + // probably because that card class just doesn't exist on NTE. if (is_trial) { return (cc == CardClass::TECH) || (cc == CardClass::PHOTON_BLAST); } else { diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index 2135aa38..ac7c20e2 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -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) // 20 = blocked by fence (as if the corresponding map_tiles value was 00) // 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-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 // preview; behaves like 10 and 20 in game) // The assist cards that each trap type can contain are: diff --git a/src/Episode3/PlayerState.cc b/src/Episode3/PlayerState.cc index 95e6bce8..35ec8b8b 100644 --- a/src/Episode3/PlayerState.cc +++ b/src/Episode3/PlayerState.cc @@ -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(); this->set_cards[set_index].reset(); } else { - this->set_cards[set_index]->card_flags |= 2; + card->card_flags |= 2; } } if (add_to_draw_pile) { @@ -852,12 +852,7 @@ uint8_t PlayerState::get_atk_points() const { return this->atk_points; } -uint8_t PlayerState::get_atk_points_nte() const { - return min(this->atk_points2_max, this->atk_points); -} - -void PlayerState::get_short_status_for_card_index_in_hand( - size_t hand_index, CardShortStatus* stat) const { +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]; } @@ -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()) { G_ClearSetCardConditions_Ep3_6xB4x4F cmd; 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]); if (ce) { auto card_class = ce->def.card_class(); - if ((card_class == CardClass::TECH) || - (card_class == CardClass::PHOTON_BLAST) || - (card_class == CardClass::BOSS_TECH)) { + if (card_class_is_tech_like(card_class, is_trial)) { this->stats.num_tech_cards_set++; } if ((card_class == CardClass::ATTACK_ACTION) || diff --git a/src/Episode3/PlayerState.hh b/src/Episode3/PlayerState.hh index 3cb5c5c2..35e25449 100644 --- a/src/Episode3/PlayerState.hh +++ b/src/Episode3/PlayerState.hh @@ -77,7 +77,6 @@ public: const Location& loc, uint8_t target_team_id) 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; std::shared_ptr get_deck(); uint8_t get_def_points() const; diff --git a/src/Episode3/PlayerStateSubordinates.hh b/src/Episode3/PlayerStateSubordinates.hh index 36b267e7..4fdc3678 100644 --- a/src/Episode3/PlayerStateSubordinates.hh +++ b/src/Episode3/PlayerStateSubordinates.hh @@ -196,7 +196,7 @@ struct ActionChainWithCondsTrial { /* 0023 */ int8_t card_tp; /* 0024 */ le_uint32_t flags; // 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 conditions; /* 00B8 */ parray target_card_refs; /* 0100 */ diff --git a/src/Episode3/RulerServer.cc b/src/Episode3/RulerServer.cc index eb650a35..26958098 100644 --- a/src/Episode3/RulerServer.cc +++ b/src/Episode3/RulerServer.cc @@ -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); for (size_t w = 0; w < num_assists; 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++; - } else if (!is_trial && (assist_effect == AssistEffect::DEFLATION)) { + } else if (is_trial && (assist_effect == AssistEffect::DEFLATION)) { assist_cost_bias--; } else if ((assist_effect == AssistEffect::BATTLE_ROYALE) && (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 - 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))) && (assist_target_client_id != 0xFF) && (assist_target_client_id != client_id_for_card_ref(card_ref))) {