fix condition apply using incorrect criterion for non-item checks
This commit is contained in:
@@ -6,6 +6,25 @@ using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
static uint16_t ref_for_card(shared_ptr<const Card> card) {
|
||||
if (card) {
|
||||
return card->get_card_ref();
|
||||
} else {
|
||||
return 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
static string refs_str_for_cards_vector(const vector<shared_ptr<const Card>>& cards) {
|
||||
string ret;
|
||||
for (const auto& card : cards) {
|
||||
if (!ret.empty()) {
|
||||
ret += ", ";
|
||||
}
|
||||
ret += string_printf("%04hX", ref_for_card(card));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
CardSpecial::DiceRoll::DiceRoll() {
|
||||
this->clear();
|
||||
}
|
||||
@@ -89,6 +108,14 @@ shared_ptr<const Server> CardSpecial::server() const {
|
||||
return s;
|
||||
}
|
||||
|
||||
ATTR_PRINTF(2, 3)
|
||||
void CardSpecial::debug_log(const char* fmt, ...) const {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
this->server()->base()->log.debug_v(fmt, va);
|
||||
va_end(va);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -252,8 +279,8 @@ bool CardSpecial::apply_defense_condition(
|
||||
if ((when == 2) && (defender_cond->type == ConditionType::GUOM) && (flags & 4)) {
|
||||
CardShortStatus stat = defender_card->get_short_status();
|
||||
if (stat.card_flags & 4) {
|
||||
this->server()->base()->log.debug("(when=2) @%04hX clearing GUOM from @%04hX",
|
||||
attacker_card_ref, defender_card->get_card_ref());
|
||||
this->debug_log("(when=2) @%04hX clearing GUOM from @%04hX",
|
||||
attacker_card_ref, ref_for_card(defender_card));
|
||||
G_ApplyConditionEffect_GC_Ep3_6xB4x06 cmd;
|
||||
cmd.effect.flags = 0x04;
|
||||
cmd.effect.attacker_card_ref = this->send_6xB4x06_if_card_ref_invalid(attacker_card_ref, 0x0E);
|
||||
@@ -273,8 +300,7 @@ bool CardSpecial::apply_defense_condition(
|
||||
(defender_cond->type == ConditionType::ACID)) {
|
||||
int16_t hp = defender_card->get_current_hp();
|
||||
if (hp > 0) {
|
||||
this->server()->base()->log.debug("(when=2) @%04hX has ACID; removing 1 HP",
|
||||
defender_cond->card_ref.load());
|
||||
this->debug_log("(when=2) @%04hX has ACID; removing 1 HP", defender_cond->card_ref.load());
|
||||
this->send_6xB4x06_for_stat_delta(
|
||||
defender_card, defender_cond->card_ref, 0x20, -1, 0, 1);
|
||||
defender_card->set_current_hp(hp - 1);
|
||||
@@ -2464,6 +2490,8 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
const ActionState& as,
|
||||
int16_t p_target_type,
|
||||
bool apply_usability_filters) const {
|
||||
this->debug_log("get_targeted_cards_for_condition(card_ref=%04hX, def_effect_index=%02hhX, setter_card_ref=%04hX, as, p_target_type=%hd, apply_usability_filters=%s)", card_ref, def_effect_index, setter_card_ref, p_target_type, apply_usability_filters ? "true" : "false");
|
||||
|
||||
vector<shared_ptr<const Card>> ret;
|
||||
|
||||
uint8_t client_id = client_id_for_card_ref(card_ref);
|
||||
@@ -2471,10 +2499,12 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (!card1) {
|
||||
card1 = this->server()->card_for_set_card_ref(setter_card_ref);
|
||||
}
|
||||
this->debug_log("get_targeted_cards_for_condition: card1=%04hX", ref_for_card(card1));
|
||||
|
||||
auto card2 = this->server()->card_for_set_card_ref((as.attacker_card_ref == 0xFFFF)
|
||||
? as.original_attacker_card_ref
|
||||
: as.attacker_card_ref);
|
||||
this->debug_log("get_targeted_cards_for_condition: card2=%04hX", ref_for_card(card2));
|
||||
|
||||
Location card1_loc;
|
||||
if (!card1) {
|
||||
@@ -2483,11 +2513,15 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
card1_loc.direction = Direction::RIGHT;
|
||||
} else {
|
||||
this->get_card1_loc_with_card2_opposite_direction(&card1_loc, card1, card2);
|
||||
|
||||
string card1_loc_str = card1_loc.str();
|
||||
this->debug_log("get_targeted_cards_for_condition: card1_loc=%s", card1_loc_str.c_str());
|
||||
}
|
||||
|
||||
AttackMedium attack_medium = card2
|
||||
? card2->action_chain.chain.attack_medium
|
||||
: AttackMedium::UNKNOWN;
|
||||
this->debug_log("get_targeted_cards_for_condition: attack_medium=%s", name_for_attack_medium(attack_medium));
|
||||
|
||||
auto add_card_refs = [&](const vector<uint16_t>& result_card_refs) -> void {
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
@@ -2503,7 +2537,10 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
case 5: {
|
||||
auto result_card = this->server()->card_for_set_card_ref(setter_card_ref);
|
||||
if (result_card) {
|
||||
this->debug_log("get_targeted_cards_for_condition: (p01/p05) result_card=%04hX", ref_for_card(result_card));
|
||||
ret.emplace_back(result_card);
|
||||
} else {
|
||||
this->debug_log("get_targeted_cards_for_condition: (p01/p05) result_card=null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2595,10 +2632,15 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
ret = this->get_all_set_cards();
|
||||
ret = this->filter_cards_by_range(ret, card1, card1_loc, card2);
|
||||
break;
|
||||
case 16:
|
||||
case 16: {
|
||||
ret = this->find_cards_in_hp_range(8, 1000);
|
||||
string range_refs_str = refs_str_for_cards_vector(ret);
|
||||
this->debug_log("get_targeted_cards_for_condition: (p16) candidate cards = [%s]", range_refs_str.c_str());
|
||||
ret = this->filter_cards_by_range(ret, card1, card1_loc, card2);
|
||||
range_refs_str = refs_str_for_cards_vector(ret);
|
||||
this->debug_log("get_targeted_cards_for_condition: (p16) filtered cards = [%s]", range_refs_str.c_str());
|
||||
break;
|
||||
}
|
||||
case 17: {
|
||||
auto result_card = this->server()->card_for_set_card_ref(card_ref);
|
||||
if (result_card) {
|
||||
@@ -3002,6 +3044,9 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (this->server()->ruler_server->check_usability_or_apply_condition_for_card_refs(
|
||||
card_ref, setter_card_ref, c->get_card_ref(), def_effect_index, attack_medium)) {
|
||||
filtered_ret.emplace_back(c);
|
||||
this->debug_log("get_targeted_cards_for_condition: usability filter: kept card %04hX", ref_for_card(c));
|
||||
} else {
|
||||
this->debug_log("get_targeted_cards_for_condition: usability filter: removed card %04hX", ref_for_card(c));
|
||||
}
|
||||
}
|
||||
return filtered_ret;
|
||||
@@ -3517,7 +3562,7 @@ void CardSpecial::unknown_8024C2B0(
|
||||
{
|
||||
string as_s = as.str();
|
||||
string eff_s = card_effect.str();
|
||||
this->server()->base()->log.debug("(when=%" PRIu32 ") set=@%04hX sc=@%04hX as=%s att=@%04hX eff=%s",
|
||||
this->debug_log("(when=%" PRIu32 ") set=@%04hX sc=@%04hX as=%s att=@%04hX eff=%s",
|
||||
when, set_card_ref, sc_card_ref, as_s.c_str(), as_attacker_card_ref, eff_s.c_str());
|
||||
}
|
||||
|
||||
|
||||
@@ -95,6 +95,8 @@ public:
|
||||
std::shared_ptr<Server> server();
|
||||
std::shared_ptr<const Server> server() const;
|
||||
|
||||
void debug_log(const char* fmt, ...) const ATTR_PRINTF(2, 3);
|
||||
|
||||
void adjust_attack_damage_due_to_conditions(
|
||||
std::shared_ptr<const Card> target_card, int16_t* inout_damage, uint16_t attacker_card_ref);
|
||||
void adjust_dice_boost_if_team_has_condition_52(
|
||||
|
||||
@@ -418,9 +418,9 @@ static const vector<const char*> description_for_p_target({
|
||||
/* p11 */ "All ally FCs", // TODO: how is this different from p10?
|
||||
/* p12 */ "All non-aerial FCs on both teams",
|
||||
/* p13 */ "All FCs on both teams that are Frozen",
|
||||
/* p14 */ "All FCs on both teams that have <= 3 HP",
|
||||
/* p15 */ "All FCs except SCs", // TODO: used during attacks only?
|
||||
/* p16 */ "All FCs except SCs", // TODO: used during attacks only? how is this different from p15?
|
||||
/* p14 */ "All FCs on both teams with <= 3 HP",
|
||||
/* p15 */ "All FCs on both teams",
|
||||
/* p16 */ "All FCs on both teams with >= 8 HP",
|
||||
/* p17 */ "This card",
|
||||
/* p18 */ "SC who equipped this card",
|
||||
/* p19 */ "Unknown: p19", // Unused
|
||||
|
||||
@@ -1777,11 +1777,11 @@ void PlayerState::roll_main_dice() {
|
||||
if (!should_exchange) {
|
||||
this->atk_points = (short)(char)this->dice_results[0];
|
||||
this->def_points = (short)(char)this->dice_results[1];
|
||||
this->assist_flags = this->assist_flags & 0xFFFFFFFD;
|
||||
this->assist_flags &= 0xFFFFFFFD;
|
||||
} else {
|
||||
this->atk_points = (short)(char)this->dice_results[1];
|
||||
this->def_points = (short)(char)this->dice_results[0];
|
||||
this->assist_flags = this->assist_flags | 2;
|
||||
this->assist_flags |= 2;
|
||||
}
|
||||
|
||||
this->atk_points = this->atk_points + this->server()->card_special->client_has_atk_dice_boost_condition(this->client_id);
|
||||
|
||||
@@ -922,25 +922,31 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
attack_medium = AttackMedium::UNKNOWN;
|
||||
}
|
||||
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply(client_id1=%02hhX, card_id1=%04hX, client_id2=%02hhX, card_id2=%04hX, card_id3=%04hX, def_effect_index=%02hhX, is_item_usability_check=%s, attack_medium=%s)", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", name_for_attack_medium(attack_medium));
|
||||
|
||||
auto ce1 = this->definition_for_card_id(card_id1);
|
||||
auto ce2 = this->definition_for_card_id(card_id2);
|
||||
auto ce3 = this->definition_for_card_id(card_id3);
|
||||
if (!ce1) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: ce1 missing");
|
||||
return false;
|
||||
}
|
||||
if ((ce1->def.type == CardType::ITEM) && this->card_id_is_boss_sc(card_id2)) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: ce1 is item and card_id2 is boss sc");
|
||||
return false;
|
||||
}
|
||||
|
||||
CriterionCode criterion_code;
|
||||
if (def_effect_index & 0xFF) {
|
||||
if (def_effect_index == 0xFF) {
|
||||
criterion_code = ce1->def.usable_criterion;
|
||||
} else {
|
||||
if (def_effect_index > 2) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: invalid def_effect_index");
|
||||
return false;
|
||||
}
|
||||
criterion_code = ce1->def.effects[def_effect_index].apply_criterion;
|
||||
}
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: criterion_code=%s", name_for_criterion_code(criterion_code));
|
||||
|
||||
// For item usability checks, prevent criteria that depend on player
|
||||
// positioning/team setup
|
||||
@@ -951,6 +957,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
(criterion_code == CriterionCode::UNKNOWN_07) ||
|
||||
(criterion_code == CriterionCode::NOT_SC) ||
|
||||
(criterion_code == CriterionCode::SC))) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: criterion is forbidden");
|
||||
criterion_code = CriterionCode::NONE;
|
||||
}
|
||||
|
||||
@@ -1000,9 +1007,12 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
break;
|
||||
case CriterionCode::UNKNOWN_07:
|
||||
// Like NOT_SC, but for ce3 instead of ce2
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: ce3 type is %s", ce3 ? name_for_card_type(ce3->def.type) : "missing");
|
||||
if (ce3 && (ce3->def.type != CardType::HUNTERS_SC) && (ce3->def.type != CardType::ARKZ_SC)) {
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: returned %s", ret ? "true" : "false");
|
||||
return ret;
|
||||
}
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: UNKNOWN_07: did not pass");
|
||||
break;
|
||||
case CriterionCode::NOT_SC:
|
||||
if (ce2 && (ce2->def.type != CardType::HUNTERS_SC) && (ce2->def.type != CardType::ARKZ_SC)) {
|
||||
@@ -1323,6 +1333,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
}
|
||||
}
|
||||
|
||||
this->server()->base()->log.debug("check_usability_or_condition_apply: default return (false)");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -560,7 +560,7 @@ void Server::clear_player_flags_after_dice_phase() {
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
ps->assist_flags = ps->assist_flags & 0xFFFFDFFE;
|
||||
ps->assist_flags &= 0xFFFFDFFE;
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
}
|
||||
@@ -1203,7 +1203,7 @@ void Server::set_client_id_ready_to_advance_phase(uint8_t client_id) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
ps->assist_flags = ps->assist_flags & 0xFFFF7FFF;
|
||||
ps->assist_flags &= 0xFFFF7FFF;
|
||||
}
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user