switch to coroutine execution model
This commit is contained in:
@@ -82,19 +82,19 @@ void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
|
||||
|
||||
void BattleRecord::Event::print(FILE* stream) const {
|
||||
string time_str = phosg::format_time(this->timestamp);
|
||||
fprintf(stream, "Event @%016" PRIX64 " (%s) ", this->timestamp, time_str.c_str());
|
||||
phosg::fwrite_fmt(stream, "Event @{:016X} ({}) ", this->timestamp, time_str);
|
||||
switch (this->type) {
|
||||
case Type::PLAYER_JOIN:
|
||||
fprintf(stream, "PLAYER_JOIN %02" PRIX32 "\n", this->players[0].lobby_data.client_id.load());
|
||||
phosg::fwrite_fmt(stream, "PLAYER_JOIN {:02X}\n", this->players[0].lobby_data.client_id);
|
||||
this->players[0].print(stream);
|
||||
break;
|
||||
case Type::PLAYER_LEAVE:
|
||||
fprintf(stream, "PLAYER_LEAVE %02hhu\n", this->leaving_client_id);
|
||||
phosg::fwrite_fmt(stream, "PLAYER_LEAVE {:02}\n", this->leaving_client_id);
|
||||
break;
|
||||
case Type::SET_INITIAL_PLAYERS:
|
||||
fprintf(stream, "SET_INITIAL_PLAYERS");
|
||||
phosg::fwrite_fmt(stream, "SET_INITIAL_PLAYERS");
|
||||
for (const auto& player : this->players) {
|
||||
fprintf(stream, " %02" PRIX32, player.lobby_data.client_id.load());
|
||||
phosg::fwrite_fmt(stream, " {:02X}", player.lobby_data.client_id);
|
||||
}
|
||||
fputc('\n', stream);
|
||||
for (const auto& player : this->players) {
|
||||
@@ -102,23 +102,23 @@ void BattleRecord::Event::print(FILE* stream) const {
|
||||
}
|
||||
break;
|
||||
case Type::BATTLE_COMMAND:
|
||||
fprintf(stream, "BATTLE_COMMAND\n");
|
||||
phosg::fwrite_fmt(stream, "BATTLE_COMMAND\n");
|
||||
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
case Type::GAME_COMMAND:
|
||||
fprintf(stream, "GAME_COMMAND\n");
|
||||
phosg::fwrite_fmt(stream, "GAME_COMMAND\n");
|
||||
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
case Type::EP3_GAME_COMMAND:
|
||||
fprintf(stream, "EP3_GAME_COMMAND\n");
|
||||
phosg::fwrite_fmt(stream, "EP3_GAME_COMMAND\n");
|
||||
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
case Type::CHAT_MESSAGE:
|
||||
fprintf(stream, "CHAT_MESSAGE %08" PRIX32 "\n", this->guild_card_number);
|
||||
phosg::fwrite_fmt(stream, "CHAT_MESSAGE {:08X}\n", this->guild_card_number);
|
||||
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
case Type::SERVER_DATA_COMMAND:
|
||||
fprintf(stream, "SERVER_DATA_COMMAND\n");
|
||||
phosg::fwrite_fmt(stream, "SERVER_DATA_COMMAND\n");
|
||||
phosg::print_data(stream, this->data, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
default:
|
||||
@@ -363,26 +363,24 @@ void BattleRecord::set_battle_end_timestamp() {
|
||||
void BattleRecord::print(FILE* stream) const {
|
||||
string start_str = phosg::format_time(this->battle_start_timestamp);
|
||||
string end_str = phosg::format_time(this->battle_end_timestamp);
|
||||
fprintf(stream, "BattleRecord %s behavior_flags=%08" PRIX32 " start=%016" PRIX64 " (%s) end=%016" PRIX64 " (%s); %zu events\n",
|
||||
phosg::fwrite_fmt(stream, "BattleRecord {} behavior_flags={:08X} start={:016X} ({}) end={:016X} ({}); {} events\n",
|
||||
this->is_writable ? "writable" : "read-only",
|
||||
this->behavior_flags,
|
||||
this->battle_start_timestamp,
|
||||
start_str.c_str(),
|
||||
start_str,
|
||||
this->battle_end_timestamp,
|
||||
end_str.c_str(), this->events.size());
|
||||
end_str, this->events.size());
|
||||
for (const auto& event : this->events) {
|
||||
event.print(stream);
|
||||
}
|
||||
}
|
||||
|
||||
BattleRecordPlayer::BattleRecordPlayer(
|
||||
shared_ptr<const BattleRecord> rec,
|
||||
shared_ptr<struct event_base> base)
|
||||
: record(rec),
|
||||
BattleRecordPlayer::BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, shared_ptr<const BattleRecord> rec)
|
||||
: io_context(io_context),
|
||||
record(rec),
|
||||
event_it(this->record->events.begin()),
|
||||
play_start_timestamp(0),
|
||||
base(base),
|
||||
next_command_ev(event_new(this->base.get(), -1, EV_TIMEOUT, &BattleRecordPlayer::dispatch_schedule_events, this), event_free) {}
|
||||
next_command_timer(*this->io_context) {}
|
||||
|
||||
shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
|
||||
return this->record;
|
||||
@@ -395,40 +393,37 @@ void BattleRecordPlayer::set_lobby(shared_ptr<Lobby> l) {
|
||||
void BattleRecordPlayer::start() {
|
||||
if (this->play_start_timestamp == 0) {
|
||||
this->play_start_timestamp = phosg::now();
|
||||
this->schedule_events();
|
||||
asio::co_spawn(*this->io_context, this->play_task(), asio::detached);
|
||||
}
|
||||
}
|
||||
|
||||
void BattleRecordPlayer::dispatch_schedule_events(evutil_socket_t, short, void* ctx) {
|
||||
reinterpret_cast<BattleRecordPlayer*>(ctx)->schedule_events();
|
||||
}
|
||||
|
||||
void BattleRecordPlayer::schedule_events() {
|
||||
// If the lobby is destroyed, we can't replay anything - just return without
|
||||
// rescheduling
|
||||
asio::awaitable<void> BattleRecordPlayer::play_task() {
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (;;) {
|
||||
uint64_t relative_ts = phosg::now() - this->play_start_timestamp + this->record->battle_start_timestamp;
|
||||
|
||||
// If the lobby is destroyed, we can't replay anything
|
||||
if (!l) {
|
||||
co_return;
|
||||
}
|
||||
|
||||
if (this->event_it == this->record->events.end()) {
|
||||
if (relative_ts >= this->record->battle_end_timestamp) {
|
||||
// If the record is complete and the end timestamp has been reached,
|
||||
// send exit commands to all players in the lobby, and don't reschedule
|
||||
// the event (it will be deleted along with the Player when the lobby is
|
||||
// destroyed, when the last client leaves)
|
||||
// the event (it will be deleted along with the Player when the lobby
|
||||
// is destroyed, when the last client leaves)
|
||||
send_command(l, 0xED, 0x00);
|
||||
break;
|
||||
|
||||
} else {
|
||||
// There are no more events to play, but the battle has not officially
|
||||
// ended yet - reschedule the event for the end time
|
||||
auto tv = phosg::usecs_to_timeval(this->record->battle_end_timestamp - relative_ts);
|
||||
event_add(this->next_command_ev.get(), &tv);
|
||||
// There are no more events to play, but the battle has not actually
|
||||
// ended yet; wait until the end time
|
||||
this->next_command_timer.expires_after(std::chrono::microseconds(this->record->battle_end_timestamp - relative_ts));
|
||||
co_await this->next_command_timer.async_wait(asio::use_awaitable);
|
||||
l = this->lobby.lock();
|
||||
}
|
||||
break;
|
||||
|
||||
} else {
|
||||
if (this->event_it->timestamp <= relative_ts) {
|
||||
@@ -464,11 +459,10 @@ void BattleRecordPlayer::schedule_events() {
|
||||
this->event_it++;
|
||||
|
||||
} else {
|
||||
// The next event should not occur yet, so reschedule for the time when
|
||||
// it should occur
|
||||
auto tv = phosg::usecs_to_timeval(this->event_it->timestamp - relative_ts);
|
||||
event_add(this->next_command_ev.get(), &tv);
|
||||
break;
|
||||
// The next event should not occur yet, so wait until its time
|
||||
this->next_command_timer.expires_after(std::chrono::microseconds(this->event_it->timestamp - relative_ts));
|
||||
co_await this->next_command_timer.async_wait(asio::use_awaitable);
|
||||
l = this->lobby.lock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <asio.hpp>
|
||||
#include <deque>
|
||||
#include <memory>
|
||||
#include <phosg/Strings.hh>
|
||||
@@ -108,7 +108,7 @@ private:
|
||||
|
||||
class BattleRecordPlayer {
|
||||
public:
|
||||
BattleRecordPlayer(std::shared_ptr<const BattleRecord> rec, std::shared_ptr<struct event_base> base);
|
||||
BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, std::shared_ptr<const BattleRecord> rec);
|
||||
~BattleRecordPlayer() = default;
|
||||
|
||||
std::shared_ptr<const BattleRecord> get_record() const;
|
||||
@@ -117,16 +117,14 @@ public:
|
||||
void start();
|
||||
|
||||
private:
|
||||
static void dispatch_schedule_events(evutil_socket_t, short, void* ctx);
|
||||
void schedule_events();
|
||||
|
||||
std::shared_ptr<asio::io_context> io_context;
|
||||
std::shared_ptr<const BattleRecord> record;
|
||||
std::deque<BattleRecord::Event>::const_iterator event_it;
|
||||
uint64_t play_start_timestamp;
|
||||
std::shared_ptr<struct event_base> base;
|
||||
std::weak_ptr<Lobby> lobby;
|
||||
std::shared_ptr<struct event> next_command_ev;
|
||||
phosg::StringReader random_r;
|
||||
asio::steady_timer next_command_timer;
|
||||
|
||||
asio::awaitable<void> play_task();
|
||||
};
|
||||
|
||||
} // namespace Episode3
|
||||
|
||||
+84
-84
@@ -123,7 +123,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
int8_t dice_roll_value,
|
||||
int8_t random_percent) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("apply_abnormal_condition(%02hhX, @%04X, @%04X, %hd, %hhd, %hhd): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
|
||||
auto log = s->log_stack(std::format("apply_abnormal_condition({:02X}, @{:04X}, @{:04X}, {}, {}, {}): ", def_effect_index, target_card_ref, sc_card_ref, value, dice_roll_value, random_percent));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
ssize_t existing_cond_index;
|
||||
@@ -150,13 +150,13 @@ ssize_t Card::apply_abnormal_condition(
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.debug("existing_cond_index < 0 (new condition) => cond_index = %zd", cond_index);
|
||||
log.debug_f("existing_cond_index < 0 (new condition) => cond_index = {}", cond_index);
|
||||
} else {
|
||||
log.debug("existing_cond_index = %zd (existing condition)", existing_cond_index);
|
||||
log.debug_f("existing_cond_index = {} (existing condition)", existing_cond_index);
|
||||
}
|
||||
|
||||
if (cond_index < 0) {
|
||||
log.debug("no space for condition");
|
||||
log.debug_f("no space for condition");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
auto& cond = this->action_chain.conditions[cond_index];
|
||||
if ((eff.type == ConditionType::MV_BONUS) && (cond.type == ConditionType::MV_BONUS)) {
|
||||
existing_cond_value = clamp<int16_t>(cond.value, -99, 99);
|
||||
log.debug("MV_BONUS combines => existing_cond_value = %hd", existing_cond_value);
|
||||
log.debug_f("MV_BONUS combines => existing_cond_value = {}", existing_cond_value);
|
||||
}
|
||||
|
||||
s->card_special->apply_stat_deltas_to_card_from_condition_and_clear_cond(cond, this->shared_from_this());
|
||||
@@ -205,7 +205,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
}
|
||||
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("wrote condition %zd => %s", cond_index, cond_str.c_str());
|
||||
log.debug_f("wrote condition {} => {}", cond_index, cond_str);
|
||||
|
||||
if (!is_nte) {
|
||||
s->card_special->update_condition_orders(this->shared_from_this());
|
||||
@@ -214,7 +214,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
continue;
|
||||
}
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("sorted conditions: [%zu] => %s", z, cond_str.c_str());
|
||||
log.debug_f("sorted conditions: [{}] => {}", z, cond_str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -298,13 +298,13 @@ void Card::commit_attack(
|
||||
size_t strike_number,
|
||||
int16_t* out_effective_damage) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("commit_attack(@%04hX #%04hX, @%04hX #%04hX => %hd (str%zu)): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id(), damage, strike_number));
|
||||
auto log = s->log_stack(std::format("commit_attack(@{:04X} #{:04X}, @{:04X} #{:04X} => {} (str{})): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id(), damage, strike_number));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
int16_t effective_damage = damage;
|
||||
s->card_special->adjust_attack_damage_due_to_conditions(
|
||||
this->shared_from_this(), &effective_damage, attacker_card->get_card_ref());
|
||||
log.debug("adjusted damage = %hd", effective_damage);
|
||||
log.debug_f("adjusted damage = {}", effective_damage);
|
||||
|
||||
size_t num_assists = s->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
for (size_t z = 0; z < num_assists; z++) {
|
||||
@@ -324,36 +324,36 @@ void Card::commit_attack(
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("after assists = %hd", effective_damage);
|
||||
log.debug_f("after assists = {}", effective_damage);
|
||||
|
||||
if (this->action_metadata.check_flag(0x10)) {
|
||||
effective_damage = 0;
|
||||
log.debug("flag 0x10 => effective damage = %hd", effective_damage);
|
||||
log.debug_f("flag 0x10 => effective damage = {}", effective_damage);
|
||||
}
|
||||
|
||||
auto attacker_ps = attacker_card->player_state();
|
||||
attacker_ps->stats.damage_given += effective_damage;
|
||||
this->player_state()->stats.damage_taken += effective_damage;
|
||||
log.debug("updated stats");
|
||||
log.debug_f("updated stats");
|
||||
|
||||
this->current_hp = clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
|
||||
log.debug("hp set to %hd", this->current_hp);
|
||||
log.debug_f("hp set to {}", this->current_hp);
|
||||
|
||||
if ((effective_damage > 0) &&
|
||||
(attacker_ps->stats.max_attack_damage < effective_damage)) {
|
||||
attacker_ps->stats.max_attack_damage = effective_damage;
|
||||
log.debug("attacker new max damage %hd", effective_damage);
|
||||
log.debug_f("attacker new max damage {}", effective_damage);
|
||||
}
|
||||
|
||||
this->last_attack_final_damage = effective_damage;
|
||||
log.debug("last attack final damage = %hd", effective_damage);
|
||||
log.debug_f("last attack final damage = {}", effective_damage);
|
||||
if (effective_damage > 0) {
|
||||
this->card_flags = this->card_flags | 4;
|
||||
log.debug("set flag 4");
|
||||
log.debug_f("set flag 4");
|
||||
}
|
||||
if (this->current_hp < 1) {
|
||||
this->destroy_set_card(attacker_card);
|
||||
log.debug("card destroyed");
|
||||
log.debug_f("card destroyed");
|
||||
}
|
||||
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06 cmd_to_send;
|
||||
@@ -507,19 +507,19 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("execute_attack(@%04X #%04X, @%04X #%04X): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id()));
|
||||
auto log = s->log_stack(std::format("execute_attack(@{:04X} #{:04X}, @{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id(), attacker_card->get_card_ref(), attacker_card->get_card_id()));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
this->card_flags &= 0xFFFFFFF3;
|
||||
int16_t attack_ap = this->action_metadata.attack_bonus;
|
||||
int16_t attack_tp = 0;
|
||||
int16_t defense_power = is_nte ? 0 : this->compute_defense_power_for_attacker_card(attacker_card);
|
||||
log.debug("ap=%hd, tp=%hd", attack_ap, attack_tp);
|
||||
log.debug_f("ap={}, tp={}", attack_ap, attack_tp);
|
||||
if (!is_nte && (attack_ap == 0) && !this->action_metadata.check_flag(0x20)) {
|
||||
log.debug("ap == 0 and flag 0x20 not set");
|
||||
log.debug_f("ap == 0 and flag 0x20 not set");
|
||||
return;
|
||||
} else {
|
||||
log.debug("ap != 0 or flag 0x20 set; continuing...");
|
||||
log.debug_f("ap != 0 or flag 0x20 set; continuing...");
|
||||
}
|
||||
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06 cmd;
|
||||
@@ -542,7 +542,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
|
||||
if (is_nte) {
|
||||
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);
|
||||
log.debug_f("ap={}, tp={}, defense={}", 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) {
|
||||
@@ -553,14 +553,14 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
|
||||
s->card_special->compute_attack_ap(this->shared_from_this(), &attack_ap, attacker_card->get_card_ref());
|
||||
log.debug("computed ap %hd", attack_ap);
|
||||
log.debug_f("computed ap {}", attack_ap);
|
||||
this->apply_ap_and_tp_adjust_assists_to_attack(attacker_card, &attack_ap, &defense_power, &attack_tp);
|
||||
log.debug("assist adjusts ap=%hd, defense=%hd", attack_ap, defense_power);
|
||||
log.debug_f("assist adjusts ap={}, defense={}", attack_ap, defense_power);
|
||||
|
||||
int16_t raw_damage = attack_ap - defense_power;
|
||||
int16_t preliminary_damage = max<int16_t>(raw_damage, 0) - attack_tp;
|
||||
this->last_attack_preliminary_damage = preliminary_damage;
|
||||
log.debug("raw_damage=%hd, preliminary_damange=%hd", raw_damage, preliminary_damage);
|
||||
log.debug_f("raw_damage={}, preliminary_damange={}", raw_damage, preliminary_damage);
|
||||
|
||||
uint32_t unknown_a9 = 0;
|
||||
auto target = s->card_special->compute_replaced_target_based_on_conditions(
|
||||
@@ -568,19 +568,19 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
|
||||
if (!target) {
|
||||
target = this->shared_from_this();
|
||||
log.debug("target is not replaced");
|
||||
log.debug_f("target is not replaced");
|
||||
} else {
|
||||
log.debug("target replaced with @%04hX #%04hX", target->get_card_ref(), target->get_card_id());
|
||||
log.debug_f("target replaced with @{:04X} #{:04X}", target->get_card_ref(), target->get_card_id());
|
||||
}
|
||||
|
||||
if (!is_nte) {
|
||||
if (unknown_a9 != 0) {
|
||||
preliminary_damage = 0;
|
||||
log.debug("a9 nonzero; preliminary_damage = 0");
|
||||
log.debug_f("a9 nonzero; preliminary_damage = 0");
|
||||
}
|
||||
if (!(this->card_flags & 2) && (!attacker_card || !(attacker_card->card_flags & 2))) {
|
||||
s->card_special->check_for_defense_interference(attacker_card, this->shared_from_this(), &preliminary_damage);
|
||||
log.debug("checked for defense interference");
|
||||
log.debug_f("checked for defense interference");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -592,19 +592,19 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
ps->stats.num_attacks_taken++;
|
||||
|
||||
if (!(target->card_flags & 2)) {
|
||||
log.debug("flag 2 not set");
|
||||
log.debug_f("flag 2 not set");
|
||||
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
|
||||
int16_t final_effective_damage = 0;
|
||||
target->commit_attack(preliminary_damage, attacker_card, &cmd, strike_num, &final_effective_damage);
|
||||
ps->stats.action_card_negated_damage += max<int16_t>(0, this->current_defense_power - final_effective_damage);
|
||||
}
|
||||
} else {
|
||||
log.debug("flag 2 set; committing zero-damage attack");
|
||||
log.debug_f("flag 2 set; committing zero-damage attack");
|
||||
target->commit_attack(0, attacker_card, &cmd, 0, nullptr);
|
||||
}
|
||||
|
||||
if (!is_nte && (this != target.get())) {
|
||||
log.debug("target was replaced; committing zero-damage attack on original card");
|
||||
log.debug_f("target was replaced; committing zero-damage attack on original card");
|
||||
this->commit_attack(0, attacker_card, &cmd, 0, nullptr);
|
||||
}
|
||||
|
||||
@@ -906,7 +906,7 @@ void Card::clear_action_chain_and_metadata_and_most_flags() {
|
||||
|
||||
void Card::compute_action_chain_results(bool apply_action_conditions, bool ignore_this_card_ap_tp) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("compute_action_chain_results(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
auto log = s->log_stack(std::format("compute_action_chain_results(@{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id()));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
this->action_chain.compute_attack_medium(s);
|
||||
@@ -914,7 +914,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
this->action_chain.chain.ap_effect_bonus = 0;
|
||||
this->action_chain.chain.tp_effect_bonus = 0;
|
||||
|
||||
log.debug("(initial) medium=%s, strike_count=%hhu, ap_effect_bonus=%hhd, tp_effect_bonus=%hhd",
|
||||
log.debug_f("(initial) medium={}, strike_count={}, ap_effect_bonus={}, tp_effect_bonus={}",
|
||||
phosg::name_for_enum(this->action_chain.chain.attack_medium),
|
||||
this->action_chain.chain.strike_count,
|
||||
this->action_chain.chain.ap_effect_bonus,
|
||||
@@ -929,9 +929,9 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
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<size_t>(stat_swap_type));
|
||||
log.debug_f("stat_swap_type = {} (0=none, 1=a/t, 2=a/h)", static_cast<size_t>(stat_swap_type));
|
||||
s->card_special->get_effective_ap_tp(stat_swap_type, &effective_ap, &effective_tp, this->get_current_hp(), this->ap, this->tp);
|
||||
log.debug("effective_ap = %hd, effective_tp = %hd", effective_ap, effective_tp);
|
||||
log.debug_f("effective_ap = {}, effective_tp = {}", effective_ap, effective_tp);
|
||||
}
|
||||
|
||||
// This option doesn't exist in NTE
|
||||
@@ -942,7 +942,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
if (ce) {
|
||||
effective_ap += ce->def.ap.stat;
|
||||
effective_tp += ce->def.tp.stat;
|
||||
log.debug("(action card @%04hX) updated effective_ap = %hd, effective_tp = %hd", this->action_chain.chain.attack_action_card_refs[z].load(), effective_ap, effective_tp);
|
||||
log.debug_f("(action card @{:04X}) updated effective_ap = {}, effective_tp = {}", this->action_chain.chain.attack_action_card_refs[z], effective_ap, effective_tp);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -957,7 +957,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
stat_swap_type, &card_ap, &card_tp, card->get_current_hp(), card->ap, card->tp);
|
||||
effective_ap += card_ap;
|
||||
effective_tp += card_tp;
|
||||
log.debug("(mag card set_index %zu @%04hX) updated effective_ap = %hd, effective_tp = %hd",
|
||||
log.debug_f("(mag card set_index {} @{:04X}) updated effective_ap = {}, effective_tp = {}",
|
||||
set_index, card->get_card_ref(), effective_ap, effective_tp);
|
||||
}
|
||||
}
|
||||
@@ -968,25 +968,25 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
sc_card->compute_action_chain_results(apply_action_conditions, true);
|
||||
effective_ap += sc_card->action_chain.chain.effective_ap + sc_card->action_chain.chain.ap_effect_bonus;
|
||||
effective_tp += sc_card->action_chain.chain.effective_tp + sc_card->action_chain.chain.tp_effect_bonus;
|
||||
log.debug("(item is attacking; adding SC stats) updated effective_ap = %hd, effective_tp = %hd",
|
||||
log.debug_f("(item is attacking; adding SC stats) updated effective_ap = {}, effective_tp = {}",
|
||||
effective_ap, effective_tp);
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x10)) {
|
||||
this->action_chain.chain.effective_ap = is_nte ? effective_ap : min<int16_t>(effective_ap, 99);
|
||||
log.debug("set chain effective_ap = %hd", this->action_chain.chain.effective_ap);
|
||||
log.debug_f("set chain effective_ap = {}", this->action_chain.chain.effective_ap);
|
||||
}
|
||||
if (!this->action_chain.check_flag(0x20)) {
|
||||
this->action_chain.chain.effective_tp = is_nte ? effective_tp : min<int16_t>(effective_tp, 99);
|
||||
log.debug("set chain effective_tp = %hd", this->action_chain.chain.effective_tp);
|
||||
log.debug_f("set chain effective_tp = {}", this->action_chain.chain.effective_tp);
|
||||
}
|
||||
|
||||
if (apply_action_conditions) {
|
||||
auto this_sh = this->shared_from_this();
|
||||
s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 1, nullptr);
|
||||
log.debug("applied action conditions (1)");
|
||||
log.debug_f("applied action conditions (1)");
|
||||
} else {
|
||||
log.debug("skipped applying action conditions (1)");
|
||||
log.debug_f("skipped applying action conditions (1)");
|
||||
}
|
||||
|
||||
size_t num_assists = s->assist_server->compute_num_assist_effects_for_client(this->client_id);
|
||||
@@ -1106,29 +1106,29 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
int16_t damage = 0;
|
||||
if (this->action_chain.chain.attack_medium == AttackMedium::TECH) {
|
||||
damage = this->action_chain.chain.effective_tp + this->action_chain.chain.tp_effect_bonus;
|
||||
log.debug("(tech) damage = %hhd (eff) + %hhd (bonus) = %hd", this->action_chain.chain.effective_tp, this->action_chain.chain.tp_effect_bonus, damage);
|
||||
log.debug_f("(tech) damage = {} (eff) + {} (bonus) = {}", this->action_chain.chain.effective_tp, this->action_chain.chain.tp_effect_bonus, damage);
|
||||
} else if (this->action_chain.chain.attack_medium == AttackMedium::PHYSICAL) {
|
||||
damage = this->action_chain.chain.effective_ap + this->action_chain.chain.ap_effect_bonus;
|
||||
log.debug("(physical) damage = %hhd (eff) + %hhd (bonus) = %hd", this->action_chain.chain.effective_ap, this->action_chain.chain.ap_effect_bonus, damage);
|
||||
log.debug_f("(physical) damage = {} (eff) + {} (bonus) = {}", this->action_chain.chain.effective_ap, this->action_chain.chain.ap_effect_bonus, damage);
|
||||
} else {
|
||||
log.debug("(unknown attack medium) damage = 0");
|
||||
log.debug_f("(unknown attack medium) damage = 0");
|
||||
}
|
||||
|
||||
this->action_chain.chain.damage = is_nte
|
||||
? (damage * this->action_chain.chain.damage_multiplier)
|
||||
: min<int16_t>(damage * this->action_chain.chain.damage_multiplier, 99);
|
||||
log.debug("overall chain damage = %hd (base) * %hhd (mult) = %hhd", damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
|
||||
log.debug_f("overall chain damage = {} (base) * {} (mult) = {}", damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
|
||||
|
||||
if (apply_action_conditions) {
|
||||
auto this_sh = this->shared_from_this();
|
||||
s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 2, nullptr);
|
||||
log.debug("applied action conditions (2)");
|
||||
log.debug_f("applied action conditions (2)");
|
||||
if (!is_nte && this->action_chain.check_flag(0x100)) {
|
||||
this->action_chain.chain.damage = min<int16_t>(this->action_chain.chain.damage + 5, 99);
|
||||
log.debug("(has flag 0x100) chain damage = %hhd", this->action_chain.chain.damage);
|
||||
log.debug_f("(has flag 0x100) chain damage = {}", this->action_chain.chain.damage);
|
||||
}
|
||||
} else {
|
||||
log.debug("skipped applying action conditions (2)");
|
||||
log.debug_f("skipped applying action conditions (2)");
|
||||
}
|
||||
|
||||
if (!is_nte) {
|
||||
@@ -1156,9 +1156,9 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
}
|
||||
}
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string chain_str = this->action_chain.str(s);
|
||||
log.debug("result computed as %s", chain_str.c_str());
|
||||
log.debug_f("result computed as {}", chain_str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1226,24 +1226,24 @@ void Card::move_phase_before() {
|
||||
|
||||
void Card::unknown_80236374(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("unknown_80236374(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
|
||||
auto log = s->log_stack(std::format("unknown_80236374(@{:04X} #{:04X}, @{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id()));
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
if (as) {
|
||||
string as_str = as->str(s);
|
||||
log.debug("as = %s", as_str.c_str());
|
||||
log.debug_f("as = {}", as_str);
|
||||
} else {
|
||||
log.debug("as = null");
|
||||
log.debug_f("as = null");
|
||||
}
|
||||
}
|
||||
|
||||
auto check_card = [&](shared_ptr<Card> card) -> void {
|
||||
if (card) {
|
||||
if (!card->unknown_80236554(other_card, as)) {
|
||||
log.debug("check_card @%04hX #%04hX => false", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("check_card @{:04X} #{:04X} => false", card->get_card_ref(), card->get_card_id());
|
||||
card->action_metadata.clear_flags(0x20);
|
||||
} else {
|
||||
log.debug("check_card @%04hX #%04hX => true", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("check_card @{:04X} #{:04X} => true", card->get_card_ref(), card->get_card_id());
|
||||
card->action_metadata.set_flags(0x20);
|
||||
}
|
||||
}
|
||||
@@ -1378,14 +1378,14 @@ bool Card::is_guard_item() const {
|
||||
bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(other_card
|
||||
? phosg::string_printf("unknown_80236554(@%04hX #%04hX, @%04hX #%04hX): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
|
||||
: phosg::string_printf("unknown_80236554(@%04hX #%04hX, null): ", this->get_card_ref(), this->get_card_id()));
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
? std::format("unknown_80236554(@{:04X} #{:04X}, @{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id(), other_card->get_card_ref(), other_card->get_card_id())
|
||||
: std::format("unknown_80236554(@{:04X} #{:04X}, null): ", this->get_card_ref(), this->get_card_id()));
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
if (as) {
|
||||
string as_str = as->str(s);
|
||||
log.debug("as = %s", as_str.c_str());
|
||||
log.debug_f("as = {}", as_str);
|
||||
} else {
|
||||
log.debug("as = null");
|
||||
log.debug_f("as = null");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1398,7 +1398,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
if (other_card->action_chain.chain.target_card_refs[z] == this->get_card_ref()) {
|
||||
attack_bonus = other_card->action_chain.chain.damage;
|
||||
ret = true;
|
||||
log.debug("attack_bonus = %hd (matched other_card->action_chain.chain.target_card_refs)", attack_bonus);
|
||||
log.debug_f("attack_bonus = {} (matched other_card->action_chain.chain.target_card_refs)", attack_bonus);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1406,7 +1406,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
for (size_t z = 0; (z < 4 * 9) && (as->target_card_refs[z] != 0xFFFF); z++) {
|
||||
if (as->target_card_refs[z] == this->get_card_ref()) {
|
||||
attack_bonus = other_card->action_chain.chain.damage;
|
||||
log.debug("attack_bonus = %hd (matched as->target_card_refs)", attack_bonus);
|
||||
log.debug_f("attack_bonus = {} (matched as->target_card_refs)", attack_bonus);
|
||||
ret = true;
|
||||
break;
|
||||
}
|
||||
@@ -1415,26 +1415,26 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
}
|
||||
|
||||
this->action_metadata.attack_bonus = max<int16_t>(attack_bonus, 0);
|
||||
log.debug("attack_bonus = %hhd", this->action_metadata.attack_bonus);
|
||||
log.debug_f("attack_bonus = {}", this->action_metadata.attack_bonus);
|
||||
this->last_attack_preliminary_damage = 0;
|
||||
this->last_attack_final_damage = 0;
|
||||
log.debug("last attack damage stats cleared");
|
||||
log.debug_f("last attack damage stats cleared");
|
||||
|
||||
if (other_card) {
|
||||
log.debug("applying BEFORE_ANY_CARD_ATTACK conditions");
|
||||
log.debug_f("applying BEFORE_ANY_CARD_ATTACK conditions");
|
||||
s->card_special->apply_action_conditions(
|
||||
EffectWhen::BEFORE_ANY_CARD_ATTACK, other_card, this->shared_from_this(), 0x20, as);
|
||||
log.debug("applying BEFORE_THIS_CARD_ATTACKED conditions");
|
||||
log.debug_f("applying BEFORE_THIS_CARD_ATTACKED conditions");
|
||||
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)) {
|
||||
log.debug("attack_bonus cleared due to cancellation");
|
||||
log.debug_f("attack_bonus cleared due to cancellation");
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
if (this->card_flags & 2) {
|
||||
log.debug("attack_bonus cleared due to destruction");
|
||||
log.debug_f("attack_bonus cleared due to destruction");
|
||||
this->action_metadata.attack_bonus = 0;
|
||||
}
|
||||
return ret;
|
||||
@@ -1464,7 +1464,7 @@ void Card::apply_attack_result() {
|
||||
auto ps = this->player_state();
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
auto log = s->log_stack(phosg::string_printf("apply_attack_result(@%04hX #%04hX): ", this->get_card_ref(), this->get_card_id()));
|
||||
auto log = s->log_stack(std::format("apply_attack_result(@{:04X} #{:04X}): ", this->get_card_ref(), this->get_card_id()));
|
||||
if (!this->action_chain.can_apply_attack()) {
|
||||
return;
|
||||
}
|
||||
@@ -1573,9 +1573,9 @@ void Card::apply_attack_result() {
|
||||
}
|
||||
}
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string as_str = as.str(s);
|
||||
log.debug("as constructed as %s", as_str.c_str());
|
||||
log.debug_f("as constructed as {}", as_str);
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
@@ -1583,36 +1583,36 @@ void Card::apply_attack_result() {
|
||||
if (card) {
|
||||
card->current_defense_power = card->action_metadata.attack_bonus;
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
log.debug("unknown_8024A6DC(@%04hX #%04hX) ...", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("unknown_8024A6DC(@{:04X} #{:04X}) ...", card->get_card_ref(), card->get_card_id());
|
||||
s->card_special->unknown_8024A6DC(this->shared_from_this(), card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("compute_action_chain_results 1 ...");
|
||||
log.debug_f("compute_action_chain_results 1 ...");
|
||||
this->compute_action_chain_results(true, false);
|
||||
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
log.debug("apply_effects_before_attack ...");
|
||||
log.debug_f("apply_effects_before_attack ...");
|
||||
s->card_special->apply_effects_before_attack(this->shared_from_this());
|
||||
}
|
||||
if (!(this->card_flags & 2)) {
|
||||
log.debug("compute_action_chain_results 2 ...");
|
||||
log.debug_f("compute_action_chain_results 2 ...");
|
||||
this->compute_action_chain_results(true, false);
|
||||
log.debug("check_for_attack_interference ...");
|
||||
log.debug_f("check_for_attack_interference ...");
|
||||
s->card_special->check_for_attack_interference(this->shared_from_this());
|
||||
}
|
||||
log.debug("compute_action_chain_results 3 ...");
|
||||
log.debug_f("compute_action_chain_results 3 ...");
|
||||
this->compute_action_chain_results(true, false);
|
||||
|
||||
log.debug("unknown_80236374 ...");
|
||||
log.debug_f("unknown_80236374 ...");
|
||||
this->unknown_80236374(this->shared_from_this(), nullptr);
|
||||
log.debug("execute_attack_on_all_valid_targets ...");
|
||||
log.debug_f("execute_attack_on_all_valid_targets ...");
|
||||
this->execute_attack_on_all_valid_targets(this->shared_from_this());
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
log.debug("apply_effects_after_attack ...");
|
||||
log.debug_f("apply_effects_after_attack ...");
|
||||
s->card_special->apply_effects_after_attack(this->shared_from_this());
|
||||
}
|
||||
ps->stats.num_attacks_given++;
|
||||
@@ -1625,7 +1625,7 @@ void Card::apply_attack_result() {
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = s->player_states[client_id];
|
||||
if (ps) {
|
||||
log.debug("unknown_8023C110(%zu) ...", client_id);
|
||||
log.debug_f("unknown_8023C110({}) ...", client_id);
|
||||
ps->unknown_8023C110();
|
||||
}
|
||||
}
|
||||
|
||||
+195
-195
@@ -21,7 +21,7 @@ static string refs_str_for_cards_vector(const vector<shared_ptr<T>>& cards) {
|
||||
if (!ret.empty()) {
|
||||
ret += ", ";
|
||||
}
|
||||
ret += phosg::string_printf("@%04hX", ref_for_card(card));
|
||||
ret += std::format("@{:04X}", ref_for_card(card));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -89,45 +89,45 @@ uint32_t CardSpecial::AttackEnvStats::at(size_t index) const {
|
||||
}
|
||||
|
||||
void CardSpecial::AttackEnvStats::print(FILE* stream) const {
|
||||
fprintf(stream, "(a) total_num_set_cards = %" PRIu32 "\n", this->total_num_set_cards);
|
||||
fprintf(stream, "(ab) num_a_beast_creatures = %" PRIu32 "\n", this->num_a_beast_creatures);
|
||||
fprintf(stream, "(ac) player_num_atk_points = %" PRIu32 "\n", this->player_num_atk_points);
|
||||
fprintf(stream, "(adm) sc_effective_ap = %" PRIu32 "\n", this->sc_effective_ap);
|
||||
fprintf(stream, "(ap) effective_ap = %" PRIu32 "\n", this->effective_ap);
|
||||
fprintf(stream, "(bi) num_native_creatures = %" PRIu32 "\n", this->num_native_creatures);
|
||||
fprintf(stream, "(cs) card_cost = %" PRIu32 "\n", this->card_cost);
|
||||
fprintf(stream, "(d) dice_roll_value1 = %" PRIu32 "\n", this->dice_roll_value1);
|
||||
fprintf(stream, "(dc) dice_roll_value2 = %" PRIu32 "\n", this->dice_roll_value2);
|
||||
fprintf(stream, "(ddm) attack_bonus = %" PRIu32 "\n", this->attack_bonus);
|
||||
fprintf(stream, "(df) num_destroyed_ally_fcs = %" PRIu32 "\n", this->num_destroyed_ally_fcs);
|
||||
fprintf(stream, "(dk) num_dark_creatures = %" PRIu32 "\n", this->num_dark_creatures);
|
||||
fprintf(stream, "(dm) effective_ap_if_not_tech = %" PRIu32 "\n", this->effective_ap_if_not_tech);
|
||||
fprintf(stream, "(dn) unknown_a1 = %" PRIu32 "\n", this->unknown_a1);
|
||||
fprintf(stream, "(edm) target_attack_bonus = %" PRIu32 "\n", this->target_attack_bonus);
|
||||
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) 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);
|
||||
fprintf(stream, "(hp) current_hp = %" PRIu32 "\n", this->current_hp);
|
||||
fprintf(stream, "(kap) action_cards_ap = %" PRIu32 "\n", this->action_cards_ap);
|
||||
fprintf(stream, "(ktp) action_cards_tp = %" PRIu32 "\n", this->action_cards_tp);
|
||||
fprintf(stream, "(ldm) last_attack_preliminary_damage = %" PRIu32 "\n", this->last_attack_preliminary_damage);
|
||||
fprintf(stream, "(lv) team_dice_bonus = %" PRIu32 "\n", this->team_dice_bonus);
|
||||
fprintf(stream, "(mc) num_machine_creatures = %" PRIu32 "\n", this->num_machine_creatures);
|
||||
fprintf(stream, "(mhp) max_hp = %" PRIu32 "\n", this->max_hp);
|
||||
fprintf(stream, "(ndm) last_attack_damage_count = %" PRIu32 "\n", this->last_attack_damage_count);
|
||||
fprintf(stream, "(php) defined_max_hp = %" PRIu32 "\n", this->defined_max_hp);
|
||||
fprintf(stream, "(rdm) last_attack_damage = %" PRIu32 "\n", this->last_attack_damage);
|
||||
fprintf(stream, "(sa) num_sword_type_items = %" PRIu32 "\n", this->num_sword_type_items);
|
||||
fprintf(stream, "(sat) num_sword_type_items_on_team = %" PRIu32 "\n", this->num_sword_type_items_on_team);
|
||||
fprintf(stream, "(tdm) effective_ap_if_not_physical = %" PRIu32 "\n", this->effective_ap_if_not_physical);
|
||||
fprintf(stream, "(tf) player_num_destroyed_fcs = %" PRIu32 "\n", this->player_num_destroyed_fcs);
|
||||
fprintf(stream, "(tp) effective_tp = %" PRIu32 "\n", this->effective_tp);
|
||||
fprintf(stream, "(tt) effective_ap_if_not_tech2 = %" PRIu32 "\n", this->effective_ap_if_not_tech2);
|
||||
fprintf(stream, "(wd) num_cane_type_items = %" PRIu32 "\n", this->num_cane_type_items);
|
||||
phosg::fwrite_fmt(stream, "(a) total_num_set_cards = {}\n", this->total_num_set_cards);
|
||||
phosg::fwrite_fmt(stream, "(ab) num_a_beast_creatures = {}\n", this->num_a_beast_creatures);
|
||||
phosg::fwrite_fmt(stream, "(ac) player_num_atk_points = {}\n", this->player_num_atk_points);
|
||||
phosg::fwrite_fmt(stream, "(adm) sc_effective_ap = {}\n", this->sc_effective_ap);
|
||||
phosg::fwrite_fmt(stream, "(ap) effective_ap = {}\n", this->effective_ap);
|
||||
phosg::fwrite_fmt(stream, "(bi) num_native_creatures = {}\n", this->num_native_creatures);
|
||||
phosg::fwrite_fmt(stream, "(cs) card_cost = {}\n", this->card_cost);
|
||||
phosg::fwrite_fmt(stream, "(d) dice_roll_value1 = {}\n", this->dice_roll_value1);
|
||||
phosg::fwrite_fmt(stream, "(dc) dice_roll_value2 = {}\n", this->dice_roll_value2);
|
||||
phosg::fwrite_fmt(stream, "(ddm) attack_bonus = {}\n", this->attack_bonus);
|
||||
phosg::fwrite_fmt(stream, "(df) num_destroyed_ally_fcs = {}\n", this->num_destroyed_ally_fcs);
|
||||
phosg::fwrite_fmt(stream, "(dk) num_dark_creatures = {}\n", this->num_dark_creatures);
|
||||
phosg::fwrite_fmt(stream, "(dm) effective_ap_if_not_tech = {}\n", this->effective_ap_if_not_tech);
|
||||
phosg::fwrite_fmt(stream, "(dn) unknown_a1 = {}\n", this->unknown_a1);
|
||||
phosg::fwrite_fmt(stream, "(edm) target_attack_bonus = {}\n", this->target_attack_bonus);
|
||||
phosg::fwrite_fmt(stream, "(ef) non_target_team_num_set_cards = {}\n", this->non_target_team_num_set_cards);
|
||||
phosg::fwrite_fmt(stream, "(ehp) target_current_hp = {}\n", this->target_current_hp);
|
||||
phosg::fwrite_fmt(stream, "(f) num_set_cards = {}\n", this->num_set_cards);
|
||||
phosg::fwrite_fmt(stream, "(fdm) final_last_attack_damage = {}\n", this->final_last_attack_damage);
|
||||
phosg::fwrite_fmt(stream, "(ff) target_team_num_set_cards = {}\n", this->target_team_num_set_cards);
|
||||
phosg::fwrite_fmt(stream, "(gn) num_gun_type_items = {}\n", this->num_gun_type_items);
|
||||
phosg::fwrite_fmt(stream, "(hf) num_item_or_creature_cards_in_hand = {}\n", this->num_item_or_creature_cards_in_hand);
|
||||
phosg::fwrite_fmt(stream, "(hp) current_hp = {}\n", this->current_hp);
|
||||
phosg::fwrite_fmt(stream, "(kap) action_cards_ap = {}\n", this->action_cards_ap);
|
||||
phosg::fwrite_fmt(stream, "(ktp) action_cards_tp = {}\n", this->action_cards_tp);
|
||||
phosg::fwrite_fmt(stream, "(ldm) last_attack_preliminary_damage = {}\n", this->last_attack_preliminary_damage);
|
||||
phosg::fwrite_fmt(stream, "(lv) team_dice_bonus = {}\n", this->team_dice_bonus);
|
||||
phosg::fwrite_fmt(stream, "(mc) num_machine_creatures = {}\n", this->num_machine_creatures);
|
||||
phosg::fwrite_fmt(stream, "(mhp) max_hp = {}\n", this->max_hp);
|
||||
phosg::fwrite_fmt(stream, "(ndm) last_attack_damage_count = {}\n", this->last_attack_damage_count);
|
||||
phosg::fwrite_fmt(stream, "(php) defined_max_hp = {}\n", this->defined_max_hp);
|
||||
phosg::fwrite_fmt(stream, "(rdm) last_attack_damage = {}\n", this->last_attack_damage);
|
||||
phosg::fwrite_fmt(stream, "(sa) num_sword_type_items = {}\n", this->num_sword_type_items);
|
||||
phosg::fwrite_fmt(stream, "(sat) num_sword_type_items_on_team = {}\n", this->num_sword_type_items_on_team);
|
||||
phosg::fwrite_fmt(stream, "(tdm) effective_ap_if_not_physical = {}\n", this->effective_ap_if_not_physical);
|
||||
phosg::fwrite_fmt(stream, "(tf) player_num_destroyed_fcs = {}\n", this->player_num_destroyed_fcs);
|
||||
phosg::fwrite_fmt(stream, "(tp) effective_tp = {}\n", this->effective_tp);
|
||||
phosg::fwrite_fmt(stream, "(tt) effective_ap_if_not_tech2 = {}\n", this->effective_ap_if_not_tech2);
|
||||
phosg::fwrite_fmt(stream, "(wd) num_cane_type_items = {}\n", this->num_cane_type_items);
|
||||
}
|
||||
|
||||
CardSpecial::CardSpecial(shared_ptr<Server> server) : w_server(server) {}
|
||||
@@ -251,14 +251,14 @@ void CardSpecial::apply_action_conditions(
|
||||
if (attacker_card == defender_card) {
|
||||
temp_as = this->create_attack_state_from_card_action_chain(attacker_card);
|
||||
if (as) {
|
||||
log.debug("using action state from override");
|
||||
log.debug_f("using action state from override");
|
||||
temp_as = *as;
|
||||
} else {
|
||||
log.debug("using action state from attacker card");
|
||||
log.debug_f("using action state from attacker card");
|
||||
}
|
||||
} else {
|
||||
temp_as = this->create_defense_state_for_card_pair_action_chains(attacker_card, defender_card);
|
||||
log.debug("using action state from card pair");
|
||||
log.debug_f("using action state from card pair");
|
||||
}
|
||||
|
||||
this->apply_defense_conditions(temp_as, when, defender_card, flags);
|
||||
@@ -307,9 +307,9 @@ bool CardSpecial::apply_defense_condition(
|
||||
bool is_nte = s->options.is_nte();
|
||||
auto log = s->log_stack("apply_defense_condition: ");
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
log.debug(
|
||||
"when=%s, cond_index=%hhu, defender_card=(@%04hX #%04hX), flags=%08" PRIX32 ", p8=%s",
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
log.debug_f(
|
||||
"when={}, cond_index={}, defender_card=(@{:04X} #{:04X}), flags={:08X}, p8={}",
|
||||
phosg::name_for_enum(when),
|
||||
cond_index,
|
||||
defender_card->get_card_ref(),
|
||||
@@ -318,32 +318,32 @@ bool CardSpecial::apply_defense_condition(
|
||||
unknown_p8 ? "true" : "false");
|
||||
auto defender_cond_str = defender_cond->str(s);
|
||||
auto defense_state_str = defense_state.str(s);
|
||||
log.debug("defender_cond = %s", defender_cond_str.c_str());
|
||||
log.debug("defense_state = %s", defense_state_str.c_str());
|
||||
log.debug_f("defender_cond = {}", defender_cond_str);
|
||||
log.debug_f("defense_state = {}", defense_state_str);
|
||||
}
|
||||
|
||||
if (defender_cond->type == ConditionType::NONE) {
|
||||
log.debug("no condition");
|
||||
log.debug_f("no condition");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto orig_eff = this->original_definition_for_condition(*defender_cond);
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
auto orig_eff_str = orig_eff->str();
|
||||
log.debug("orig_eff = %s", orig_eff_str.c_str());
|
||||
log.debug_f("orig_eff = {}", orig_eff_str);
|
||||
}
|
||||
|
||||
uint16_t attacker_card_ref = defense_state.attacker_card_ref;
|
||||
if (attacker_card_ref == 0xFFFF) {
|
||||
attacker_card_ref = defense_state.original_attacker_card_ref;
|
||||
}
|
||||
log.debug("attacker_card_ref = @%04hX", attacker_card_ref);
|
||||
log.debug_f("attacker_card_ref = @{:04X}", attacker_card_ref);
|
||||
|
||||
bool defender_has_ability_trap = !is_nte && this->card_ref_has_ability_trap(*defender_cond);
|
||||
log.debug("defender_has_ability_trap = %s", defender_has_ability_trap ? "true" : "false");
|
||||
log.debug_f("defender_has_ability_trap = {}", defender_has_ability_trap ? "true" : "false");
|
||||
|
||||
if ((is_nte || (flags & 4)) && !this->is_card_targeted_by_condition(*defender_cond, defense_state, defender_card)) {
|
||||
log.debug("not targeted by condition");
|
||||
log.debug_f("not targeted by condition");
|
||||
if (defender_cond->type != ConditionType::NONE) {
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06 cmd;
|
||||
cmd.effect.flags = 0x04;
|
||||
@@ -359,7 +359,7 @@ bool CardSpecial::apply_defense_condition(
|
||||
}
|
||||
|
||||
if ((when == EffectWhen::AFTER_ANY_CARD_ATTACK) && (defender_cond->type == ConditionType::GUOM) && (flags & 4)) {
|
||||
log.debug("deleting guom condition");
|
||||
log.debug_f("deleting guom condition");
|
||||
CardShortStatus stat = defender_card->get_short_status();
|
||||
if (stat.card_flags & 4) {
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06 cmd;
|
||||
@@ -396,7 +396,7 @@ bool CardSpecial::apply_defense_condition(
|
||||
}
|
||||
|
||||
if ((when == EffectWhen::BEFORE_DICE_PHASE_THIS_TEAM_TURN) && (flags & 4) && !defender_has_ability_trap && (defender_cond->type == ConditionType::ACID)) {
|
||||
log.debug("applying acid");
|
||||
log.debug_f("applying 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);
|
||||
@@ -406,11 +406,11 @@ bool CardSpecial::apply_defense_condition(
|
||||
}
|
||||
|
||||
if (!orig_eff || (orig_eff->when != when)) {
|
||||
log.debug("unsetting flag 4");
|
||||
log.debug_f("unsetting flag 4");
|
||||
flags &= ~4;
|
||||
}
|
||||
if ((flags == 0) || defender_has_ability_trap) {
|
||||
log.debug("no condition remains to apply");
|
||||
log.debug_f("no condition remains to apply");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -427,10 +427,10 @@ bool CardSpecial::apply_defense_condition(
|
||||
|
||||
string expr = orig_eff->expr.decode();
|
||||
int16_t expr_value = this->evaluate_effect_expr(astats, expr.c_str(), dice_roll);
|
||||
log.debug("execute_effect ...");
|
||||
log.debug_f("execute_effect ...");
|
||||
this->execute_effect(*defender_cond, defender_card, expr_value, defender_cond->value, orig_eff->type, flags, attacker_card_ref);
|
||||
if (flags & 4) {
|
||||
log.debug("recomputing action chaing results");
|
||||
log.debug_f("recomputing action chaing results");
|
||||
if (is_nte || !(defender_card->card_flags & 2)) {
|
||||
defender_card->compute_action_chain_results(true, false);
|
||||
}
|
||||
@@ -440,7 +440,7 @@ bool CardSpecial::apply_defense_condition(
|
||||
}
|
||||
|
||||
if (dice_roll.value_used_in_expr && !(original_cond_flags & 1) && !unknown_p8) {
|
||||
log.debug("dice roll was used; setting dice display flag");
|
||||
log.debug_f("dice roll was used; setting dice display flag");
|
||||
defender_cond->flags |= 1;
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06 cmd;
|
||||
cmd.effect.flags = 0x08;
|
||||
@@ -491,11 +491,11 @@ bool CardSpecial::apply_stat_deltas_to_all_cards_from_all_conditions_with_card_r
|
||||
|
||||
bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condition& cond, shared_ptr<Card> card) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("apply_stat_deltas_to_card_from_condition_and_clear_cond(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
auto log = s->log_stack(std::format("apply_stat_deltas_to_card_from_condition_and_clear_cond(@{:04X} #{:04X}): ", card->get_card_ref(), card->get_card_id()));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
string cond_str = cond.str(s);
|
||||
log.debug("cond: %s", cond_str.c_str());
|
||||
log.debug_f("cond: {}", cond_str);
|
||||
|
||||
ConditionType cond_type = cond.type;
|
||||
int16_t cond_value = is_nte ? cond.value.load() : clamp<int16_t>(cond.value, -99, 99);
|
||||
@@ -508,7 +508,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
if (cond_flags & 2) {
|
||||
int16_t ap = clamp<int16_t>(card->ap, -99, 99);
|
||||
int16_t tp = clamp<int16_t>(card->tp, -99, 99);
|
||||
log.debug("A_T_SWAP_0C: swapping AP (%hd) and TP (%hd)", ap, tp);
|
||||
log.debug_f("A_T_SWAP_0C: swapping AP ({}) and TP ({})", ap, tp);
|
||||
if (!is_nte) {
|
||||
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);
|
||||
@@ -516,7 +516,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
card->ap = tp;
|
||||
card->tp = ap;
|
||||
} else {
|
||||
log.debug("A_T_SWAP_0C: required flag is missing");
|
||||
log.debug_f("A_T_SWAP_0C: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::A_H_SWAP:
|
||||
@@ -524,7 +524,7 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
int16_t ap = clamp<int16_t>(card->ap, -99, 99);
|
||||
int16_t hp = clamp<int16_t>(card->get_current_hp(), -99, 99);
|
||||
if (hp != ap) {
|
||||
log.debug("A_H_SWAP: swapping AP (%hd) and HP (%hd)", ap, hp);
|
||||
log.debug_f("A_H_SWAP: swapping AP ({}) and HP ({})", ap, hp);
|
||||
if (!is_nte) {
|
||||
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);
|
||||
@@ -533,10 +533,10 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
card->ap = hp;
|
||||
this->destroy_card_if_hp_zero(card, cond_card_ref);
|
||||
} else {
|
||||
log.debug("A_H_SWAP: AP (%hd) == HP (%hd)", ap, hp);
|
||||
log.debug_f("A_H_SWAP: AP ({}) == HP ({})", ap, hp);
|
||||
}
|
||||
} else {
|
||||
log.debug("A_H_SWAP: required flag is missing");
|
||||
log.debug_f("A_H_SWAP: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::AP_OVERRIDE:
|
||||
@@ -550,12 +550,12 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0);
|
||||
}
|
||||
card->ap = max<int16_t>(card->ap - cond_value, 0);
|
||||
log.debug("AP_OVERRIDE: subtracting %hd from AP => %hd", cond_value, card->ap);
|
||||
log.debug_f("AP_OVERRIDE: subtracting {} from AP => {}", cond_value, card->ap);
|
||||
} else {
|
||||
other_cond->value = clamp<int16_t>(other_cond->value + cond_value, -99, 99);
|
||||
}
|
||||
} else {
|
||||
log.debug("AP_OVERRIDE: required flag is missing");
|
||||
log.debug_f("AP_OVERRIDE: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::TP_OVERRIDE:
|
||||
@@ -567,12 +567,12 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0);
|
||||
}
|
||||
card->tp = max<int16_t>(card->tp - cond_value, 0);
|
||||
log.debug("TP_OVERRIDE: subtracting %hd from TP => %hd", cond_value, card->tp);
|
||||
log.debug_f("TP_OVERRIDE: subtracting {} from TP => {}", cond_value, card->tp);
|
||||
} else {
|
||||
other_cond->value = clamp<int16_t>(other_cond->value + cond_value, -99, 99);
|
||||
}
|
||||
} else {
|
||||
log.debug("TP_OVERRIDE: required flag is missing");
|
||||
log.debug_f("TP_OVERRIDE: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::MISC_AP_BONUSES:
|
||||
@@ -581,9 +581,9 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, -cond_value, 0, 0);
|
||||
}
|
||||
card->ap = max<int16_t>(card->ap - cond_value, 0);
|
||||
log.debug("MISC_AP_BONUSES: subtracting %hd from AP => %hd", cond_value, card->ap);
|
||||
log.debug_f("MISC_AP_BONUSES: subtracting {} from AP => {}", cond_value, card->ap);
|
||||
} else {
|
||||
log.debug("MISC_AP_BONUSES: required flag is missing");
|
||||
log.debug_f("MISC_AP_BONUSES: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::MISC_TP_BONUSES:
|
||||
@@ -592,9 +592,9 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, -cond_value, 0, 0);
|
||||
}
|
||||
card->tp = max<int16_t>(card->tp - cond_value, 0);
|
||||
log.debug("MISC_TP_BONUSES: subtracting %hd from TP => %hd", cond_value, card->tp);
|
||||
log.debug_f("MISC_TP_BONUSES: subtracting {} from TP => {}", cond_value, card->tp);
|
||||
} else {
|
||||
log.debug("MISC_TP_BONUSES: required flag is missing");
|
||||
log.debug_f("MISC_TP_BONUSES: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::AP_SILENCE:
|
||||
@@ -604,9 +604,9 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
if (cond_flags & 2) {
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0xA0, cond_value, 0, 0);
|
||||
card->ap = max<int16_t>(card->ap + cond_value, 0);
|
||||
log.debug("AP_SILENCE: adding %hd to AP => %hd", cond_value, card->ap);
|
||||
log.debug_f("AP_SILENCE: adding {} to AP => {}", cond_value, card->ap);
|
||||
} else {
|
||||
log.debug("AP_SILENCE: required flag is missing");
|
||||
log.debug_f("AP_SILENCE: required flag is missing");
|
||||
}
|
||||
break;
|
||||
case ConditionType::TP_SILENCE:
|
||||
@@ -616,14 +616,14 @@ bool CardSpecial::apply_stat_deltas_to_card_from_condition_and_clear_cond(Condit
|
||||
if (cond_flags & 2) {
|
||||
this->send_6xB4x06_for_stat_delta(card, cond_card_ref, 0x80, cond_value, 0, 0);
|
||||
card->tp = max<int16_t>(card->tp + cond_value, 0);
|
||||
log.debug("TP_SILENCE: adding %hd to TP => %hd", cond_value, card->tp);
|
||||
log.debug_f("TP_SILENCE: adding {} to TP => {}", cond_value, card->tp);
|
||||
} else {
|
||||
log.debug("TP_SILENCE: required flag is missing");
|
||||
log.debug_f("TP_SILENCE: required flag is missing");
|
||||
}
|
||||
break;
|
||||
trial_unimplemented:
|
||||
default:
|
||||
log.debug("%s: no adjustments for condition type", phosg::name_for_enum(cond_type));
|
||||
log.debug_f("{}: no adjustments for condition type", phosg::name_for_enum(cond_type));
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -741,22 +741,22 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
string pa_str = pa.str(s);
|
||||
log.debug("pa=%s, card=@%04hX #%04hX, dice_roll=%hhu, target=@%04hX, condition_giver=@%04hX", pa_str.c_str(), card->get_card_ref(), card->get_card_id(), dice_roll.value, target_card_ref, condition_giver_card_ref);
|
||||
log.debug_f("pa={}, card=@{:04X} #{:04X}, dice_roll={}, target=@{:04X}, condition_giver=@{:04X}", pa_str, card->get_card_ref(), card->get_card_id(), dice_roll.value, target_card_ref, condition_giver_card_ref);
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (!attacker_card && (pa.original_attacker_card_ref != 0xFFFF)) {
|
||||
attacker_card = s->card_for_set_card_ref(pa.original_attacker_card_ref);
|
||||
log.debug("attacker=@%04hX #%04hX (from original)", attacker_card->get_card_ref(), attacker_card->get_card_id());
|
||||
log.debug_f("attacker=@{:04X} #{:04X} (from original)", attacker_card->get_card_ref(), attacker_card->get_card_id());
|
||||
} else if (attacker_card) {
|
||||
log.debug("attacker=@%04hX #%04hX (from set)", attacker_card->get_card_ref(), attacker_card->get_card_id());
|
||||
log.debug_f("attacker=@{:04X} #{:04X} (from set)", attacker_card->get_card_ref(), attacker_card->get_card_id());
|
||||
} else {
|
||||
log.debug("attacker=null (from set)");
|
||||
log.debug_f("attacker=null (from set)");
|
||||
}
|
||||
|
||||
AttackEnvStats ast;
|
||||
|
||||
auto ps = card->player_state();
|
||||
log.debug("base ps = %hhu", ps->client_id);
|
||||
log.debug_f("base ps = {}", ps->client_id);
|
||||
ast.num_set_cards = is_nte ? ps->count_set_cards_for_env_stats_nte() : ps->count_set_cards();
|
||||
auto condition_giver_card = s->card_for_set_card_ref(condition_giver_card_ref);
|
||||
auto target_card = s->card_for_set_card_ref(target_card_ref);
|
||||
@@ -871,8 +871,8 @@ CardSpecial::AttackEnvStats CardSpecial::compute_attack_env_stats(
|
||||
// Note: The (z < 8) conditions in these two loops are not present in the
|
||||
// original code.
|
||||
for (z = 0;
|
||||
((target_card_ref != z_ref) && (z < 8) && ((z_ref = pa.action_card_refs[z]) != 0xFFFF));
|
||||
z++) {
|
||||
((target_card_ref != z_ref) && (z < 8) && ((z_ref = pa.action_card_refs[z]) != 0xFFFF));
|
||||
z++) {
|
||||
}
|
||||
|
||||
ast.action_cards_ap = 0;
|
||||
@@ -1227,9 +1227,9 @@ shared_ptr<Card> CardSpecial::compute_replaced_target_based_on_conditions(
|
||||
|
||||
StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) const {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("compute_stat_swap_type(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
auto log = s->log_stack(std::format("compute_stat_swap_type(@{:04X} #{:04X}): ", card->get_card_ref(), card->get_card_id()));
|
||||
if (!card) {
|
||||
log.debug("card is missing");
|
||||
log.debug_f("card is missing");
|
||||
return StatSwapType::NONE;
|
||||
}
|
||||
|
||||
@@ -1237,33 +1237,33 @@ StatSwapType CardSpecial::compute_stat_swap_type(shared_ptr<const Card> card) co
|
||||
for (size_t cond_index = 0; cond_index < 9; cond_index++) {
|
||||
auto& cond = card->action_chain.conditions[cond_index];
|
||||
if (cond.type != ConditionType::NONE) {
|
||||
auto cond_log = log.sub(phosg::string_printf("(%zu) ", cond_index));
|
||||
auto cond_log = log.sub(std::format("({}) ", cond_index));
|
||||
string cond_str = cond.str(s);
|
||||
cond_log.debug("%s", cond_str.c_str());
|
||||
cond_log.debug_f("{}", cond_str);
|
||||
if (!this->card_ref_has_ability_trap(cond)) {
|
||||
if (cond.type == ConditionType::UNKNOWN_75) {
|
||||
if (ret == StatSwapType::A_H_SWAP) {
|
||||
log.debug("UNKNOWN_75: clearing");
|
||||
log.debug_f("UNKNOWN_75: clearing");
|
||||
ret = StatSwapType::NONE;
|
||||
} else {
|
||||
log.debug("UNKNOWN_75: setting A_H_SWAP");
|
||||
log.debug_f("UNKNOWN_75: setting A_H_SWAP");
|
||||
ret = StatSwapType::A_H_SWAP;
|
||||
}
|
||||
} else if (cond.type == ConditionType::A_T_SWAP) {
|
||||
if (ret == StatSwapType::A_T_SWAP) {
|
||||
log.debug("A_T_SWAP: clearing");
|
||||
log.debug_f("A_T_SWAP: clearing");
|
||||
ret = StatSwapType::NONE;
|
||||
} else {
|
||||
log.debug("A_T_SWAP: setting A_T_SWAP");
|
||||
log.debug_f("A_T_SWAP: setting A_T_SWAP");
|
||||
ret = StatSwapType::A_T_SWAP;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log.debug("skipping due to ability trap");
|
||||
log.debug_f("skipping due to ability trap");
|
||||
}
|
||||
}
|
||||
}
|
||||
log.debug("ret = %zu", static_cast<size_t>(ret));
|
||||
log.debug_f("ret = {}", static_cast<size_t>(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1713,8 +1713,8 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
const char* expr,
|
||||
DiceRoll& dice_roll) const {
|
||||
auto log = this->server()->log_stack("evaluate_effect_expr: ");
|
||||
if (log.min_level == phosg::LogLevel::DEBUG) {
|
||||
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);
|
||||
if (log.min_level == phosg::LogLevel::L_DEBUG) {
|
||||
log.debug_f("ast, expr=\"{}\", dice_roll=(client_id={:02X}, a2={:02X}, value={:02X}, value_used_in_expr={}, a5={:04X})", expr, dice_roll.client_id, dice_roll.unknown_a2, dice_roll.value, dice_roll.value_used_in_expr ? "true" : "false", dice_roll.unknown_a5);
|
||||
ast.print(stderr);
|
||||
}
|
||||
|
||||
@@ -1747,7 +1747,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
// Operators are evaluated left-to-right - there are no operator precedence
|
||||
// rules
|
||||
int32_t value = 0;
|
||||
log.debug("value=%" PRId32 " (start)", value);
|
||||
log.debug_f("value={} (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;
|
||||
@@ -1756,7 +1756,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
}
|
||||
if (token_type == ExpressionTokenType::NUMBER) {
|
||||
value = token_value;
|
||||
log.debug("value=%" PRId32 " (token_type=NUMBER, token_value=%" PRId32 ")", value, token_value);
|
||||
log.debug_f("value={} (token_type=NUMBER, token_value={})", value, token_value);
|
||||
} else {
|
||||
if (token_index >= tokens.size() - 1) {
|
||||
throw runtime_error("no token on right side of binary operator");
|
||||
@@ -1770,23 +1770,23 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
switch (token_type) {
|
||||
case ExpressionTokenType::ROUND_DIVIDE:
|
||||
value = lround(static_cast<double>(value) / right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=ROUND_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug_f("value={} (token_type=ROUND_DIVIDE, right_token_value={})", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::SUBTRACT:
|
||||
value -= right_value;
|
||||
log.debug("value=%" PRId32 " (token_type=SUBTRACT, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug_f("value={} (token_type=SUBTRACT, right_token_value={})", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::ADD:
|
||||
value += right_value;
|
||||
log.debug("value=%" PRId32 " (token_type=ADD, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug_f("value={} (token_type=ADD, right_token_value={})", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::MULTIPLY:
|
||||
value *= right_value;
|
||||
log.debug("value=%" PRId32 " (token_type=MULTIPLY, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug_f("value={} (token_type=MULTIPLY, right_token_value={})", value, right_value);
|
||||
break;
|
||||
case ExpressionTokenType::FLOOR_DIVIDE:
|
||||
value = floor(value / right_value);
|
||||
log.debug("value=%" PRId32 " (token_type=FLOOR_DIVIDE, right_token_value=%" PRId32 ")", value, right_value);
|
||||
log.debug_f("value={} (token_type=FLOOR_DIVIDE, right_token_value={})", value, right_value);
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid binary operator");
|
||||
@@ -1794,7 +1794,7 @@ int32_t CardSpecial::evaluate_effect_expr(
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("value=%" PRId32 " (result)", value);
|
||||
log.debug_f("value={} (result)", value);
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1807,10 +1807,10 @@ bool CardSpecial::execute_effect(
|
||||
uint32_t unknown_p7,
|
||||
uint16_t attacker_card_ref) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("execute_effect(@%04hX #%04hX): ", card->get_card_ref(), card->get_card_id()));
|
||||
auto log = s->log_stack(std::format("execute_effect(@{:04X} #{:04X}): ", card->get_card_ref(), card->get_card_id()));
|
||||
{
|
||||
string cond_str = cond.str(s);
|
||||
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, phosg::name_for_enum(cond_type), unknown_p7, attacker_card_ref);
|
||||
log.debug_f("cond={}, card=@{:04X}, expr_value={}, unknown_p5={}, cond_type={}, unknown_p7={} attacker_card_ref=@{:04X}", cond_str, ref_for_card(card), expr_value, unknown_p5, phosg::name_for_enum(cond_type), unknown_p7, attacker_card_ref);
|
||||
}
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
@@ -1959,7 +1959,7 @@ bool CardSpecial::execute_effect(
|
||||
if (unknown_p7 & 4) {
|
||||
int16_t hp = is_nte ? card->get_current_hp() : clamp<int16_t>(card->get_current_hp(), -99, 99);
|
||||
int16_t new_hp = is_nte ? (hp + positive_expr_value) : clamp<int16_t>(hp + positive_expr_value, -99, 99);
|
||||
log.debug("HEAL: hp=%hd, positive_expr_value=%hd, new_hp=%hd", hp, positive_expr_value, new_hp);
|
||||
log.debug_f("HEAL: hp={}, positive_expr_value={}, new_hp={}", hp, positive_expr_value, new_hp);
|
||||
this->send_6xB4x06_for_stat_delta(card, attacker_card_ref, 0x20, new_hp - hp, true, true);
|
||||
if (new_hp != hp) {
|
||||
card->set_current_hp(new_hp);
|
||||
@@ -2842,8 +2842,8 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
int16_t p_target_type,
|
||||
bool apply_usability_filters) const {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("get_targeted_cards_for_condition(@%04hX, %hhu, @%04hX): ", card_ref, def_effect_index, setter_card_ref));
|
||||
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");
|
||||
auto log = s->log_stack(std::format("get_targeted_cards_for_condition(@{:04X}, {}, @{:04X}): ", card_ref, def_effect_index, setter_card_ref));
|
||||
log.debug_f("card_ref=@{:04X}, def_effect_index={:02X}, setter_card_ref=@{:04X}, as, p_target_type={}, apply_usability_filters={}", card_ref, def_effect_index, setter_card_ref, p_target_type, apply_usability_filters ? "true" : "false");
|
||||
|
||||
vector<shared_ptr<const Card>> ret;
|
||||
|
||||
@@ -2852,12 +2852,12 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (!card1) {
|
||||
card1 = s->card_for_set_card_ref(setter_card_ref);
|
||||
}
|
||||
log.debug("card1=@%04hX", ref_for_card(card1));
|
||||
log.debug_f("card1=@{:04X}", ref_for_card(card1));
|
||||
|
||||
auto card2 = s->card_for_set_card_ref((as.attacker_card_ref == 0xFFFF)
|
||||
? as.original_attacker_card_ref
|
||||
: as.attacker_card_ref);
|
||||
log.debug("card2=@%04hX", ref_for_card(card2));
|
||||
log.debug_f("card2=@{:04X}", ref_for_card(card2));
|
||||
|
||||
Location card1_loc;
|
||||
if (!card1) {
|
||||
@@ -2868,13 +2868,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();
|
||||
log.debug("card1_loc=%s", card1_loc_str.c_str());
|
||||
log.debug_f("card1_loc={}", card1_loc_str);
|
||||
}
|
||||
|
||||
AttackMedium attack_medium = card2
|
||||
? card2->action_chain.chain.attack_medium
|
||||
: AttackMedium::UNKNOWN;
|
||||
log.debug("attack_medium=%s", phosg::name_for_enum(attack_medium));
|
||||
log.debug_f("attack_medium={}", phosg::name_for_enum(attack_medium));
|
||||
|
||||
auto add_card_refs = [&](const vector<uint16_t>& result_card_refs) -> void {
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
@@ -2890,10 +2890,10 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
case 0x05: { // p05
|
||||
auto result_card = s->card_for_set_card_ref(setter_card_ref);
|
||||
if (result_card) {
|
||||
log.debug("(p01/p05) result_card=@%04hX", ref_for_card(result_card));
|
||||
log.debug_f("(p01/p05) result_card=@{:04X}", ref_for_card(result_card));
|
||||
ret.emplace_back(result_card);
|
||||
} else {
|
||||
log.debug("(p01/p05) result_card=null");
|
||||
log.debug_f("(p01/p05) result_card=null");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3073,28 +3073,28 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
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);
|
||||
log23.debug_f("effective range card ID is #{:04X}", range_card_id);
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, s->options.card_index, range_card_id, card1_loc, s->map_and_rules, &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());
|
||||
log23.debug_f("{} result card refs", result_card_refs.size());
|
||||
for (uint16_t result_card_ref : result_card_refs) {
|
||||
auto result_log = log23.subf("(result @%04hX) ", result_card_ref);
|
||||
auto result_log = log23.sub(std::format("(result @{:04X}) ", result_card_ref));
|
||||
auto result_card = s->card_for_set_card_ref(result_card_ref);
|
||||
if (!result_card) {
|
||||
result_log.debug("result card not found");
|
||||
result_log.debug_f("result card not found");
|
||||
} else if (result_card->get_definition()->def.type == CardType::ITEM) {
|
||||
result_log.debug("result card is item");
|
||||
result_log.debug_f("result card is item");
|
||||
} else {
|
||||
result_log.debug("result card found and is not item");
|
||||
result_log.debug_f("result card found and is not item");
|
||||
ret.emplace_back(result_card);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log23.debug("def or ps is missing");
|
||||
log23.debug_f("def or ps is missing");
|
||||
}
|
||||
} else {
|
||||
log23.debug("card1 is missing");
|
||||
log23.debug_f("card1 is missing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3194,28 +3194,28 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
};
|
||||
bool is_nte = s->options.is_nte();
|
||||
if (as.original_attacker_card_ref == 0xFFFF) {
|
||||
log36.debug("original_attacker_card_ref missing");
|
||||
log36.debug_f("original_attacker_card_ref missing");
|
||||
// debug_str_for_card_ref
|
||||
for (size_t z = 0; (z < 4 * 9) && (as.target_card_refs[z] != 0xFFFF); z++) {
|
||||
string debug_ref_str = s->debug_str_for_card_ref(as.target_card_refs[z]);
|
||||
log36.debug("examining %s", debug_ref_str.c_str());
|
||||
log36.debug_f("examining {}", debug_ref_str);
|
||||
auto result_card = s->card_for_set_card_ref(as.target_card_refs[z]);
|
||||
if (result_card && should_include(result_card->get_definition(), is_nte)) {
|
||||
log36.debug("adding %s", debug_ref_str.c_str());
|
||||
log36.debug_f("adding {}", debug_ref_str);
|
||||
ret.emplace_back(result_card);
|
||||
} else {
|
||||
log36.debug("skipping %s", debug_ref_str.c_str());
|
||||
log36.debug_f("skipping {}", debug_ref_str);
|
||||
}
|
||||
}
|
||||
} else if (card2 && should_include(card2->get_definition(), is_nte)) {
|
||||
string debug_ref_str = s->debug_str_for_card_ref(card2->get_card_ref());
|
||||
log36.debug("original_attacker_card_ref present; adding card2 = %s", debug_ref_str.c_str());
|
||||
log36.debug_f("original_attacker_card_ref present; adding card2 = {}", debug_ref_str);
|
||||
ret.emplace_back(card2);
|
||||
} else if (card2) {
|
||||
string debug_ref_str = s->debug_str_for_card_ref(card2->get_card_ref());
|
||||
log36.debug("original_attacker_card_ref present and card2 (%s) not eligible", debug_ref_str.c_str());
|
||||
log36.debug_f("original_attacker_card_ref present and card2 ({}) not eligible", debug_ref_str);
|
||||
} else {
|
||||
log36.debug("original_attacker_card_ref present and card2 missing");
|
||||
log36.debug_f("original_attacker_card_ref present and card2 missing");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -3252,17 +3252,17 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
ret = this->find_all_set_cards_with_cost_in_range(
|
||||
(p_target_type == 0x27) ? 4 : 0,
|
||||
(p_target_type == 0x27) ? 99 : 3);
|
||||
if (log3940.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log3940.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
for (const auto& card : ret) {
|
||||
log3940.debug("found target @%04hX #%04hX", card->get_card_ref(), card->get_card_id());
|
||||
log3940.debug_f("found target @{:04X} #{:04X}", card->get_card_ref(), card->get_card_id());
|
||||
}
|
||||
}
|
||||
if (!s->options.is_nte()) {
|
||||
log3940.debug("filtering targets");
|
||||
log3940.debug_f("filtering targets");
|
||||
ret = this->filter_cards_by_range(ret, card1, card1_loc, card2);
|
||||
if (log3940.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log3940.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
for (const auto& card : ret) {
|
||||
log3940.debug("retained target @%04hX #%04hX", card->get_card_ref(), card->get_card_id());
|
||||
log3940.debug_f("retained target @{:04X} #{:04X}", card->get_card_ref(), card->get_card_id());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3497,9 +3497,9 @@ vector<shared_ptr<const Card>> CardSpecial::get_targeted_cards_for_condition(
|
||||
if (s->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);
|
||||
log.debug("usability filter: kept card @%04hX", ref_for_card(c));
|
||||
log.debug_f("usability filter: kept card @{:04X}", ref_for_card(c));
|
||||
} else {
|
||||
log.debug("usability filter: removed card @%04hX", ref_for_card(c));
|
||||
log.debug_f("usability filter: removed card @{:04X}", ref_for_card(c));
|
||||
}
|
||||
}
|
||||
return filtered_ret;
|
||||
@@ -3526,16 +3526,16 @@ bool CardSpecial::is_card_targeted_by_condition(
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack("is_card_targeted_by_condition: ");
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
log.debug("card=(@%04hX #%04hX)", card->get_card_ref(), card->get_card_id());
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
log.debug_f("card=(@{:04X} #{:04X})", card->get_card_ref(), card->get_card_id());
|
||||
auto cond_str = cond.str(s);
|
||||
auto as_str = as.str(s);
|
||||
log.debug("cond = %s", cond_str.c_str());
|
||||
log.debug("as = %s", as_str.c_str());
|
||||
log.debug_f("cond = {}", cond_str);
|
||||
log.debug_f("as = {}", as_str);
|
||||
}
|
||||
|
||||
if (cond.type == ConditionType::NONE) {
|
||||
log.debug("condition is NONE (=> true)");
|
||||
log.debug_f("condition is NONE (=> true)");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3546,12 +3546,12 @@ bool CardSpecial::is_card_targeted_by_condition(
|
||||
((ce->def.type == CardType::ITEM) || ce->def.is_sc()) &&
|
||||
(cond.remaining_turns != 100) &&
|
||||
(s->options.is_nte() || (client_id_for_card_ref(card->get_card_ref()) == client_id_for_card_ref(cond.card_ref)))) {
|
||||
log.debug("failed item or SC check (=> false)");
|
||||
log.debug_f("failed item or SC check (=> false)");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (cond.remaining_turns != 102) {
|
||||
log.debug("remaining_turns != 102 (=> true)");
|
||||
log.debug_f("remaining_turns != 102 (=> true)");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -3569,15 +3569,15 @@ bool CardSpecial::is_card_targeted_by_condition(
|
||||
0);
|
||||
for (auto c : target_cards) {
|
||||
if (c == card) {
|
||||
log.debug("targeted by p condition (=> true)");
|
||||
log.debug_f("targeted by p condition (=> true)");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
log.debug("not targeted by p condition (=> false)");
|
||||
log.debug_f("not targeted by p condition (=> false)");
|
||||
return false;
|
||||
} else {
|
||||
|
||||
log.debug("SC check does not apply");
|
||||
log.debug_f("SC check does not apply");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -3806,7 +3806,7 @@ size_t CardSpecial::sum_last_attack_damage(
|
||||
size_t damage_count = 0;
|
||||
auto check_card = [&](shared_ptr<const Card> c) -> void {
|
||||
if (c && (c->last_attack_final_damage > 0)) {
|
||||
log.debug("check_card @%04hX #%04hX => %hd", c->get_card_ref(), c->get_card_id(), c->last_attack_final_damage);
|
||||
log.debug_f("check_card @{:04X} #{:04X} => {}", c->get_card_ref(), c->get_card_id(), c->last_attack_final_damage);
|
||||
if (out_damage_sum) {
|
||||
*out_damage_sum += c->last_attack_final_damage;
|
||||
}
|
||||
@@ -4013,13 +4013,13 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
bool apply_defense_condition_to_all_cards,
|
||||
uint16_t apply_defense_condition_to_card_ref) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("evaluate_and_apply_effects(%s, @%04hX, @%04hX): ", phosg::name_for_enum(when), set_card_ref, sc_card_ref));
|
||||
auto log = s->log_stack(std::format("evaluate_and_apply_effects({}, @{:04X}, @{:04X}): ", phosg::name_for_enum(when), set_card_ref, sc_card_ref));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
{
|
||||
string as_str = as.str(s);
|
||||
log.debug("when=%s, set_card_ref=@%04hX, as=%s, sc_card_ref=@%04hX, apply_defense_condition_to_all_cards=%s, apply_defense_condition_to_card_ref=@%04hX",
|
||||
phosg::name_for_enum(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);
|
||||
log.debug_f("when={}, set_card_ref=@{:04X}, as={}, sc_card_ref=@{:04X}, apply_defense_condition_to_all_cards={}, apply_defense_condition_to_card_ref=@{:04X}",
|
||||
phosg::name_for_enum(when), set_card_ref, as_str, sc_card_ref, apply_defense_condition_to_all_cards ? "true" : "false", apply_defense_condition_to_card_ref);
|
||||
}
|
||||
|
||||
if (!is_nte) {
|
||||
@@ -4028,7 +4028,7 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
|
||||
auto ce = this->server()->definition_for_card_ref(set_card_ref);
|
||||
if (!ce) {
|
||||
log.debug("ce missing");
|
||||
log.debug_f("ce missing");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -4076,15 +4076,15 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
dice_roll.unknown_a2 = 3;
|
||||
dice_roll.value_used_in_expr = false;
|
||||
|
||||
log.debug("inputs: dice_roll=%02hhX, random_percent=%hhu, unknown_v1=%s", dice_roll.value, random_percent, unknown_v1 ? "true" : "false");
|
||||
log.debug_f("inputs: dice_roll={:02X}, random_percent={}, unknown_v1={}", 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 = log.sub(phosg::string_printf("(effect:%zu) ", def_effect_index));
|
||||
auto effect_log = log.sub(std::format("(effect:{}) ", 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());
|
||||
effect_log.debug_f("effect: {}", card_effect_str);
|
||||
if (card_effect.when != when) {
|
||||
effect_log.debug("does not apply (effect.when=%s, when=%s)", phosg::name_for_enum(card_effect.when), phosg::name_for_enum(when));
|
||||
effect_log.debug_f("does not apply (effect.when={}, when={})", phosg::name_for_enum(card_effect.when), phosg::name_for_enum(when));
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -4093,18 +4093,18 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
throw runtime_error("card effect arg3 is missing");
|
||||
}
|
||||
int16_t arg3_value = atoi(arg3_s.c_str() + 1);
|
||||
effect_log.debug("arg3_value=%hd", arg3_value);
|
||||
effect_log.debug_f("arg3_value={}", 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());
|
||||
effect_log.debug_f("targeted_cards=[{}]", refs_str);
|
||||
bool all_targets_matched = false;
|
||||
if (!is_nte &&
|
||||
!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");
|
||||
effect_log.debug_f("special targeting applies");
|
||||
size_t count = 0;
|
||||
for (size_t z = 0; z < targeted_cards.size(); z++) {
|
||||
dice_roll.value_used_in_expr = false;
|
||||
@@ -4132,22 +4132,22 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
targeted_cards.clear();
|
||||
}
|
||||
} else {
|
||||
effect_log.debug("special targeting does not apply");
|
||||
effect_log.debug_f("special targeting does not apply");
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < targeted_cards.size(); z++) {
|
||||
auto target_log = effect_log.sub(phosg::string_printf("(target:@%04hX) ", targeted_cards[z]->get_card_ref()));
|
||||
auto target_log = effect_log.sub(std::format("(target:@{:04X}) ", targeted_cards[z]->get_card_ref()));
|
||||
dice_roll.value_used_in_expr = false;
|
||||
string arg2_str = card_effect.arg2.decode();
|
||||
target_log.debug("arg2_str = %s", arg2_str.c_str());
|
||||
target_log.debug_f("arg2_str = {}", arg2_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");
|
||||
target_log.debug_f("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.decode();
|
||||
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);
|
||||
target_log.debug_f("expr = {}, value = {}", expr_str, value);
|
||||
|
||||
uint32_t unknown_v1 = 0;
|
||||
auto target_card = this->compute_replaced_target_based_on_conditions(
|
||||
@@ -4163,16 +4163,16 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
sc_card_ref);
|
||||
if (!target_card) {
|
||||
target_card = targeted_cards[z];
|
||||
target_log.debug("target card (not replaced) = @%04hX", target_card->get_card_ref());
|
||||
target_log.debug_f("target card (not replaced) = @{:04X}", target_card->get_card_ref());
|
||||
} else {
|
||||
target_log.debug("target card (replaced) = @%04hX", target_card->get_card_ref());
|
||||
target_log.debug_f("target card (replaced) = @{:04X}", 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");
|
||||
target_log.debug_f("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);
|
||||
}
|
||||
@@ -4202,12 +4202,12 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
if (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_log.debug_f("applied defense condition");
|
||||
}
|
||||
}
|
||||
target_card->send_6xB4x4E_4C_4D_if_needed(0);
|
||||
} else {
|
||||
target_log.debug("arg2 condition failed");
|
||||
target_log.debug_f("arg2 condition failed");
|
||||
}
|
||||
if (dice_roll.value_used_in_expr) {
|
||||
any_expr_used_dice_roll = true;
|
||||
@@ -4712,73 +4712,73 @@ vector<shared_ptr<const Card>> CardSpecial::filter_cards_by_range(
|
||||
shared_ptr<const Card> card2) const {
|
||||
auto log = this->server()->log_stack("filter_cards_by_range: ");
|
||||
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
auto card1_str = card1 ? phosg::string_printf("@%04hX #%04hX", card1->get_card_ref(), card1->get_card_id()) : "null";
|
||||
auto card2_str = card2 ? phosg::string_printf("@%04hX #%04hX", card2->get_card_ref(), card2->get_card_id()) : "null";
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
auto card1_str = card1 ? std::format("@{:04X} #{:04X}", card1->get_card_ref(), card1->get_card_id()) : "null";
|
||||
auto card2_str = card2 ? std::format("@{:04X} #{:04X}", card2->get_card_ref(), card2->get_card_id()) : "null";
|
||||
auto loc_str = card1_loc.str();
|
||||
log.debug("card1=(%s), card2=(%s), loc=%s", card1_str.c_str(), card2_str.c_str(), loc_str.c_str());
|
||||
log.debug_f("card1=({}), card2=({}), loc={}", card1_str, card2_str, loc_str);
|
||||
|
||||
for (const auto& card : cards) {
|
||||
if (card) {
|
||||
log.debug("input card: @%04hX #%04hX", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("input card: @{:04X} #{:04X}", card->get_card_ref(), card->get_card_id());
|
||||
} else {
|
||||
log.debug("input card: null");
|
||||
log.debug_f("input card: null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
vector<shared_ptr<const Card>> ret;
|
||||
if (!card1 || cards.empty()) {
|
||||
log.debug("card1 missing or input list is blank");
|
||||
log.debug_f("card1 missing or input list is blank");
|
||||
return ret;
|
||||
}
|
||||
|
||||
auto ps = card1->player_state();
|
||||
if (!ps) {
|
||||
log.debug("ps is missing");
|
||||
log.debug_f("ps is missing");
|
||||
return ret;
|
||||
}
|
||||
|
||||
// TODO: Remove hardcoded card ID here (Earthquake)
|
||||
uint16_t card_id = this->get_card_id_with_effective_range(card1, 0x00ED, card2);
|
||||
log.debug("card_id = #%04hX", card_id);
|
||||
log.debug_f("card_id = #{:04X}", card_id);
|
||||
|
||||
parray<uint8_t, 9 * 9> range;
|
||||
compute_effective_range(range, this->server()->options.card_index, card_id, card1_loc, this->server()->map_and_rules);
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
auto loc_str = card1_loc.str();
|
||||
log.debug("compute_effective_range(range, ci, #%04hX, %s, map) =>", card_id, loc_str.c_str());
|
||||
log.debug_f("compute_effective_range(range, ci, #{:04X}, {}, map) =>", card_id, loc_str);
|
||||
for (size_t y = 0; y < 9; y++) {
|
||||
const uint8_t* row = &range[y * 9];
|
||||
log.debug(" range[%zu] = %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX",
|
||||
log.debug_f(" range[{}] = {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X} {:02X}",
|
||||
y, row[0], row[1], row[2], row[3], row[4], row[5], row[6], row[7], row[8]);
|
||||
}
|
||||
}
|
||||
|
||||
auto card_refs_in_range = ps->get_card_refs_within_range_from_all_players(range, card1_loc, CardType::ITEM);
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
for (uint16_t card_ref : card_refs_in_range) {
|
||||
log.debug("ref in range: @%04hX", card_ref);
|
||||
log.debug_f("ref in range: @{:04X}", card_ref);
|
||||
}
|
||||
}
|
||||
|
||||
for (auto card : cards) {
|
||||
if (!card || (card->get_card_ref() == 0xFFFF)) {
|
||||
if (card) {
|
||||
log.debug("(@%04hX #%04hX) out of range", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("(@{:04X} #{:04X}) out of range", card->get_card_ref(), card->get_card_id());
|
||||
} else {
|
||||
log.debug("(null) card missing");
|
||||
log.debug_f("(null) card missing");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
for (uint16_t card_ref_in_range : card_refs_in_range) {
|
||||
if (card_ref_in_range == card->get_card_ref()) {
|
||||
log.debug("(@%04hX #%04hX) in range", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("(@{:04X} #{:04X}) in range", card->get_card_ref(), card->get_card_id());
|
||||
ret.emplace_back(card);
|
||||
break;
|
||||
}
|
||||
}
|
||||
log.debug("(@%04hX #%04hX) out of range", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("(@{:04X} #{:04X}) out of range", card->get_card_ref(), card->get_card_id());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -4787,7 +4787,7 @@ void CardSpecial::apply_effects_after_attack_target_resolution(const ActionState
|
||||
auto s = this->server();
|
||||
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());
|
||||
log.debug_f("as={}", as_str);
|
||||
|
||||
for (size_t z = 0; (z < 8) && (as.action_card_refs[z] != 0xFFFF); z++) {
|
||||
uint16_t card_ref = this->send_6xB4x06_if_card_ref_invalid(as.action_card_refs[z], 0x1E);
|
||||
@@ -4878,7 +4878,7 @@ void CardSpecial::dice_phase_before_for_card(shared_ptr<Card> card) {
|
||||
template <EffectWhen When1, EffectWhen When2>
|
||||
void CardSpecial::apply_effects_on_phase_change_t(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("apply_effects_on_phase_change_t<%s, %s>(@%04hX #%04hX): ", phosg::name_for_enum(When1), phosg::name_for_enum(When2), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
auto log = s->log_stack(std::format("apply_effects_on_phase_change_t<{}, {}>(@{:04X} #{:04X}): ", phosg::name_for_enum(When1), phosg::name_for_enum(When2), unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
ActionState as;
|
||||
@@ -4929,7 +4929,7 @@ void CardSpecial::unknown_8024945C(shared_ptr<Card> unknown_p2, const ActionStat
|
||||
}
|
||||
|
||||
void CardSpecial::unknown_8024966C(shared_ptr<Card> unknown_p2, const ActionState* existing_as) {
|
||||
auto log = this->server()->log_stack(phosg::string_printf("unknown_8024966C(@%04hX #%04hX): ", unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
auto log = this->server()->log_stack(std::format("unknown_8024966C(@{:04X} #{:04X}): ", unknown_p2->get_card_ref(), unknown_p2->get_card_id()));
|
||||
|
||||
ActionState as;
|
||||
if (!existing_as) {
|
||||
@@ -5080,7 +5080,7 @@ template <
|
||||
EffectWhen WhenTargetsAndActionCards>
|
||||
void CardSpecial::apply_effects_before_or_after_attack(shared_ptr<Card> unknown_p2) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(phosg::string_printf("apply_effects_before_or_after_attack<%s, %s, %s, %s>(@%04hX #%04hX): ",
|
||||
auto log = s->log_stack(std::format("apply_effects_before_or_after_attack<{}, {}, {}, {}>(@{:04X} #{:04X}): ",
|
||||
phosg::name_for_enum(WhenAllCards), phosg::name_for_enum(WhenAttackerAndActionCards), phosg::name_for_enum(WhenAttackerOrHunterSCCard), phosg::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);
|
||||
|
||||
+295
-292
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
|
||||
#include <array>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <phosg/Encoding.hh>
|
||||
@@ -1566,8 +1567,8 @@ public:
|
||||
std::shared_ptr<const CardEntry> definition_for_name(const std::string& name) const;
|
||||
std::shared_ptr<const CardEntry> definition_for_name_normalized(const std::string& name) const;
|
||||
std::set<uint32_t> all_ids() const;
|
||||
uint64_t definitions_mtime() const;
|
||||
phosg::JSON definitions_json() const;
|
||||
uint64_t definitions_hash() const;
|
||||
|
||||
private:
|
||||
static std::string normalize_card_name(const std::string& name);
|
||||
@@ -1576,7 +1577,7 @@ private:
|
||||
std::unordered_map<uint32_t, std::shared_ptr<CardEntry>> card_definitions;
|
||||
std::unordered_map<std::string, std::shared_ptr<CardEntry>> card_definitions_by_name;
|
||||
std::unordered_map<std::string, std::shared_ptr<CardEntry>> card_definitions_by_name_normalized;
|
||||
uint64_t mtime_for_card_definitions;
|
||||
uint64_t defs_hash;
|
||||
};
|
||||
|
||||
class MapIndex {
|
||||
|
||||
@@ -187,7 +187,7 @@ void DeckState::restart() {
|
||||
this->shuffle();
|
||||
}
|
||||
|
||||
void DeckState::do_mulligan(bool is_nte) {
|
||||
void DeckState::redraw_initial_hand(bool is_nte) {
|
||||
for (size_t z = 0; z < this->entries.size(); z++) {
|
||||
if (this->entries[z].state == CardState::DISCARDED) {
|
||||
this->entries[z].state = CardState::DRAWABLE;
|
||||
@@ -308,7 +308,7 @@ static const char* name_for_card_state(DeckState::CardState st) {
|
||||
}
|
||||
|
||||
void DeckState::print(FILE* stream, std::shared_ptr<const CardIndex> card_index) const {
|
||||
fprintf(stream, "DeckState: client_id=%hhu draw_index=%hhu card_ref_base=@%04hX shuffle=%s loop=%s\n",
|
||||
phosg::fwrite_fmt(stream, "DeckState: client_id={} draw_index={} card_ref_base=@{:04X} shuffle={} loop={}\n",
|
||||
this->client_id, this->draw_index, this->card_ref_base, this->shuffle_enabled ? "true" : "false", this->loop_enabled ? "true" : "false");
|
||||
for (size_t z = 0; z < 31; z++) {
|
||||
const auto& e = this->entries[z];
|
||||
@@ -321,10 +321,10 @@ void DeckState::print(FILE* stream, std::shared_ptr<const CardIndex> card_index)
|
||||
}
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode(1);
|
||||
fprintf(stream, " (%02zu) index=%02hhX ref=@%04hX card_id=#%04hX \"%s\" %s\n",
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, name.c_str(), name_for_card_state(e.state));
|
||||
phosg::fwrite_fmt(stream, " ({:02}) index={:02X} ref=@{:04X} card_id=#{:04X} \"{}\" {}\n",
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, name, name_for_card_state(e.state));
|
||||
} else {
|
||||
fprintf(stream, " (%02zu) index=%02hhX ref=@%04hX card_id=#%04hX %s\n",
|
||||
phosg::fwrite_fmt(stream, " ({:02}) index={:02X} ref=@{:04X} card_id=#{:04X} {}\n",
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, name_for_card_state(e.state));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
|
||||
void restart();
|
||||
void shuffle();
|
||||
void do_mulligan(bool is_nte);
|
||||
void redraw_initial_hand(bool is_nte);
|
||||
|
||||
void print(FILE* stream, std::shared_ptr<const CardIndex> card_index = nullptr) const;
|
||||
|
||||
|
||||
@@ -20,11 +20,11 @@ void MapState::clear() {
|
||||
}
|
||||
|
||||
void MapState::print(FILE* stream) const {
|
||||
fprintf(stream, "[Map: w=%hu h=%hu]\n", this->width.load(), this->height.load());
|
||||
phosg::fwrite_fmt(stream, "[Map: w={} h={}]\n", this->width, this->height);
|
||||
for (size_t y = 0; y < this->height; y++) {
|
||||
fputc(' ', stream);
|
||||
for (size_t x = 0; x < this->width; x++) {
|
||||
fprintf(stream, " %02hhX", this->tiles[y][x]);
|
||||
phosg::fwrite_fmt(stream, " {:02X}", this->tiles[y][x]);
|
||||
}
|
||||
fputc('\n', stream);
|
||||
}
|
||||
|
||||
+21
-21
@@ -9,7 +9,7 @@ namespace Episode3 {
|
||||
PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
client_id(client_id),
|
||||
num_mulligans_allowed(1),
|
||||
num_hand_redraws_allowed(1),
|
||||
sc_card_type(CardType::HUNTERS_SC),
|
||||
team_id(0xFF),
|
||||
atk_points(0),
|
||||
@@ -705,14 +705,14 @@ void PlayerState::discard_set_assist_card() {
|
||||
s->destroy_cards_with_zero_hp();
|
||||
}
|
||||
|
||||
bool PlayerState::do_mulligan() {
|
||||
if (!this->is_mulligan_allowed()) {
|
||||
bool PlayerState::redraw_initial_hand() {
|
||||
if (!this->is_hand_redraw_allowed()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto s = this->server();
|
||||
|
||||
this->num_mulligans_allowed--;
|
||||
this->num_hand_redraws_allowed--;
|
||||
while (this->card_refs[0] != 0xFFFF) {
|
||||
this->discard_ref_from_hand(this->card_refs[0]);
|
||||
}
|
||||
@@ -727,7 +727,7 @@ bool PlayerState::do_mulligan() {
|
||||
s->send(cmd);
|
||||
}
|
||||
|
||||
this->deck_state->do_mulligan(s->options.is_nte());
|
||||
this->deck_state->redraw_initial_hand(s->options.is_nte());
|
||||
this->draw_hand(5);
|
||||
|
||||
if (!s->options.is_nte()) {
|
||||
@@ -841,7 +841,7 @@ vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
|
||||
auto log = s->log_stack("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);
|
||||
log.debug_f("loc={}, target_team_id={:02X}", loc_str, target_team_id);
|
||||
|
||||
vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
@@ -939,8 +939,8 @@ size_t PlayerState::set_index_for_card_ref(uint16_t card_ref) const {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool PlayerState::is_mulligan_allowed() const {
|
||||
return (this->num_mulligans_allowed > 0);
|
||||
bool PlayerState::is_hand_redraw_allowed() const {
|
||||
return (this->num_hand_redraws_allowed > 0);
|
||||
}
|
||||
|
||||
bool PlayerState::is_team_turn() const {
|
||||
@@ -1766,20 +1766,20 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
|
||||
auto attacker_card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (attacker_card) {
|
||||
log.debug("attacker card present");
|
||||
log.debug_f("attacker card present");
|
||||
attacker_card->card_flags |= 0x100;
|
||||
}
|
||||
|
||||
auto action_type = s->ruler_server->get_pending_action_type(pa);
|
||||
if (action_type == ActionType::DEFENSE) {
|
||||
log.debug("action type is DEFENSE");
|
||||
log.debug_f("action type is DEFENSE");
|
||||
} else if (action_type == ActionType::ATTACK) {
|
||||
log.debug("action type is ATTACK");
|
||||
log.debug_f("action type is ATTACK");
|
||||
} else {
|
||||
log.debug("action type is UNKNOWN");
|
||||
log.debug_f("action type is UNKNOWN");
|
||||
}
|
||||
if (!is_nte) {
|
||||
log.debug("(non-nte) subtracting action points");
|
||||
log.debug_f("(non-nte) subtracting action points");
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, true);
|
||||
}
|
||||
|
||||
@@ -1787,7 +1787,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
auto card = s->card_for_set_card_ref(pa.attacker_card_ref);
|
||||
if (card) {
|
||||
card->loc.direction = pa.facing_direction;
|
||||
log.debug("set facing direction to %s", phosg::name_for_enum(card->loc.direction));
|
||||
log.debug_f("set facing direction to {}", phosg::name_for_enum(card->loc.direction));
|
||||
|
||||
G_AddToSetCardLog_Ep3_6xB4x4A cmd;
|
||||
cmd.card_refs.clear(0xFFFF);
|
||||
@@ -1796,9 +1796,9 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
cmd.entry_count = 0;
|
||||
size_t z = 0;
|
||||
do {
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug("on action card ref %s", ref_str.c_str());
|
||||
log.debug_f("on action card ref {}", ref_str);
|
||||
}
|
||||
card->unknown_80237A90(pa, pa.action_card_refs[z]);
|
||||
card->unknown_802379BC(pa.action_card_refs[z]);
|
||||
@@ -1833,9 +1833,9 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
|
||||
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
if (target_card) {
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.target_card_refs[z]);
|
||||
log.debug("on target card ref %s", ref_str.c_str());
|
||||
log.debug_f("on target card ref {}", ref_str);
|
||||
}
|
||||
target_card->unknown_802379DC(pa);
|
||||
if (!is_nte) {
|
||||
@@ -1859,13 +1859,13 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
}
|
||||
}
|
||||
if (is_nte) {
|
||||
log.debug("(nte) subtracting action points");
|
||||
log.debug_f("(nte) subtracting action points");
|
||||
this->subtract_or_check_atk_or_def_points_for_action(pa, 1);
|
||||
}
|
||||
for (size_t z = 0; (z < pa.action_card_refs.size()) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug("discarding %s from hand", ref_str.c_str());
|
||||
log.debug_f("discarding {} from hand", ref_str);
|
||||
}
|
||||
this->discard_ref_from_hand(pa.action_card_refs[z]);
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
void discard_random_hand_card();
|
||||
bool discard_ref_from_hand(uint16_t card_ref);
|
||||
void discard_set_assist_card();
|
||||
bool do_mulligan();
|
||||
bool redraw_initial_hand();
|
||||
void draw_hand(ssize_t override_count = 0);
|
||||
void draw_initial_hand();
|
||||
int32_t error_code_for_client_setting_card(
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
uint8_t get_team_id() const;
|
||||
ssize_t hand_index_for_card_ref(uint16_t card_ref) const;
|
||||
size_t set_index_for_card_ref(uint16_t card_ref) const;
|
||||
bool is_mulligan_allowed() const;
|
||||
bool is_hand_redraw_allowed() const;
|
||||
bool is_team_turn() const;
|
||||
void log_discard(uint16_t card_ref, uint16_t reason);
|
||||
uint16_t pop_from_discard_log(uint16_t reason);
|
||||
@@ -152,7 +152,7 @@ public:
|
||||
std::shared_ptr<Card> sc_card;
|
||||
bcarray<std::shared_ptr<Card>, 8> set_cards;
|
||||
uint8_t client_id;
|
||||
uint16_t num_mulligans_allowed;
|
||||
uint16_t num_hand_redraws_allowed;
|
||||
CardType sc_card_type;
|
||||
uint8_t team_id;
|
||||
uint8_t atk_points;
|
||||
|
||||
@@ -64,19 +64,19 @@ void Condition::clear_FF() {
|
||||
std::string Condition::str(shared_ptr<const Server> s) const {
|
||||
auto card_ref_str = s->debug_str_for_card_ref(this->card_ref);
|
||||
auto giver_ref_str = s->debug_str_for_card_ref(this->condition_giver_card_ref);
|
||||
return phosg::string_printf(
|
||||
"Condition[type=%s, turns=%hhu, a_arg=%hhd, dice=%hhu, flags=%02hhX, "
|
||||
"def_eff_index=%hhu, ref=%s, value=%hd, giver_ref=%s "
|
||||
"percent=%hhu value8=%hd order=%hu a8=%hu]",
|
||||
return std::format(
|
||||
"Condition[type={}, turns={}, a_arg={}, dice={}, flags={:02X}, "
|
||||
"def_eff_index={}, ref={}, value={}, giver_ref={} "
|
||||
"percent={} value8={} order={} a8={}]",
|
||||
phosg::name_for_enum(this->type),
|
||||
this->remaining_turns,
|
||||
this->a_arg_value,
|
||||
this->dice_roll_value,
|
||||
this->flags,
|
||||
this->card_definition_effect_index,
|
||||
card_ref_str.c_str(),
|
||||
this->value.load(),
|
||||
giver_ref_str.c_str(),
|
||||
card_ref_str,
|
||||
this->value,
|
||||
giver_ref_str,
|
||||
this->random_percent,
|
||||
this->value8,
|
||||
this->order,
|
||||
@@ -103,12 +103,12 @@ void EffectResult::clear() {
|
||||
std::string EffectResult::str(shared_ptr<const Server> s) const {
|
||||
string attacker_ref_str = s->debug_str_for_card_ref(this->attacker_card_ref);
|
||||
string target_ref_str = s->debug_str_for_card_ref(this->target_card_ref);
|
||||
return phosg::string_printf(
|
||||
"EffectResult[att_ref=%s, target_ref=%s, value=%hhd, "
|
||||
"cur_hp=%hhd, ap=%hhd, tp=%hhd, flags=%02hhX, op=%hhd, "
|
||||
"cond_index=%hhu, dice=%hhu]",
|
||||
attacker_ref_str.c_str(),
|
||||
target_ref_str.c_str(),
|
||||
return std::format(
|
||||
"EffectResult[att_ref={}, target_ref={}, value={}, "
|
||||
"cur_hp={}, ap={}, tp={}, flags={:02X}, op={}, "
|
||||
"cond_index={}, dice={}]",
|
||||
attacker_ref_str,
|
||||
target_ref_str,
|
||||
this->value,
|
||||
this->current_hp,
|
||||
this->ap,
|
||||
@@ -139,14 +139,14 @@ bool CardShortStatus::operator!=(const CardShortStatus& other) const {
|
||||
std::string CardShortStatus::str(shared_ptr<const Server> s) const {
|
||||
string loc_s = this->loc.str();
|
||||
string ref_str = s->debug_str_for_card_ref(this->card_ref);
|
||||
return phosg::string_printf(
|
||||
"CardShortStatus[ref=%s, cur_hp=%hd, flags=%08" PRIX32 ", loc=%s, "
|
||||
"u1=%04hX, max_hp=%hhd, u2=%hhu]",
|
||||
ref_str.c_str(),
|
||||
this->current_hp.load(),
|
||||
this->card_flags.load(),
|
||||
loc_s.c_str(),
|
||||
this->unused1.load(),
|
||||
return std::format(
|
||||
"CardShortStatus[ref={}, cur_hp={}, flags={:08X}, loc={}, "
|
||||
"u1={:04X}, max_hp={}, u2={}]",
|
||||
ref_str,
|
||||
this->current_hp,
|
||||
this->card_flags,
|
||||
loc_s,
|
||||
this->unused1,
|
||||
this->max_hp,
|
||||
this->unused2);
|
||||
}
|
||||
@@ -193,18 +193,18 @@ std::string ActionState::str(shared_ptr<const Server> s) const {
|
||||
string original_attacker_ref_s = s->debug_str_for_card_ref(this->original_attacker_card_ref);
|
||||
string target_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
string action_refs_s = s->debug_str_for_card_refs(this->action_card_refs);
|
||||
return phosg::string_printf(
|
||||
"ActionState[client=%hX, u=%hhu, facing=%s, attacker_ref=%s, "
|
||||
"def_ref=%s, target_refs=%s, action_refs=%s, "
|
||||
"orig_attacker_ref=%s]",
|
||||
this->client_id.load(),
|
||||
return std::format(
|
||||
"ActionState[client={:X}, u={}, facing={}, attacker_ref={}, "
|
||||
"def_ref={}, target_refs={}, action_refs={}, "
|
||||
"orig_attacker_ref={}]",
|
||||
this->client_id,
|
||||
this->unused,
|
||||
phosg::name_for_enum(this->facing_direction),
|
||||
attacker_ref_s.c_str(),
|
||||
defense_ref_s.c_str(),
|
||||
target_refs_s.c_str(),
|
||||
action_refs_s.c_str(),
|
||||
original_attacker_ref_s.c_str());
|
||||
attacker_ref_s,
|
||||
defense_ref_s,
|
||||
target_refs_s,
|
||||
action_refs_s,
|
||||
original_attacker_ref_s);
|
||||
}
|
||||
|
||||
ActionChain::ActionChain() {
|
||||
@@ -243,20 +243,20 @@ std::string ActionChain::str(shared_ptr<const Server> s) const {
|
||||
string unknown_card_ref_a3_s = s->debug_str_for_card_ref(this->unknown_card_ref_a3);
|
||||
string attack_action_card_refs_s = s->debug_str_for_card_refs(this->attack_action_card_refs);
|
||||
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
return phosg::string_printf(
|
||||
"ActionChain[eff_ap=%hhd, eff_tp=%hhd, ap_bonus=%hhd, damage=%hhd, "
|
||||
"acting_ref=%s, unknown_ref_a3=%s, attack_action_refs=%s, "
|
||||
"attack_action_ref_count=%hhu, medium=%s, target_ref_count=%hhu, "
|
||||
"subphase=%s, strikes=%hhu, damage_mult=%hhd, attack_num=%hhu, "
|
||||
"tp_bonus=%hhd, phys_bonus_nte=%hhu, tech_bonus_nte=%hhu, card_ap=%hhd, "
|
||||
"card_tp=%hhd, flags=%08" PRIX32 ", target_refs=%s]",
|
||||
return std::format(
|
||||
"ActionChain[eff_ap={}, eff_tp={}, ap_bonus={}, damage={}, "
|
||||
"acting_ref={}, unknown_ref_a3={}, attack_action_refs={}, "
|
||||
"attack_action_ref_count={}, medium={}, target_ref_count={}, "
|
||||
"subphase={}, strikes={}, damage_mult={}, attack_num={}, "
|
||||
"tp_bonus={}, phys_bonus_nte={}, tech_bonus_nte={}, card_ap={}, "
|
||||
"card_tp={}, flags={:08X}, target_refs={}]",
|
||||
this->effective_ap,
|
||||
this->effective_tp,
|
||||
this->ap_effect_bonus,
|
||||
this->damage,
|
||||
acting_card_ref_s.c_str(),
|
||||
unknown_card_ref_a3_s.c_str(),
|
||||
attack_action_card_refs_s.c_str(),
|
||||
acting_card_ref_s,
|
||||
unknown_card_ref_a3_s,
|
||||
attack_action_card_refs_s,
|
||||
this->attack_action_card_ref_count,
|
||||
phosg::name_for_enum(this->attack_medium),
|
||||
this->target_card_ref_count,
|
||||
@@ -269,8 +269,8 @@ std::string ActionChain::str(shared_ptr<const Server> s) const {
|
||||
this->tech_attack_bonus_nte,
|
||||
this->card_ap,
|
||||
this->card_tp,
|
||||
this->flags.load(),
|
||||
target_card_refs_s.c_str());
|
||||
this->flags,
|
||||
target_card_refs_s);
|
||||
}
|
||||
|
||||
void ActionChain::clear() {
|
||||
@@ -341,7 +341,7 @@ std::string ActionChainWithConds::str(shared_ptr<const Server> s) const {
|
||||
if (ret.back() != '[') {
|
||||
ret += ", ";
|
||||
}
|
||||
ret += phosg::string_printf("%zu:", z);
|
||||
ret += std::format("{}:", z);
|
||||
ret += this->conditions[z].str(s);
|
||||
}
|
||||
}
|
||||
@@ -580,22 +580,22 @@ std::string ActionMetadata::str(shared_ptr<const Server> s) const {
|
||||
string target_card_refs_s = s->debug_str_for_card_refs(this->target_card_refs);
|
||||
string defense_card_refs_s = s->debug_str_for_card_refs(this->defense_card_refs);
|
||||
string original_attacker_card_refs_s = s->debug_str_for_card_refs(this->original_attacker_card_refs);
|
||||
return phosg::string_printf(
|
||||
"ActionMetadata[ref=%s, target_ref_count=%hhu, def_ref_count=%hhu, "
|
||||
"subphase=%s, def_power=%hhd, def_bonus=%hhd, "
|
||||
"att_bonus=%hhd, flags=%08" PRIX32 ", target_refs=%s, "
|
||||
"defense_refs=%s, original_attacker_refs=%s]",
|
||||
card_ref_s.c_str(),
|
||||
return std::format(
|
||||
"ActionMetadata[ref={}, target_ref_count={}, def_ref_count={}, "
|
||||
"subphase={}, def_power={}, def_bonus={}, "
|
||||
"att_bonus={}, flags={:08X}, target_refs={}, "
|
||||
"defense_refs={}, original_attacker_refs={}]",
|
||||
card_ref_s,
|
||||
this->target_card_ref_count,
|
||||
this->defense_card_ref_count,
|
||||
phosg::name_for_enum(this->action_subphase),
|
||||
this->defense_power,
|
||||
this->defense_bonus,
|
||||
this->attack_bonus,
|
||||
this->flags.load(),
|
||||
target_card_refs_s.c_str(),
|
||||
defense_card_refs_s.c_str(),
|
||||
original_attacker_card_refs_s.c_str());
|
||||
this->flags,
|
||||
target_card_refs_s,
|
||||
defense_card_refs_s,
|
||||
original_attacker_card_refs_s);
|
||||
}
|
||||
|
||||
void ActionMetadata::clear() {
|
||||
@@ -683,13 +683,13 @@ std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
|
||||
string set_card_refs_s = s->debug_str_for_card_refs(this->set_card_refs);
|
||||
string hand_card_refs2_s = s->debug_str_for_card_refs(this->hand_card_refs2);
|
||||
string set_card_refs2_s = s->debug_str_for_card_refs(this->set_card_refs2);
|
||||
return phosg::string_printf(
|
||||
"HandAndEquipState[dice=[%hhu, %hhu], atk=%hhu, def=%hhu, atk2=%hhu, "
|
||||
"a1=%hhu, total_set_cost=%hhu, is_cpu=%hhu, assist_flags=%08" PRIX32 ", "
|
||||
"hand_refs=%s, assist_ref=%s, set_refs=%s, sc_ref=%s, hand_refs2=%s, "
|
||||
"set_refs2=%s, assist_ref2=%s, assist_set_num=%hu, assist_card_id=%s, "
|
||||
"assist_turns=%hhu, assist_delay=%hhu, atk_bonus=%hhu, def_bonus=%hhu, "
|
||||
"u2=[%hhu, %hhu]]",
|
||||
return std::format(
|
||||
"HandAndEquipState[dice=[{}, {}], atk={}, def={}, atk2={}, "
|
||||
"a1={}, total_set_cost={}, is_cpu={}, assist_flags={:08X}, "
|
||||
"hand_refs={}, assist_ref={}, set_refs={}, sc_ref={}, hand_refs2={}, "
|
||||
"set_refs2={}, assist_ref2={}, assist_set_num={}, assist_card_id={}, "
|
||||
"assist_turns={}, assist_delay={}, atk_bonus={}, def_bonus={}, "
|
||||
"u2=[{}, {}]]",
|
||||
this->dice_results[0],
|
||||
this->dice_results[1],
|
||||
this->atk_points,
|
||||
@@ -698,16 +698,16 @@ std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
|
||||
this->unknown_a1,
|
||||
this->total_set_cards_cost,
|
||||
this->is_cpu_player,
|
||||
this->assist_flags.load(),
|
||||
hand_card_refs_s.c_str(),
|
||||
assist_card_ref_s.c_str(),
|
||||
set_card_refs_s.c_str(),
|
||||
sc_card_ref_s.c_str(),
|
||||
hand_card_refs2_s.c_str(),
|
||||
set_card_refs2_s.c_str(),
|
||||
assist_card_ref2_s.c_str(),
|
||||
this->assist_card_set_number.load(),
|
||||
assist_card_id_s.c_str(),
|
||||
this->assist_flags,
|
||||
hand_card_refs_s,
|
||||
assist_card_ref_s,
|
||||
set_card_refs_s,
|
||||
sc_card_ref_s,
|
||||
hand_card_refs2_s,
|
||||
set_card_refs2_s,
|
||||
assist_card_ref2_s,
|
||||
this->assist_card_set_number,
|
||||
assist_card_id_s,
|
||||
this->assist_remaining_turns,
|
||||
this->assist_delay_turns,
|
||||
this->atk_bonuses,
|
||||
@@ -838,19 +838,19 @@ const char* PlayerBattleStats::name_for_rank(uint8_t rank) {
|
||||
}
|
||||
|
||||
PlayerBattleStatsTrial::PlayerBattleStatsTrial(const PlayerBattleStats& data)
|
||||
: damage_given(data.damage_given.load()),
|
||||
damage_taken(data.damage_taken.load()),
|
||||
num_opponent_cards_destroyed(data.num_opponent_cards_destroyed.load()),
|
||||
num_owned_cards_destroyed(data.num_owned_cards_destroyed.load()),
|
||||
total_move_distance(data.total_move_distance.load()) {}
|
||||
: damage_given(data.damage_given),
|
||||
damage_taken(data.damage_taken),
|
||||
num_opponent_cards_destroyed(data.num_opponent_cards_destroyed),
|
||||
num_owned_cards_destroyed(data.num_owned_cards_destroyed),
|
||||
total_move_distance(data.total_move_distance) {}
|
||||
|
||||
PlayerBattleStatsTrial::operator PlayerBattleStats() const {
|
||||
PlayerBattleStats ret;
|
||||
ret.damage_given = this->damage_given.load();
|
||||
ret.damage_taken = this->damage_taken.load();
|
||||
ret.num_opponent_cards_destroyed = this->num_opponent_cards_destroyed.load();
|
||||
ret.num_owned_cards_destroyed = this->num_owned_cards_destroyed.load();
|
||||
ret.total_move_distance = this->total_move_distance.load();
|
||||
ret.damage_given = this->damage_given;
|
||||
ret.damage_taken = this->damage_taken;
|
||||
ret.num_opponent_cards_destroyed = this->num_opponent_cards_destroyed;
|
||||
ret.num_owned_cards_destroyed = this->num_owned_cards_destroyed;
|
||||
ret.total_move_distance = this->total_move_distance;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -861,26 +861,26 @@ static bool is_card_within_range(
|
||||
phosg::PrefixedLogger* log) {
|
||||
if (ss.card_ref == 0xFFFF) {
|
||||
if (log) {
|
||||
log->debug("is_card_within_range: (false) ss.card_ref missing");
|
||||
log->debug_f("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");
|
||||
log->debug_f("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);
|
||||
log->debug_f("is_card_within_range: (false) outside x range (ss.loc.x={}, anchor_loc.x={})", 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);
|
||||
log->debug_f("is_card_within_range: (false) outside y range (ss.loc.y={}, anchor_loc.y={})", ss.loc.y, anchor_loc.y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -889,7 +889,7 @@ static bool is_card_within_range(
|
||||
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))",
|
||||
log->debug_f("is_card_within_range: ({}) (ss.loc=({},{}), anchor_loc=({},{}), indexes=({},{}))",
|
||||
ret ? "true" : "false", ss.loc.x, ss.loc.y, anchor_loc.x, anchor_loc.y, x_index, y_index);
|
||||
}
|
||||
return ret;
|
||||
@@ -903,24 +903,24 @@ vector<uint16_t> get_card_refs_within_range(
|
||||
vector<uint16_t> ret;
|
||||
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());
|
||||
log->debug_f("get_card_refs_within_range: sc card @{:04X} within range", short_statuses[0].card_ref);
|
||||
}
|
||||
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());
|
||||
log->debug_f("get_card_refs_within_range: sc card @{:04X} not within range", short_statuses[0].card_ref);
|
||||
}
|
||||
}
|
||||
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, log)) {
|
||||
if (log) {
|
||||
log->debug("get_card_refs_within_range: card @%04hX within range", ss.card_ref.load());
|
||||
log->debug_f("get_card_refs_within_range: card @{:04X} within range", ss.card_ref);
|
||||
}
|
||||
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());
|
||||
log->debug_f("get_card_refs_within_range: card @{:04X} not within range", ss.card_ref);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+34
-34
@@ -16,10 +16,10 @@ void compute_effective_range(
|
||||
const Location& loc,
|
||||
shared_ptr<const MapAndRulesState> map_and_rules,
|
||||
phosg::PrefixedLogger* log) {
|
||||
if (log && log->should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log && log->should_log(phosg::LogLevel::L_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:");
|
||||
log->debug_f("compute_effective_range: card_id=#{:04X}, loc={}", card_id, loc_str);
|
||||
log->debug_f("compute_effective_range: map_and_rules->map:");
|
||||
map_and_rules->map.print(stderr);
|
||||
}
|
||||
ret.clear(0);
|
||||
@@ -40,14 +40,14 @@ void compute_effective_range(
|
||||
}
|
||||
}
|
||||
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]);
|
||||
log->debug_f("compute_effective_range: range_def: {:05X} {:05X} {:05X} {:05X} {:05X} {:05X}", 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)");
|
||||
log->debug_f("compute_effective_range: entire field (2)");
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -64,7 +64,7 @@ void compute_effective_range(
|
||||
}
|
||||
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",
|
||||
log->debug_f("compute_effective_range: decoded_range: {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X}",
|
||||
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]);
|
||||
}
|
||||
}
|
||||
@@ -98,7 +98,7 @@ void compute_effective_range(
|
||||
}
|
||||
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]);
|
||||
log->debug_f("compute_effective_range: x={} y={} up_x={} up_y={} v={:X}", x, y, up_x, up_y, ret[y * 9 + x]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,7 @@ void compute_effective_range(
|
||||
|
||||
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",
|
||||
log->debug_f("compute_effective_range: ret: {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X} {:X}",
|
||||
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]);
|
||||
}
|
||||
}
|
||||
@@ -941,7 +941,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
AttackMedium attack_medium) const {
|
||||
auto s = this->server();
|
||||
bool is_nte = s->options.is_nte();
|
||||
auto log = s->log_stack(phosg::string_printf("check_usability_or_condition_apply(%02hhX, #%04hX, %02hhX, #%04hX, #%04hX, %02hhX, %s, %s): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", phosg::name_for_enum(attack_medium)));
|
||||
auto log = s->log_stack(std::format("check_usability_or_condition_apply({:02X}, #{:04X}, {:02X}, #{:04X}, #{:04X}, {:02X}, {}, {}): ", client_id1, card_id1, client_id2, card_id2, card_id3, def_effect_index, is_item_usability_check ? "true" : "false", phosg::name_for_enum(attack_medium)));
|
||||
|
||||
if (static_cast<uint8_t>(attack_medium) & 0x80) {
|
||||
attack_medium = AttackMedium::UNKNOWN;
|
||||
@@ -951,11 +951,11 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
auto ce2 = this->definition_for_card_id(card_id2);
|
||||
auto ce3 = this->definition_for_card_id(card_id3);
|
||||
if (!ce1) {
|
||||
log.debug("ce1 missing");
|
||||
log.debug_f("ce1 missing");
|
||||
return false;
|
||||
}
|
||||
if (!is_nte && (ce1->def.type == CardType::ITEM) && this->card_id_is_boss_sc(card_id2)) {
|
||||
log.debug("ce1 is item and card_id2 is boss sc");
|
||||
log.debug_f("ce1 is item and card_id2 is boss sc");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -964,12 +964,12 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
criterion_code = ce1->def.usable_criterion;
|
||||
} else {
|
||||
if (def_effect_index > 2) {
|
||||
log.debug("invalid def_effect_index");
|
||||
log.debug_f("invalid def_effect_index");
|
||||
return false;
|
||||
}
|
||||
criterion_code = ce1->def.effects[def_effect_index].apply_criterion;
|
||||
}
|
||||
log.debug("criterion_code=%s", phosg::name_for_enum(criterion_code));
|
||||
log.debug_f("criterion_code={}", phosg::name_for_enum(criterion_code));
|
||||
|
||||
// For item usability checks, prevent criteria that depend on player
|
||||
// positioning/team setup
|
||||
@@ -980,7 +980,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
(criterion_code == CriterionCode::FC) ||
|
||||
(criterion_code == CriterionCode::NOT_SC) ||
|
||||
(criterion_code == CriterionCode::SC))) {
|
||||
log.debug("criterion is forbidden");
|
||||
log.debug_f("criterion is forbidden");
|
||||
criterion_code = CriterionCode::NONE;
|
||||
}
|
||||
|
||||
@@ -1354,7 +1354,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
}
|
||||
}
|
||||
|
||||
log.debug("default return (false)");
|
||||
log.debug_f("default return (false)");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1478,43 +1478,43 @@ bool RulerServer::compute_effective_range_and_target_mode_for_attack(
|
||||
for (z = 0; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
}
|
||||
if (z >= 8) {
|
||||
log.debug("too many action card refs");
|
||||
log.debug_f("too many action card refs");
|
||||
return false;
|
||||
}
|
||||
log.debug("%zu action card refs", z);
|
||||
log.debug_f("{} action card refs", z);
|
||||
uint16_t card_ref = (z == 0) ? pa.attacker_card_ref : pa.action_card_refs[z - 1];
|
||||
log.debug("base card ref = @%04hX", card_ref);
|
||||
log.debug_f("base card ref = @{:04X}", card_ref);
|
||||
|
||||
uint16_t card_id = this->card_id_for_card_ref(card_ref);
|
||||
if (card_id == 0xFFFF) {
|
||||
log.debug("card ref is broken");
|
||||
log.debug_f("card ref is broken");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ce = this->definition_for_card_id(card_id);
|
||||
uint8_t client_id = client_id_for_card_ref(pa.attacker_card_ref);
|
||||
if ((client_id == 0xFF) || !ce) {
|
||||
log.debug("card ref is broken or definition is missing");
|
||||
log.debug_f("card ref is broken or definition is missing");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (out_orig_card_ref) {
|
||||
log.debug("orig_card_ref = @%04hX", card_ref);
|
||||
log.debug_f("orig_card_ref = @{:04X}", card_ref);
|
||||
*out_orig_card_ref = card_ref;
|
||||
}
|
||||
|
||||
auto target_mode = ce->def.target_mode;
|
||||
if (this->card_ref_or_sc_has_fixed_range(pa.attacker_card_ref)) {
|
||||
const char* target_mode_name = name_for_target_mode(target_mode);
|
||||
log.debug("attacker card ref @%04hX has fixed range; target mode is %s (%hhu)",
|
||||
pa.attacker_card_ref.load(), target_mode_name, static_cast<uint8_t>(target_mode));
|
||||
log.debug_f("attacker card ref @{:04X} has fixed range; target mode is {} ({})",
|
||||
pa.attacker_card_ref, target_mode_name, static_cast<uint8_t>(target_mode));
|
||||
card_id = this->card_id_for_card_ref(pa.attacker_card_ref);
|
||||
if (!is_nte) {
|
||||
auto sc_ce = this->definition_for_card_id(card_id);
|
||||
if (sc_ce && (static_cast<uint8_t>(target_mode) < 6)) {
|
||||
target_mode = sc_ce->def.target_mode;
|
||||
const char* target_mode_name = name_for_target_mode(target_mode);
|
||||
log.debug("sc_ce overrides target mode with %s (%hhu)",
|
||||
log.debug_f("sc_ce overrides target mode with {} ({})",
|
||||
target_mode_name, static_cast<uint8_t>(target_mode));
|
||||
}
|
||||
}
|
||||
@@ -1525,10 +1525,10 @@ bool RulerServer::compute_effective_range_and_target_mode_for_attack(
|
||||
auto assist_effect = this->assist_server->get_active_assist_by_index(z);
|
||||
if (assist_effect == AssistEffect::SIMPLE) {
|
||||
card_id = this->card_id_for_card_ref(pa.attacker_card_ref);
|
||||
log.debug("SIMPLE assist overrides card id with #%04hX", card_id);
|
||||
log.debug_f("SIMPLE assist overrides card id with #{:04X}", card_id);
|
||||
} else if (assist_effect == AssistEffect::HEAVY_FOG) {
|
||||
card_id = 0xFFFE;
|
||||
log.debug("HEAVY_FOG assist overrides card id with #%04hX", card_id);
|
||||
log.debug_f("HEAVY_FOG assist overrides card id with #{:04X}", card_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2059,27 +2059,27 @@ shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint3
|
||||
|
||||
uint32_t RulerServer::get_card_id_with_effective_range(
|
||||
uint16_t card_ref, uint16_t card_id_override, TargetMode* out_target_mode) const {
|
||||
auto log = this->server()->log_stack(phosg::string_printf("get_card_id_with_effective_range(@%04hX, #%04hX): ", card_ref, card_id_override));
|
||||
auto log = this->server()->log_stack(std::format("get_card_id_with_effective_range(@{:04X}, #{:04X}): ", card_ref, card_id_override));
|
||||
|
||||
uint16_t card_id = (card_id_override == 0xFFFF)
|
||||
? this->card_id_for_card_ref(card_ref)
|
||||
: card_id_override;
|
||||
log.debug("card_id=#%04hX", card_id);
|
||||
log.debug_f("card_id=#{:04X}", card_id);
|
||||
|
||||
if (card_id != 0xFFFF) {
|
||||
auto ce = this->definition_for_card_id(card_id);
|
||||
uint8_t client_id = client_id_for_card_ref(card_ref);
|
||||
if ((client_id != 0xFF) && ce) {
|
||||
TargetMode effective_target_mode = ce->def.target_mode;
|
||||
log.debug("ce valid for #%04hX with effective target mode %s", card_id, name_for_target_mode(effective_target_mode));
|
||||
log.debug_f("ce valid for #{:04X} with effective target mode {}", card_id, name_for_target_mode(effective_target_mode));
|
||||
|
||||
if (this->card_ref_or_sc_has_fixed_range(card_ref)) {
|
||||
// Undo the override that may have been passed in
|
||||
log.debug("@%04hX has FIXED_RANGE", card_ref);
|
||||
log.debug_f("@{:04X} has FIXED_RANGE", card_ref);
|
||||
card_id = this->card_id_for_card_ref(card_ref);
|
||||
auto orig_ce = this->definition_for_card_id(card_id);
|
||||
if (orig_ce && (static_cast<uint8_t>(effective_target_mode) < 6)) {
|
||||
log.debug("ce valid for #%04hX with effective target mode %s; overriding to %s", card_id, name_for_target_mode(effective_target_mode), name_for_target_mode(orig_ce->def.target_mode));
|
||||
log.debug_f("ce valid for #{:04X} with effective target mode {}; overriding to {}", card_id, name_for_target_mode(effective_target_mode), name_for_target_mode(orig_ce->def.target_mode));
|
||||
effective_target_mode = orig_ce->def.target_mode;
|
||||
}
|
||||
}
|
||||
@@ -2089,17 +2089,17 @@ uint32_t RulerServer::get_card_id_with_effective_range(
|
||||
auto eff = this->assist_server->get_active_assist_by_index(z);
|
||||
if (eff == AssistEffect::SIMPLE) {
|
||||
card_id = this->card_id_for_card_ref(card_ref);
|
||||
log.debug("SIMPLE assist effect is active; using #%04hX for range", card_id);
|
||||
log.debug_f("SIMPLE assist effect is active; using #{:04X} for range", card_id);
|
||||
} else if (eff == AssistEffect::HEAVY_FOG) {
|
||||
card_id = 0xFFFE;
|
||||
log.debug("HEAVY_FOG assist effect is active; limiting range to one tile in front");
|
||||
log.debug_f("HEAVY_FOG assist effect is active; limiting range to one tile in front");
|
||||
}
|
||||
}
|
||||
|
||||
if (out_target_mode) {
|
||||
*out_target_mode = effective_target_mode;
|
||||
}
|
||||
log.debug("results: card_id=#%04hX, target_mode=%s", card_id, name_for_target_mode(effective_target_mode));
|
||||
log.debug_f("results: card_id=#{:04X}, target_mode={}", card_id, name_for_target_mode(effective_target_mode));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+73
-93
@@ -58,7 +58,7 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
|
||||
battle_start_usecs(0),
|
||||
should_copy_prev_states_to_current_states(0),
|
||||
card_special(nullptr),
|
||||
clients_done_in_mulligan_phase(false),
|
||||
clients_done_in_redraw_initial_hand_phase(false),
|
||||
num_pending_attacks_with_cards(0),
|
||||
unknown_a14(0),
|
||||
unknown_a15(0),
|
||||
@@ -83,12 +83,14 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
|
||||
|
||||
Server::~Server() noexcept(false) {
|
||||
if (this->logger_stack.size() != 1) {
|
||||
throw logic_error(phosg::string_printf("incorrect logger stack size: expected 1, received %zu", this->logger_stack.size()));
|
||||
throw logic_error(std::format("incorrect logger stack size: expected 1, received {}", this->logger_stack.size()));
|
||||
}
|
||||
delete this->logger_stack.back();
|
||||
}
|
||||
|
||||
void Server::init() {
|
||||
this->log().info_f("Creating server with random seed {:08X}", this->options.rand_crypt->seed());
|
||||
|
||||
this->map_and_rules = make_shared<MapAndRulesState>();
|
||||
this->num_clients_present = 0;
|
||||
this->overlay_state.clear();
|
||||
@@ -173,9 +175,9 @@ std::string Server::debug_str_for_card_ref(uint16_t card_ref) const {
|
||||
auto ce = this->definition_for_card_ref(card_ref);
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode();
|
||||
return phosg::string_printf("@%04hX (#%04" PRIX32 " %s)", card_ref, ce->def.card_id.load(), name.c_str());
|
||||
return std::format("@{:04X} (#{:04X} {})", card_ref, ce->def.card_id, name);
|
||||
} else {
|
||||
return phosg::string_printf("@%04hX (missing)", card_ref);
|
||||
return std::format("@{:04X} (missing)", card_ref);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -186,9 +188,9 @@ std::string Server::debug_str_for_card_id(uint16_t card_id) const {
|
||||
auto ce = this->definition_for_card_id(card_id);
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode();
|
||||
return phosg::string_printf("#%04hX (%s)", card_id, name.c_str());
|
||||
return std::format("#{:04X} ({})", card_id, name);
|
||||
} else {
|
||||
return phosg::string_printf("#%04hX (missing)", card_id);
|
||||
return std::format("#{:04X} (missing)", card_id);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +262,7 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
|
||||
}
|
||||
|
||||
} else if ((this->options.behavior_flags & BehaviorFlag::LOG_COMMANDS_IF_LOBBY_MISSING) &&
|
||||
this->log().info("Generated command")) {
|
||||
this->log().info_f("Generated command")) {
|
||||
phosg::print_data(stderr, data, size, 0, nullptr, phosg::PrintDataFlags::PRINT_ASCII | phosg::PrintDataFlags::DISABLE_COLOR | phosg::PrintDataFlags::OFFSET_16_BITS);
|
||||
}
|
||||
}
|
||||
@@ -273,9 +275,9 @@ void Server::send_6xB4x46() const {
|
||||
// debugging easier.
|
||||
G_ServerVersionStrings_Ep3_6xB4x46 cmd;
|
||||
cmd.version_signature.encode(this->options.is_nte() ? VERSION_SIGNATURE_NTE : VERSION_SIGNATURE, 1);
|
||||
cmd.date_str1.encode(phosg::format_time(this->options.card_index->definitions_mtime() * 1000000), 1);
|
||||
cmd.date_str1.encode(std::format("Card definitions: {:016X}", this->options.card_index->definitions_hash()), 1);
|
||||
string build_date = phosg::format_time(BUILD_TIMESTAMP);
|
||||
cmd.date_str2.encode(phosg::string_printf("newserv %s compiled at %s", GIT_REVISION_HASH, build_date.c_str()), 1);
|
||||
cmd.date_str2.encode(std::format("newserv {} compiled at {}", GIT_REVISION_HASH, build_date), 1);
|
||||
this->send(cmd);
|
||||
}
|
||||
|
||||
@@ -291,7 +293,7 @@ string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> ma
|
||||
return std::move(w.str());
|
||||
}
|
||||
|
||||
void Server::send_commands_for_joining_spectator(Channel& ch) const {
|
||||
void Server::send_commands_for_joining_spectator(std::shared_ptr<Channel> ch) const {
|
||||
bool should_send_state = true;
|
||||
if (this->setup_phase == SetupPhase::REGISTRATION) {
|
||||
// If registration is still in progress, we only need to send the map data
|
||||
@@ -303,84 +305,62 @@ void Server::send_commands_for_joining_spectator(Channel& ch) const {
|
||||
}
|
||||
|
||||
if (this->last_chosen_map) {
|
||||
string data = this->prepare_6xB6x41_map_definition(this->last_chosen_map, ch.language, this->options.is_nte());
|
||||
this->log().info("Sending %c version of map %08" PRIX32, char_for_language_code(ch.language), this->last_chosen_map->map_number);
|
||||
ch.send(0x6C, 0x00, data);
|
||||
string data = this->prepare_6xB6x41_map_definition(this->last_chosen_map, ch->language, this->options.is_nte());
|
||||
this->log().info_f("Sending {} version of map {:08X}", char_for_language_code(ch->language), this->last_chosen_map->map_number);
|
||||
ch->send(0x6C, 0x00, data);
|
||||
}
|
||||
|
||||
if (should_send_state) {
|
||||
ch.send(0xC9, 0x00, this->prepare_6xB4x03());
|
||||
ch->send(0xC9, 0x00, this->prepare_6xB4x03());
|
||||
for (uint8_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->player_states[client_id];
|
||||
if (ps) {
|
||||
ch.send(0xC9, 0x00, ps->prepare_6xB4x02());
|
||||
ch.send(0xC9, 0x00, ps->prepare_6xB4x04());
|
||||
ch->send(0xC9, 0x00, ps->prepare_6xB4x02());
|
||||
ch->send(0xC9, 0x00, ps->prepare_6xB4x04());
|
||||
}
|
||||
}
|
||||
if (ch.version == Version::GC_EP3_NTE) {
|
||||
if (ch->version == Version::GC_EP3_NTE) {
|
||||
G_UpdateMap_Ep3NTE_6xB4x05 cmd;
|
||||
cmd.state = *this->map_and_rules;
|
||||
ch.send(0xC9, 0x00, cmd);
|
||||
ch->send(0xC9, 0x00, cmd);
|
||||
} else {
|
||||
G_UpdateMap_Ep3_6xB4x05 cmd;
|
||||
cmd.state = *this->map_and_rules;
|
||||
ch.send(0xC9, 0x00, cmd);
|
||||
ch->send(0xC9, 0x00, cmd);
|
||||
}
|
||||
// TODO: Sega does something like this; do we have to do this too?
|
||||
// for (uint8_t client_id = 0; client_id < 4; client_id++) {
|
||||
// (send 6xB4x4E, 6xB4x4C, 6xB4x4D for each set card)
|
||||
// (send 6xB4x4F for client_id)
|
||||
// }
|
||||
ch.send(0xC9, 0x00, this->prepare_6xB4x07_decks_update());
|
||||
ch->send(0xC9, 0x00, this->prepare_6xB4x07_decks_update());
|
||||
// TODO: Sega sends 6xB4x05 here again; why? Is that necessary? They also
|
||||
// send 6xB4x02 again for each player after that (but not 6xB4x04)
|
||||
ch.send(0xC9, 0x00, this->prepare_6xB4x1C_names_update());
|
||||
ch.send(0xC9, 0x00, this->prepare_6xB4x50_trap_tile_locations());
|
||||
ch->send(0xC9, 0x00, this->prepare_6xB4x1C_names_update());
|
||||
ch->send(0xC9, 0x00, this->prepare_6xB4x50_trap_tile_locations());
|
||||
{
|
||||
G_LoadCurrentEnvironment_Ep3_6xB4x3B cmd_3B;
|
||||
ch.send(0xC9, 0x00, &cmd_3B, sizeof(cmd_3B));
|
||||
ch->send(0xC9, 0x00, &cmd_3B, sizeof(cmd_3B));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_debug_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->lobby.lock();
|
||||
if (l && (this->options.behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::string buf = phosg::string_vprintf(fmt, va);
|
||||
va_end(va);
|
||||
send_text_message(l, buf);
|
||||
}
|
||||
}
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void Server::send_info_message_printf(const char* fmt, ...) const {
|
||||
auto l = this->lobby.lock();
|
||||
if (l) {
|
||||
va_list va;
|
||||
va_start(va, fmt);
|
||||
std::string buf = phosg::string_vprintf(fmt, va);
|
||||
va_end(va);
|
||||
send_text_message(l, buf);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::send_debug_command_received_message(
|
||||
uint8_t client_id, uint8_t subsubcommand, const char* description) const {
|
||||
this->log().debug("%hhu/CAx%02hhX %s", client_id, subsubcommand, description);
|
||||
this->send_debug_message_printf("$C5%hhu/CAx%02hhX %s", client_id, subsubcommand, description);
|
||||
this->log().debug_f("{}/CAx{:02X} {}", client_id, subsubcommand, description);
|
||||
this->send_debug_message("$C5{}/CAx{:02X} {}", client_id, subsubcommand, description);
|
||||
}
|
||||
|
||||
void Server::send_debug_command_received_message(uint8_t subsubcommand, const char* description) const {
|
||||
this->log().debug("*/CAx%02hhX %s", subsubcommand, description);
|
||||
this->send_debug_message_printf("$C5*/CAx%02hhX %s", subsubcommand, description);
|
||||
this->log().debug_f("*/CAx{:02X} {}", subsubcommand, description);
|
||||
this->send_debug_message("$C5*/CAx{:02X} {}", subsubcommand, description);
|
||||
}
|
||||
|
||||
void Server::send_debug_message_if_error_code_nonzero(uint8_t client_id, int32_t error_code) const {
|
||||
if (error_code < 0) {
|
||||
this->send_debug_message_printf("$C4%hhu/ERROR -0x%zX", client_id, static_cast<ssize_t>(-error_code));
|
||||
this->send_debug_message("$C4{}/ERROR -0x{:X}", client_id, static_cast<ssize_t>(-error_code));
|
||||
} else if (error_code > 0) {
|
||||
this->send_debug_message_printf("$C4%hhu/ERROR 0x%zX", client_id, static_cast<ssize_t>(error_code));
|
||||
this->send_debug_message("$C4{}/ERROR 0x{:X}", client_id, static_cast<ssize_t>(error_code));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -949,62 +929,62 @@ void Server::end_action_phase() {
|
||||
|
||||
bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
|
||||
auto log = this->log_stack("enqueue_attack_or_defense: ");
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string s = pa->str(this->shared_from_this());
|
||||
log.debug("input: %s", s.c_str());
|
||||
log.debug_f("input: {}", s);
|
||||
}
|
||||
|
||||
if (client_id >= 4) {
|
||||
this->ruler_server->error_code3 = -0x78;
|
||||
log.debug("failed: invalid client ID");
|
||||
log.debug_f("failed: invalid client ID");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ps = this->player_states[client_id];
|
||||
if (!ps) {
|
||||
this->ruler_server->error_code3 = -0x72;
|
||||
log.debug("failed: player not present");
|
||||
log.debug_f("failed: player not present");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pa->action_card_refs[0] == 0xFFFF) {
|
||||
if (pa->defense_card_ref != 0xFFFF) {
|
||||
pa->action_card_refs[0] = pa->defense_card_ref;
|
||||
log.debug("moved defense card ref to action card ref 0");
|
||||
log.debug_f("moved defense card ref to action card ref 0");
|
||||
}
|
||||
} else {
|
||||
pa->defense_card_ref = pa->action_card_refs[0];
|
||||
log.debug("moved action card ref 0 to defense card ref");
|
||||
log.debug_f("moved action card ref 0 to defense card ref");
|
||||
}
|
||||
|
||||
if (!this->ruler_server->is_attack_or_defense_valid(*pa)) {
|
||||
log.debug("failed: attack or defense not valid");
|
||||
log.debug_f("failed: attack or defense not valid");
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t ally_atk_result = this->send_6xB4x33_remove_ally_atk_if_needed(*pa);
|
||||
if (ally_atk_result == 1) {
|
||||
log.debug("pending: need ally approval");
|
||||
log.debug_f("pending: need ally approval");
|
||||
return true;
|
||||
} else if (ally_atk_result == -1) {
|
||||
log.debug("failed: ally declined");
|
||||
log.debug_f("failed: ally declined");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->num_pending_attacks >= 0x20) {
|
||||
this->ruler_server->error_code3 = -0x71;
|
||||
log.debug("failed: too many pending attacks");
|
||||
log.debug_f("failed: too many pending attacks");
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t attack_index = this->num_pending_attacks++;
|
||||
this->pending_attacks[attack_index] = *pa;
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string pa_str = this->pending_attacks[attack_index].str(this->shared_from_this());
|
||||
log.debug("set pending attack %zu: %s", attack_index, pa_str.c_str());
|
||||
log.debug_f("set pending attack {}: {}", attack_index, pa_str);
|
||||
}
|
||||
ps->set_action_cards_for_action_state(*pa);
|
||||
log.debug("set action cards");
|
||||
log.debug_f("set action cards");
|
||||
auto card = this->card_for_set_card_ref(this->send_6xB4x06_if_card_ref_invalid(pa->attacker_card_ref, 1));
|
||||
if (card) {
|
||||
card->card_flags |= 0x400;
|
||||
@@ -1056,7 +1036,7 @@ uint32_t Server::get_random_raw() {
|
||||
if (this->options.opt_rand_stream) {
|
||||
this->options.opt_rand_stream->readx(&ret, sizeof(ret));
|
||||
} else {
|
||||
ret = random_from_optional_crypt(this->options.opt_rand_crypt);
|
||||
ret = this->options.rand_crypt->next();
|
||||
}
|
||||
|
||||
if (this->battle_record && this->battle_record->writable()) {
|
||||
@@ -1740,20 +1720,20 @@ bool Server::update_registration_phase() {
|
||||
auto log = this->log_stack("update_registration_phase: ");
|
||||
|
||||
if (this->setup_phase != SetupPhase::REGISTRATION) {
|
||||
log.debug("setup_phase is not REGISTRATION");
|
||||
log.debug_f("setup_phase is not REGISTRATION");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->map_and_rules->num_players == 0) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_NUM_PLAYERS;
|
||||
log.debug("registration_phase set to AWAITING_NUM_PLAYERS");
|
||||
log.debug_f("registration_phase set to AWAITING_NUM_PLAYERS");
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->map_and_rules->num_players != this->num_clients_present) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_PLAYERS;
|
||||
log.debug("registration_phase set to AWAITING_PLAYERS");
|
||||
log.debug_f("registration_phase set to AWAITING_PLAYERS");
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
}
|
||||
@@ -1767,20 +1747,20 @@ bool Server::update_registration_phase() {
|
||||
|
||||
if (num_team0_registered_players != this->map_and_rules->num_team0_players) {
|
||||
this->registration_phase = RegistrationPhase::AWAITING_DECKS;
|
||||
log.debug("registration_phase set to AWAITING_DECKS");
|
||||
log.debug_f("registration_phase set to AWAITING_DECKS");
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
return false;
|
||||
}
|
||||
|
||||
this->registration_phase = RegistrationPhase::REGISTERED;
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
log.debug("battle can begin");
|
||||
log.debug_f("battle can begin");
|
||||
return true;
|
||||
}
|
||||
|
||||
const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
{0x0B, &Server::handle_CAx0B_mulligan_hand},
|
||||
{0x0C, &Server::handle_CAx0C_end_mulligan_phase},
|
||||
{0x0B, &Server::handle_CAx0B_redraw_initial_hand},
|
||||
{0x0C, &Server::handle_CAx0C_end_redraw_initial_hand_phase},
|
||||
{0x0D, &Server::handle_CAx0D_end_non_action_phase},
|
||||
{0x0E, &Server::handle_CAx0E_discard_card_from_hand},
|
||||
{0x0F, &Server::handle_CAx0F_set_card_from_hand},
|
||||
@@ -1809,7 +1789,7 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
|
||||
size_t expected_size = header.size * 4;
|
||||
if (expected_size < data.size()) {
|
||||
phosg::print_data(stderr, data);
|
||||
throw runtime_error(phosg::string_printf("command is incomplete: expected %zX bytes, received %zX bytes", expected_size, data.size()));
|
||||
throw runtime_error(std::format("command is incomplete: expected {:X} bytes, received {:X} bytes", expected_size, data.size()));
|
||||
}
|
||||
if (header.subcommand != 0xB3) {
|
||||
throw runtime_error("server data command is not 6xB3");
|
||||
@@ -1835,7 +1815,7 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx0B_mulligan_hand(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0B_redraw_initial_hand(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_RedrawInitialHand_Ep3_CAx0B>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "REDRAW");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1854,20 +1834,20 @@ void Server::handle_CAx0B_mulligan_hand(shared_ptr<Client>, const string& data)
|
||||
if (!ps) {
|
||||
error_code = -0x72;
|
||||
} else {
|
||||
ps->do_mulligan();
|
||||
ps->redraw_initial_hand();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this->options.is_nte() || (error_code == 0)) {
|
||||
G_ActionResult_Ep3_6xB4x1E out_cmd;
|
||||
out_cmd.sequence_num = in_cmd.header.sequence_num.load();
|
||||
out_cmd.sequence_num = in_cmd.header.sequence_num;
|
||||
out_cmd.error_code = error_code;
|
||||
this->send(out_cmd);
|
||||
}
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
|
||||
}
|
||||
|
||||
void Server::handle_CAx0C_end_mulligan_phase(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0C_end_redraw_initial_hand_phase(shared_ptr<Client>, const string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndInitialRedrawPhase_Ep3_CAx0C>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "HAND READY");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
@@ -1898,13 +1878,13 @@ void Server::handle_CAx0C_end_mulligan_phase(shared_ptr<Client>, const string& d
|
||||
if (!ps) {
|
||||
error_code = -0x72;
|
||||
} else {
|
||||
this->clients_done_in_mulligan_phase[in_cmd.client_id] = true;
|
||||
this->clients_done_in_redraw_initial_hand_phase[in_cmd.client_id] = true;
|
||||
ps->assist_flags |= AssistFlag::READY_TO_END_PHASE;
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
|
||||
bool all_clients_ready = true;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (this->player_states[z] && !this->clients_done_in_mulligan_phase[z]) {
|
||||
if (this->player_states[z] && !this->clients_done_in_redraw_initial_hand_phase[z]) {
|
||||
all_clients_ready = false;
|
||||
break;
|
||||
}
|
||||
@@ -2229,7 +2209,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
|
||||
}
|
||||
}
|
||||
if (verify_error) {
|
||||
throw runtime_error(phosg::string_printf("invalid deck: -0x%" PRIX32, verify_error));
|
||||
throw runtime_error(std::format("invalid deck: -0x{:X}", verify_error));
|
||||
}
|
||||
if (!this->options.is_nte() && !(this->options.behavior_flags & BehaviorFlag::SKIP_D1_D2_REPLACE)) {
|
||||
this->ruler_server->replace_D1_D2_rank_cards_with_Attack(entry.card_ids);
|
||||
@@ -2573,7 +2553,7 @@ void Server::send_6xB6x41_to_all_clients() const {
|
||||
map_commands_by_language[c->language()] = this->prepare_6xB6x41_map_definition(
|
||||
this->last_chosen_map, c->language(), this->options.is_nte());
|
||||
}
|
||||
this->log().info("Sending %c version of map %08" PRIX32, char_for_language_code(c->language()), this->last_chosen_map->map_number);
|
||||
this->log().info_f("Sending {} version of map {:08X}", char_for_language_code(c->language()), this->last_chosen_map->map_number);
|
||||
send_command(c, 0x6C, 0x00, map_commands_by_language[c->language()]);
|
||||
};
|
||||
for (const auto& c : l->clients) {
|
||||
@@ -2782,7 +2762,7 @@ void Server::unknown_8023EEF4() {
|
||||
auto log = this->log_stack("unknown_8023EEF4: ");
|
||||
|
||||
if (this->unknown_a14 >= 0x20) {
|
||||
log.debug("unknown_a14 too large (0x%" PRIX32 ")", this->unknown_a14);
|
||||
log.debug_f("unknown_a14 too large (0x{:X})", this->unknown_a14);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2791,34 +2771,34 @@ void Server::unknown_8023EEF4() {
|
||||
auto card = this->attack_cards[this->unknown_a14];
|
||||
if (this->get_current_team_turn() == card->get_team_id()) {
|
||||
ActionState as = this->pending_attacks_with_cards[this->unknown_a14];
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
log.debug("card @%04hX #%04hX can attack", card->get_card_ref(), card->get_card_id());
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
log.debug_f("card @{:04X} #{:04X} can attack", card->get_card_ref(), card->get_card_id());
|
||||
string as_str = as.str(this->shared_from_this());
|
||||
log.debug("as: %s", as_str.c_str());
|
||||
log.debug_f("as: {}", as_str);
|
||||
}
|
||||
if (is_nte) {
|
||||
this->replace_targets_due_to_destruction_nte(&as);
|
||||
} else {
|
||||
this->replace_targets_due_to_destruction_or_conditions(&as);
|
||||
}
|
||||
if (log.should_log(phosg::LogLevel::DEBUG)) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string as_str = as.str(this->shared_from_this());
|
||||
log.debug("as after target replacement: %s", as_str.c_str());
|
||||
log.debug_f("as after target replacement: {}", as_str);
|
||||
}
|
||||
if (this->any_target_exists_for_attack(as)) {
|
||||
log.debug("as is valid");
|
||||
log.debug_f("as is valid");
|
||||
break;
|
||||
} else {
|
||||
log.debug("as is not valid");
|
||||
log.debug_f("as is not valid");
|
||||
}
|
||||
} else {
|
||||
log.debug("card @%04hX #%04hX cannot attack (wrong turn)", card->get_card_ref(), card->get_card_id());
|
||||
log.debug_f("card @{:04X} #{:04X} cannot attack (wrong turn)", card->get_card_ref(), card->get_card_id());
|
||||
}
|
||||
this->unknown_a14++;
|
||||
}
|
||||
|
||||
if (this->unknown_a14 < this->num_pending_attacks_with_cards) {
|
||||
log.debug("a14 (%" PRIu32 ") < num_pending_attacks_with_cards (%" PRIu32 ")", this->unknown_a14, this->num_pending_attacks_with_cards);
|
||||
log.debug_f("a14 ({}) < num_pending_attacks_with_cards ({})", this->unknown_a14, this->num_pending_attacks_with_cards);
|
||||
this->defense_list_ended_for_client.clear(false);
|
||||
|
||||
G_UpdateAttackTargets_Ep3_6xB4x29 cmd;
|
||||
@@ -3142,13 +3122,13 @@ void Server::unknown_802402F4() {
|
||||
if (ps && (this->current_team_turn2 == ps->get_team_id())) {
|
||||
auto card = ps->get_sc_card();
|
||||
if (card) {
|
||||
log.debug("SC card has action chain");
|
||||
log.debug_f("SC card has action chain");
|
||||
card->compute_action_chain_results(true, false);
|
||||
}
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
card = ps->get_set_card(set_index);
|
||||
if (card) {
|
||||
log.debug("set card %zu has action chain", set_index);
|
||||
log.debug_f("set card {} has action chain", set_index);
|
||||
card->compute_action_chain_results(true, false);
|
||||
}
|
||||
}
|
||||
|
||||
+17
-14
@@ -73,7 +73,7 @@ public:
|
||||
std::shared_ptr<const MapIndex> map_index;
|
||||
uint32_t behavior_flags;
|
||||
std::shared_ptr<phosg::StringReader> opt_rand_stream;
|
||||
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt;
|
||||
std::shared_ptr<RandomGenerator> rand_crypt;
|
||||
std::shared_ptr<const Tournament> tournament;
|
||||
std::array<std::vector<uint16_t>, 5> trap_card_ids;
|
||||
|
||||
@@ -109,7 +109,7 @@ public:
|
||||
for (size_t z = 0; z < count; z++) {
|
||||
if (refs[z] != 0xFFFF) {
|
||||
std::string ref_str = this->debug_str_for_card_ref(refs[z]);
|
||||
ret += phosg::string_printf("%zu:%s ", z, ref_str.c_str());
|
||||
ret += std::format("{}:{} ", z, ref_str);
|
||||
}
|
||||
}
|
||||
if (ret.size() > 1) {
|
||||
@@ -145,20 +145,23 @@ public:
|
||||
this->send(&cmd, cmd.header.size * 4, command, enable_masking);
|
||||
}
|
||||
void send(const void* data, size_t size, uint8_t command = 0xC9, bool enable_masking = true) const;
|
||||
void send_commands_for_joining_spectator(Channel& ch) const;
|
||||
void send_commands_for_joining_spectator(std::shared_ptr<Channel> ch) const;
|
||||
|
||||
void force_battle_result(uint8_t surrendered_client_id, bool set_winner);
|
||||
void force_replace_assist_card(uint8_t client_id, uint16_t card_id);
|
||||
void force_destroy_field_character(uint8_t client_id, size_t set_index);
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void send_debug_message_printf(const char* fmt, ...) const;
|
||||
__attribute__((format(printf, 2, 3))) void send_info_message_printf(const char* fmt, ...) const;
|
||||
void send_debug_command_received_message(
|
||||
uint8_t client_id, uint8_t subsubcommand, const char* description) const;
|
||||
void send_debug_command_received_message(
|
||||
uint8_t subsubcommand, const char* description) const;
|
||||
void send_debug_message_if_error_code_nonzero(
|
||||
uint8_t client_id, int32_t error_code) const;
|
||||
template <typename... ArgTs>
|
||||
void send_debug_message(std::format_string<ArgTs...> fmt, ArgTs&&... args) const {
|
||||
auto l = this->lobby.lock();
|
||||
if (l && (this->options.behavior_flags & Episode3::BehaviorFlag::ENABLE_STATUS_MESSAGES)) {
|
||||
send_text_message(l, std::format(std::forward<std::format_string<ArgTs...>>(fmt), std::forward<ArgTs>(args)...));
|
||||
}
|
||||
}
|
||||
|
||||
void send_debug_command_received_message(uint8_t client_id, uint8_t subsubcommand, const char* description) const;
|
||||
void send_debug_command_received_message(uint8_t subsubcommand, const char* description) const;
|
||||
void send_debug_message_if_error_code_nonzero(uint8_t client_id, int32_t error_code) const;
|
||||
|
||||
void send_6xB4x46() const;
|
||||
|
||||
@@ -218,8 +221,8 @@ public:
|
||||
void update_battle_state_flags_and_send_6xB4x03_if_needed(bool always_send = false);
|
||||
bool update_registration_phase();
|
||||
void on_server_data_input(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0B_mulligan_hand(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0C_end_mulligan_phase(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0B_redraw_initial_hand(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0C_end_redraw_initial_hand_phase(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0D_end_non_action_phase(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0E_discard_card_from_hand(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
void handle_CAx0F_set_card_from_hand(std::shared_ptr<Client> sender_c, const std::string& data);
|
||||
@@ -330,7 +333,7 @@ public:
|
||||
std::shared_ptr<CardSpecial> card_special;
|
||||
std::shared_ptr<StateFlags> state_flags;
|
||||
std::array<std::shared_ptr<PlayerState>, 4> player_states;
|
||||
parray<uint32_t, 4> clients_done_in_mulligan_phase;
|
||||
parray<uint32_t, 4> clients_done_in_redraw_initial_hand_phase;
|
||||
uint32_t num_pending_attacks_with_cards;
|
||||
bcarray<std::shared_ptr<Card>, 0x20> attack_cards;
|
||||
bcarray<ActionState, 0x20> pending_attacks_with_cards;
|
||||
|
||||
+27
-21
@@ -3,7 +3,9 @@
|
||||
#include <phosg/Random.hh>
|
||||
|
||||
#include "../CommandFormats.hh"
|
||||
#include "../GameServer.hh"
|
||||
#include "../SendCommands.hh"
|
||||
#include "../ServerState.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
@@ -49,16 +51,16 @@ string Tournament::Team::str() const {
|
||||
num_com_players += player.is_com();
|
||||
}
|
||||
|
||||
string ret = phosg::string_printf("[Team/%zu %s %zuH/%zuC/%zuP name=%s pass=%s rounds=%zu",
|
||||
string ret = std::format("[Team/{} {} {}H/{}C/{}P name={} pass={} rounds={}",
|
||||
this->index, this->is_active ? "active" : "inactive",
|
||||
num_human_players, num_com_players, this->max_players, this->name.c_str(),
|
||||
this->password.c_str(), this->num_rounds_cleared);
|
||||
num_human_players, num_com_players, this->max_players, this->name,
|
||||
this->password, this->num_rounds_cleared);
|
||||
for (const auto& player : this->players) {
|
||||
if (player.is_human()) {
|
||||
if (player.player_name.empty()) {
|
||||
ret += phosg::string_printf(" %08" PRIX32, player.account_id);
|
||||
ret += std::format(" {:08X}", player.account_id);
|
||||
} else {
|
||||
ret += phosg::string_printf(" %08" PRIX32 " (%s)", player.account_id, player.player_name.c_str());
|
||||
ret += std::format(" {:08X} ({})", player.account_id, player.player_name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +208,7 @@ Tournament::Match::Match(
|
||||
|
||||
string Tournament::Match::str() const {
|
||||
string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
|
||||
return phosg::string_printf("[Match round=%zu winner=%s]", this->round_num, winner_str.c_str());
|
||||
return std::format("[Match round={} winner={}]", this->round_num, winner_str);
|
||||
}
|
||||
|
||||
bool Tournament::Match::resolve_if_skippable() {
|
||||
@@ -318,7 +320,7 @@ Tournament::Tournament(
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
uint8_t flags)
|
||||
: log(phosg::string_printf("[Tournament:%s] ", name.c_str())),
|
||||
: log(std::format("[Tournament:{}] ", name)),
|
||||
map_index(map_index),
|
||||
com_deck_index(com_deck_index),
|
||||
name(name),
|
||||
@@ -343,7 +345,7 @@ Tournament::Tournament(
|
||||
shared_ptr<const MapIndex> map_index,
|
||||
shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const phosg::JSON& json)
|
||||
: log(phosg::string_printf("[Tournament:%s] ", json.get_string("name").c_str())),
|
||||
: log(std::format("[Tournament:{}] ", json.get_string("name"))),
|
||||
map_index(map_index),
|
||||
com_deck_index(com_deck_index),
|
||||
source_json(json),
|
||||
@@ -665,7 +667,7 @@ void Tournament::start() {
|
||||
auto m = this->zero_round_matches[z];
|
||||
auto t = m->winner_team;
|
||||
if (t->name.empty()) {
|
||||
t->name = has_com_teams ? phosg::string_printf("COM:%zu", z) : "(no entrant)";
|
||||
t->name = has_com_teams ? std::format("COM:{}", z) : "(no entrant)";
|
||||
}
|
||||
for (const auto& player : t->players) {
|
||||
if (player.is_com()) {
|
||||
@@ -718,7 +720,7 @@ void Tournament::send_all_state_updates_on_deletion() const {
|
||||
}
|
||||
|
||||
string Tournament::bracket_str() const {
|
||||
string ret = phosg::string_printf("Tournament \"%s\"\n", this->name.c_str());
|
||||
string ret = std::format("Tournament \"{}\"\n", this->name);
|
||||
|
||||
function<void(shared_ptr<Match>, size_t)> add_match = [&](shared_ptr<Match> m, size_t indent_level) -> void {
|
||||
ret.append(2 * indent_level, ' ');
|
||||
@@ -738,16 +740,16 @@ string Tournament::bracket_str() const {
|
||||
auto en_vm = this->map->version(1);
|
||||
if (en_vm) {
|
||||
string map_name = en_vm->map->name.decode(en_vm->language);
|
||||
ret += phosg::string_printf(" Map: %08" PRIX32 " (%s)\n", this->map->map_number, map_name.c_str());
|
||||
ret += std::format(" Map: {:08X} ({})\n", this->map->map_number, map_name);
|
||||
} else {
|
||||
ret += phosg::string_printf(" Map: %08" PRIX32 "\n", this->map->map_number);
|
||||
ret += std::format(" Map: {:08X}\n", this->map->map_number);
|
||||
}
|
||||
string rules_str = this->rules.str();
|
||||
ret += phosg::string_printf(" Rules: %s\n", rules_str.c_str());
|
||||
ret += phosg::string_printf(" Structure: %s, %zu entries\n", (this->flags & Flag::IS_2V2) ? "2v2" : "1v1", this->num_teams);
|
||||
ret += phosg::string_printf(" COM teams: %s\n", (this->flags & Flag::HAS_COM_TEAMS) ? "allowed" : "forbidden");
|
||||
ret += phosg::string_printf(" Shuffle entries: %s\n", (this->flags & Flag::SHUFFLE_ENTRIES) ? "yes" : "no");
|
||||
ret += phosg::string_printf(" Resize on start: %s\n", (this->flags & Flag::RESIZE_ON_START) ? "yes" : "no");
|
||||
ret += std::format(" Rules: {}\n", rules_str);
|
||||
ret += std::format(" Structure: {}, {} entries\n", (this->flags & Flag::IS_2V2) ? "2v2" : "1v1", this->num_teams);
|
||||
ret += std::format(" COM teams: {}\n", (this->flags & Flag::HAS_COM_TEAMS) ? "allowed" : "forbidden");
|
||||
ret += std::format(" Shuffle entries: {}\n", (this->flags & Flag::SHUFFLE_ENTRIES) ? "yes" : "no");
|
||||
ret += std::format(" Resize on start: {}\n", (this->flags & Flag::RESIZE_ON_START) ? "yes" : "no");
|
||||
switch (this->current_state) {
|
||||
case State::REGISTRATION:
|
||||
ret += " State: REGISTRATION\n";
|
||||
@@ -770,13 +772,13 @@ string Tournament::bracket_str() const {
|
||||
ret += " Teams:\n";
|
||||
for (const auto& team : this->teams) {
|
||||
string team_str = team->str();
|
||||
ret += phosg::string_printf(" %s\n", team_str.c_str());
|
||||
ret += std::format(" {}\n", team_str);
|
||||
}
|
||||
} else {
|
||||
ret += " Pending matches:\n";
|
||||
for (const auto& match : this->pending_matches) {
|
||||
string match_str = match->str();
|
||||
ret += phosg::string_printf(" %s\n", match_str.c_str());
|
||||
ret += std::format(" {}\n", match_str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -940,8 +942,12 @@ void TournamentIndex::link_client(shared_ptr<Client> c) {
|
||||
}
|
||||
|
||||
void TournamentIndex::link_all_clients(std::shared_ptr<ServerState> s) {
|
||||
for (const auto& c_it : s->channel_to_client) {
|
||||
this->link_client(c_it.second);
|
||||
// This can be called before the game server exists, so do nothing in that
|
||||
// case
|
||||
if (s->game_server) {
|
||||
for (const auto& c : s->game_server->all_clients()) {
|
||||
this->link_client(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <event2/event.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory>
|
||||
|
||||
Reference in New Issue
Block a user