diff --git a/src/Episode3/Card.cc b/src/Episode3/Card.cc index e9a15ff4..44432d92 100644 --- a/src/Episode3/Card.cc +++ b/src/Episode3/Card.cc @@ -396,8 +396,8 @@ int16_t Card::compute_defense_power_for_attacker_card(shared_ptr att } } - 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); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, attacker_card, this->shared_from_this(), 0x08, nullptr); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, attacker_card, this->shared_from_this(), 0x10, nullptr); return this->action_metadata.defense_power + this->action_metadata.defense_bonus; } @@ -982,7 +982,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor if (apply_action_conditions) { auto this_sh = this->shared_from_this(); - s->card_special->apply_action_conditions(3, this_sh, this_sh, 1, nullptr); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 1, nullptr); log.debug("applied action conditions (1)"); } else { log.debug("skipped applying action conditions (1)"); @@ -1120,7 +1120,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor if (apply_action_conditions) { auto this_sh = this->shared_from_this(); - s->card_special->apply_action_conditions(0x03, this_sh, this_sh, 2, nullptr); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 2, nullptr); log.debug("applied action conditions (2)"); if (!is_nte && this->action_chain.check_flag(0x100)) { this->action_chain.chain.damage = min(this->action_chain.chain.damage + 5, 99); @@ -1171,7 +1171,7 @@ void Card::unknown_80237F98(bool require_condition_20_or_21) { for (ssize_t z = 8; z >= 0; z--) { if (this->action_chain.conditions[z].type != ConditionType::NONE) { if (!require_condition_20_or_21 || - s->card_special->condition_has_when_20_or_21(this->action_chain.conditions[z])) { + s->card_special->condition_applies_on_sc_or_item_attack(this->action_chain.conditions[z])) { ActionState as; auto& cond = this->action_chain.conditions[z]; if (!s->card_special->is_card_targeted_by_condition(cond, as, this->shared_from_this())) { @@ -1402,8 +1402,8 @@ bool Card::unknown_80236554(shared_ptr other_card, const ActionState* as) log.debug("last attack damage stats cleared"); if (other_card) { - s->card_special->apply_action_conditions(0x03, other_card, this->shared_from_this(), 0x20, as); - s->card_special->apply_action_conditions(0x17, other_card, this->shared_from_this(), 0x40, as); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, other_card, this->shared_from_this(), 0x20, as); + s->card_special->apply_action_conditions(EffectWhen::BEFORE_THIS_CARD_ATTACKED, other_card, this->shared_from_this(), 0x40, as); if (other_card->action_chain.check_flag(0x20000)) { this->action_metadata.attack_bonus = 0; return ret; @@ -1518,7 +1518,7 @@ void Card::apply_attack_result() { this->compute_action_chain_results(true, false); if (!this->action_chain.check_flag(0x40)) { - s->card_special->unknown_8024997C(this->shared_from_this()); + s->card_special->apply_effects_before_attack(this->shared_from_this()); } this->compute_action_chain_results(true, false); @@ -1558,21 +1558,21 @@ void Card::apply_attack_result() { } } - this->compute_action_chain_results(1, 0); + this->compute_action_chain_results(true, false); if (!this->action_chain.check_flag(0x40)) { - s->card_special->unknown_8024997C(this->shared_from_this()); + s->card_special->apply_effects_before_attack(this->shared_from_this()); } if (!(this->card_flags & 2)) { - this->compute_action_chain_results(1, 0); + this->compute_action_chain_results(true, false); s->card_special->check_for_attack_interference(this->shared_from_this()); } - this->compute_action_chain_results(1, 0); + this->compute_action_chain_results(true, false); this->unknown_80236374(this->shared_from_this(), nullptr); this->unknown_802362D8(this->shared_from_this()); } if (!this->action_chain.check_flag(0x40)) { - s->card_special->unknown_8024A394(this->shared_from_this()); + s->card_special->apply_effects_after_attack(this->shared_from_this()); } ps->stats.num_attacks_given++; diff --git a/src/Episode3/CardSpecial.cc b/src/Episode3/CardSpecial.cc index d0c2dfea..3757a8d5 100644 --- a/src/Episode3/CardSpecial.cc +++ b/src/Episode3/CardSpecial.cc @@ -79,7 +79,7 @@ void CardSpecial::AttackEnvStats::clear() { this->target_attack_bonus = 0; this->last_attack_preliminary_damage = 0; this->last_attack_damage = 0; - this->total_last_attack_damage = 0; + this->final_last_attack_damage = 0; this->last_attack_damage_count = 0; this->target_current_hp = 0; } @@ -107,7 +107,7 @@ void CardSpecial::AttackEnvStats::print(FILE* stream) const { fprintf(stream, "(ef) non_target_team_num_set_cards = %" PRIu32 "\n", this->non_target_team_num_set_cards); fprintf(stream, "(ehp) target_current_hp = %" PRIu32 "\n", this->target_current_hp); fprintf(stream, "(f) num_set_cards = %" PRIu32 "\n", this->num_set_cards); - fprintf(stream, "(fdm) total_last_attack_damage = %" PRIu32 "\n", this->total_last_attack_damage); + fprintf(stream, "(fdm) final_last_attack_damage = %" PRIu32 "\n", this->final_last_attack_damage); fprintf(stream, "(ff) target_team_num_set_cards = %" PRIu32 "\n", this->target_team_num_set_cards); fprintf(stream, "(gn) num_gun_type_items = %" PRIu32 "\n", this->num_gun_type_items); fprintf(stream, "(hf) num_item_or_creature_cards_in_hand = %" PRIu32 "\n", this->num_item_or_creature_cards_in_hand); @@ -239,7 +239,7 @@ void CardSpecial::adjust_dice_boost_if_team_has_condition_52( } void CardSpecial::apply_action_conditions( - uint8_t when, + EffectWhen when, shared_ptr attacker_card, shared_ptr defender_card, uint32_t flags, @@ -290,7 +290,7 @@ bool CardSpecial::apply_attribute_guard_if_possible( } bool CardSpecial::apply_defense_condition( - uint8_t when, + EffectWhen when, Condition* defender_cond, uint8_t cond_index, const ActionState& defense_state, @@ -327,7 +327,7 @@ bool CardSpecial::apply_defense_condition( return false; } - if ((when == 0x02) && (defender_cond->type == ConditionType::GUOM) && (flags & 4)) { + if ((when == EffectWhen::AFTER_ANY_CARD_ATTACK) && (defender_cond->type == ConditionType::GUOM) && (flags & 4)) { CardShortStatus stat = defender_card->get_short_status(); if (stat.card_flags & 4) { G_ApplyConditionEffect_Ep3_6xB4x06 cmd; @@ -346,7 +346,7 @@ bool CardSpecial::apply_defense_condition( if (s->options.is_nte()) { auto defender_ps = defender_card->player_state(); - if ((when == 0x0F) && (flags & 4) && (defender_cond->type == ConditionType::DROP) && defender_ps) { + if ((when == EffectWhen::BEFORE_DRAW_PHASE) && (flags & 4) && (defender_cond->type == ConditionType::DROP) && defender_ps) { auto defender_sc_card = defender_ps->get_sc_card(); uint8_t defender_team_id = defender_ps->get_team_id(); if (defender_sc_card && s->team_exp[defender_team_id]) { @@ -363,7 +363,7 @@ bool CardSpecial::apply_defense_condition( } } - if ((when == 0x04) && (flags & 4) && !defender_has_ability_trap && (defender_cond->type == ConditionType::ACID)) { + if ((when == EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN) && (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); @@ -417,7 +417,7 @@ bool CardSpecial::apply_defense_condition( bool CardSpecial::apply_defense_conditions( const ActionState& as, - uint8_t when, + EffectWhen when, shared_ptr defender_card, uint32_t flags) { for (size_t z = 0; z < 9; z++) { @@ -810,7 +810,7 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats( int32_t total_last_attack_damage = 0; size_t last_attack_damage_count = 0; this->sum_last_attack_damage(nullptr, &total_last_attack_damage, &last_attack_damage_count); - ast.total_last_attack_damage = total_last_attack_damage; + ast.final_last_attack_damage = total_last_attack_damage; ast.last_attack_damage_count = last_attack_damage_count; if (!target_card) { @@ -1236,13 +1236,14 @@ void CardSpecial::compute_team_dice_bonus(uint8_t team_id) { s->team_dice_bonus[team_id] = min(value, 8); } -bool CardSpecial::condition_has_when_20_or_21(const Condition& cond) const { +bool CardSpecial::condition_applies_on_sc_or_item_attack(const Condition& cond) const { auto ce = this->server()->definition_for_card_ref(cond.card_ref); if (!ce) { return false; } - uint8_t when = ce->def.effects[cond.card_definition_effect_index].when; - return ((when == 0x20) || (when == 0x21)); + EffectWhen when = ce->def.effects[cond.card_definition_effect_index].when; + return ((when == EffectWhen::AFTER_CREATURE_OR_HUNTER_SC_ATTACK) || + (when == EffectWhen::BEFORE_CREATURE_OR_HUNTER_SC_ATTACK)); } size_t CardSpecial::count_action_cards_with_condition_for_all_current_attacks( @@ -1408,7 +1409,7 @@ bool CardSpecial::evaluate_effect_arg2_condition( uint16_t set_card_ref, uint16_t sc_card_ref, uint8_t random_percent, - uint8_t when) const { + EffectWhen when) const { // Note: In the original code, as and dice_roll were optional pointers, but // they are non-null at all callsites, so we've replaced them with references // (and eliminated the null checks within this function). @@ -1648,7 +1649,7 @@ bool CardSpecial::evaluate_effect_arg2_condition( // or comment it appropriately. if (is_nte) { return (v < set_card->unknown_a9); - } else if (when == 4) { + } else if (when == EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN) { uint32_t y = set_card->unknown_a9 & 0xFFFFFFFE; if ((set_card->unknown_a9 > 0) && (y == (y / (v & 0xFFFFFFFE)) * (v & 0xFFFFFFFE))) { @@ -3517,7 +3518,7 @@ void CardSpecial::on_card_set(shared_ptr ps, uint16_t card_ref) { uint16_t sc_card_ref = sc_card ? sc_card->get_card_ref() : 0xFFFF; ActionState as; - this->evaluate_and_apply_effects(0x01, card_ref, as, sc_card_ref); + this->evaluate_and_apply_effects(EffectWhen::CARD_SET, card_ref, as, sc_card_ref); } const CardDefinition::Effect* CardSpecial::original_definition_for_condition(const Condition& cond) const { @@ -3825,7 +3826,7 @@ int16_t CardSpecial::max_all_attack_bonuses(size_t* out_count) const { return max_attack_bonus; } -void CardSpecial::unknown_80244AA8(shared_ptr card) { +void CardSpecial::apply_effects_after_card_move(shared_ptr card) { ActionState as = this->create_attack_state_from_card_action_chain(card); bool is_nte = this->server()->options.is_nte(); @@ -3845,12 +3846,12 @@ void CardSpecial::unknown_80244AA8(shared_ptr card) { } } } - this->apply_defense_conditions(as, 0x27, card, 0x04); - this->evaluate_and_apply_effects(0x27, card->get_card_ref(), as, 0xFFFF); + this->apply_defense_conditions(as, EffectWhen::BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL, card, 0x04); + this->evaluate_and_apply_effects(EffectWhen::BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL, card->get_card_ref(), as, 0xFFFF); } - this->apply_defense_conditions(as, 0x13, card, is_nte ? 0x1F : 0x04); - this->evaluate_and_apply_effects(0x13, card->get_card_ref(), as, 0xFFFF); + this->apply_defense_conditions(as, EffectWhen::AFTER_CARD_MOVE, card, is_nte ? 0x1F : 0x04); + this->evaluate_and_apply_effects(EffectWhen::AFTER_CARD_MOVE, card->get_card_ref(), as, 0xFFFF); } void CardSpecial::check_for_defense_interference( @@ -3936,7 +3937,7 @@ void CardSpecial::check_for_defense_interference( } void CardSpecial::evaluate_and_apply_effects( - uint8_t when, + EffectWhen when, uint16_t set_card_ref, const ActionState& as, uint16_t sc_card_ref, @@ -4014,7 +4015,7 @@ void CardSpecial::evaluate_and_apply_effects( string card_effect_str = card_effect.str(); effect_log.debug("effect: %s", card_effect_str.c_str()); if (card_effect.when != when) { - effect_log.debug("does not apply (effect.when=%02hhX, when=%02" PRIX32 ")", card_effect.when, when); + effect_log.debug("does not apply (effect.when=%02hhX, when=%s)", card_effect.when, name_for_enum(when)); continue; } @@ -4426,10 +4427,10 @@ void CardSpecial::on_card_destroyed( attacker_card, destroyed_card); uint16_t destroyed_card_ref = destroyed_card->get_card_ref(); - this->evaluate_and_apply_effects(0x05, destroyed_card_ref, defense_as, 0xFFFF); + this->evaluate_and_apply_effects(EffectWhen::CARD_DESTROYED, destroyed_card_ref, defense_as, 0xFFFF); for (size_t z = 0; (z < 8) && (defense_as.action_card_refs[z] != 0xFFFF); z++) { this->evaluate_and_apply_effects( - 0x05, defense_as.action_card_refs[z], defense_as, destroyed_card->get_card_ref()); + EffectWhen::CARD_DESTROYED, defense_as.action_card_refs[z], defense_as, destroyed_card->get_card_ref()); } if (attacker_card) { @@ -4671,9 +4672,9 @@ vector> CardSpecial::filter_cards_by_range( return ret; } -void CardSpecial::unknown_8024AAB8(const ActionState& as) { +void CardSpecial::apply_effects_after_attack_target_resolution(const ActionState& as) { auto s = this->server(); - auto log = s->log_stack("unknown_8024AAB8: "); + auto log = s->log_stack("apply_effects_after_attack_target_resolution: "); string as_str = as.str(s); log.debug("as=%s", as_str.c_str()); @@ -4685,31 +4686,37 @@ void CardSpecial::unknown_8024AAB8(const ActionState& as) { if (this->send_6xB4x06_if_card_ref_invalid(as.original_attacker_card_ref, 0x1F) == 0xFFFF) { this->evaluate_and_apply_effects( - 0x01, as.action_card_refs[z], as, this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x21)); + EffectWhen::CARD_SET, + as.action_card_refs[z], + as, + this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x21)); this->evaluate_and_apply_effects( - 0x0B, as.action_card_refs[z], as, this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x22)); + EffectWhen::AFTER_ATTACK_TARGET_RESOLUTION, + as.action_card_refs[z], + as, + this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x22)); } else { uint16_t card_ref = this->send_6xB4x06_if_card_ref_invalid(as.target_card_refs[0], 0x20); if (card_ref != 0xFFFF) { - this->evaluate_and_apply_effects(0x01, as.action_card_refs[z], as, card_ref); - this->evaluate_and_apply_effects(0x15, as.action_card_refs[z], as, card_ref); + this->evaluate_and_apply_effects(EffectWhen::CARD_SET, as.action_card_refs[z], as, card_ref); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_15, as.action_card_refs[z], as, card_ref); } } } - if (as.original_attacker_card_ref == 0xffff) { + if (as.original_attacker_card_ref == 0xFFFF) { uint16_t card_ref1 = this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x23); uint16_t card_ref2 = this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x25); - this->evaluate_and_apply_effects(0x33, card_ref2, as, card_ref1); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_33, card_ref2, as, card_ref1); card_ref1 = this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x24); card_ref2 = this->send_6xB4x06_if_card_ref_invalid(as.attacker_card_ref, 0x26); - this->evaluate_and_apply_effects(0x34, card_ref2, as, card_ref1); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_34, card_ref2, as, card_ref1); for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) { uint16_t card_ref = this->send_6xB4x06_if_card_ref_invalid(as.action_card_refs[z], 0x27); if (card_ref == 0xFFFF) { break; } - this->evaluate_and_apply_effects(0x35, as.target_card_refs[z], as, as.attacker_card_ref); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_35, as.target_card_refs[z], as, as.attacker_card_ref); } } } @@ -4717,11 +4724,11 @@ void CardSpecial::unknown_8024AAB8(const ActionState& as) { void CardSpecial::move_phase_before_for_card(shared_ptr card) { bool is_nte = this->server()->options.is_nte(); ActionState as = this->create_attack_state_from_card_action_chain(card); - this->apply_defense_conditions(as, 0x09, card, is_nte ? 0x1F : 0x04); - this->evaluate_and_apply_effects(0x09, card->get_card_ref(), as, 0xFFFF); + this->apply_defense_conditions(as, EffectWhen::BEFORE_MOVE_PHASE, card, is_nte ? 0x1F : 0x04); + this->evaluate_and_apply_effects(EffectWhen::BEFORE_MOVE_PHASE, card->get_card_ref(), as, 0xFFFF); if (!is_nte) { - this->apply_defense_conditions(as, 0x27, card, 0x04); - this->evaluate_and_apply_effects(0x27, card->get_card_ref(), as, 0xFFFF); + this->apply_defense_conditions(as, EffectWhen::BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL, card, 0x04); + this->evaluate_and_apply_effects(EffectWhen::BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL, card->get_card_ref(), as, 0xFFFF); } } @@ -4748,16 +4755,16 @@ void CardSpecial::dice_phase_before_for_card(shared_ptr card) { } if (!is_nte) { - this->apply_defense_conditions(as, 0x46, card, 0x04); - this->evaluate_and_apply_effects(0x46, card->get_card_ref(), as, sc_card_ref); + this->apply_defense_conditions(as, EffectWhen::BEFORE_DICE_PHASE_ALL_TURNS_FINAL, card, 0x04); + this->evaluate_and_apply_effects(EffectWhen::BEFORE_DICE_PHASE_ALL_TURNS_FINAL, card->get_card_ref(), as, sc_card_ref); } if (ps->is_team_turn()) { - this->apply_defense_conditions(as, 0x04, card, 0x04); - this->evaluate_and_apply_effects(0x04, card->get_card_ref(), as, sc_card_ref); + this->apply_defense_conditions(as, EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN, card, 0x04); + this->evaluate_and_apply_effects(EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN, card->get_card_ref(), as, sc_card_ref); } } -template +template void CardSpecial::apply_effects_on_phase_change_t(shared_ptr unknown_p2, const ActionState* existing_as) { auto s = this->server(); auto log = s->log_stack(string_printf("apply_effects_on_phase_change_t<%02hhX, %02hhX>(@%04hX #%04hX): ", When1, When2, unknown_p2->get_card_ref(), unknown_p2->get_card_id())); @@ -4797,17 +4804,17 @@ void CardSpecial::apply_effects_on_phase_change_t(shared_ptr unknown_p2, c } void CardSpecial::draw_phase_before_for_card(shared_ptr unknown_p2) { - this->apply_effects_on_phase_change_t<0x0F, 0x0A>(unknown_p2); + this->apply_effects_on_phase_change_t(unknown_p2); } void CardSpecial::action_phase_before_for_card(shared_ptr unknown_p2) { if (unknown_p2->player_state()->is_team_turn()) { - this->apply_effects_on_phase_change_t<0x0E, 0x0A>(unknown_p2); + this->apply_effects_on_phase_change_t(unknown_p2); } } void CardSpecial::unknown_8024945C(shared_ptr unknown_p2, const ActionState* existing_as) { - this->apply_effects_on_phase_change_t<0x0A, 0x0A>(unknown_p2, this->server()->options.is_nte() ? nullptr : existing_as); + this->apply_effects_on_phase_change_t(unknown_p2, this->server()->options.is_nte() ? nullptr : existing_as); } void CardSpecial::unknown_8024966C(shared_ptr unknown_p2, const ActionState* existing_as) { @@ -4826,38 +4833,38 @@ void CardSpecial::unknown_8024966C(shared_ptr unknown_p2, const ActionStat auto ce = unknown_p2->get_definition(); auto defender_card = (ce && (ce->def.type == CardType::ITEM) && card) ? card : unknown_p2; - this->apply_defense_conditions(as, 0x3D, unknown_p2, 4); - this->apply_defense_conditions(as, 0x3E, unknown_p2, 4); + this->apply_defense_conditions(as, EffectWhen::ATTACK_STAT_OVERRIDES, unknown_p2, 4); + this->apply_defense_conditions(as, EffectWhen::ATTACK_DAMAGE_ADJUSTMENT, unknown_p2, 4); if (defender_card) { - this->apply_defense_conditions(as, 0x22, defender_card, 4); + this->apply_defense_conditions(as, EffectWhen::UNKNOWN_22, defender_card, 4); } for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) { auto card = this->server()->card_for_set_card_ref(as.target_card_refs[z]); if (card) { ActionState defense_as = this->create_defense_state_for_card_pair_action_chains(unknown_p2, card); - this->apply_defense_conditions(defense_as, 0x3D, card, 4); - this->apply_defense_conditions(defense_as, 0x3F, card, 4); + this->apply_defense_conditions(defense_as, EffectWhen::ATTACK_STAT_OVERRIDES, card, 4); + this->apply_defense_conditions(defense_as, EffectWhen::DEFENSE_DAMAGE_ADJUSTMENT, card, 4); } } - this->evaluate_and_apply_effects(0x3D, unknown_p2->get_card_ref(), as, card_ref); - this->evaluate_and_apply_effects(0x3E, unknown_p2->get_card_ref(), as, card_ref); + this->evaluate_and_apply_effects(EffectWhen::ATTACK_STAT_OVERRIDES, unknown_p2->get_card_ref(), as, card_ref); + this->evaluate_and_apply_effects(EffectWhen::ATTACK_DAMAGE_ADJUSTMENT, unknown_p2->get_card_ref(), as, card_ref); if (defender_card) { - this->evaluate_and_apply_effects(0x22, defender_card->get_card_ref(), as, card_ref); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_22, defender_card->get_card_ref(), as, card_ref); } for (size_t z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) { - this->evaluate_and_apply_effects(0x3D, as.action_card_refs[z], as, unknown_p2->get_card_ref()); - this->evaluate_and_apply_effects(0x3E, as.action_card_refs[z], as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::ATTACK_STAT_OVERRIDES, as.action_card_refs[z], as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::ATTACK_DAMAGE_ADJUSTMENT, 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++) { card = this->server()->card_for_set_card_ref(as.target_card_refs[z]); if (card) { ActionState defense_as = this->create_defense_state_for_card_pair_action_chains(unknown_p2, card); - this->evaluate_and_apply_effects(0x3D, card->get_card_ref(), defense_as, unknown_p2->get_card_ref()); - this->evaluate_and_apply_effects(0x3F, card->get_card_ref(), defense_as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::ATTACK_STAT_OVERRIDES, card->get_card_ref(), defense_as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::DEFENSE_DAMAGE_ADJUSTMENT, card->get_card_ref(), defense_as, unknown_p2->get_card_ref()); } } } @@ -4871,11 +4878,11 @@ void CardSpecial::unknown_8024A9D8(const ActionState& pa, uint16_t action_card_r for (size_t z = 0; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) { if (this->server()->options.is_nte() || (action_card_ref == 0xFFFF) || (action_card_ref == pa.action_card_refs[z])) { if (pa.original_attacker_card_ref == 0xFFFF) { - this->evaluate_and_apply_effects(0x29, pa.action_card_refs[z], pa, pa.attacker_card_ref); - this->evaluate_and_apply_effects(0x2A, pa.action_card_refs[z], pa, pa.attacker_card_ref); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_29, pa.action_card_refs[z], pa, pa.attacker_card_ref); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_2A, pa.action_card_refs[z], pa, pa.attacker_card_ref); } else { - this->evaluate_and_apply_effects(0x29, pa.action_card_refs[z], pa, pa.target_card_refs[0]); - this->evaluate_and_apply_effects(0x2B, pa.action_card_refs[z], pa, pa.target_card_refs[0]); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_29, pa.action_card_refs[z], pa, pa.target_card_refs[0]); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_2B, pa.action_card_refs[z], pa, pa.target_card_refs[0]); } } } @@ -4955,10 +4962,15 @@ void CardSpecial::check_for_attack_interference(shared_ptr unknown_p2) { this->server()->send(cmd); } -template -void CardSpecial::unknown_t2(shared_ptr unknown_p2) { +template < + EffectWhen WhenAllCards, + EffectWhen WhenAttackerAndActionCards, + EffectWhen WhenAttackerOrHunterSCCard, + EffectWhen WhenTargetsAndActionCards> +void CardSpecial::apply_effects_before_or_after_attack(shared_ptr unknown_p2) { 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())); + auto log = s->log_stack(string_printf("apply_effects_before_or_after_attack<%s, %s, %s, %s>(@%04hX #%04hX): ", + name_for_enum(WhenAllCards), name_for_enum(WhenAttackerAndActionCards), name_for_enum(WhenAttackerOrHunterSCCard), name_for_enum(WhenTargetsAndActionCards), unknown_p2->get_card_ref(), unknown_p2->get_card_id())); ActionState as = this->create_attack_state_from_card_action_chain(unknown_p2); @@ -4968,56 +4980,64 @@ void CardSpecial::unknown_t2(shared_ptr unknown_p2) { sc_card_ref = sc_card->get_card_ref(); } - auto defender_card = unknown_p2; + auto attacker_card = unknown_p2; if (unknown_p2->get_definition() && (unknown_p2->get_definition()->def.type == CardType::ITEM) && sc_card) { - defender_card = sc_card; + attacker_card = sc_card; } uint8_t apply_defense_conditions_flags = s->options.is_nte() ? 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, apply_defense_conditions_flags); + this->apply_defense_conditions(as, WhenAllCards, unknown_p2, apply_defense_conditions_flags); + this->apply_defense_conditions(as, WhenAttackerAndActionCards, unknown_p2, apply_defense_conditions_flags); + if (attacker_card) { + this->apply_defense_conditions(as, WhenAttackerOrHunterSCCard, attacker_card, apply_defense_conditions_flags); } for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); 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, apply_defense_conditions_flags); - this->apply_defense_conditions(target_as, When4, set_card, apply_defense_conditions_flags); + this->apply_defense_conditions(target_as, WhenAllCards, set_card, apply_defense_conditions_flags); + this->apply_defense_conditions(target_as, WhenTargetsAndActionCards, set_card, apply_defense_conditions_flags); } } - this->evaluate_and_apply_effects(When1, unknown_p2->get_card_ref(), as, sc_card_ref); - this->evaluate_and_apply_effects(When2, unknown_p2->get_card_ref(), as, sc_card_ref); - if (defender_card) { - this->evaluate_and_apply_effects(When3, defender_card->get_card_ref(), as, sc_card_ref); + this->evaluate_and_apply_effects(WhenAllCards, unknown_p2->get_card_ref(), as, sc_card_ref); + this->evaluate_and_apply_effects(WhenAttackerAndActionCards, unknown_p2->get_card_ref(), as, sc_card_ref); + if (attacker_card) { + this->evaluate_and_apply_effects(WhenAttackerOrHunterSCCard, attacker_card->get_card_ref(), as, sc_card_ref); } for (size_t z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) { - this->evaluate_and_apply_effects(When1, as.action_card_refs[z], as, unknown_p2->get_card_ref()); - this->evaluate_and_apply_effects(When2, as.action_card_refs[z], as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(WhenAllCards, as.action_card_refs[z], as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(WhenAttackerAndActionCards, 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 = 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()); - this->evaluate_and_apply_effects(When4, set_card->get_card_ref(), target_as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(WhenAllCards, set_card->get_card_ref(), target_as, unknown_p2->get_card_ref()); + this->evaluate_and_apply_effects(WhenTargetsAndActionCards, set_card->get_card_ref(), target_as, unknown_p2->get_card_ref()); for (size_t z = 0; (z < 8) && (target_as.action_card_refs[z] != 0xFFFF); z++) { - this->evaluate_and_apply_effects(When1, target_as.action_card_refs[z], target_as, set_card->get_card_ref()); - this->evaluate_and_apply_effects(When4, target_as.action_card_refs[z], target_as, set_card->get_card_ref()); + this->evaluate_and_apply_effects(WhenAllCards, target_as.action_card_refs[z], target_as, set_card->get_card_ref()); + this->evaluate_and_apply_effects(WhenTargetsAndActionCards, target_as.action_card_refs[z], target_as, set_card->get_card_ref()); } } } } -void CardSpecial::unknown_8024997C(shared_ptr card) { - return this->unknown_t2<0x03, 0x0D, 0x21, 0x17>(card); +void CardSpecial::apply_effects_after_attack(shared_ptr card) { + return this->apply_effects_before_or_after_attack< + EffectWhen::AFTER_ANY_CARD_ATTACK, + EffectWhen::AFTER_THIS_CARD_ATTACK, + EffectWhen::AFTER_CREATURE_OR_HUNTER_SC_ATTACK, + EffectWhen::AFTER_THIS_CARD_ATTACKED>(card); } -void CardSpecial::unknown_8024A394(shared_ptr card) { - return this->unknown_t2<0x02, 0x0C, 0x20, 0x16>(card); +void CardSpecial::apply_effects_before_attack(shared_ptr card) { + return this->apply_effects_before_or_after_attack< + EffectWhen::BEFORE_ANY_CARD_ATTACK, + EffectWhen::BEFORE_THIS_CARD_ATTACK, + EffectWhen::BEFORE_CREATURE_OR_HUNTER_SC_ATTACK, + EffectWhen::BEFORE_THIS_CARD_ATTACKED>(card); } bool CardSpecial::client_has_atk_dice_boost_condition(uint8_t client_id) { @@ -5054,8 +5074,8 @@ void CardSpecial::unknown_8024A6DC(shared_ptr unknown_p2, shared_ptr 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++) { - this->evaluate_and_apply_effects(0x01, as.action_card_refs[z], as, unknown_p3->get_card_ref()); - this->evaluate_and_apply_effects(0x15, as.action_card_refs[z], as, unknown_p3->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::CARD_SET, as.action_card_refs[z], as, unknown_p3->get_card_ref()); + this->evaluate_and_apply_effects(EffectWhen::UNKNOWN_15, as.action_card_refs[z], as, unknown_p3->get_card_ref()); } } diff --git a/src/Episode3/CardSpecial.hh b/src/Episode3/CardSpecial.hh index ef1b970f..dd18d23d 100644 --- a/src/Episode3/CardSpecial.hh +++ b/src/Episode3/CardSpecial.hh @@ -85,7 +85,7 @@ public: /* 84 */ uint32_t target_attack_bonus; // "edm" in expr /* 88 */ uint32_t last_attack_preliminary_damage; // "ldm" in expr /* 8C */ uint32_t last_attack_damage; // "rdm" in expr - /* 90 */ uint32_t total_last_attack_damage; // "fdm" in expr + /* 90 */ uint32_t final_last_attack_damage; // "fdm" in expr /* 94 */ uint32_t last_attack_damage_count; // "ndm" in expr /* 98 */ uint32_t target_current_hp; // "ehp" in expr /* 9C */ @@ -106,7 +106,7 @@ public: void adjust_dice_boost_if_team_has_condition_52( uint8_t team_id, uint8_t* inout_dice_boost, std::shared_ptr card); void apply_action_conditions( - uint8_t when, + EffectWhen when, std::shared_ptr attacker_card, std::shared_ptr defender_card, uint32_t flags, @@ -118,7 +118,7 @@ public: uint16_t condition_giver_card_ref, uint16_t attacker_card_ref); bool apply_defense_condition( - uint8_t when, + EffectWhen when, Condition* defender_cond, uint8_t cond_index, const ActionState& defense_state, @@ -127,7 +127,7 @@ public: bool unknown_p8); bool apply_defense_conditions( const ActionState& as, - uint8_t when, + EffectWhen when, std::shared_ptr defender_card, uint32_t flags); bool apply_stat_deltas_to_all_cards_from_all_conditions_with_card_ref( @@ -165,7 +165,7 @@ public: uint16_t sc_card_ref); StatSwapType compute_stat_swap_type(std::shared_ptr card) const; void compute_team_dice_bonus(uint8_t team_id); - bool condition_has_when_20_or_21(const Condition& cond) const; + bool condition_applies_on_sc_or_item_attack(const Condition& cond) const; size_t count_action_cards_with_condition_for_all_current_attacks( ConditionType cond_type, uint16_t card_ref) const; size_t count_action_cards_with_condition_for_current_attack( @@ -189,7 +189,7 @@ public: uint16_t set_card_ref, uint16_t sc_card_ref, uint8_t random_percent, - uint8_t when) const; + EffectWhen when) const; int32_t evaluate_effect_expr( const AttackEnvStats& ast, const char* expr, @@ -276,13 +276,13 @@ public: size_t* out_damage_count) const; void update_condition_orders(std::shared_ptr card); int16_t max_all_attack_bonuses(size_t* out_count) const; - void unknown_80244AA8(std::shared_ptr card); + void apply_effects_after_card_move(std::shared_ptr card); void check_for_defense_interference( std::shared_ptr attacker_card, std::shared_ptr target_card, int16_t* inout_unknown_p4); void evaluate_and_apply_effects( - uint8_t when, + EffectWhen when, uint16_t set_card_ref, const ActionState& as, uint16_t sc_card_ref, @@ -313,10 +313,10 @@ public: std::shared_ptr card1, const Location& card1_loc, std::shared_ptr card2) const; - void unknown_8024AAB8(const ActionState& as); + void apply_effects_after_attack_target_resolution(const ActionState& as); void move_phase_before_for_card(std::shared_ptr unknown_p2); void dice_phase_before_for_card(std::shared_ptr card); - template + template void apply_effects_on_phase_change_t(std::shared_ptr unknown_p2, const ActionState* existing_as = nullptr); void draw_phase_before_for_card(std::shared_ptr unknown_p2); void action_phase_before_for_card(std::shared_ptr unknown_p2); @@ -325,10 +325,14 @@ public: static std::shared_ptr sc_card_for_card(std::shared_ptr unknown_p2); void unknown_8024A9D8(const ActionState& pa, uint16_t action_card_ref); void check_for_attack_interference(std::shared_ptr unknown_p2); - template - void unknown_t2(std::shared_ptr unknown_p2); - void unknown_8024997C(std::shared_ptr card); - void unknown_8024A394(std::shared_ptr card); + template < + EffectWhen WhenAllCards, + EffectWhen WhenAttackerAndActionCards, + EffectWhen WhenAttackerOrHunterSCCard, + EffectWhen WhenTargetsAndActionCards> + void apply_effects_before_or_after_attack(std::shared_ptr unknown_p2); + void apply_effects_before_attack(std::shared_ptr card); + void apply_effects_after_attack(std::shared_ptr card); bool client_has_atk_dice_boost_condition(uint8_t client_id); void unknown_8024A6DC( std::shared_ptr unknown_p2, std::shared_ptr unknown_p3); diff --git a/src/Episode3/DataIndexes.cc b/src/Episode3/DataIndexes.cc index e9a1c9c1..340a0262 100644 --- a/src/Episode3/DataIndexes.cc +++ b/src/Episode3/DataIndexes.cc @@ -517,7 +517,7 @@ bool CardDefinition::Effect::is_empty() const { return (this->effect_num == 0 && this->type == ConditionType::NONE && this->expr.empty() && - this->when == 0 && + this->when == EffectWhen::NONE && this->arg1.empty() && this->arg2.empty() && this->arg3.empty() && @@ -603,7 +603,7 @@ string CardDefinition::Effect::str(const char* separator, const TextSet* text_ar if (!this->expr.empty()) { tokens.emplace_back("expr=" + this->expr.decode()); } - tokens.emplace_back(string_printf("when=%02hhX", this->when)); + tokens.emplace_back(string_printf("when=%s", name_for_enum(this->when))); tokens.emplace_back("arg1=" + this->str_for_arg(this->arg1.decode())); tokens.emplace_back("arg2=" + this->str_for_arg(this->arg2.decode())); tokens.emplace_back("arg3=" + this->str_for_arg(this->arg3.decode())); @@ -1068,7 +1068,7 @@ JSON CardDefinition::Effect::json() const { {"EffectNum", this->effect_num}, {"ConditionType", name_for_enum(this->type)}, {"Expression", this->expr.decode()}, - {"When", this->when}, + {"When", name_for_enum(this->when)}, {"Arg1", this->arg1.decode()}, {"Arg2", this->arg2.decode()}, {"Arg3", this->arg3.decode()}, @@ -3117,6 +3117,78 @@ const char* name_for_enum(Episode3::ConditionType cond_ } } +template <> +const char* name_for_enum(Episode3::EffectWhen when) { + switch (when) { + case Episode3::EffectWhen::NONE: + return "NONE"; + case Episode3::EffectWhen::CARD_SET: + return "CARD_SET"; + case Episode3::EffectWhen::AFTER_ANY_CARD_ATTACK: + return "AFTER_ANY_CARD_ATTACK"; + case Episode3::EffectWhen::BEFORE_ANY_CARD_ATTACK: + return "BEFORE_ANY_CARD_ATTACK"; + case Episode3::EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN: + return "BEFORE_DICE_PHASE_THIS_TEAM_TURN"; + case Episode3::EffectWhen::CARD_DESTROYED: + return "CARD_DESTROYED"; + case Episode3::EffectWhen::AFTER_SET_PHASE: + return "AFTER_SET_PHASE"; + case Episode3::EffectWhen::BEFORE_MOVE_PHASE: + return "BEFORE_MOVE_PHASE"; + case Episode3::EffectWhen::UNKNOWN_0A: + return "UNKNOWN_0A"; + case Episode3::EffectWhen::AFTER_ATTACK_TARGET_RESOLUTION: + return "AFTER_ATTACK_TARGET_RESOLUTION"; + case Episode3::EffectWhen::AFTER_THIS_CARD_ATTACK: + return "AFTER_THIS_CARD_ATTACK"; + case Episode3::EffectWhen::BEFORE_THIS_CARD_ATTACK: + return "BEFORE_THIS_CARD_ATTACK"; + case Episode3::EffectWhen::BEFORE_ACT_PHASE: + return "BEFORE_ACT_PHASE"; + case Episode3::EffectWhen::BEFORE_DRAW_PHASE: + return "BEFORE_DRAW_PHASE"; + case Episode3::EffectWhen::AFTER_CARD_MOVE: + return "AFTER_CARD_MOVE"; + case Episode3::EffectWhen::UNKNOWN_15: + return "UNKNOWN_15"; + case Episode3::EffectWhen::AFTER_THIS_CARD_ATTACKED: + return "AFTER_THIS_CARD_ATTACKED"; + case Episode3::EffectWhen::BEFORE_THIS_CARD_ATTACKED: + return "BEFORE_THIS_CARD_ATTACKED"; + case Episode3::EffectWhen::AFTER_CREATURE_OR_HUNTER_SC_ATTACK: + return "AFTER_CREATURE_OR_HUNTER_SC_ATTACK"; + case Episode3::EffectWhen::BEFORE_CREATURE_OR_HUNTER_SC_ATTACK: + return "BEFORE_CREATURE_OR_HUNTER_SC_ATTACK"; + case Episode3::EffectWhen::UNKNOWN_22: + return "UNKNOWN_22"; + case Episode3::EffectWhen::BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL: + return "BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL"; + case Episode3::EffectWhen::UNKNOWN_29: + return "UNKNOWN_29"; + case Episode3::EffectWhen::UNKNOWN_2A: + return "UNKNOWN_2A"; + case Episode3::EffectWhen::UNKNOWN_2B: + return "UNKNOWN_2B"; + case Episode3::EffectWhen::UNKNOWN_33: + return "UNKNOWN_33"; + case Episode3::EffectWhen::UNKNOWN_34: + return "UNKNOWN_34"; + case Episode3::EffectWhen::UNKNOWN_35: + return "UNKNOWN_35"; + case Episode3::EffectWhen::ATTACK_STAT_OVERRIDES: + return "ATTACK_STAT_OVERRIDES"; + case Episode3::EffectWhen::ATTACK_DAMAGE_ADJUSTMENT: + return "ATTACK_DAMAGE_ADJUSTMENT"; + case Episode3::EffectWhen::DEFENSE_DAMAGE_ADJUSTMENT: + return "DEFENSE_DAMAGE_ADJUSTMENT"; + case Episode3::EffectWhen::BEFORE_DICE_PHASE_ALL_TURNS_FINAL: + return "BEFORE_DICE_PHASE_ALL_TURNS_FINAL"; + default: + return "__INVALID__"; + } +} + template <> const char* name_for_enum(Episode3::Direction d) { switch (d) { diff --git a/src/Episode3/DataIndexes.hh b/src/Episode3/DataIndexes.hh index e7af4bea..79cfb957 100644 --- a/src/Episode3/DataIndexes.hh +++ b/src/Episode3/DataIndexes.hh @@ -306,6 +306,41 @@ enum class ConditionType : uint8_t { ANY_FF = 0xFF, // Used as a wildcard in some search functions }; +enum class EffectWhen : uint8_t { + NONE = 0x00, + CARD_SET = 0x01, // Permanent effects like RAMPAGE/PIERCE on SCs, BIG_SWING, AERIAL, etc.; many AC effects also + AFTER_ANY_CARD_ATTACK = 0x02, // GIVE_DAMAGE, HEAL, A_H_SWAP_PERM + BEFORE_ANY_CARD_ATTACK = 0x03, // AP_LOSS, COMBO_TP + BEFORE_DICE_PHASE_THIS_TEAM_TURN = 0x04, // Many different effects + CARD_DESTROYED = 0x05, // RETURN_TO_HAND, RETURN, FILIAL, GIVE_OR_TAKE_EXP + AFTER_SET_PHASE = 0x06, // Unused + BEFORE_MOVE_PHASE = 0x09, // Unused + UNKNOWN_0A = 0x0A, // ANTI_ABNORMALITY_2 on Tollaw (non-SC version of another when?) + AFTER_ATTACK_TARGET_RESOLUTION = 0x0B, // ABILITY_TRAP via First Attack action card only + AFTER_THIS_CARD_ATTACK = 0x0C, // Many effects + BEFORE_THIS_CARD_ATTACK = 0x0D, // Conditions, AP_BOOST/TP_BOOST, AP_SILENCE, MULTI_STRIKE + BEFORE_ACT_PHASE = 0x0E, // Before act phase (ANTI_ABNORMALITY_2, FIXED_RANGE) + BEFORE_DRAW_PHASE = 0x0F, // Unused + AFTER_CARD_MOVE = 0x13, // Unused + UNKNOWN_15 = 0x15, // Unused + AFTER_THIS_CARD_ATTACKED = 0x16, // Conditions, DEATH_COMPANION, GIVE_DAMAGE, AP_GROWTH (Nidra) + BEFORE_THIS_CARD_ATTACKED = 0x17, // Defense damage adjustments + AFTER_CREATURE_OR_HUNTER_SC_ATTACK = 0x20, // RETURN_TO_HAND, A_T_SWAP_PERM, GIVE_OR_TAKE_EXP + BEFORE_CREATURE_OR_HUNTER_SC_ATTACK = 0x21, // Unused + UNKNOWN_22 = 0x22, // MISC_AP_BONUSES (SCs only?) + BEFORE_MOVE_PHASE_AND_AFTER_CARD_MOVE_FINAL = 0x27, // SET_MV + UNKNOWN_29 = 0x29, // MIGHTY_KNUCKLE + UNKNOWN_2A = 0x2A, // Unused + UNKNOWN_2B = 0x2B, // Unused + UNKNOWN_33 = 0x33, // DEF_DISABLE_BY_COST + UNKNOWN_34 = 0x34, // Unused + UNKNOWN_35 = 0x35, // Unused + ATTACK_STAT_OVERRIDES = 0x3D, // BONUS_FROM_LEADER, COPY, ABILITY_TRAP + ATTACK_DAMAGE_ADJUSTMENT = 0x3E, // AP_BOOST, SLAYERS_ASSASSINS, WEAK_SPOT_INFLUENCE, GROUP + DEFENSE_DAMAGE_ADJUSTMENT = 0x3F, // MOSTLY_HALFGUARDS, ACTION_DISRUPTER + BEFORE_DICE_PHASE_ALL_TURNS_FINAL = 0x46, // Pollux Timed Pierce +}; + enum class AssistEffect : uint16_t { NONE = 0x0000, DICE_HALF = 0x0001, @@ -488,7 +523,7 @@ struct CardDefinition { /* 02 */ pstring expr; // when specifies in which phase the effect should activate. // TODO: There are many values that can be used here; document them. - /* 11 */ uint8_t when; + /* 11 */ EffectWhen when; // arg1 generally specifies how long the effect activates for. /* 12 */ pstring arg1; // arg2 generally specifies a condition for when the effect activates. @@ -1577,4 +1612,6 @@ const char* name_for_enum(Episode3::CardClass cc); template <> const char* name_for_enum(Episode3::ConditionType cond_type); template <> +const char* name_for_enum(Episode3::EffectWhen when); +template <> const char* name_for_enum(Episode3::Direction d); diff --git a/src/Episode3/PlayerState.cc b/src/Episode3/PlayerState.cc index 9b23bf9c..1801c296 100644 --- a/src/Episode3/PlayerState.cc +++ b/src/Episode3/PlayerState.cc @@ -1003,7 +1003,7 @@ bool PlayerState::move_card_to_location_by_card_index(size_t card_index, const L this->send_6xB4x04_if_needed(); s->send_6xB4x05(); s->send_6xB4x39(); - s->card_special->unknown_80244AA8(card); + s->card_special->apply_effects_after_card_move(card); return true; } diff --git a/src/Episode3/Server.cc b/src/Episode3/Server.cc index cc0fe6ac..639d60c3 100644 --- a/src/Episode3/Server.cc +++ b/src/Episode3/Server.cc @@ -1462,12 +1462,12 @@ void Server::set_phase_after() { if (ps) { auto card = ps->get_sc_card(); if (card) { - this->card_special->apply_action_conditions(0x06, nullptr, card, is_nte ? 0x1F : 0x04, nullptr); + this->card_special->apply_action_conditions(EffectWhen::AFTER_SET_PHASE, nullptr, card, is_nte ? 0x1F : 0x04, nullptr); } for (size_t set_index = 0; set_index < 8; set_index++) { auto card = ps->get_set_card(set_index); if (card) { - this->card_special->apply_action_conditions(0x06, nullptr, card, is_nte ? 0x1F : 0x04, nullptr); + this->card_special->apply_action_conditions(EffectWhen::AFTER_SET_PHASE, nullptr, card, is_nte ? 0x1F : 0x04, nullptr); } } } @@ -2869,7 +2869,7 @@ void Server::unknown_8023EEF4() { ActionState as = cmd.state; this->send(cmd); - this->card_special->unknown_8024AAB8(as); + this->card_special->apply_effects_after_attack_target_resolution(as); if (!is_nte) { this->attack_cards[this->unknown_a14]->compute_action_chain_results(1, 0);