fix all-players range gathering bug
This commit is contained in:
+74
-44
@@ -14,7 +14,8 @@ static uint16_t ref_for_card(shared_ptr<const Card> card) {
|
||||
}
|
||||
}
|
||||
|
||||
static string refs_str_for_cards_vector(const vector<shared_ptr<const Card>>& cards) {
|
||||
template <typename T>
|
||||
static string refs_str_for_cards_vector(const vector<shared_ptr<T>>& cards) {
|
||||
string ret;
|
||||
for (const auto& card : cards) {
|
||||
if (!ret.empty()) {
|
||||
@@ -108,14 +109,6 @@ 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);
|
||||
@@ -279,8 +272,6 @@ 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->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);
|
||||
@@ -300,7 +291,6 @@ bool CardSpecial::apply_defense_condition(
|
||||
(defender_cond->type == ConditionType::ACID)) {
|
||||
int16_t hp = defender_card->get_current_hp();
|
||||
if (hp > 0) {
|
||||
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);
|
||||
@@ -1537,7 +1527,8 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
const AttackEnvStats& ast,
|
||||
const char* expr,
|
||||
DiceRoll& dice_roll) const {
|
||||
this->debug_log("evaluate_effect_expr(ast, expr=\"%s\", dice_roll=(client_id=%02hhX, a2=%02hhX, value=%02hhX, value_used_in_expr=%s, a5=%04hX))", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5);
|
||||
auto log = this->server()->base()->log.sub("evaluate_effect_expr: ");
|
||||
log.debug("ast, expr=\"%s\", dice_roll=(client_id=%02hhX, a2=%02hhX, value=%02hhX, value_used_in_expr=%s, a5=%04hX)", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5);
|
||||
|
||||
// Note: This implementation is not based on the original code because the
|
||||
// original code was hard to follow - it used a look-behind approach with lots
|
||||
@@ -1568,7 +1559,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
// Operators are evaluated left-to-right - there are no operator precedence
|
||||
// rules
|
||||
int32_t value = 0;
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (start)", value);
|
||||
log.debug("value=%" PRId32 " (start)", value);
|
||||
for (size_t token_index = 0; token_index < tokens.size(); token_index++) {
|
||||
auto token_type = tokens[token_index].first;
|
||||
int32_t token_value = tokens[token_index].second;
|
||||
@@ -1577,7 +1568,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
}
|
||||
if (token_type == ExpressionTokenType::NUMBER) {
|
||||
value = token_value;
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=NUMBER, token_value=%" PRId32 ")", value, token_value);
|
||||
log.debug("value=%" PRId32 " (token_type=NUMBER, token_value=%" PRId32 ")", value, token_value);
|
||||
} else {
|
||||
if (token_index >= tokens.size() - 1) {
|
||||
throw runtime_error("no token on right side of binary operator");
|
||||
@@ -1591,23 +1582,23 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
switch (token_type) {
|
||||
case ExpressionTokenType::ROUND_DIVIDE:
|
||||
value = lround(static_cast<double>(value) / right_value);
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=ROUND_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=ROUND_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::SUBTRACT:
|
||||
value -= right_value;
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=SUBTRACT, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=SUBTRACT, right_token_value=%" PRId32 ")", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::ADD:
|
||||
value += right_value;
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=ADD, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=ADD, right_token_value=%" PRId32 ")", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::MULTIPLY:
|
||||
value *= right_value;
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=MULTIPLY, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=MULTIPLY, right_token_value=%" PRId32 ")", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::FLOOR_DIVIDE:
|
||||
value = floor(value / right_value);
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (token_type=FLOOR_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=FLOOR_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid binary operator");
|
||||
@@ -1615,7 +1606,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
}
|
||||
}
|
||||
|
||||
this->debug_log("evaluate_effect_expr: value=%" PRId32 " (result)", value);
|
||||
log.debug("value=%" PRId32 " (result)", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1627,9 +1618,10 @@ bool CardSpecial::execute_effect(
|
||||
ConditionType cond_type,
|
||||
uint32_t unknown_p7,
|
||||
uint16_t attacker_card_ref) {
|
||||
auto log = this->server()->base()->log.sub("execute_effect: ");
|
||||
{
|
||||
string cond_str = cond.str();
|
||||
this->debug_log("execute_effect(cond=%s, card=%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=%04hX)", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, name_for_condition_type(cond_type), unknown_p7, attacker_card_ref);
|
||||
log.debug("cond=%s, card=%04hX, expr_value=%hd, unknown_p5=%hd, cond_type=%s, unknown_p7=%" PRIu32 ", attacker_card_ref=%04hX", cond_str.c_str(), ref_for_card(card), expr_value, unknown_p5, name_for_condition_type(cond_type), unknown_p7, attacker_card_ref);
|
||||
}
|
||||
int16_t clamped_expr_value = clamp<int16_t>(expr_value, -99, 99);
|
||||
int16_t clamped_unknown_p5 = clamp<int16_t>(unknown_p5, -99, 99);
|
||||
@@ -2504,7 +2496,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");
|
||||
auto log = this->server()->base()->log.sub("get_targeted_cards_for_condition: ");
|
||||
log.debug("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;
|
||||
|
||||
@@ -2513,12 +2506,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));
|
||||
log.debug("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));
|
||||
log.debug("card2=%04hX", ref_for_card(card2));
|
||||
|
||||
Location card1_loc;
|
||||
if (!card1) {
|
||||
@@ -2529,13 +2522,13 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
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());
|
||||
log.debug("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));
|
||||
log.debug("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) {
|
||||
@@ -2551,10 +2544,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));
|
||||
log.debug("(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");
|
||||
log.debug("(p01/p05) result_card=null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2649,10 +2642,10 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
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());
|
||||
log.debug("(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());
|
||||
log.debug("(p16) filtered cards = [%s]", range_refs_str.c_str());
|
||||
break;
|
||||
}
|
||||
case 17: {
|
||||
@@ -2703,26 +2696,39 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
case 23: {
|
||||
auto log23 = log.sub("(p23) ");
|
||||
if (card1) {
|
||||
auto def = this->server()->definition_for_card_ref(card_ref);
|
||||
auto ps = card1->player_state();
|
||||
if (def && ps) {
|
||||
// TODO: Again with the Gifoie hardcoding...
|
||||
uint16_t range_card_id = this->get_card_id_with_effective_range(card1, 0x00D9, card2);
|
||||
log23.debug("effective range card ID is %04hX", range_card_id);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1);
|
||||
compute_effective_range(range, this->server()->base()->card_index, range_card_id, card1_loc, this->server()->base()->map_and_rules1, &log23);
|
||||
auto result_card_refs = ps->get_all_cards_within_range(range, card1_loc, 0xFF);
|
||||
log23.debug("%zu result card refs", result_card_refs.size());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_log = log23.subf("(result ref %04hX) ", result_card_ref);
|
||||
auto result_card = this->server()->card_for_set_card_ref(result_card_ref);
|
||||
if (result_card &&
|
||||
(result_card->get_definition()->def.type != CardType::ITEM)) {
|
||||
if (!result_card) {
|
||||
result_log.debug("result card not found");
|
||||
} else if (result_card->get_definition()->def.type == CardType::ITEM) {
|
||||
result_log.debug("result card is item");
|
||||
} else {
|
||||
result_log.debug("result card found and is not item");
|
||||
ret.emplace_back(result_card);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log23.debug("def or ps is missing");
|
||||
}
|
||||
} else {
|
||||
log23.debug("card1 is missing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case 24:
|
||||
ret = this->find_cards_by_condition_inc_exc(ConditionType::PARALYZE);
|
||||
break;
|
||||
@@ -3058,9 +3064,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));
|
||||
log.debug("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));
|
||||
log.debug("usability filter: removed card %04hX", ref_for_card(c));
|
||||
}
|
||||
}
|
||||
return filtered_ret;
|
||||
@@ -3524,9 +3530,17 @@ void CardSpecial::unknown_8024C2B0(
|
||||
uint16_t sc_card_ref,
|
||||
bool apply_defense_condition_to_all_cards,
|
||||
uint16_t apply_defense_condition_to_card_ref) {
|
||||
auto debug_log = this->server()->base()->log.sub("unknown_8024C2B0: ");
|
||||
{
|
||||
string as_str = as.str();
|
||||
debug_log.debug("when=%02" PRIX32 ", 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);
|
||||
}
|
||||
|
||||
set_card_ref = this->send_6xB4x06_if_card_ref_invalid(set_card_ref, 1);
|
||||
auto ce = this->server()->definition_for_card_ref(set_card_ref);
|
||||
if (!ce) {
|
||||
debug_log.debug("ce missing");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3567,27 +3581,30 @@ void CardSpecial::unknown_8024C2B0(
|
||||
dice_roll.unknown_a2 = 3;
|
||||
dice_roll.value_used_in_expr = false;
|
||||
|
||||
debug_log.debug("inputs: dice_roll=%02hhX, random_percent=%hhu, unknown_v1=%s", dice_roll.value, random_percent, unknown_v1 ? "true" : "false");
|
||||
|
||||
for (size_t def_effect_index = 0; (def_effect_index < 3) && !unknown_v1 && (ce->def.effects[def_effect_index].type != ConditionType::NONE); def_effect_index++) {
|
||||
auto effect_log = debug_log.sub(string_printf("(effect:%zu) ", def_effect_index));
|
||||
const auto& card_effect = ce->def.effects[def_effect_index];
|
||||
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);
|
||||
continue;
|
||||
}
|
||||
|
||||
{
|
||||
string as_s = as.str();
|
||||
string eff_s = card_effect.str();
|
||||
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());
|
||||
}
|
||||
|
||||
int16_t arg3_value = atoi(&card_effect.arg3[1]);
|
||||
effect_log.debug("arg3_value=%hd", arg3_value);
|
||||
auto targeted_cards = this->get_targeted_cards_for_condition(
|
||||
set_card_ref, def_effect_index, sc_card_ref, as, arg3_value, 1);
|
||||
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 (!targeted_cards.empty() &&
|
||||
((card_effect.type == ConditionType::UNKNOWN_64) ||
|
||||
(card_effect.type == ConditionType::MISC_DEFENSE_BONUSES) ||
|
||||
(card_effect.type == ConditionType::MOSTLY_HALFGUARDS))) {
|
||||
effect_log.debug("special targeting applies");
|
||||
size_t count = 0;
|
||||
for (size_t z = 0; z < targeted_cards.size(); z++) {
|
||||
dice_roll.value_used_in_expr = false;
|
||||
@@ -3614,18 +3631,24 @@ void CardSpecial::unknown_8024C2B0(
|
||||
} else {
|
||||
targeted_cards.clear();
|
||||
}
|
||||
} else {
|
||||
effect_log.debug("special targeting does not apply");
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < targeted_cards.size(); z++) {
|
||||
auto target_log = effect_log.sub(string_printf("(target:%04hX) ", targeted_cards[z]->get_card_ref()));
|
||||
dice_roll.value_used_in_expr = false;
|
||||
string arg2_str = card_effect.arg2;
|
||||
target_log.debug("arg2_str = %s", arg2_str.c_str());
|
||||
if (all_targets_matched ||
|
||||
this->evaluate_effect_arg2_condition(
|
||||
as, targeted_cards[z], arg2_str.c_str(), dice_roll, set_card_ref, sc_card_ref, random_percent, when)) {
|
||||
target_log.debug("arg2 condition passed");
|
||||
auto env_stats = this->compute_attack_env_stats(
|
||||
as, targeted_cards[z], dice_roll, set_card_ref, sc_card_ref);
|
||||
string expr_str = card_effect.expr;
|
||||
int16_t value = this->evaluate_effect_expr(env_stats, expr_str.c_str(), dice_roll);
|
||||
target_log.debug("expr = %s, value = %hd", expr_str.c_str(), value);
|
||||
|
||||
uint32_t unknown_v1 = 0;
|
||||
auto target_card = this->compute_replaced_target_based_on_conditions(
|
||||
@@ -3641,12 +3664,16 @@ void CardSpecial::unknown_8024C2B0(
|
||||
sc_card_ref);
|
||||
if (!target_card) {
|
||||
target_card = targeted_cards[z];
|
||||
target_log.debug("target card (not replaced) = %04hX", target_card->get_card_ref());
|
||||
} else {
|
||||
target_log.debug("target card (replaced) = %04hX", target_card->get_card_ref());
|
||||
}
|
||||
|
||||
ssize_t applied_cond_index = -1;
|
||||
if ((unknown_v1 == 0) && !this->should_cancel_condition_due_to_anti_abnormality(card_effect, target_card, dice_cmd.effect.target_card_ref, sc_card_ref)) {
|
||||
applied_cond_index = target_card->apply_abnormal_condition(
|
||||
card_effect, def_effect_index, dice_cmd.effect.target_card_ref, sc_card_ref, value, dice_roll.value, random_percent);
|
||||
target_log.debug("applied abnormal condition");
|
||||
// This debug_print call is in the original code.
|
||||
// this->debug_print(when, 4, &env_stats, "!set_abnormal..", target_card, card_effect.type);
|
||||
}
|
||||
@@ -3668,8 +3695,11 @@ void CardSpecial::unknown_8024C2B0(
|
||||
(apply_defense_condition_to_all_cards || (apply_defense_condition_to_card_ref == targeted_cards[z]->get_card_ref()))) {
|
||||
this->apply_defense_condition(
|
||||
when, &target_card->action_chain.conditions[applied_cond_index], applied_cond_index, as, target_card, 4, 1);
|
||||
target_log.debug("applied defense condition");
|
||||
}
|
||||
target_card->send_6xB4x4E_4C_4D_if_needed(0);
|
||||
} else {
|
||||
target_log.debug("arg2 condition failed");
|
||||
}
|
||||
if (dice_roll.value_used_in_expr) {
|
||||
any_expr_used_dice_roll = true;
|
||||
|
||||
@@ -95,8 +95,6 @@ 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(
|
||||
|
||||
@@ -751,13 +751,17 @@ vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
uint8_t target_team_id) const {
|
||||
auto log = this->server()->base()->log.sub("get_all_cards_within_range: ");
|
||||
string loc_str = loc.str();
|
||||
log.debug("loc=%s, target_team_id=%02hhX", loc_str.c_str(), target_team_id);
|
||||
|
||||
vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = this->server()->player_states[client_id];
|
||||
if (other_ps &&
|
||||
((target_team_id == 0xFF) || (target_team_id == other_ps->get_team_id()))) {
|
||||
ret = get_card_refs_within_range(
|
||||
range, loc, *other_ps->card_short_statuses);
|
||||
auto card_refs = get_card_refs_within_range(range, loc, *other_ps->card_short_statuses, &log);
|
||||
ret.insert(ret.end(), card_refs.begin(), card_refs.end());
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -759,38 +759,74 @@ const char* PlayerBattleStats::name_for_rank(uint8_t rank) {
|
||||
return RANK_NAMES[rank];
|
||||
}
|
||||
|
||||
bool is_card_within_range(
|
||||
static bool is_card_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& anchor_loc,
|
||||
const CardShortStatus& ss) {
|
||||
const CardShortStatus& ss,
|
||||
PrefixedLogger* log) {
|
||||
if (ss.card_ref == 0xFFFF) {
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (false) ss.card_ref missing");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (range[0] == 2) {
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (true) range is entire field");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((ss.loc.x < anchor_loc.x - 4) || (ss.loc.x > anchor_loc.x + 4)) {
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (false) outside x range (ss.loc.x=%hhu, anchor_loc.x=%hhu)", ss.loc.x, anchor_loc.x);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if ((ss.loc.y < anchor_loc.y - 4) || (ss.loc.y > anchor_loc.y + 4)) {
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (false) outside y range (ss.loc.y=%hhu, anchor_loc.y=%hhu)", ss.loc.y, anchor_loc.y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return (range[(ss.loc.x - anchor_loc.x) + ((ss.loc.y - anchor_loc.y) + 4) * 9 + 4] != 0);
|
||||
|
||||
uint8_t y_index = (ss.loc.y - anchor_loc.y) + 4;
|
||||
uint8_t x_index = (ss.loc.x - anchor_loc.x) + 4;
|
||||
bool ret = (range[y_index * 9 + x_index] != 0);
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (%s) (ss.loc=(%hhu,%hhu), anchor_loc=(%hhu,%hhu), indexes=(%hhu,%hhu))",
|
||||
ret ? "true" : "false", ss.loc.x, ss.loc.y, anchor_loc.x, anchor_loc.y, x_index, y_index);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<uint16_t> get_card_refs_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
const parray<CardShortStatus, 0x10>& short_statuses) {
|
||||
const parray<CardShortStatus, 0x10>& short_statuses,
|
||||
PrefixedLogger* log) {
|
||||
vector<uint16_t> ret;
|
||||
if (is_card_within_range(range, loc, short_statuses[0])) {
|
||||
if (is_card_within_range(range, loc, short_statuses[0], log)) {
|
||||
if (log) {
|
||||
log->debug("get_card_refs_within_range: sc card %04hX within range", short_statuses[0].card_ref.load());
|
||||
}
|
||||
ret.emplace_back(short_statuses[0].card_ref);
|
||||
} else {
|
||||
if (log) {
|
||||
log->debug("get_card_refs_within_range: sc card %04hX not within range", short_statuses[0].card_ref.load());
|
||||
}
|
||||
}
|
||||
for (size_t card_index = 7; card_index < 15; card_index++) {
|
||||
const auto& ss = short_statuses[card_index];
|
||||
if (is_card_within_range(range, loc, ss)) {
|
||||
if (is_card_within_range(range, loc, ss, log)) {
|
||||
if (log) {
|
||||
log->debug("get_card_refs_within_range: card %04hX within range", ss.card_ref.load());
|
||||
}
|
||||
ret.emplace_back(ss.card_ref);
|
||||
} else {
|
||||
if (log) {
|
||||
log->debug("get_card_refs_within_range: card %04hX not within range", ss.card_ref.load());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
|
||||
@@ -270,6 +270,7 @@ struct PlayerBattleStats {
|
||||
std::vector<uint16_t> get_card_refs_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
const parray<CardShortStatus, 0x10>& short_statuses);
|
||||
const parray<CardShortStatus, 0x10>& short_statuses,
|
||||
PrefixedLogger* log = nullptr);
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+56
-71
@@ -11,7 +11,14 @@ void compute_effective_range(
|
||||
shared_ptr<const CardIndex> card_index,
|
||||
uint16_t card_id,
|
||||
const Location& loc,
|
||||
shared_ptr<const MapAndRulesState> map_and_rules) {
|
||||
shared_ptr<const MapAndRulesState> map_and_rules,
|
||||
PrefixedLogger* log) {
|
||||
if (log && log->should_log(LogLevel::DEBUG)) {
|
||||
string loc_str = loc.str();
|
||||
log->debug("compute_effective_range: card_id=%04hX, loc=%s", card_id, loc_str.c_str());
|
||||
log->debug("compute_effective_range: map_and_rules->map:");
|
||||
map_and_rules->map.print(stderr);
|
||||
}
|
||||
ret.clear(0);
|
||||
|
||||
parray<uint32_t, 6> range_def;
|
||||
@@ -29,10 +36,16 @@ void compute_effective_range(
|
||||
range_def[z] = ce->def.range[z];
|
||||
}
|
||||
}
|
||||
if (log) {
|
||||
log->debug("compute_effective_range: range_def: %05" PRIX32 " %05" PRIX32 " %05" PRIX32 " %05" PRIX32 " %05" PRIX32 " %05" PRIX32, range_def[0], range_def[1], range_def[2], range_def[3], range_def[4], range_def[5]);
|
||||
}
|
||||
|
||||
if (range_def[0] == 0x000FFFFF) {
|
||||
// Entire field
|
||||
ret.clear(2);
|
||||
if (log) {
|
||||
log->debug("compute_effective_range: entire field (2)");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -46,82 +59,54 @@ void compute_effective_range(
|
||||
row >>= 4;
|
||||
}
|
||||
}
|
||||
if (log) {
|
||||
for (size_t y = 0; y < 9; y++) {
|
||||
log->debug("compute_effective_range: decoded_range: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX",
|
||||
decoded_range[y * 9 + 0], decoded_range[y * 9 + 1], decoded_range[y * 9 + 2], decoded_range[y * 9 + 3], decoded_range[y * 9 + 4], decoded_range[y * 9 + 5], decoded_range[y * 9 + 6], decoded_range[y * 9 + 7], decoded_range[y * 9 + 8]);
|
||||
}
|
||||
}
|
||||
|
||||
switch (loc.direction) {
|
||||
case Direction::LEFT:
|
||||
for (int16_t y = 0; y < 9; y++) {
|
||||
int16_t map_y = loc.y + y - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.height))) {
|
||||
for (int16_t x = 0; x < 9; x++) {
|
||||
int16_t map_x = loc.x + x - 4;
|
||||
if (!map_and_rules || ((map_x >= 0) && (map_x < map_and_rules->map.width))) {
|
||||
ret[y * 9 + x] = decoded_range[(8 - x) * 9 + y];
|
||||
} else {
|
||||
for (int16_t y = 0; y < 9; y++) {
|
||||
int16_t map_y = y + loc.y - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.height))) {
|
||||
for (int16_t x = 0; x < 9; x++) {
|
||||
int16_t map_x = x + loc.x - 4;
|
||||
if (!map_and_rules || ((map_x >= 0) && (map_x < map_and_rules->map.width))) {
|
||||
int16_t up_x, up_y;
|
||||
switch (loc.direction) {
|
||||
case Direction::LEFT:
|
||||
up_x = y;
|
||||
up_y = 9 - x - 1;
|
||||
break;
|
||||
}
|
||||
case Direction::RIGHT:
|
||||
up_x = 9 - y - 1;
|
||||
up_y = x;
|
||||
break;
|
||||
case Direction::UP:
|
||||
up_x = x;
|
||||
up_y = y;
|
||||
break;
|
||||
case Direction::DOWN:
|
||||
up_x = 9 - x - 1;
|
||||
up_y = 9 - y - 1;
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid direction");
|
||||
}
|
||||
ret[y * 9 + x] = decoded_range[up_y * 9 + up_x];
|
||||
if (log) {
|
||||
log->debug("compute_effective_range: x=%hd y=%hd up_x=%hd up_y=%hd v=%hhX", x, y, up_x, up_y, ret[y * 9 + x]);
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
case Direction::RIGHT:
|
||||
for (int16_t y = 0; y < 9; y++) {
|
||||
int16_t map_y = loc.y + y - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.height))) {
|
||||
for (int16_t x = 0; x < 9; x++) {
|
||||
int16_t map_x = loc.x + x - 4;
|
||||
if (!map_and_rules || ((map_x >= 0) && (map_x < map_and_rules->map.width))) {
|
||||
ret[y * 9 + x] = decoded_range[((x * 9) - y) + 8];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Direction::UP:
|
||||
for (int16_t y = 0; y < 9; y++) {
|
||||
int16_t map_y = loc.y + y - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.height))) {
|
||||
for (int16_t x = 0; x < 9; x++) {
|
||||
int16_t map_x = loc.x + x - 4;
|
||||
if (!map_and_rules || ((map_x >= 0) && (map_x < map_and_rules->map.width))) {
|
||||
ret[y * 9 + x] = decoded_range[y * 9 + x];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case Direction::DOWN:
|
||||
for (int16_t y = 0; y < 9; y++) {
|
||||
int16_t map_y = loc.y + y - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.height))) {
|
||||
for (int16_t x = 0; x < 9; x++) {
|
||||
int16_t map_y = loc.x + x - 4;
|
||||
if (!map_and_rules || ((map_y >= 0) && (map_y < map_and_rules->map.width))) {
|
||||
ret[y * 9 + x] = decoded_range[((8 - y) * 9 - x) + 8];
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
if (log) {
|
||||
for (size_t y = 0; y < 9; y++) {
|
||||
log->debug("compute_effective_range: ret: %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX %hhX",
|
||||
ret[y * 9 + 0], ret[y * 9 + 1], ret[y * 9 + 2], ret[y * 9 + 3], ret[y * 9 + 4], ret[y * 9 + 5], ret[y * 9 + 6], ret[y * 9 + 7], ret[y * 9 + 8]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,8 @@ void compute_effective_range(
|
||||
std::shared_ptr<const CardIndex> card_index,
|
||||
uint16_t card_id,
|
||||
const Location& loc,
|
||||
std::shared_ptr<const MapAndRulesState> map_and_rules);
|
||||
std::shared_ptr<const MapAndRulesState> map_and_rules,
|
||||
PrefixedLogger* log = nullptr);
|
||||
|
||||
bool card_linkage_is_valid(
|
||||
std::shared_ptr<const CardIndex::CardEntry> right_def,
|
||||
|
||||
Reference in New Issue
Block a user