eliminate using namespace
This commit is contained in:
@@ -2,22 +2,20 @@
|
||||
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
const vector<uint16_t>& all_assist_card_ids(bool is_nte) {
|
||||
const std::vector<uint16_t>& all_assist_card_ids(bool is_nte) {
|
||||
// Note: This order matches the order that the cards are defined in the original
|
||||
// code. This is relevant for consistency of results when choosing a random card
|
||||
// (for God Whim).
|
||||
static const vector<uint16_t> ALL_ASSIST_CARD_IDS_TRIAL = {
|
||||
static const std::vector<uint16_t> ALL_ASSIST_CARD_IDS_TRIAL = {
|
||||
0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x0101, 0x0102,
|
||||
0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D, 0x010E, 0x010F, 0x0121,
|
||||
0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F, 0x0130, 0x0131, 0x0132,
|
||||
0x0133, 0x0134, 0x0135, 0x0136, 0x0137, 0x0138, 0x0139, 0x013A, 0x013B, 0x013C, 0x013D, 0x013E, 0x013F, 0x0140,
|
||||
0x0141, 0x0142, 0x0143, 0x0144, 0x0145, 0x0146, 0x0148, 0x014A, 0x014B, 0x014C, 0x014D, 0x014E, 0x023F, 0x0240,
|
||||
0x0241, 0x0242};
|
||||
static const vector<uint16_t> ALL_ASSIST_CARD_IDS_FINAL = {
|
||||
static const std::vector<uint16_t> ALL_ASSIST_CARD_IDS_FINAL = {
|
||||
0x0018, 0x0019, 0x001A, 0x00F5, 0x00F6, 0x00F7, 0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF,
|
||||
0x0100, 0x0101, 0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010B, 0x010C, 0x010D,
|
||||
0x010E, 0x010F, 0x0121, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012A, 0x012B, 0x012C, 0x012D, 0x012E, 0x012F,
|
||||
@@ -28,12 +26,12 @@ const vector<uint16_t>& all_assist_card_ids(bool is_nte) {
|
||||
}
|
||||
|
||||
AssistEffect assist_effect_number_for_card_id(uint16_t card_id, bool is_nte) {
|
||||
static const unordered_map<uint16_t, AssistEffect> card_id_to_effect_final_only({
|
||||
static const std::unordered_map<uint16_t, AssistEffect> card_id_to_effect_final_only({
|
||||
{0x0018, /* 0x0049 */ AssistEffect::DICE_FEVER_PLUS},
|
||||
{0x0019, /* 0x004A */ AssistEffect::RICH_PLUS},
|
||||
{0x001A, /* 0x004B */ AssistEffect::CHARITY_PLUS},
|
||||
});
|
||||
static const unordered_map<uint16_t, AssistEffect> card_id_to_effect({
|
||||
static const std::unordered_map<uint16_t, AssistEffect> card_id_to_effect({
|
||||
{0x00F5, /* 0x0001 */ AssistEffect::DICE_HALF},
|
||||
{0x00F6, /* 0x0002 */ AssistEffect::DICE_PLUS_1},
|
||||
{0x00F7, /* 0x0003 */ AssistEffect::DICE_FEVER},
|
||||
@@ -109,18 +107,18 @@ AssistEffect assist_effect_number_for_card_id(uint16_t card_id, bool is_nte) {
|
||||
});
|
||||
try {
|
||||
return card_id_to_effect.at(card_id);
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
if (!is_nte) {
|
||||
try {
|
||||
return card_id_to_effect_final_only.at(card_id);
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
return AssistEffect::NONE;
|
||||
}
|
||||
|
||||
AssistServer::AssistServer(shared_ptr<Server> server)
|
||||
AssistServer::AssistServer(std::shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
assist_effects(AssistEffect::NONE),
|
||||
num_assist_cards_set(0),
|
||||
@@ -128,18 +126,18 @@ AssistServer::AssistServer(shared_ptr<Server> server)
|
||||
active_assist_effects(AssistEffect::NONE),
|
||||
num_active_assists(0) {}
|
||||
|
||||
shared_ptr<Server> AssistServer::server() {
|
||||
std::shared_ptr<Server> AssistServer::server() {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const Server> AssistServer::server() const {
|
||||
std::shared_ptr<const Server> AssistServer::server() const {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -148,7 +146,7 @@ uint16_t AssistServer::card_id_for_card_ref(uint16_t card_ref) const {
|
||||
return this->server()->card_id_for_card_ref(card_ref);
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> AssistServer::definition_for_card_id(
|
||||
std::shared_ptr<const CardIndex::CardEntry> AssistServer::definition_for_card_id(
|
||||
uint16_t card_id) const {
|
||||
return this->server()->definition_for_card_id(card_id);
|
||||
}
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
#include "../CommandFormats.hh"
|
||||
#include "../SendCommands.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
void BattleRecord::PlayerEntry::print(FILE* stream) const {
|
||||
@@ -41,7 +39,7 @@ BattleRecord::Event::Event(phosg::StringReader& r) {
|
||||
this->data = r.read(r.get_u16l());
|
||||
break;
|
||||
default:
|
||||
throw logic_error("unknown event type");
|
||||
throw std::logic_error("unknown event type");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +49,7 @@ void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
|
||||
switch (this->type) {
|
||||
case Event::Type::PLAYER_JOIN:
|
||||
if (this->players.size() != 1) {
|
||||
throw logic_error("player join event does not contain 1 player entry");
|
||||
throw std::logic_error("player join event does not contain 1 player entry");
|
||||
}
|
||||
w.put(this->players[0]);
|
||||
break;
|
||||
@@ -75,13 +73,12 @@ void BattleRecord::Event::serialize(phosg::StringWriter& w) const {
|
||||
w.write(this->data);
|
||||
break;
|
||||
default:
|
||||
throw logic_error("unknown event type");
|
||||
throw std::logic_error("unknown event type");
|
||||
}
|
||||
}
|
||||
|
||||
void BattleRecord::Event::print(FILE* stream) const {
|
||||
string time_str = phosg::format_time(this->timestamp);
|
||||
phosg::fwrite_fmt(stream, "Event @{:016X} ({}) ", this->timestamp, time_str);
|
||||
phosg::fwrite_fmt(stream, "Event @{:016X} ({}) ", this->timestamp, phosg::format_time(this->timestamp));
|
||||
switch (this->type) {
|
||||
case Type::PLAYER_JOIN:
|
||||
phosg::fwrite_fmt(stream, "PLAYER_JOIN {:02X}\n", this->players[0].lobby_data.client_id);
|
||||
@@ -121,7 +118,7 @@ void BattleRecord::Event::print(FILE* stream) const {
|
||||
phosg::print_data(stream, this->data, 0, phosg::FormatDataFlags::PRINT_ASCII | phosg::FormatDataFlags::OFFSET_16_BITS);
|
||||
break;
|
||||
default:
|
||||
throw runtime_error("unknown event type in battle record");
|
||||
throw std::runtime_error("unknown event type in battle record");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,11 +128,8 @@ BattleRecord::BattleRecord(uint32_t behavior_flags)
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) {}
|
||||
|
||||
BattleRecord::BattleRecord(const string& data)
|
||||
: is_writable(false),
|
||||
behavior_flags(0),
|
||||
battle_start_timestamp(0),
|
||||
battle_end_timestamp(0) {
|
||||
BattleRecord::BattleRecord(const std::string& data)
|
||||
: is_writable(false), behavior_flags(0), battle_start_timestamp(0), battle_end_timestamp(0) {
|
||||
phosg::StringReader r(data);
|
||||
|
||||
uint64_t signature = r.get_u64l();
|
||||
@@ -145,7 +139,7 @@ BattleRecord::BattleRecord(const string& data)
|
||||
} else if (signature == this->SIGNATURE_V2) {
|
||||
has_random_stream = true;
|
||||
} else {
|
||||
throw runtime_error("incorrect battle record signature");
|
||||
throw std::runtime_error("incorrect battle record signature");
|
||||
}
|
||||
|
||||
this->battle_start_timestamp = r.get_u64l();
|
||||
@@ -159,7 +153,7 @@ BattleRecord::BattleRecord(const string& data)
|
||||
}
|
||||
}
|
||||
|
||||
string BattleRecord::serialize() const {
|
||||
std::string BattleRecord::serialize() const {
|
||||
phosg::StringWriter w;
|
||||
w.put_u64l(this->SIGNATURE_V2);
|
||||
w.put_u64l(this->battle_start_timestamp);
|
||||
@@ -179,10 +173,10 @@ void BattleRecord::add_player(
|
||||
const PlayerDispDataDCPCV3& disp,
|
||||
uint32_t level) {
|
||||
if (!this->is_writable) {
|
||||
throw logic_error("cannot write to battle record");
|
||||
throw std::logic_error("cannot write to battle record");
|
||||
}
|
||||
if (this->battle_start_timestamp != 0) {
|
||||
throw runtime_error("cannot add player during battle");
|
||||
throw std::runtime_error("cannot add player during battle");
|
||||
}
|
||||
Event& ev = this->events.emplace_back();
|
||||
ev.type = Event::Type::PLAYER_JOIN;
|
||||
@@ -196,7 +190,7 @@ void BattleRecord::add_player(
|
||||
|
||||
void BattleRecord::delete_player(uint8_t client_id) {
|
||||
if (!this->is_writable) {
|
||||
throw logic_error("cannot write to battle record");
|
||||
throw std::logic_error("cannot write to battle record");
|
||||
}
|
||||
Event& ev = this->events.emplace_back();
|
||||
ev.type = Event::Type::PLAYER_LEAVE;
|
||||
@@ -206,7 +200,7 @@ void BattleRecord::delete_player(uint8_t client_id) {
|
||||
|
||||
void BattleRecord::add_command(Event::Type type, const void* data, size_t size) {
|
||||
if (!this->is_writable) {
|
||||
throw logic_error("cannot write to battle record");
|
||||
throw std::logic_error("cannot write to battle record");
|
||||
}
|
||||
Event& ev = this->events.emplace_back();
|
||||
ev.type = type;
|
||||
@@ -214,9 +208,9 @@ void BattleRecord::add_command(Event::Type type, const void* data, size_t size)
|
||||
ev.data.assign(reinterpret_cast<const char*>(data), size);
|
||||
}
|
||||
|
||||
void BattleRecord::add_command(Event::Type type, string&& data) {
|
||||
void BattleRecord::add_command(Event::Type type, std::string&& data) {
|
||||
if (!this->is_writable) {
|
||||
throw logic_error("cannot write to battle record");
|
||||
throw std::logic_error("cannot write to battle record");
|
||||
}
|
||||
Event& ev = this->events.emplace_back();
|
||||
ev.type = type;
|
||||
@@ -224,10 +218,9 @@ void BattleRecord::add_command(Event::Type type, string&& data) {
|
||||
ev.data = std::move(data);
|
||||
}
|
||||
|
||||
void BattleRecord::add_chat_message(
|
||||
uint32_t guild_card_number, string&& data) {
|
||||
void BattleRecord::add_chat_message(uint32_t guild_card_number, std::string&& data) {
|
||||
if (!this->is_writable) {
|
||||
throw logic_error("cannot write to battle record");
|
||||
throw std::logic_error("cannot write to battle record");
|
||||
}
|
||||
Event& ev = this->events.emplace_back();
|
||||
ev.type = Event::Type::CHAT_MESSAGE;
|
||||
@@ -240,7 +233,7 @@ void BattleRecord::add_random_data(const void* data, size_t size) {
|
||||
this->random_stream.append(reinterpret_cast<const char*>(data), size);
|
||||
}
|
||||
|
||||
const string& BattleRecord::get_random_stream() const {
|
||||
const std::string& BattleRecord::get_random_stream() const {
|
||||
return this->random_stream;
|
||||
}
|
||||
|
||||
@@ -259,7 +252,7 @@ bool BattleRecord::is_map_definition_event(const Event& ev) {
|
||||
|
||||
void BattleRecord::set_battle_start_timestamp() {
|
||||
if (this->battle_start_timestamp != 0) {
|
||||
throw logic_error("battle start timestamp is already set");
|
||||
throw std::logic_error("battle start timestamp is already set");
|
||||
}
|
||||
this->battle_start_timestamp = phosg::now();
|
||||
|
||||
@@ -271,30 +264,30 @@ void BattleRecord::set_battle_start_timestamp() {
|
||||
for (auto& ev : this->events) {
|
||||
if (ev.type == Event::Type::PLAYER_JOIN) {
|
||||
if (ev.players.size() != 1) {
|
||||
throw logic_error("player join event does not contain 1 player entry");
|
||||
throw std::logic_error("player join event does not contain 1 player entry");
|
||||
}
|
||||
auto& player = ev.players[0];
|
||||
if (player.lobby_data.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
players[player.lobby_data.client_id] = player;
|
||||
players_present[player.lobby_data.client_id] = true;
|
||||
|
||||
} else if (ev.type == Event::Type::PLAYER_LEAVE) {
|
||||
if (ev.leaving_client_id >= 4) {
|
||||
throw logic_error("invalid client ID");
|
||||
throw std::logic_error("invalid client ID");
|
||||
}
|
||||
players_present[ev.leaving_client_id] = false;
|
||||
|
||||
} else if (ev.type == Event::Type::SET_INITIAL_PLAYERS) {
|
||||
throw logic_error("BattleRecord::set_battle_start_timestamp called twice");
|
||||
throw std::logic_error("BattleRecord::set_battle_start_timestamp called twice");
|
||||
|
||||
} else if (this->is_map_definition_event(ev)) {
|
||||
num_map_events++;
|
||||
}
|
||||
}
|
||||
|
||||
deque<Event> new_events;
|
||||
std::deque<Event> new_events;
|
||||
|
||||
// Generate the initial players event
|
||||
Event initial_ev;
|
||||
@@ -335,32 +328,31 @@ 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);
|
||||
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,
|
||||
phosg::format_time(this->battle_start_timestamp),
|
||||
this->battle_end_timestamp,
|
||||
end_str, this->events.size());
|
||||
phosg::format_time(this->battle_end_timestamp),
|
||||
this->events.size());
|
||||
for (const auto& event : this->events) {
|
||||
event.print(stream);
|
||||
}
|
||||
}
|
||||
|
||||
BattleRecordPlayer::BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, shared_ptr<const BattleRecord> rec)
|
||||
BattleRecordPlayer::BattleRecordPlayer(std::shared_ptr<asio::io_context> io_context, std::shared_ptr<const BattleRecord> rec)
|
||||
: io_context(io_context),
|
||||
record(rec),
|
||||
event_it(this->record->events.begin()),
|
||||
play_start_timestamp(0),
|
||||
next_command_timer(*this->io_context) {}
|
||||
|
||||
shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
|
||||
std::shared_ptr<const BattleRecord> BattleRecordPlayer::get_record() const {
|
||||
return this->record;
|
||||
}
|
||||
|
||||
void BattleRecordPlayer::set_lobby(shared_ptr<Lobby> l) {
|
||||
void BattleRecordPlayer::set_lobby(std::shared_ptr<Lobby> l) {
|
||||
this->lobby = l;
|
||||
}
|
||||
|
||||
@@ -406,7 +398,7 @@ asio::awaitable<void> BattleRecordPlayer::play_task() {
|
||||
switch (ev.type) {
|
||||
case BattleRecord::Event::Type::PLAYER_JOIN:
|
||||
// Technically we can support this, but it should never happen
|
||||
throw runtime_error("player join event during battle replay");
|
||||
throw std::runtime_error("player join event during battle replay");
|
||||
case BattleRecord::Event::Type::PLAYER_LEAVE:
|
||||
send_player_leave_notification(l, ev.leaving_client_id);
|
||||
break;
|
||||
|
||||
+52
-59
@@ -3,11 +3,9 @@
|
||||
#include "../CommandFormats.hh"
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
Card::Card(uint16_t card_id, uint16_t card_ref, uint16_t client_id, shared_ptr<Server> server)
|
||||
Card::Card(uint16_t card_id, uint16_t card_ref, uint16_t client_id, std::shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
w_player_state(server->get_player_state(client_id)),
|
||||
client_id(client_id),
|
||||
@@ -39,7 +37,7 @@ void Card::init() {
|
||||
// Arkz-side. This could break things later on in the battle, and even if it
|
||||
// doesn't, it certainly isn't behavior that the player would expect, so we
|
||||
// prevent it instead.
|
||||
throw runtime_error("card definition is missing");
|
||||
throw std::runtime_error("card definition is missing");
|
||||
}
|
||||
this->sc_card_ref = ps->get_sc_card_ref();
|
||||
this->sc_def_entry = s->definition_for_card_id(ps->get_sc_card_id());
|
||||
@@ -56,7 +54,7 @@ void Card::init() {
|
||||
} else {
|
||||
int16_t rules_char_hp = s->map_and_rules->rules.char_hp;
|
||||
int16_t base_char_hp = (rules_char_hp == 0) ? 15 : rules_char_hp;
|
||||
int16_t hp = clamp<int16_t>(base_char_hp + this->def_entry->def.hp.stat, 1, 99);
|
||||
int16_t hp = std::clamp<int16_t>(base_char_hp + this->def_entry->def.hp.stat, 1, 99);
|
||||
this->max_hp = hp;
|
||||
this->current_hp = hp;
|
||||
}
|
||||
@@ -78,34 +76,34 @@ void Card::init() {
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Server> Card::server() {
|
||||
std::shared_ptr<Server> Card::server() {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const Server> Card::server() const {
|
||||
std::shared_ptr<const Server> Card::server() const {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<PlayerState> Card::player_state() {
|
||||
std::shared_ptr<PlayerState> Card::player_state() {
|
||||
auto s = this->w_player_state.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const PlayerState> Card::player_state() const {
|
||||
std::shared_ptr<const PlayerState> Card::player_state() const {
|
||||
auto s = this->w_player_state.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -158,7 +156,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
int16_t existing_cond_value = 0;
|
||||
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);
|
||||
existing_cond_value = std::clamp<int16_t>(cond.value, -99, 99);
|
||||
log.debug_f("MV_BONUS combines => existing_cond_value = {}", existing_cond_value);
|
||||
}
|
||||
|
||||
@@ -176,7 +174,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
|
||||
switch (eff.arg1.at(0)) {
|
||||
case 'a': {
|
||||
string s = eff.arg1.decode();
|
||||
std::string s = eff.arg1.decode();
|
||||
cond.a_arg_value = atoi(s.c_str() + 1);
|
||||
break;
|
||||
}
|
||||
@@ -190,13 +188,12 @@ ssize_t Card::apply_abnormal_condition(
|
||||
cond.remaining_turns = 102;
|
||||
break;
|
||||
case 't': {
|
||||
string s = eff.arg1.decode();
|
||||
std::string s = eff.arg1.decode();
|
||||
cond.remaining_turns = atoi(s.c_str() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
string cond_str = cond.str(s);
|
||||
log.debug_f("wrote condition {} => {}", cond_index, cond_str);
|
||||
log.debug_f("wrote condition {} => {}", cond_index, cond.str(s));
|
||||
|
||||
if (!is_nte) {
|
||||
s->card_special->update_condition_orders(this->shared_from_this());
|
||||
@@ -204,8 +201,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
if (this->action_chain.conditions[z].type == ConditionType::NONE) {
|
||||
continue;
|
||||
}
|
||||
string cond_str = cond.str(s);
|
||||
log.debug_f("sorted conditions: [{}] => {}", z, cond_str);
|
||||
log.debug_f("sorted conditions: [{}] => {}", z, cond.str(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +209,7 @@ ssize_t Card::apply_abnormal_condition(
|
||||
}
|
||||
|
||||
void Card::apply_ap_and_tp_adjust_assists_to_attack(
|
||||
shared_ptr<const Card> attacker_card,
|
||||
std::shared_ptr<const Card> attacker_card,
|
||||
int16_t* inout_attacker_ap,
|
||||
int16_t* in_defense_power,
|
||||
int16_t* inout_attacker_tp) const {
|
||||
@@ -226,12 +222,12 @@ void Card::apply_ap_and_tp_adjust_assists_to_attack(
|
||||
switch (s->assist_server->get_active_assist_by_index(z)) {
|
||||
case AssistEffect::POWERLESS_RAIN:
|
||||
if (is_nte) {
|
||||
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap - 2, 0);
|
||||
*inout_attacker_ap = std::max<int16_t>(*inout_attacker_ap - 2, 0);
|
||||
}
|
||||
break;
|
||||
case AssistEffect::BRAVE_WIND:
|
||||
if (is_nte) {
|
||||
*inout_attacker_ap = max<int16_t>(*inout_attacker_ap + 2, 0);
|
||||
*inout_attacker_ap = std::max<int16_t>(*inout_attacker_ap + 2, 0);
|
||||
}
|
||||
break;
|
||||
case AssistEffect::SILENT_COLOSSEUM:
|
||||
@@ -284,7 +280,7 @@ bool Card::check_card_flag(uint32_t flags) const {
|
||||
|
||||
void Card::commit_attack(
|
||||
int16_t damage,
|
||||
shared_ptr<Card> attacker_card,
|
||||
std::shared_ptr<Card> attacker_card,
|
||||
G_ApplyConditionEffect_Ep3_6xB4x06* cmd,
|
||||
size_t strike_number,
|
||||
int16_t* out_effective_damage) {
|
||||
@@ -302,7 +298,7 @@ void Card::commit_attack(
|
||||
auto eff = s->assist_server->get_active_assist_by_index(z);
|
||||
if ((eff == AssistEffect::RANSOM) && (attacker_card->action_chain.chain.attack_medium == AttackMedium::PHYSICAL)) {
|
||||
uint8_t team_id = this->player_state()->get_team_id();
|
||||
int16_t exp_amount = clamp<int16_t>(s->team_exp[team_id], 0, effective_damage);
|
||||
int16_t exp_amount = std::clamp<int16_t>(s->team_exp[team_id], 0, effective_damage);
|
||||
s->team_exp[team_id] -= exp_amount;
|
||||
effective_damage -= exp_amount;
|
||||
if (!is_nte) {
|
||||
@@ -326,7 +322,7 @@ void Card::commit_attack(
|
||||
this->player_state()->stats.damage_taken += effective_damage;
|
||||
log.debug_f("updated stats");
|
||||
|
||||
this->current_hp = clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
|
||||
this->current_hp = std::clamp<int16_t>(this->current_hp - effective_damage, 0, this->max_hp);
|
||||
log.debug_f("hp set to {}", this->current_hp);
|
||||
|
||||
if ((effective_damage > 0) && (attacker_ps->stats.max_attack_damage < effective_damage)) {
|
||||
@@ -366,7 +362,7 @@ void Card::commit_attack(
|
||||
}
|
||||
}
|
||||
|
||||
int16_t Card::compute_defense_power_for_attacker_card(shared_ptr<const Card> attacker_card) {
|
||||
int16_t Card::compute_defense_power_for_attacker_card(std::shared_ptr<const Card> attacker_card) {
|
||||
if (!attacker_card) {
|
||||
return 0;
|
||||
}
|
||||
@@ -392,7 +388,7 @@ int16_t Card::compute_defense_power_for_attacker_card(shared_ptr<const Card> att
|
||||
return this->action_metadata.defense_power + this->action_metadata.defense_bonus;
|
||||
}
|
||||
|
||||
void Card::destroy_set_card(shared_ptr<Card> attacker_card) {
|
||||
void Card::destroy_set_card(std::shared_ptr<Card> attacker_card) {
|
||||
auto s = this->server();
|
||||
auto ps = this->player_state();
|
||||
|
||||
@@ -490,7 +486,7 @@ int32_t Card::error_code_for_move_to_location(const Location& loc) const {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
void Card::execute_attack(std::shared_ptr<Card> attacker_card) {
|
||||
if (!attacker_card) {
|
||||
return;
|
||||
}
|
||||
@@ -518,7 +514,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
if (attacker_card->action_chain.chain.attack_medium == AttackMedium::UNKNOWN_03) {
|
||||
// Probably Resta
|
||||
for (size_t strike_num = 0; strike_num < attacker_card->action_chain.chain.strike_count; strike_num++) {
|
||||
this->current_hp = min<int16_t>(this->current_hp + attacker_card->action_chain.chain.effective_tp, this->max_hp);
|
||||
this->current_hp = std::min<int16_t>(this->current_hp + attacker_card->action_chain.chain.effective_tp, this->max_hp);
|
||||
}
|
||||
this->propagate_shared_hp_if_needed();
|
||||
cmd.effect.tp = attacker_card->action_chain.chain.effective_tp;
|
||||
@@ -545,7 +541,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
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;
|
||||
int16_t preliminary_damage = std::max<int16_t>(raw_damage, 0) - attack_tp;
|
||||
this->last_attack_preliminary_damage = preliminary_damage;
|
||||
log.debug_f("raw_damage={}, preliminary_damange={}", raw_damage, preliminary_damage);
|
||||
|
||||
@@ -571,8 +567,8 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
}
|
||||
}
|
||||
|
||||
cmd.effect.current_hp = is_nte ? attack_ap : min<int16_t>(attack_ap, 99);
|
||||
cmd.effect.ap = is_nte ? defense_power : min<int16_t>(defense_power, 99);
|
||||
cmd.effect.current_hp = is_nte ? attack_ap : std::min<int16_t>(attack_ap, 99);
|
||||
cmd.effect.ap = is_nte ? defense_power : std::min<int16_t>(defense_power, 99);
|
||||
cmd.effect.tp = attack_tp;
|
||||
|
||||
auto ps = this->player_state();
|
||||
@@ -583,7 +579,7 @@ void Card::execute_attack(shared_ptr<Card> attacker_card) {
|
||||
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);
|
||||
ps->stats.action_card_negated_damage += std::max<int16_t>(0, this->current_defense_power - final_effective_damage);
|
||||
}
|
||||
} else {
|
||||
log.debug_f("flag 2 set; committing zero-damage attack");
|
||||
@@ -618,7 +614,7 @@ const Condition* Card::find_condition(ConditionType cond_type) const {
|
||||
return const_cast<Card*>(this)->find_condition(cond_type);
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Card::get_definition() const {
|
||||
std::shared_ptr<const CardIndex::CardEntry> Card::get_definition() const {
|
||||
return this->def_entry;
|
||||
}
|
||||
|
||||
@@ -839,10 +835,10 @@ void Card::set_current_and_max_hp(int16_t hp) {
|
||||
void Card::set_current_hp(
|
||||
uint32_t new_hp, bool propagate_shared_hp, bool enforce_max_hp) {
|
||||
if (!enforce_max_hp) {
|
||||
new_hp = max<int16_t>(new_hp, 0);
|
||||
this->max_hp = max<int16_t>(this->max_hp, new_hp);
|
||||
new_hp = std::max<int16_t>(new_hp, 0);
|
||||
this->max_hp = std::max<int16_t>(this->max_hp, new_hp);
|
||||
} else {
|
||||
new_hp = clamp<int16_t>(new_hp, 0, this->max_hp);
|
||||
new_hp = std::clamp<int16_t>(new_hp, 0, this->max_hp);
|
||||
}
|
||||
|
||||
this->current_hp = new_hp;
|
||||
@@ -955,11 +951,11 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
}
|
||||
|
||||
if (!this->action_chain.check_flag(0x10)) {
|
||||
this->action_chain.chain.effective_ap = is_nte ? effective_ap : min<int16_t>(effective_ap, 99);
|
||||
this->action_chain.chain.effective_ap = is_nte ? effective_ap : std::min<int16_t>(effective_ap, 99);
|
||||
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);
|
||||
this->action_chain.chain.effective_tp = is_nte ? effective_tp : std::min<int16_t>(effective_tp, 99);
|
||||
log.debug_f("set chain effective_tp = {}", this->action_chain.chain.effective_tp);
|
||||
}
|
||||
|
||||
@@ -1099,7 +1095,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
|
||||
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);
|
||||
: std::min<int16_t>(damage * this->action_chain.chain.damage_multiplier, 99);
|
||||
log.debug_f("overall chain damage = {} (base) * {} (mult) = {}",
|
||||
damage, this->action_chain.chain.damage_multiplier, this->action_chain.chain.damage);
|
||||
|
||||
@@ -1108,7 +1104,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
s->card_special->apply_action_conditions(EffectWhen::BEFORE_ANY_CARD_ATTACK, this_sh, this_sh, 2, nullptr);
|
||||
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);
|
||||
this->action_chain.chain.damage = std::min<int16_t>(this->action_chain.chain.damage + 5, 99);
|
||||
log.debug_f("(has flag 0x100) chain damage = {}", this->action_chain.chain.damage);
|
||||
}
|
||||
} else {
|
||||
@@ -1141,8 +1137,7 @@ void Card::compute_action_chain_results(bool apply_action_conditions, bool ignor
|
||||
}
|
||||
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string chain_str = this->action_chain.str(s);
|
||||
log.debug_f("result computed as {}", chain_str);
|
||||
log.debug_f("result computed as {}", this->action_chain.str(s));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1208,20 +1203,19 @@ void Card::move_phase_before() {
|
||||
this->server()->card_special->move_phase_before_for_card(this->shared_from_this());
|
||||
}
|
||||
|
||||
void Card::unknown_80236374(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
void Card::unknown_80236374(std::shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto s = this->server();
|
||||
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::L_DEBUG)) {
|
||||
if (as) {
|
||||
string as_str = as->str(s);
|
||||
log.debug_f("as = {}", as_str);
|
||||
log.debug_f("as = {}", as->str(s));
|
||||
} else {
|
||||
log.debug_f("as = null");
|
||||
}
|
||||
}
|
||||
|
||||
auto check_card = [&](shared_ptr<Card> card) -> void {
|
||||
auto check_card = [&](std::shared_ptr<Card> card) -> void {
|
||||
if (card) {
|
||||
if (!card->unknown_80236554(other_card, as)) {
|
||||
log.debug_f("check_card @{:04X} #{:04X} => false", card->get_card_ref(), card->get_card_id());
|
||||
@@ -1263,7 +1257,7 @@ void Card::unknown_802379DC(const ActionState& pa) {
|
||||
pa.defense_card_ref, this->shared_from_this(), pa.original_attacker_card_ref);
|
||||
this->server()->card_special->unknown_8024A9D8(pa, 0xFFFF);
|
||||
for (size_t z = 0; z < this->action_metadata.target_card_ref_count; z++) {
|
||||
shared_ptr<Card> card = this->server()->card_for_set_card_ref(this->action_metadata.target_card_refs[z]);
|
||||
std::shared_ptr<Card> card = this->server()->card_for_set_card_ref(this->action_metadata.target_card_refs[z]);
|
||||
if (card) {
|
||||
card->action_chain.set_action_subphase_from_card(this->shared_from_this());
|
||||
card->send_6xB4x4E_4C_4D_if_needed();
|
||||
@@ -1302,7 +1296,7 @@ void Card::unknown_80237A90(const ActionState& pa, uint16_t action_card_ref) {
|
||||
if (this->action_chain.chain.target_card_ref_count == 0) {
|
||||
for (size_t z = 0; (z < 4 * 9) && (pa.target_card_refs[z] != 0xFFFF); z++) {
|
||||
this->action_chain.add_target_card_ref(pa.target_card_refs[z]);
|
||||
shared_ptr<Card> sc_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
std::shared_ptr<Card> sc_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
if (sc_card) {
|
||||
sc_card->action_metadata.add_target_card_ref(this->card_ref);
|
||||
sc_card->card_flags |= 8;
|
||||
@@ -1357,7 +1351,7 @@ bool Card::is_guard_item() const {
|
||||
return (this->def_entry->def.card_class() == CardClass::GUARD_ITEM);
|
||||
}
|
||||
|
||||
bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as) {
|
||||
bool Card::unknown_80236554(std::shared_ptr<Card> other_card, const ActionState* as) {
|
||||
auto s = this->server();
|
||||
auto log = s->log_stack(other_card
|
||||
? 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())
|
||||
@@ -1395,7 +1389,7 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
}
|
||||
}
|
||||
|
||||
this->action_metadata.attack_bonus = max<int16_t>(attack_bonus, 0);
|
||||
this->action_metadata.attack_bonus = std::max<int16_t>(attack_bonus, 0);
|
||||
log.debug_f("attack_bonus = {}", this->action_metadata.attack_bonus);
|
||||
this->last_attack_preliminary_damage = 0;
|
||||
this->last_attack_final_damage = 0;
|
||||
@@ -1421,17 +1415,17 @@ bool Card::unknown_80236554(shared_ptr<Card> other_card, const ActionState* as)
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Card::execute_attack_on_all_valid_targets(shared_ptr<Card> attacker_card) {
|
||||
void Card::execute_attack_on_all_valid_targets(std::shared_ptr<Card> attacker_card) {
|
||||
auto s = this->server();
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = s->player_states[client_id];
|
||||
if (ps) {
|
||||
shared_ptr<Card> card = ps->get_sc_card();
|
||||
std::shared_ptr<Card> card = ps->get_sc_card();
|
||||
if (card) {
|
||||
card->execute_attack(attacker_card);
|
||||
}
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
shared_ptr<Card> card = ps->get_set_card(set_index);
|
||||
std::shared_ptr<Card> card = ps->get_set_card(set_index);
|
||||
if (card) {
|
||||
card->execute_attack(attacker_card);
|
||||
}
|
||||
@@ -1476,7 +1470,7 @@ void Card::apply_attack_result() {
|
||||
temp_chain.chain.target_card_ref_count++;
|
||||
} else if ((target_card->get_definition()->def.type == CardType::ITEM) && !this->action_chain.check_flag(0x02)) {
|
||||
auto target_ps = target_card->player_state();
|
||||
shared_ptr<Card> candidate_card;
|
||||
std::shared_ptr<Card> candidate_card;
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto set_card = target_ps->get_set_card(set_index);
|
||||
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2) && set_card->is_guard_item()) {
|
||||
@@ -1555,12 +1549,11 @@ void Card::apply_attack_result() {
|
||||
}
|
||||
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string as_str = as.str(s);
|
||||
log.debug_f("as constructed as {}", as_str);
|
||||
log.debug_f("as constructed as {}", as.str(s));
|
||||
}
|
||||
|
||||
for (size_t z = 0; z < this->action_chain.chain.target_card_ref_count; z++) {
|
||||
shared_ptr<Card> card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
std::shared_ptr<Card> card = s->card_for_set_card_ref(this->action_chain.chain.target_card_refs[z]);
|
||||
if (card) {
|
||||
card->current_defense_power = card->action_metadata.attack_bonus;
|
||||
if (!this->action_chain.check_flag(0x40)) {
|
||||
|
||||
+223
-236
File diff suppressed because it is too large
Load Diff
+234
-245
File diff suppressed because it is too large
Load Diff
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
NameEntry::NameEntry() {
|
||||
@@ -198,7 +196,7 @@ void DeckState::redraw_initial_hand(bool is_nte) {
|
||||
|
||||
auto s = this->server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is missing");
|
||||
throw std::runtime_error("server is missing");
|
||||
}
|
||||
|
||||
// Shuffle the deck, except the first 5 cards (which are about to be drawn).
|
||||
@@ -260,7 +258,7 @@ void DeckState::shuffle() {
|
||||
if (this->shuffle_enabled) {
|
||||
auto s = this->server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is missing");
|
||||
throw std::runtime_error("server is missing");
|
||||
}
|
||||
|
||||
size_t max = this->num_drawable_cards();
|
||||
@@ -305,17 +303,17 @@ void DeckState::print(FILE* stream, std::shared_ptr<const CardIndex> card_index)
|
||||
this->loop_enabled ? "true" : "false");
|
||||
for (size_t z = 0; z < 31; z++) {
|
||||
const auto& e = this->entries[z];
|
||||
shared_ptr<const CardIndex::CardEntry> ce;
|
||||
std::shared_ptr<const CardIndex::CardEntry> ce;
|
||||
if (card_index) {
|
||||
try {
|
||||
ce = card_index->definition_for_id(e.card_id);
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
}
|
||||
if (ce) {
|
||||
string name = ce->def.en_name.decode(Language::ENGLISH);
|
||||
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));
|
||||
z, e.deck_index, this->card_refs[z], e.card_id, ce->def.en_name.decode(Language::ENGLISH),
|
||||
name_for_card_state(e.state));
|
||||
} else {
|
||||
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));
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#include "MapState.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
MapState::MapState() {
|
||||
|
||||
+47
-53
@@ -2,11 +2,9 @@
|
||||
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
PlayerState::PlayerState(uint8_t client_id, std::shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
client_id(client_id),
|
||||
num_hand_redraws_allowed(1),
|
||||
@@ -46,10 +44,10 @@ void PlayerState::init() {
|
||||
if (s->player_states.at(this->client_id).get() != this) {
|
||||
// Note: The original code handles this, but we don't. This appears not to
|
||||
// ever happen, so we didn't bother implementing it.
|
||||
throw logic_error("replacing a player state object is not permitted");
|
||||
throw std::logic_error("replacing a player state object is not permitted");
|
||||
}
|
||||
|
||||
this->deck_state = make_shared<DeckState>(this->client_id, s->deck_entries[client_id]->card_ids, s);
|
||||
this->deck_state = std::make_shared<DeckState>(this->client_id, s->deck_entries[client_id]->card_ids, s);
|
||||
if (s->map_and_rules->rules.disable_deck_shuffle) {
|
||||
this->deck_state->disable_shuffle();
|
||||
}
|
||||
@@ -62,7 +60,7 @@ void PlayerState::init() {
|
||||
this->team_id = s->deck_entries[this->client_id]->team_id;
|
||||
auto sc_ce = s->definition_for_card_ref(this->sc_card_ref);
|
||||
if (!sc_ce) {
|
||||
throw runtime_error("SC card definition is missing");
|
||||
throw std::runtime_error("SC card definition is missing");
|
||||
}
|
||||
if (sc_ce->def.type == CardType::HUNTERS_SC) {
|
||||
this->sc_card_type = CardType::HUNTERS_SC;
|
||||
@@ -72,13 +70,13 @@ void PlayerState::init() {
|
||||
// In the original code, sc_card_type gets left as 0xFFFFFFFF (yes, it's a
|
||||
// uint32_t). This probably breaks some things later on, so we instead
|
||||
// prevent it upfront.
|
||||
throw runtime_error("SC card is not a Hunters or Arkz SC");
|
||||
throw std::runtime_error("SC card is not a Hunters or Arkz SC");
|
||||
}
|
||||
|
||||
this->hand_and_equip = make_shared<HandAndEquipState>();
|
||||
this->card_short_statuses = make_shared<parray<CardShortStatus, 0x10>>();
|
||||
this->set_card_action_chains = make_shared<parray<ActionChainWithConds, 9>>();
|
||||
this->set_card_action_metadatas = make_shared<parray<ActionMetadata, 9>>();
|
||||
this->hand_and_equip = std::make_shared<HandAndEquipState>();
|
||||
this->card_short_statuses = std::make_shared<parray<CardShortStatus, 0x10>>();
|
||||
this->set_card_action_chains = std::make_shared<parray<ActionChainWithConds, 9>>();
|
||||
this->set_card_action_metadatas = std::make_shared<parray<ActionMetadata, 9>>();
|
||||
|
||||
this->hand_and_equip->clear_FF();
|
||||
for (size_t z = 0; z < 0x10; z++) {
|
||||
@@ -89,7 +87,7 @@ void PlayerState::init() {
|
||||
this->set_card_action_metadatas->at(z).clear_FF();
|
||||
}
|
||||
|
||||
this->sc_card = make_shared<Card>(this->deck_state->sc_card_id(), this->sc_card_ref, this->client_id, s);
|
||||
this->sc_card = std::make_shared<Card>(this->deck_state->sc_card_id(), this->sc_card_ref, this->client_id, s);
|
||||
this->sc_card->init();
|
||||
this->draw_initial_hand();
|
||||
if (s->options.is_nte()) {
|
||||
@@ -114,18 +112,18 @@ void PlayerState::init() {
|
||||
this->god_whim_can_use_hidden_cards = (s->deck_entries[this->client_id]->god_whim_flag != 3);
|
||||
}
|
||||
|
||||
shared_ptr<Server> PlayerState::server() {
|
||||
std::shared_ptr<Server> PlayerState::server() {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const Server> PlayerState::server() const {
|
||||
std::shared_ptr<const Server> PlayerState::server() const {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
@@ -151,7 +149,7 @@ bool PlayerState::draw_cards_allowed() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter_ps) {
|
||||
void PlayerState::apply_assist_card_effect_on_set(std::shared_ptr<PlayerState> setter_ps) {
|
||||
auto s = this->server();
|
||||
|
||||
uint16_t assist_card_id = this->set_assist_card_id;
|
||||
@@ -244,7 +242,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
|
||||
case AssistEffect::LEGACY: {
|
||||
uint16_t total_cost = 0;
|
||||
for (ssize_t z = 7; z >= 0; z--) {
|
||||
shared_ptr<const Card> card = this->set_cards[z];
|
||||
std::shared_ptr<const Card> card = this->set_cards[z];
|
||||
if (card) {
|
||||
auto ce = card->get_definition();
|
||||
uint8_t card_cost = ce->def.self_cost;
|
||||
@@ -258,7 +256,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
|
||||
if (!is_nte) {
|
||||
this->on_cards_destroyed();
|
||||
}
|
||||
this->atk_points = min<uint8_t>(9, this->atk_points + (total_cost >> 1));
|
||||
this->atk_points = std::min<uint8_t>(9, this->atk_points + (total_cost >> 1));
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
if (!is_nte) {
|
||||
s->send_6xB4x05();
|
||||
@@ -353,7 +351,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
|
||||
if (is_nte
|
||||
? (other_ps->assist_remaining_turns != 90 && other_ps->assist_remaining_turns != 99)
|
||||
: (other_ps->assist_remaining_turns < 10)) {
|
||||
other_ps->assist_remaining_turns = min<uint8_t>(9, other_ps->assist_remaining_turns << 1);
|
||||
other_ps->assist_remaining_turns = std::min<uint8_t>(9, other_ps->assist_remaining_turns << 1);
|
||||
}
|
||||
|
||||
for (ssize_t set_index = is_nte ? 0 : -1; set_index < 8; set_index++) {
|
||||
@@ -369,7 +367,7 @@ void PlayerState::apply_assist_card_effect_on_set(shared_ptr<PlayerState> setter
|
||||
cond.remaining_turns <<= 1;
|
||||
}
|
||||
} else if (cond.remaining_turns < 10) {
|
||||
cond.remaining_turns = min<uint8_t>(9, cond.remaining_turns << 1);
|
||||
cond.remaining_turns = std::min<uint8_t>(9, cond.remaining_turns << 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -480,7 +478,7 @@ void PlayerState::apply_dice_effects() {
|
||||
}
|
||||
|
||||
for (size_t die_index = 0; die_index < 2; die_index++) {
|
||||
this->dice_results[die_index] = min<uint8_t>(this->dice_results[die_index], 9);
|
||||
this->dice_results[die_index] = std::min<uint8_t>(this->dice_results[die_index], 9);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -818,15 +816,14 @@ int32_t PlayerState::error_code_for_client_setting_card(
|
||||
}
|
||||
}
|
||||
|
||||
vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
std::vector<uint16_t> PlayerState::get_all_cards_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range, const Location& loc, uint8_t target_team_id) const {
|
||||
auto s = this->server();
|
||||
|
||||
auto log = s->log_stack("get_all_cards_within_range: ");
|
||||
string loc_str = loc.str();
|
||||
log.debug_f("loc={}, target_team_id={:02X}", loc_str, target_team_id);
|
||||
log.debug_f("loc={}, target_team_id={:02X}", loc.str(), target_team_id);
|
||||
|
||||
vector<uint16_t> ret;
|
||||
std::vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = s->player_states[client_id];
|
||||
if (other_ps && ((target_team_id == 0xFF) || (target_team_id == other_ps->get_team_id()))) {
|
||||
@@ -845,7 +842,7 @@ void PlayerState::get_short_status_for_card_index_in_hand(size_t hand_index, Car
|
||||
stat->card_ref = this->card_refs[hand_index - 1];
|
||||
}
|
||||
|
||||
shared_ptr<DeckState> PlayerState::get_deck() {
|
||||
std::shared_ptr<DeckState> PlayerState::get_deck() {
|
||||
return this->deck_state;
|
||||
}
|
||||
|
||||
@@ -871,11 +868,11 @@ uint16_t PlayerState::get_sc_card_id() const {
|
||||
return this->sc_card_id;
|
||||
}
|
||||
|
||||
shared_ptr<Card> PlayerState::get_sc_card() {
|
||||
std::shared_ptr<Card> PlayerState::get_sc_card() {
|
||||
return this->sc_card;
|
||||
}
|
||||
|
||||
shared_ptr<const Card> PlayerState::get_sc_card() const {
|
||||
std::shared_ptr<const Card> PlayerState::get_sc_card() const {
|
||||
return this->sc_card;
|
||||
}
|
||||
|
||||
@@ -887,11 +884,11 @@ CardType PlayerState::get_sc_card_type() const {
|
||||
return this->sc_card_type;
|
||||
}
|
||||
|
||||
shared_ptr<Card> PlayerState::get_set_card(size_t set_index) {
|
||||
std::shared_ptr<Card> PlayerState::get_set_card(size_t set_index) {
|
||||
return (set_index < 8) ? this->set_cards[set_index] : nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<const Card> PlayerState::get_set_card(size_t set_index) const {
|
||||
std::shared_ptr<const Card> PlayerState::get_set_card(size_t set_index) const {
|
||||
return (set_index < 8) ? this->set_cards[set_index] : nullptr;
|
||||
}
|
||||
|
||||
@@ -964,7 +961,7 @@ uint16_t PlayerState::pop_from_discard_log(uint16_t) {
|
||||
bool PlayerState::move_card_to_location_by_card_index(size_t card_index, const Location& new_loc) {
|
||||
auto s = this->server();
|
||||
|
||||
shared_ptr<Card> card;
|
||||
std::shared_ptr<Card> card;
|
||||
if (card_index == 0) {
|
||||
card = this->sc_card;
|
||||
} else {
|
||||
@@ -1010,7 +1007,7 @@ void PlayerState::move_null_hand_refs_to_end() {
|
||||
void PlayerState::on_cards_destroyed() {
|
||||
auto s = this->server();
|
||||
|
||||
unordered_multimap<uint16_t, bool> card_refs_map; // {card_ref: should_return_to_hand}
|
||||
std::unordered_multimap<uint16_t, bool> card_refs_map; // {card_ref: should_return_to_hand}
|
||||
for (size_t z = 0; z < 8; z++) {
|
||||
auto card = this->set_cards[z];
|
||||
if (!card || !(card->card_flags & 2)) {
|
||||
@@ -1333,7 +1330,7 @@ bool PlayerState::set_card_from_hand(
|
||||
}
|
||||
this->card_refs[card_index + 1] = card_ref;
|
||||
// Note: NTE doesn't call the destructor on the existing card, if there is one. Is that a bug?
|
||||
this->set_cards[card_index - 7] = make_shared<Card>(s->card_id_for_card_ref(card_ref), card_ref, this->client_id, s);
|
||||
this->set_cards[card_index - 7] = std::make_shared<Card>(s->card_id_for_card_ref(card_ref), card_ref, this->client_id, s);
|
||||
auto new_card = this->set_cards[card_index - 7];
|
||||
new_card->init();
|
||||
|
||||
@@ -1433,7 +1430,7 @@ void PlayerState::set_initial_location() {
|
||||
|
||||
static const uint8_t start_tile_defs_offset_for_team_size[4] = {0, 0, 1, 3};
|
||||
if (num_team_players >= 4) {
|
||||
throw logic_error("too many players on team");
|
||||
throw std::logic_error("too many players on team");
|
||||
}
|
||||
size_t start_tile_def_index = start_tile_defs_offset_for_team_size[num_team_players] + player_index_within_team;
|
||||
uint8_t player_start_tile = mr->map.start_tile_definitions[this->team_id][start_tile_def_index];
|
||||
@@ -1455,11 +1452,11 @@ void PlayerState::set_initial_location() {
|
||||
}
|
||||
}
|
||||
if (!start_tile_found) {
|
||||
throw runtime_error("player start location not set");
|
||||
throw std::runtime_error("player start location not set");
|
||||
}
|
||||
}
|
||||
|
||||
void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(shared_ptr<const Card> card) {
|
||||
void PlayerState::set_map_occupied_bit_for_card_on_warp_tile(std::shared_ptr<const Card> card) {
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
@@ -1524,7 +1521,7 @@ bool PlayerState::subtract_or_check_atk_or_def_points_for_action(const ActionSta
|
||||
|
||||
void PlayerState::subtract_atk_points(uint8_t cost) {
|
||||
this->atk_points -= cost;
|
||||
this->atk_points2 = min<uint8_t>(this->atk_points, this->atk_points2_max);
|
||||
this->atk_points2 = std::min<uint8_t>(this->atk_points, this->atk_points2_max);
|
||||
}
|
||||
|
||||
G_UpdateHand_Ep3_6xB4x02 PlayerState::prepare_6xB4x02() const {
|
||||
@@ -1571,7 +1568,7 @@ void PlayerState::set_random_assist_card_from_hand_for_free() {
|
||||
auto s = this->server();
|
||||
bool is_nte = s->options.is_nte();
|
||||
|
||||
vector<uint16_t> candidate_card_refs;
|
||||
std::vector<uint16_t> candidate_card_refs;
|
||||
for (size_t hand_index = 0; hand_index < 6; hand_index++) {
|
||||
uint16_t card_ref = this->card_refs[hand_index];
|
||||
auto ce = s->definition_for_card_ref(card_ref);
|
||||
@@ -1636,11 +1633,11 @@ void PlayerState::send_6xB4x04_if_needed(bool always_send) {
|
||||
}
|
||||
}
|
||||
|
||||
vector<uint16_t> PlayerState::get_card_refs_within_range_from_all_players(
|
||||
std::vector<uint16_t> PlayerState::get_card_refs_within_range_from_all_players(
|
||||
const parray<uint8_t, 9 * 9>& range, const Location& loc, CardType type) const {
|
||||
auto s = this->server();
|
||||
|
||||
vector<uint16_t> ret;
|
||||
std::vector<uint16_t> ret;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto other_ps = s->player_states[client_id];
|
||||
if (other_ps && ((other_ps->get_sc_card_type() == type) || (type == CardType::ITEM))) {
|
||||
@@ -1697,7 +1694,7 @@ void PlayerState::handle_before_turn_assist_effects() {
|
||||
break;
|
||||
case AssistEffect::ATK_DICE_2:
|
||||
// Note: This behavior doesn't match the card description. Is it supposed to add 2 or multiply by 2?
|
||||
this->atk_points = min<int16_t>(this->atk_points + 2, 9);
|
||||
this->atk_points = std::min<int16_t>(this->atk_points + 2, 9);
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
break;
|
||||
case AssistEffect::SKIP_TURN:
|
||||
@@ -1756,8 +1753,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
size_t z = 0;
|
||||
do {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug_f("on action card ref {}", ref_str);
|
||||
log.debug_f("on action card ref {}", s->debug_str_for_card_ref(pa.action_card_refs[z]));
|
||||
}
|
||||
card->unknown_80237A90(pa, pa.action_card_refs[z]);
|
||||
card->unknown_802379BC(pa.action_card_refs[z]);
|
||||
@@ -1793,8 +1789,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
auto target_card = s->card_for_set_card_ref(pa.target_card_refs[z]);
|
||||
if (target_card) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.target_card_refs[z]);
|
||||
log.debug_f("on target card ref {}", ref_str);
|
||||
log.debug_f("on target card ref {}", s->debug_str_for_card_ref(pa.target_card_refs[z]));
|
||||
}
|
||||
target_card->unknown_802379DC(pa);
|
||||
if (!is_nte) {
|
||||
@@ -1823,8 +1818,7 @@ bool PlayerState::set_action_cards_for_action_state(const ActionState& pa) {
|
||||
}
|
||||
for (size_t z = 0; (z < pa.action_card_refs.size()) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string ref_str = s->debug_str_for_card_ref(pa.action_card_refs[z]);
|
||||
log.debug_f("discarding {} from hand", ref_str);
|
||||
log.debug_f("discarding {} from hand", s->debug_str_for_card_ref(pa.action_card_refs[z]));
|
||||
}
|
||||
this->discard_ref_from_hand(pa.action_card_refs[z]);
|
||||
}
|
||||
@@ -1866,7 +1860,7 @@ void PlayerState::dice_phase_before() {
|
||||
this->send_set_card_updates();
|
||||
}
|
||||
|
||||
void PlayerState::handle_homesick_assist_effect_from_bomb(shared_ptr<Card> card) {
|
||||
void PlayerState::handle_homesick_assist_effect_from_bomb(std::shared_ptr<Card> card) {
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
@@ -1998,13 +1992,13 @@ void PlayerState::roll_main_dice_or_apply_after_effects() {
|
||||
}
|
||||
this->atk_points += s->team_dice_bonus[this->team_id];
|
||||
this->def_points += s->team_dice_bonus[this->team_id];
|
||||
this->atk_points = clamp<uint8_t>(this->atk_points, 1, 9);
|
||||
this->def_points = clamp<uint8_t>(this->def_points, 1, 9);
|
||||
this->atk_points = std::clamp<uint8_t>(this->atk_points, 1, 9);
|
||||
this->def_points = std::clamp<uint8_t>(this->def_points, 1, 9);
|
||||
if (!s->options.is_nte()) {
|
||||
this->atk_bonuses = this->atk_points - atk_before_bonuses;
|
||||
this->def_bonuses = this->def_points - def_before_bonuses;
|
||||
}
|
||||
this->atk_points2 = min<uint8_t>(this->atk_points2_max, this->atk_points);
|
||||
this->atk_points2 = std::min<uint8_t>(this->atk_points2_max, this->atk_points);
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
@@ -2036,7 +2030,7 @@ void PlayerState::compute_team_dice_bonus_after_draw_phase() {
|
||||
uint8_t current_team_turn = s->get_current_team_turn();
|
||||
uint8_t dice_boost = s->get_team_exp(current_team_turn) / (s->team_client_count[current_team_turn] * 12);
|
||||
s->card_special->adjust_dice_boost_if_team_has_condition_52(current_team_turn, &dice_boost, 0);
|
||||
s->team_dice_bonus[current_team_turn] = clamp<int16_t>(dice_boost, 0, 8);
|
||||
s->team_dice_bonus[current_team_turn] = std::clamp<int16_t>(dice_boost, 0, 8);
|
||||
this->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
Condition::Condition() {
|
||||
@@ -61,7 +59,7 @@ void Condition::clear_FF() {
|
||||
this->unknown_a8 = 0xFF;
|
||||
}
|
||||
|
||||
std::string Condition::str(shared_ptr<const Server> s) const {
|
||||
std::string Condition::str(std::shared_ptr<const Server> s) const {
|
||||
return std::format(
|
||||
"Condition[type={}, turns={}, a_arg={}, dice={}, flags={:02X}, "
|
||||
"def_eff_index={}, ref={}, value={}, giver_ref={} "
|
||||
@@ -98,7 +96,7 @@ void EffectResult::clear() {
|
||||
this->dice_roll_value = 0;
|
||||
}
|
||||
|
||||
std::string EffectResult::str(shared_ptr<const Server> s) const {
|
||||
std::string EffectResult::str(std::shared_ptr<const Server> s) const {
|
||||
return std::format(
|
||||
"EffectResult[att_ref={}, target_ref={}, value={}, cur_hp={}, ap={}, tp={}, flags={:02X}, op={}, cond_index={}, dice={}]",
|
||||
s->debug_str_for_card_ref(this->attacker_card_ref),
|
||||
@@ -130,7 +128,7 @@ bool CardShortStatus::operator!=(const CardShortStatus& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string CardShortStatus::str(shared_ptr<const Server> s) const {
|
||||
std::string CardShortStatus::str(std::shared_ptr<const Server> s) const {
|
||||
return std::format(
|
||||
"CardShortStatus[ref={}, cur_hp={}, flags={:08X}, loc={}, u1={:04X}, max_hp={}, u2={}]",
|
||||
s->debug_str_for_card_ref(this->card_ref),
|
||||
@@ -178,7 +176,7 @@ void ActionState::clear() {
|
||||
this->unused2 = 0xFFFF;
|
||||
}
|
||||
|
||||
std::string ActionState::str(shared_ptr<const Server> s) const {
|
||||
std::string ActionState::str(std::shared_ptr<const Server> s) const {
|
||||
return std::format(
|
||||
"ActionState[client={:X}, u={}, facing={}, attacker_ref={}, def_ref={}, target_refs={}, action_refs={}, orig_attacker_ref={}]",
|
||||
this->client_id,
|
||||
@@ -222,7 +220,7 @@ bool ActionChain::operator!=(const ActionChain& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionChain::str(shared_ptr<const Server> s) const {
|
||||
std::string ActionChain::str(std::shared_ptr<const Server> s) const {
|
||||
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={}, "
|
||||
@@ -309,8 +307,8 @@ bool ActionChainWithConds::operator!=(const ActionChainWithConds& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionChainWithConds::str(shared_ptr<const Server> s) const {
|
||||
string ret = "ActionChainWithConds[chain=";
|
||||
std::string ActionChainWithConds::str(std::shared_ptr<const Server> s) const {
|
||||
std::string ret = "ActionChainWithConds[chain=";
|
||||
ret += this->chain.str(s);
|
||||
ret += ", conds=[";
|
||||
for (size_t z = 0; z < this->conditions.size(); z++) {
|
||||
@@ -383,7 +381,7 @@ void ActionChainWithConds::set_flags(uint32_t flags) {
|
||||
this->chain.flags |= flags;
|
||||
}
|
||||
|
||||
void ActionChainWithConds::add_attack_action_card_ref(uint16_t card_ref, shared_ptr<Server> server) {
|
||||
void ActionChainWithConds::add_attack_action_card_ref(uint16_t card_ref, std::shared_ptr<Server> server) {
|
||||
if (card_ref != 0xFFFF) {
|
||||
this->chain.attack_action_card_refs[this->chain.attack_action_card_ref_count++] = card_ref;
|
||||
}
|
||||
@@ -397,7 +395,7 @@ void ActionChainWithConds::add_target_card_ref(uint16_t card_ref) {
|
||||
}
|
||||
}
|
||||
|
||||
void ActionChainWithConds::compute_attack_medium(shared_ptr<Server> server) {
|
||||
void ActionChainWithConds::compute_attack_medium(std::shared_ptr<Server> server) {
|
||||
this->chain.attack_medium = AttackMedium::PHYSICAL;
|
||||
for (size_t z = 0; z < this->chain.attack_action_card_ref_count; z++) {
|
||||
uint16_t card_ref = this->chain.attack_action_card_refs[z];
|
||||
@@ -437,7 +435,7 @@ bool ActionChainWithConds::get_condition_value(
|
||||
return any_found;
|
||||
}
|
||||
|
||||
void ActionChainWithConds::set_action_subphase_from_card(shared_ptr<const Card> card) {
|
||||
void ActionChainWithConds::set_action_subphase_from_card(std::shared_ptr<const Card> card) {
|
||||
this->chain.action_subphase = card->server()->get_current_action_subphase();
|
||||
}
|
||||
|
||||
@@ -545,7 +543,7 @@ bool ActionMetadata::operator!=(const ActionMetadata& other) const {
|
||||
return !this->operator==(other);
|
||||
}
|
||||
|
||||
std::string ActionMetadata::str(shared_ptr<const Server> s) const {
|
||||
std::string ActionMetadata::str(std::shared_ptr<const Server> s) const {
|
||||
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={}]",
|
||||
@@ -621,7 +619,7 @@ void ActionMetadata::add_target_card_ref(uint16_t card_ref) {
|
||||
}
|
||||
|
||||
void ActionMetadata::add_defense_card_ref(
|
||||
uint16_t defense_card_ref, shared_ptr<Card> card, uint16_t original_attacker_card_ref) {
|
||||
uint16_t defense_card_ref, std::shared_ptr<Card> card, uint16_t original_attacker_card_ref) {
|
||||
if ((defense_card_ref != 0xFFFF) && (this->defense_card_ref_count < 8)) {
|
||||
this->defense_card_refs[this->defense_card_ref_count] = defense_card_ref;
|
||||
this->original_attacker_card_refs[this->defense_card_ref_count] = original_attacker_card_ref;
|
||||
@@ -634,7 +632,7 @@ HandAndEquipState::HandAndEquipState() {
|
||||
this->clear();
|
||||
}
|
||||
|
||||
std::string HandAndEquipState::str(shared_ptr<const Server> s) const {
|
||||
std::string HandAndEquipState::str(std::shared_ptr<const Server> s) const {
|
||||
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={}, "
|
||||
@@ -777,7 +775,7 @@ uint8_t PlayerBattleStats::rank_for_score(float score) {
|
||||
|
||||
const char* PlayerBattleStats::name_for_rank(uint8_t rank) {
|
||||
if (rank >= RANK_THRESHOLD_COUNT + 1) {
|
||||
throw invalid_argument("invalid rank");
|
||||
throw std::invalid_argument("invalid rank");
|
||||
}
|
||||
return RANK_NAMES[rank];
|
||||
}
|
||||
@@ -842,12 +840,12 @@ static bool is_card_within_range(
|
||||
return ret;
|
||||
}
|
||||
|
||||
vector<uint16_t> get_card_refs_within_range(
|
||||
std::vector<uint16_t> get_card_refs_within_range(
|
||||
const parray<uint8_t, 9 * 9>& range,
|
||||
const Location& loc,
|
||||
const parray<CardShortStatus, 0x10>& short_statuses,
|
||||
phosg::PrefixedLogger* log) {
|
||||
vector<uint16_t> ret;
|
||||
std::vector<uint16_t> ret;
|
||||
if (is_card_within_range(range, loc, short_statuses[0], log)) {
|
||||
if (log) {
|
||||
log->debug_f("get_card_refs_within_range: sc card @{:04X} within range", short_statuses[0].card_ref);
|
||||
|
||||
+57
-64
@@ -5,20 +5,17 @@
|
||||
#include "DataIndexes.hh"
|
||||
#include "Server.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
void compute_effective_range(
|
||||
parray<uint8_t, 9 * 9>& ret,
|
||||
shared_ptr<const CardIndex> card_index,
|
||||
std::shared_ptr<const CardIndex> card_index,
|
||||
uint16_t card_id,
|
||||
const Location& loc,
|
||||
shared_ptr<const MapAndRulesState> map_and_rules,
|
||||
std::shared_ptr<const MapAndRulesState> map_and_rules,
|
||||
phosg::PrefixedLogger* log) {
|
||||
if (log && log->should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string loc_str = loc.str();
|
||||
log->debug_f("compute_effective_range: card_id=#{:04X}, loc={}", card_id, loc_str);
|
||||
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);
|
||||
}
|
||||
@@ -28,10 +25,10 @@ void compute_effective_range(
|
||||
if (card_id == 0xFFFE) { // Heavy Fog: one tile directly in front
|
||||
range_def[3] = 0x00000100;
|
||||
} else {
|
||||
shared_ptr<const CardIndex::CardEntry> ce;
|
||||
std::shared_ptr<const CardIndex::CardEntry> ce;
|
||||
try {
|
||||
ce = card_index->definition_for_id(card_id);
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
return;
|
||||
}
|
||||
for (size_t z = 0; z < 6; z++) {
|
||||
@@ -95,7 +92,7 @@ void compute_effective_range(
|
||||
up_y = 9 - y - 1;
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid direction");
|
||||
throw std::logic_error("invalid direction");
|
||||
}
|
||||
ret[y * 9 + x] = decoded_range[up_y * 9 + up_x];
|
||||
if (log) {
|
||||
@@ -117,9 +114,9 @@ void compute_effective_range(
|
||||
}
|
||||
|
||||
bool card_linkage_is_valid(
|
||||
shared_ptr<const CardIndex::CardEntry> right_ce,
|
||||
shared_ptr<const CardIndex::CardEntry> left_ce,
|
||||
shared_ptr<const CardIndex::CardEntry> sc_ce,
|
||||
std::shared_ptr<const CardIndex::CardEntry> right_ce,
|
||||
std::shared_ptr<const CardIndex::CardEntry> left_ce,
|
||||
std::shared_ptr<const CardIndex::CardEntry> sc_ce,
|
||||
bool has_permission_effect) {
|
||||
if (!right_ce) {
|
||||
return false;
|
||||
@@ -173,31 +170,27 @@ bool card_linkage_is_valid(
|
||||
return false;
|
||||
}
|
||||
|
||||
RulerServer::RulerServer(shared_ptr<Server> server)
|
||||
: w_server(server),
|
||||
team_id_for_client_id(0xFF),
|
||||
error_code1(0),
|
||||
error_code2(0),
|
||||
error_code3(0) {}
|
||||
RulerServer::RulerServer(std::shared_ptr<Server> server)
|
||||
: w_server(server), team_id_for_client_id(0xFF), error_code1(0), error_code2(0), error_code3(0) {}
|
||||
|
||||
shared_ptr<Server> RulerServer::server() {
|
||||
std::shared_ptr<Server> RulerServer::server() {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
shared_ptr<const Server> RulerServer::server() const {
|
||||
std::shared_ptr<const Server> RulerServer::server() const {
|
||||
auto s = this->w_server.lock();
|
||||
if (!s) {
|
||||
throw runtime_error("server is deleted");
|
||||
throw std::runtime_error("server is deleted");
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
ActionChainWithConds* RulerServer::action_chain_with_conds_for_card_ref(uint16_t card_ref) {
|
||||
return const_cast<ActionChainWithConds*>(as_const(*this).action_chain_with_conds_for_card_ref(card_ref));
|
||||
return const_cast<ActionChainWithConds*>(std::as_const(*this).action_chain_with_conds_for_card_ref(card_ref));
|
||||
}
|
||||
|
||||
const ActionChainWithConds* RulerServer::action_chain_with_conds_for_card_ref(uint16_t card_ref) const {
|
||||
@@ -398,7 +391,7 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(const ActionState& pa
|
||||
last_action_card_index = z;
|
||||
}
|
||||
|
||||
auto check_chain = [&]() -> optional<bool> {
|
||||
auto check_chain = [&]() -> std::optional<bool> {
|
||||
const auto* chain = this->action_chain_with_conds_for_card_ref(pa.attacker_card_ref);
|
||||
if (chain) {
|
||||
for (ssize_t cond_index = 8; cond_index >= 0; cond_index--) {
|
||||
@@ -415,7 +408,7 @@ bool RulerServer::attack_action_has_pierce_and_not_rampage(const ActionState& pa
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullopt;
|
||||
return std::nullopt;
|
||||
};
|
||||
|
||||
if (is_nte) {
|
||||
@@ -767,7 +760,7 @@ bool RulerServer::check_move_path_and_get_cost(
|
||||
if (max_dist < 1) {
|
||||
return false;
|
||||
}
|
||||
max_dist = min<uint8_t>(max_dist, 9);
|
||||
max_dist = std::min<uint8_t>(max_dist, 9);
|
||||
|
||||
const auto* short_status = this->short_status_for_card_ref(card_ref);
|
||||
if (!short_status) {
|
||||
@@ -1030,7 +1023,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
}
|
||||
break;
|
||||
case CriterionCode::HUNTER_NON_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0003, // Ino'lis
|
||||
@@ -1059,7 +1052,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_CLASS_MALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0113, // Teifu
|
||||
0x02AA, // H-HUmar
|
||||
@@ -1070,7 +1063,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
@@ -1094,7 +1087,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_NON_RA_CLASS_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
@@ -1117,7 +1110,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_CLASS_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
0x02AC, // H-HUcast
|
||||
@@ -1128,7 +1121,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_NON_RA_CLASS_NON_NEWMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0003, // Ino'lis
|
||||
0x0110, // Saligun
|
||||
@@ -1148,7 +1141,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_NON_NEWMAN_NON_FORCE_MALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
@@ -1166,7 +1159,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HUNEWEARL_CLASS_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0004, // Sil'fer
|
||||
0x02AB, // H-HUnewearl
|
||||
0x02CF, // H-HUnewearl
|
||||
@@ -1174,7 +1167,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_MALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0002, // Kranz
|
||||
0x0005, // Guykild
|
||||
0x02AE, // H-RAmar
|
||||
@@ -1185,7 +1178,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0006, // Kylria
|
||||
0x0114, // Stella
|
||||
0x02AF, // H-RAmarl
|
||||
@@ -1196,7 +1189,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_OR_FO_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0006, // Kylria
|
||||
0x0112, // Viviana
|
||||
@@ -1213,7 +1206,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HU_OR_RA_CLASS_HUMAN_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0001, // Orland
|
||||
0x0002, // Kranz
|
||||
0x0004, // Sil'fer
|
||||
@@ -1230,7 +1223,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_RA_CLASS_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0005, // Guykild
|
||||
0x0114, // Stella
|
||||
0x02B0, // H-RAcast
|
||||
@@ -1241,7 +1234,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_FO_CLASS_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0112, // Viviana
|
||||
0x02B3, // H-FOmarl
|
||||
@@ -1252,7 +1245,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_HUMAN_FEMALE_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0003, // Ino'lis
|
||||
0x0004, // Sil'fer
|
||||
0x0006, // Kylria
|
||||
@@ -1269,7 +1262,7 @@ bool RulerServer::check_usability_or_condition_apply(
|
||||
return ret && card_ids.count(card_id2);
|
||||
}
|
||||
case CriterionCode::HUNTER_ANDROID_SC: {
|
||||
static const unordered_set<uint16_t> card_ids = {
|
||||
static const std::unordered_set<uint16_t> card_ids = {
|
||||
0x0005, // Guykild
|
||||
0x0110, // Saligun
|
||||
0x0113, // Teifu
|
||||
@@ -1433,14 +1426,14 @@ uint16_t RulerServer::compute_attack_or_defense_costs(
|
||||
final_cost = 0;
|
||||
}
|
||||
} else {
|
||||
final_cost = max<int16_t>(final_cost, this->hand_and_equip_states[pa.client_id]->atk_points);
|
||||
final_cost = std::max<int16_t>(final_cost, this->hand_and_equip_states[pa.client_id]->atk_points);
|
||||
}
|
||||
}
|
||||
|
||||
if (out_ally_cost) {
|
||||
*out_ally_cost = total_ally_cost;
|
||||
}
|
||||
return max<int16_t>(final_cost, total_cost + assist_cost_bias);
|
||||
return std::max<int16_t>(final_cost, total_cost + assist_cost_bias);
|
||||
}
|
||||
|
||||
bool RulerServer::compute_effective_range_and_target_mode_for_attack(
|
||||
@@ -1627,7 +1620,7 @@ bool RulerServer::defense_card_can_apply_to_attack(
|
||||
bool RulerServer::defense_card_matches_any_attack_card_top_color(const ActionState& pa) const {
|
||||
auto ce = this->definition_for_card_ref(pa.action_card_refs[0]);
|
||||
if (!ce) {
|
||||
throw runtime_error("defense card definition is missing");
|
||||
throw std::runtime_error("defense card definition is missing");
|
||||
}
|
||||
const auto* chain = this->action_chain_with_conds_for_card_ref(pa.original_attacker_card_ref);
|
||||
if (chain->chain.attack_action_card_ref_count < 1) {
|
||||
@@ -1646,7 +1639,7 @@ bool RulerServer::defense_card_matches_any_attack_card_top_color(const ActionSta
|
||||
return false;
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_ref(uint16_t card_ref) const {
|
||||
std::shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_ref(uint16_t card_ref) const {
|
||||
uint16_t card_id = this->card_id_for_card_ref(card_ref);
|
||||
if (card_id == 0xFFFF) {
|
||||
return nullptr;
|
||||
@@ -1841,7 +1834,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
|
||||
return -0x7E;
|
||||
}
|
||||
} else {
|
||||
int16_t diff = max<int16_t>(summon_area_size - summon_cost, 0);
|
||||
int16_t diff = std::max<int16_t>(summon_area_size - summon_cost, 0);
|
||||
if (x_offset > 0) {
|
||||
if (loc->x < summon_area_loc.x) {
|
||||
return -0x7E;
|
||||
@@ -1860,7 +1853,7 @@ int32_t RulerServer::error_code_for_client_setting_card(
|
||||
return -0x7E;
|
||||
}
|
||||
} else {
|
||||
int16_t diff = max<int16_t>(summon_area_size - summon_cost, 0);
|
||||
int16_t diff = std::max<int16_t>(summon_area_size - summon_cost, 0);
|
||||
if (y_offset > 0) {
|
||||
if (loc->y < summon_area_loc.y) {
|
||||
return -0x7E;
|
||||
@@ -1974,7 +1967,7 @@ bool RulerServer::flood_fill_move_path(
|
||||
Direction dirs[3] = {direction, turn_left(direction), turn_right(direction)};
|
||||
for (size_t dir_index = 0; dir_index < 3; dir_index++) {
|
||||
if (static_cast<uint8_t>(dirs[dir_index]) > 3) {
|
||||
throw logic_error("invalid direction");
|
||||
throw std::logic_error("invalid direction");
|
||||
}
|
||||
ret |= this->flood_fill_move_path(
|
||||
chain,
|
||||
@@ -2017,7 +2010,7 @@ uint16_t RulerServer::get_ally_sc_card_ref(uint16_t card_ref) const {
|
||||
return 0xFFFF;
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint32_t card_id) const {
|
||||
std::shared_ptr<const CardIndex::CardEntry> RulerServer::definition_for_card_id(uint32_t card_id) const {
|
||||
return this->server()->definition_for_card_id(card_id);
|
||||
}
|
||||
|
||||
@@ -2130,11 +2123,11 @@ bool RulerServer::get_creature_summon_area(uint8_t client_id, Location* out_loc,
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) {
|
||||
std::shared_ptr<HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) {
|
||||
return (client_id < 4) ? this->hand_and_equip_states[client_id] : nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<const HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) const {
|
||||
std::shared_ptr<const HandAndEquipState> RulerServer::get_hand_and_equip_state_for_client_id(uint8_t client_id) const {
|
||||
return (client_id < 4) ? this->hand_and_equip_states[client_id] : nullptr;
|
||||
}
|
||||
|
||||
@@ -2171,7 +2164,7 @@ ssize_t RulerServer::get_path_cost(
|
||||
path_length *= cond.value;
|
||||
}
|
||||
}
|
||||
return clamp<ssize_t>(path_length + cost_penalty, 0, 99);
|
||||
return std::clamp<ssize_t>(path_length + cost_penalty, 0, 99);
|
||||
}
|
||||
|
||||
ActionType RulerServer::get_pending_action_type(const ActionState& pa) const {
|
||||
@@ -2440,9 +2433,9 @@ bool RulerServer::is_defense_valid(const ActionState& pa) {
|
||||
}
|
||||
|
||||
void RulerServer::link_objects(
|
||||
shared_ptr<MapAndRulesState> map_and_rules,
|
||||
shared_ptr<StateFlags> state_flags,
|
||||
shared_ptr<AssistServer> assist_server) {
|
||||
std::shared_ptr<MapAndRulesState> map_and_rules,
|
||||
std::shared_ptr<StateFlags> state_flags,
|
||||
std::shared_ptr<AssistServer> assist_server) {
|
||||
this->map_and_rules = map_and_rules;
|
||||
this->state_flags = state_flags;
|
||||
this->assist_server = assist_server;
|
||||
@@ -2491,7 +2484,7 @@ size_t RulerServer::max_move_distance_for_card_ref(uint32_t card_ref) const {
|
||||
if (this->find_condition_on_card_ref(card_ref, ConditionType::SET_MV, &cond, nullptr, true)) {
|
||||
ret = cond.value;
|
||||
}
|
||||
ret = max<ssize_t>(0, ret);
|
||||
ret = std::max<ssize_t>(0, ret);
|
||||
|
||||
size_t num_assists = this->assist_server->compute_num_assist_effects_for_client(client_id);
|
||||
bool has_stamina_effect = false;
|
||||
@@ -2505,7 +2498,7 @@ size_t RulerServer::max_move_distance_for_card_ref(uint32_t card_ref) const {
|
||||
}
|
||||
}
|
||||
|
||||
return has_stamina_effect ? 9 : min<ssize_t>(9, ret);
|
||||
return has_stamina_effect ? 9 : std::min<ssize_t>(9, ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2566,11 +2559,11 @@ void RulerServer::offsets_for_direction(
|
||||
|
||||
void RulerServer::register_player(
|
||||
uint8_t client_id,
|
||||
shared_ptr<HandAndEquipState> hes,
|
||||
shared_ptr<parray<CardShortStatus, 0x10>> short_statuses,
|
||||
shared_ptr<DeckEntry> deck_entry,
|
||||
shared_ptr<parray<ActionChainWithConds, 9>> set_card_action_chains,
|
||||
shared_ptr<parray<ActionMetadata, 9>> set_card_action_metadatas) {
|
||||
std::shared_ptr<HandAndEquipState> hes,
|
||||
std::shared_ptr<parray<CardShortStatus, 0x10>> short_statuses,
|
||||
std::shared_ptr<DeckEntry> deck_entry,
|
||||
std::shared_ptr<parray<ActionChainWithConds, 9>> set_card_action_chains,
|
||||
std::shared_ptr<parray<ActionMetadata, 9>> set_card_action_metadatas) {
|
||||
this->hand_and_equip_states[client_id] = hes;
|
||||
this->short_statuses[client_id] = short_statuses;
|
||||
this->deck_entries[client_id] = deck_entry;
|
||||
@@ -2656,7 +2649,7 @@ int32_t RulerServer::set_cost_for_card(uint8_t client_id, uint16_t card_ref) con
|
||||
// In NTE, Land Price is apparently 2x rather than 1.5x
|
||||
ret = is_nte ? (ret << 1) : (ret + (ret >> 1));
|
||||
} else if (eff == AssistEffect::DEFLATION) {
|
||||
ret = max<int32_t>(0, ret - 1);
|
||||
ret = std::max<int32_t>(0, ret - 1);
|
||||
} else if (eff == AssistEffect::INFLATION) {
|
||||
ret++;
|
||||
}
|
||||
|
||||
+117
-119
@@ -7,11 +7,9 @@
|
||||
#include "../Revision.hh"
|
||||
#include "../SendCommands.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
// This is (obviously) not the original string. The original string is:
|
||||
// This is (obviously) not the original std::string. The original std::string is:
|
||||
// NTE: "03/05/29 18:00 by K.Toya"
|
||||
// Final: "[V1][FINAL2.0] 03/09/13 15:30 by K.Toya"
|
||||
static const char* VERSION_SIGNATURE = "newserv Ep3 based on [V1][FINAL2.0] 03/09/13 15:30 by K.Toya";
|
||||
@@ -27,7 +25,7 @@ void Server::PresenceEntry::clear() {
|
||||
this->is_cpu_player = 0;
|
||||
}
|
||||
|
||||
Server::Server(shared_ptr<Lobby> lobby, Options&& options)
|
||||
Server::Server(std::shared_ptr<Lobby> lobby, Options&& options)
|
||||
: lobby(lobby),
|
||||
battle_record(lobby ? lobby->battle_record : nullptr),
|
||||
has_lobby(lobby != nullptr),
|
||||
@@ -81,7 +79,7 @@ Server::Server(shared_ptr<Lobby> lobby, Options&& options)
|
||||
|
||||
Server::~Server() noexcept(false) {
|
||||
if (this->logger_stack.size() != 1) {
|
||||
throw logic_error(std::format("incorrect logger stack size: expected 1, received {}", this->logger_stack.size()));
|
||||
throw std::logic_error(std::format("incorrect logger stack size: expected 1, received {}", this->logger_stack.size()));
|
||||
}
|
||||
delete this->logger_stack.back();
|
||||
}
|
||||
@@ -89,31 +87,31 @@ Server::~Server() noexcept(false) {
|
||||
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->map_and_rules = std::make_shared<MapAndRulesState>();
|
||||
this->num_clients_present = 0;
|
||||
this->overlay_state.clear();
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
this->presence_entries[z].clear();
|
||||
this->deck_entries[z] = make_shared<DeckEntry>();
|
||||
this->deck_entries[z] = std::make_shared<DeckEntry>();
|
||||
this->name_entries[z].clear();
|
||||
this->name_entries_valid[z] = false;
|
||||
}
|
||||
|
||||
this->card_special = make_shared<CardSpecial>(this->shared_from_this());
|
||||
this->card_special = std::make_shared<CardSpecial>(this->shared_from_this());
|
||||
|
||||
// Note: The original implementation calls the default PSOV2Encryption constructor for random_crypt, which just uses
|
||||
// 0 as the seed. It then re-seeds the generator later. We instead expect the caller to provide a seeded generator,
|
||||
// and we don't re-seed it at all.
|
||||
// this->random_crypt = make_shared<PSOV2Encryption>(0);
|
||||
// this->random_crypt = std::make_shared<PSOV2Encryption>(0);
|
||||
|
||||
this->state_flags = make_shared<StateFlags>();
|
||||
this->state_flags = std::make_shared<StateFlags>();
|
||||
|
||||
this->clear_player_flags_after_dice_phase();
|
||||
|
||||
this->update_battle_state_flags_and_send_6xB4x03_if_needed();
|
||||
|
||||
this->assist_server = make_shared<AssistServer>(this->shared_from_this());
|
||||
this->ruler_server = make_shared<RulerServer>(this->shared_from_this());
|
||||
this->assist_server = std::make_shared<AssistServer>(this->shared_from_this());
|
||||
this->ruler_server = std::make_shared<RulerServer>(this->shared_from_this());
|
||||
this->ruler_server->link_objects(this->map_and_rules, this->state_flags, this->assist_server);
|
||||
|
||||
this->send_6xB4x46();
|
||||
@@ -135,7 +133,7 @@ Server::StackLogger::StackLogger(StackLogger&& other)
|
||||
: PrefixedLogger(std::move(other)),
|
||||
server(other.server) {
|
||||
if (this->server->logger_stack.back() != &other) {
|
||||
throw logic_error("cannot move StackLogger unless it is the last one");
|
||||
throw std::logic_error("cannot move StackLogger unless it is the last one");
|
||||
}
|
||||
this->server->logger_stack.back() = this;
|
||||
}
|
||||
@@ -144,7 +142,7 @@ Server::StackLogger& Server::StackLogger::operator=(StackLogger&& other) {
|
||||
this->PrefixedLogger::operator=(std::move(other));
|
||||
this->server = other.server;
|
||||
if (this->server->logger_stack.back() != &other) {
|
||||
throw logic_error("cannot move StackLogger unless it is the last one");
|
||||
throw std::logic_error("cannot move StackLogger unless it is the last one");
|
||||
}
|
||||
this->server->logger_stack.back() = this;
|
||||
return *this;
|
||||
@@ -152,7 +150,7 @@ Server::StackLogger& Server::StackLogger::operator=(StackLogger&& other) {
|
||||
|
||||
Server::StackLogger::~StackLogger() noexcept(false) {
|
||||
if (this->server->logger_stack.back() != this) {
|
||||
throw logic_error("incorrect logger stack unwind order");
|
||||
throw std::logic_error("incorrect logger stack unwind order");
|
||||
}
|
||||
this->server->logger_stack.pop_back();
|
||||
}
|
||||
@@ -171,8 +169,7 @@ 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 std::format("@{:04X} (#{:04X} {})", card_ref, ce->def.card_id, name);
|
||||
return std::format("@{:04X} (#{:04X} {})", card_ref, ce->def.card_id, ce->def.en_name.decode());
|
||||
} else {
|
||||
return std::format("@{:04X} (missing)", card_ref);
|
||||
}
|
||||
@@ -184,8 +181,7 @@ 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 std::format("#{:04X} ({})", card_id, name);
|
||||
return std::format("#{:04X} ({})", card_id, ce->def.en_name.decode());
|
||||
} else {
|
||||
return std::format("#{:04X} (missing)", card_id);
|
||||
}
|
||||
@@ -209,17 +205,17 @@ int8_t Server::get_winner_team_id() const {
|
||||
}
|
||||
|
||||
if (!team_player_counts[0] || !team_player_counts[1]) {
|
||||
throw logic_error("at least one team has no players");
|
||||
throw std::logic_error("at least one team has no players");
|
||||
}
|
||||
if (team_win_flag_counts[0] && team_win_flag_counts[1]) {
|
||||
throw logic_error("both teams have winning players");
|
||||
throw std::logic_error("both teams have winning players");
|
||||
}
|
||||
for (int8_t z = 0; z < 2; z++) {
|
||||
if (!team_win_flag_counts[z]) {
|
||||
continue;
|
||||
}
|
||||
if (team_win_flag_counts[z] != team_player_counts[z]) {
|
||||
throw logic_error("only some players on team have won");
|
||||
throw std::logic_error("only some players on team have won");
|
||||
}
|
||||
return z;
|
||||
}
|
||||
@@ -236,10 +232,10 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
|
||||
if (this->has_lobby) {
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
throw std::runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
string masked_data;
|
||||
std::string masked_data;
|
||||
if (enable_masking &&
|
||||
!this->options.is_nte() &&
|
||||
!(this->options.behavior_flags & BehaviorFlag::DISABLE_MASKING) &&
|
||||
@@ -267,7 +263,7 @@ void Server::send(const void* data, size_t size, uint8_t command, bool enable_ma
|
||||
|
||||
void Server::send_6xB4x46() const {
|
||||
// Note: This function is not part of the original implementation; it was factored out from its callsites in this
|
||||
// file and the strings were changed.
|
||||
// file and the std::strings were changed.
|
||||
|
||||
// NTE doesn't have the date_str2 field, but we send it anyway to make debugging easier.
|
||||
G_ServerVersionStrings_Ep3_6xB4x46 cmd;
|
||||
@@ -275,12 +271,13 @@ void Server::send_6xB4x46() const {
|
||||
cmd.date_str1.encode(
|
||||
std::format("Card definitions: {:016X}", this->options.card_index->definitions_hash()),
|
||||
Language::ENGLISH);
|
||||
string build_date = phosg::format_time(BUILD_TIMESTAMP);
|
||||
std::string build_date = phosg::format_time(BUILD_TIMESTAMP);
|
||||
cmd.date_str2.encode(std::format("newserv {} compiled at {}", GIT_REVISION_HASH, build_date), Language::ENGLISH);
|
||||
this->send(cmd);
|
||||
}
|
||||
|
||||
string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> map, Language language, bool is_nte) {
|
||||
std::string Server::prepare_6xB6x41_map_definition(
|
||||
std::shared_ptr<const MapIndex::Map> map, Language language, bool is_nte) {
|
||||
auto vm = map->version(language);
|
||||
|
||||
const auto& compressed = vm->compressed(is_nte);
|
||||
@@ -295,7 +292,8 @@ string Server::prepare_6xB6x41_map_definition(shared_ptr<const MapIndex::Map> ma
|
||||
|
||||
void Server::send_commands_for_joining_spectator(std::shared_ptr<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());
|
||||
std::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}", name_for_language(ch->language), this->last_chosen_map->map_number);
|
||||
ch->send(0x6C, 0x00, data);
|
||||
@@ -366,11 +364,12 @@ void Server::add_team_exp(uint8_t team_id, int32_t exp) {
|
||||
}
|
||||
}
|
||||
|
||||
this->team_exp[team_id] = clamp<int16_t>(this->team_exp[team_id] + exp, 0, this->team_client_count[team_id] * 96);
|
||||
this->team_exp[team_id] = std::clamp<int16_t>(
|
||||
this->team_exp[team_id] + exp, 0, this->team_client_count[team_id] * 96);
|
||||
|
||||
uint8_t dice_boost = this->team_exp[team_id] / (this->team_client_count[team_id] * 12);
|
||||
this->card_special->adjust_dice_boost_if_team_has_condition_52(team_id, &dice_boost, 0);
|
||||
this->team_dice_bonus[team_id] = min<uint8_t>(dice_boost, 8);
|
||||
this->team_dice_bonus[team_id] = std::min<uint8_t>(dice_boost, 8);
|
||||
}
|
||||
|
||||
bool Server::advance_battle_phase() {
|
||||
@@ -396,7 +395,7 @@ bool Server::advance_battle_phase() {
|
||||
this->dice_phase_before();
|
||||
break;
|
||||
default:
|
||||
throw logic_error("invalid battle phase");
|
||||
throw std::logic_error("invalid battle phase");
|
||||
}
|
||||
return this->check_for_battle_end();
|
||||
}
|
||||
@@ -414,15 +413,15 @@ void Server::draw_phase_before() {
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_ref(uint16_t card_ref) const {
|
||||
std::shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_ref(uint16_t card_ref) const {
|
||||
try {
|
||||
return this->options.card_index->definition_for_id(this->card_id_for_card_ref(card_ref));
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
|
||||
std::shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
|
||||
if (card_ref == 0xFFFF) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -447,7 +446,7 @@ shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
|
||||
std::shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
|
||||
return const_cast<Server*>(this)->card_for_set_card_ref(card_ref);
|
||||
}
|
||||
|
||||
@@ -584,7 +583,7 @@ bool Server::check_for_battle_end() {
|
||||
void Server::force_replace_assist_card(uint8_t client_id, uint16_t card_id) {
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
throw runtime_error("player does not exist");
|
||||
throw std::runtime_error("player does not exist");
|
||||
}
|
||||
if (card_id == 0xFFFF) {
|
||||
ps->discard_set_assist_card();
|
||||
@@ -599,12 +598,12 @@ void Server::force_replace_assist_card(uint8_t client_id, uint16_t card_id) {
|
||||
void Server::force_destroy_field_character(uint8_t client_id, size_t visible_index) {
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
throw runtime_error("player does not exist");
|
||||
throw std::runtime_error("player does not exist");
|
||||
}
|
||||
|
||||
// TODO: Is it possible for there to be gaps in the set cards array? If not, we could just do a direct array lookup
|
||||
// here instead of this loop
|
||||
shared_ptr<Card> set_card = nullptr;
|
||||
std::shared_ptr<Card> set_card = nullptr;
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
if (!ps->set_cards[set_index]) {
|
||||
continue;
|
||||
@@ -681,7 +680,7 @@ void Server::compute_all_map_occupied_bits() {
|
||||
}
|
||||
|
||||
void Server::compute_team_dice_bonus(uint8_t team_id) {
|
||||
this->team_dice_bonus[team_id] = clamp<int16_t>(
|
||||
this->team_dice_bonus[team_id] = std::clamp<int16_t>(
|
||||
this->team_exp[team_id] / (this->team_client_count[team_id] * 12), 0, 8);
|
||||
}
|
||||
|
||||
@@ -700,10 +699,10 @@ void Server::copy_player_states_to_prev_states() {
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_id(uint16_t card_id) const {
|
||||
std::shared_ptr<const CardIndex::CardEntry> Server::definition_for_card_id(uint16_t card_id) const {
|
||||
try {
|
||||
return this->options.card_index->definition_for_id(card_id);
|
||||
} catch (const out_of_range&) {
|
||||
} catch (const std::out_of_range&) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -731,7 +730,7 @@ void Server::determine_first_team_turn() {
|
||||
this->team_client_count[0] = this->map_and_rules->num_team0_players;
|
||||
this->team_client_count[1] = this->map_and_rules->num_players - this->team_client_count[0];
|
||||
if (this->team_client_count[0] == 0 || this->team_client_count[1] == 0) {
|
||||
throw runtime_error("one or both teams have no players");
|
||||
throw std::runtime_error("one or both teams have no players");
|
||||
}
|
||||
this->first_team_turn = 0xFF;
|
||||
while (this->first_team_turn == 0xFF) {
|
||||
@@ -927,7 +926,7 @@ 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::L_DEBUG)) {
|
||||
string s = pa->str(this->shared_from_this());
|
||||
std::string s = pa->str(this->shared_from_this());
|
||||
log.debug_f("input: {}", s);
|
||||
}
|
||||
|
||||
@@ -977,8 +976,8 @@ bool Server::enqueue_attack_or_defense(uint8_t client_id, ActionState* pa) {
|
||||
size_t attack_index = this->num_pending_attacks++;
|
||||
this->pending_attacks[attack_index] = *pa;
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string pa_str = this->pending_attacks[attack_index].str(this->shared_from_this());
|
||||
log.debug_f("set pending attack {}: {}", attack_index, pa_str);
|
||||
log.debug_f("set pending attack {}: {}",
|
||||
attack_index, this->pending_attacks[attack_index].str(this->shared_from_this()));
|
||||
}
|
||||
ps->set_action_cards_for_action_state(*pa);
|
||||
log.debug_f("set action cards");
|
||||
@@ -1013,14 +1012,14 @@ uint8_t Server::get_current_team_turn() const {
|
||||
return this->current_team_turn1;
|
||||
}
|
||||
|
||||
shared_ptr<PlayerState> Server::get_player_state(uint8_t client_id) {
|
||||
std::shared_ptr<PlayerState> Server::get_player_state(uint8_t client_id) {
|
||||
if (client_id >= 4) {
|
||||
return nullptr;
|
||||
}
|
||||
return this->player_states[client_id];
|
||||
}
|
||||
|
||||
shared_ptr<const PlayerState> Server::get_player_state(uint8_t client_id) const {
|
||||
std::shared_ptr<const PlayerState> Server::get_player_state(uint8_t client_id) const {
|
||||
if (client_id >= 4) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1094,19 +1093,19 @@ void Server::move_phase_after() {
|
||||
continue;
|
||||
}
|
||||
|
||||
static const array<vector<uint16_t>, 5> DEFAULT_TRAP_CARD_IDS = {
|
||||
static const std::array<std::vector<uint16_t>, 5> DEFAULT_TRAP_CARD_IDS = {
|
||||
// Red: Dice Fever, Heavy Fog, Muscular, Immortality, Snail Pace
|
||||
vector<uint16_t>{0x00F7, 0x010F, 0x012E, 0x013B, 0x013C},
|
||||
std::vector<uint16_t>{0x00F7, 0x010F, 0x012E, 0x013B, 0x013C},
|
||||
// Blue: Gold Rush, Charity, Requiem
|
||||
vector<uint16_t>{0x0131, 0x012B, 0x0133},
|
||||
std::vector<uint16_t>{0x0131, 0x012B, 0x0133},
|
||||
// Purple: Powerless Rain, Trash 1, Empty Hand, Skip Draw
|
||||
vector<uint16_t>{0x00FA, 0x0125, 0x0126, 0x0137},
|
||||
std::vector<uint16_t>{0x00FA, 0x0125, 0x0126, 0x0137},
|
||||
// Green: Brave Wind, Homesick, Fly
|
||||
vector<uint16_t>{0x00FB, 0x014E, 0x0107},
|
||||
std::vector<uint16_t>{0x00FB, 0x014E, 0x0107},
|
||||
// Yellow: Dice+1, Battle Royale, Reverse Card, Giant Garden, Fix
|
||||
vector<uint16_t>{0x00F6, 0x0242, 0x014B, 0x0145, 0x012D}};
|
||||
std::vector<uint16_t>{0x00F6, 0x0242, 0x014B, 0x0145, 0x012D}};
|
||||
|
||||
const vector<uint16_t>* trap_card_ids = &this->options.trap_card_ids.at(trap_type);
|
||||
const std::vector<uint16_t>* trap_card_ids = &this->options.trap_card_ids.at(trap_type);
|
||||
if (trap_card_ids->empty()) {
|
||||
trap_card_ids = &DEFAULT_TRAP_CARD_IDS.at(trap_type);
|
||||
}
|
||||
@@ -1201,7 +1200,7 @@ int8_t Server::send_6xB4x33_remove_ally_atk_if_needed(const ActionState& pa) {
|
||||
bool has_ally_cost = false;
|
||||
uint8_t ally_cost = 0;
|
||||
uint8_t setter_client_id = 0xFF;
|
||||
shared_ptr<PlayerState> setter_ps = nullptr;
|
||||
std::shared_ptr<PlayerState> setter_ps = nullptr;
|
||||
cmd.card_ref = 0xFFFF;
|
||||
for (size_t z = 0; (z < 8) && (pa.action_card_refs[z] != 0xFFFF); z++) {
|
||||
auto ce = this->definition_for_card_ref(pa.action_card_refs[z]);
|
||||
@@ -1509,7 +1508,7 @@ void Server::setup_and_start_battle() {
|
||||
this->name_entries[z].clear();
|
||||
}
|
||||
} else {
|
||||
this->player_states[z] = make_shared<PlayerState>(z, this->shared_from_this());
|
||||
this->player_states[z] = std::make_shared<PlayerState>(z, this->shared_from_this());
|
||||
this->player_states[z]->init();
|
||||
}
|
||||
}
|
||||
@@ -1523,7 +1522,7 @@ void Server::setup_and_start_battle() {
|
||||
}
|
||||
auto card = ps->get_sc_card();
|
||||
if (card) {
|
||||
team_hp[ps->get_team_id()] = min<int16_t>(team_hp[ps->get_team_id()], card->get_current_hp());
|
||||
team_hp[ps->get_team_id()] = std::min<int16_t>(team_hp[ps->get_team_id()], card->get_current_hp());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1739,7 +1738,7 @@ bool Server::update_registration_phase() {
|
||||
return true;
|
||||
}
|
||||
|
||||
const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
const std::unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
{0x0B, &Server::handle_CAx0B_redraw_initial_hand},
|
||||
{0x0C, &Server::handle_CAx0C_end_redraw_initial_hand_phase},
|
||||
{0x0D, &Server::handle_CAx0D_end_non_action_phase},
|
||||
@@ -1765,23 +1764,23 @@ const unordered_map<uint8_t, Server::handler_t> Server::subcommand_handlers({
|
||||
{0x49, &Server::handle_CAx49_card_counts},
|
||||
});
|
||||
|
||||
void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& data) {
|
||||
void Server::on_server_data_input(std::shared_ptr<Client> sender_c, const std::string& data) {
|
||||
auto header = check_size_t<G_CardBattleCommandHeader>(data, 0xFFFF);
|
||||
size_t expected_size = header.size * 4;
|
||||
if (expected_size < data.size()) {
|
||||
phosg::print_data(stderr, data);
|
||||
throw runtime_error(std::format(
|
||||
throw std::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");
|
||||
throw std::runtime_error("server data command is not 6xB3");
|
||||
}
|
||||
|
||||
handler_t handler = nullptr;
|
||||
try {
|
||||
handler = this->subcommand_handlers.at(header.subsubcommand);
|
||||
} catch (const out_of_range&) {
|
||||
throw runtime_error("unknown CAx subsubcommand");
|
||||
} catch (const std::out_of_range&) {
|
||||
throw std::runtime_error("unknown CAx subsubcommand");
|
||||
}
|
||||
|
||||
if (this->battle_record && this->battle_record->writable()) {
|
||||
@@ -1791,17 +1790,17 @@ void Server::on_server_data_input(shared_ptr<Client> sender_c, const string& dat
|
||||
if ((sender_c && (sender_c->version() == Version::GC_EP3_NTE)) || !header.mask_key) {
|
||||
(this->*handler)(sender_c, data);
|
||||
} else {
|
||||
string unmasked_data = data;
|
||||
std::string unmasked_data = data;
|
||||
set_mask_for_ep3_game_command(unmasked_data.data(), unmasked_data.size(), 0);
|
||||
(this->*handler)(sender_c, unmasked_data);
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx0B_redraw_initial_hand(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0B_redraw_initial_hand(std::shared_ptr<Client>, const std::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) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -1829,11 +1828,11 @@ void Server::handle_CAx0B_redraw_initial_hand(shared_ptr<Client>, const string&
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
|
||||
}
|
||||
|
||||
void Server::handle_CAx0C_end_redraw_initial_hand_phase(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0C_end_redraw_initial_hand_phase(std::shared_ptr<Client>, const std::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) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -1887,11 +1886,11 @@ void Server::handle_CAx0C_end_redraw_initial_hand_phase(shared_ptr<Client>, cons
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
|
||||
}
|
||||
|
||||
void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0D_end_non_action_phase(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndNonAttackPhase_Ep3_CAx0D>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END PHASE");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
if (!this->options.is_nte()) {
|
||||
@@ -1909,11 +1908,11 @@ void Server::handle_CAx0D_end_non_action_phase(shared_ptr<Client>, const string&
|
||||
this->send(out_cmd_fin);
|
||||
}
|
||||
|
||||
void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0E_discard_card_from_hand(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_DiscardCardFromHand_Ep3_CAx0E>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "DISCARD");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -1948,11 +1947,11 @@ void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const strin
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, error_code);
|
||||
}
|
||||
|
||||
void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx0F_set_card_from_hand(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetCardFromHand_Ep3_CAx0F>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "SET FC");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -1994,11 +1993,11 @@ void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& d
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code1);
|
||||
}
|
||||
|
||||
void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx10_move_fc_to_location(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_MoveFieldCharacter_Ep3_CAx10>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "MOVE");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -2034,11 +2033,11 @@ void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string&
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code2);
|
||||
}
|
||||
|
||||
void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx11_enqueue_attack_or_defense(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EnqueueAttackOrDefense_Ep3_CAx11>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "ENQUEUE ACT");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -2072,11 +2071,11 @@ void Server::handle_CAx11_enqueue_attack_or_defense(shared_ptr<Client>, const st
|
||||
this->send_debug_message_if_error_code_nonzero(in_cmd.client_id, this->ruler_server->error_code3);
|
||||
}
|
||||
|
||||
void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx12_end_attack_list(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndAttackList_Ep3_CAx12>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END ATK LIST");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
int32_t error_code = 0;
|
||||
@@ -2097,7 +2096,7 @@ void Server::handle_CAx12_end_attack_list(shared_ptr<Client>, const string& data
|
||||
}
|
||||
|
||||
template <typename CmdT>
|
||||
void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client> c, const string& data) {
|
||||
void Server::handle_CAx13_update_map_during_setup_t(std::shared_ptr<Client> c, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<CmdT>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "UPDATE MAP");
|
||||
|
||||
@@ -2157,7 +2156,7 @@ void Server::handle_CAx13_update_map_during_setup_t(shared_ptr<Client> c, const
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client> c, const string& data) {
|
||||
void Server::handle_CAx13_update_map_during_setup(std::shared_ptr<Client> c, const std::string& data) {
|
||||
if (this->options.is_nte()) {
|
||||
this->handle_CAx13_update_map_during_setup_t<G_SetMapState_Ep3NTE_CAx13>(c, data);
|
||||
} else {
|
||||
@@ -2165,7 +2164,7 @@ void Server::handle_CAx13_update_map_during_setup(shared_ptr<Client> c, const st
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx14_update_deck_during_setup(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerDeck_Ep3_CAx14>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "UPDATE DECK");
|
||||
|
||||
@@ -2188,7 +2187,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
|
||||
}
|
||||
}
|
||||
if (verify_error) {
|
||||
throw runtime_error(std::format("invalid deck: -0x{:X}", verify_error));
|
||||
throw std::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);
|
||||
@@ -2211,7 +2210,7 @@ void Server::handle_CAx14_update_deck_during_setup(shared_ptr<Client>, const str
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx15_unused_hard_reset_server_state(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_HardResetServerState_Ep3_CAx15>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "HARD RESET");
|
||||
|
||||
@@ -2224,10 +2223,10 @@ void Server::handle_CAx15_unused_hard_reset_server_state(shared_ptr<Client>, con
|
||||
// this->send_all_state_updates();
|
||||
// this->update_registration_phase();
|
||||
// this->setup_and_start_battle();
|
||||
throw runtime_error("hard reset command received");
|
||||
throw std::runtime_error("hard reset command received");
|
||||
}
|
||||
|
||||
void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx1B_update_player_name(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_SetPlayerName_Ep3_CAx1B>(data);
|
||||
this->send_debug_command_received_message(in_cmd.entry.client_id, in_cmd.header.subsubcommand, "UPDATE NAME");
|
||||
|
||||
@@ -2258,7 +2257,7 @@ void Server::handle_CAx1B_update_player_name(shared_ptr<Client>, const string& d
|
||||
this->send(out_cmd);
|
||||
}
|
||||
|
||||
void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx1D_start_battle(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_StartBattle_Ep3_CAx1D>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "START BATTLE");
|
||||
|
||||
@@ -2304,7 +2303,7 @@ void Server::handle_CAx1D_start_battle(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx21_end_battle(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndBattle_Ep3_CAx21>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "END BATTLE");
|
||||
if (this->setup_phase == SetupPhase::BATTLE_ENDED) {
|
||||
@@ -2318,11 +2317,11 @@ void Server::handle_CAx21_end_battle(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx28_end_defense_list(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndDefenseList_Ep3_CAx28>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END DEF LIST");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
G_ActionResult_Ep3_6xB4x1E out_cmd_ack;
|
||||
@@ -2369,13 +2368,13 @@ void Server::handle_CAx28_end_defense_list(shared_ptr<Client>, const string& dat
|
||||
this->send(out_cmd_fin);
|
||||
}
|
||||
|
||||
void Server::handle_CAx2B_legacy_set_card(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx2B_legacy_set_card(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_ExecLegacyCard_Ep3_CAx2B>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "EXEC LEGACY");
|
||||
// Sega's original implementation does nothing here, so we do nothing as well.
|
||||
}
|
||||
|
||||
void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx34_subtract_ally_atk_points(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_PhotonBlastRequest_Ep3_CAx34>(data);
|
||||
|
||||
uint8_t card_ref_client_id = client_id_for_card_ref(in_cmd.card_ref);
|
||||
@@ -2450,11 +2449,11 @@ void Server::handle_CAx34_subtract_ally_atk_points(shared_ptr<Client>, const str
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_AdvanceFromStartingRollsPhase_Ep3_CAx37>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "CHOOSE ORDER");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
auto ps = this->player_states[in_cmd.client_id];
|
||||
@@ -2479,19 +2478,19 @@ void Server::handle_CAx37_client_ready_to_advance_from_starter_roll_phase(shared
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx3A_time_limit_expired(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx3A_time_limit_expired(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_OverallTimeLimitExpired_Ep3_CAx3A>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "TIME EXPIRED");
|
||||
// We don't need to do anything here because the overall time limit is tracked server-side instead.
|
||||
}
|
||||
|
||||
void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const string& data) {
|
||||
void Server::handle_CAx40_map_list_request(std::shared_ptr<Client> sender_c, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_MapListRequest_Ep3_CAx40>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.subsubcommand, "MAP LIST");
|
||||
|
||||
auto l = this->lobby.lock();
|
||||
if (!l) {
|
||||
throw runtime_error("lobby is deleted");
|
||||
throw std::runtime_error("lobby is deleted");
|
||||
}
|
||||
|
||||
size_t num_players = l ? l->count_clients() : 1;
|
||||
@@ -2512,13 +2511,13 @@ void Server::handle_CAx40_map_list_request(shared_ptr<Client> sender_c, const st
|
||||
|
||||
void Server::send_6xB6x41_to_all_clients() const {
|
||||
if (!this->last_chosen_map) {
|
||||
throw logic_error("cannot send 6xB4x41 without a map chosen");
|
||||
throw std::logic_error("cannot send 6xB4x41 without a map chosen");
|
||||
}
|
||||
|
||||
auto l = this->lobby.lock();
|
||||
if (l) {
|
||||
vector<string> map_commands_by_language;
|
||||
auto send_to_client = [&](shared_ptr<Client> c) -> void {
|
||||
std::vector<std::string> map_commands_by_language;
|
||||
auto send_to_client = [&](std::shared_ptr<Client> c) -> void {
|
||||
if (!c) {
|
||||
return;
|
||||
}
|
||||
@@ -2545,7 +2544,7 @@ void Server::send_6xB6x41_to_all_clients() const {
|
||||
if (this->battle_record && this->battle_record->writable()) {
|
||||
// TODO: It's not great that we just pick the first one; ideally we'd put all of them in the recording and send
|
||||
// the appropriate one to the client in the playback lobby
|
||||
for (string& data : map_commands_by_language) {
|
||||
for (std::string& data : map_commands_by_language) {
|
||||
if (!data.empty()) {
|
||||
this->battle_record->add_command(BattleRecord::Event::Type::BATTLE_COMMAND, std::move(data));
|
||||
break;
|
||||
@@ -2559,7 +2558,7 @@ void Server::send_6xB6x41_to_all_clients() const {
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx41_map_request(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& cmd = check_size_t<G_MapDataRequest_Ep3_CAx41>(data);
|
||||
this->send_debug_command_received_message(cmd.header.subsubcommand, "MAP DATA");
|
||||
if (!this->options.tournament || (this->options.tournament->get_map()->map_number == cmd.map_number)) {
|
||||
@@ -2568,11 +2567,11 @@ void Server::handle_CAx41_map_request(shared_ptr<Client>, const string& data) {
|
||||
}
|
||||
}
|
||||
|
||||
void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx48_end_turn(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_EndTurn_Ep3_CAx48>(data);
|
||||
this->send_debug_command_received_message(in_cmd.client_id, in_cmd.header.subsubcommand, "END TURN");
|
||||
if (in_cmd.client_id >= 4) {
|
||||
throw runtime_error("invalid client ID");
|
||||
throw std::runtime_error("invalid client ID");
|
||||
}
|
||||
|
||||
auto ps = this->get_player_state(in_cmd.client_id);
|
||||
@@ -2585,7 +2584,7 @@ void Server::handle_CAx48_end_turn(shared_ptr<Client>, const string& data) {
|
||||
this->send(out_cmd);
|
||||
}
|
||||
|
||||
void Server::handle_CAx49_card_counts(shared_ptr<Client>, const string& data) {
|
||||
void Server::handle_CAx49_card_counts(std::shared_ptr<Client>, const std::string& data) {
|
||||
const auto& in_cmd = check_size_t<G_CardCounts_Ep3_CAx49>(data);
|
||||
this->send_debug_command_received_message(in_cmd.header.sender_client_id, in_cmd.header.subsubcommand, "CARD COUNTS");
|
||||
|
||||
@@ -2612,7 +2611,7 @@ void Server::compute_losing_team_id_and_add_winner_flags(uint32_t flags) {
|
||||
uint32_t winner_flags = flags | AssistFlag::HAS_WON_BATTLE | AssistFlag::WINNER_DECIDED_BY_DEFEAT;
|
||||
|
||||
int8_t losing_team_id = -1;
|
||||
array<uint32_t, 2> team_counts = {0, 0};
|
||||
std::array<uint32_t, 2> team_counts{0, 0};
|
||||
|
||||
if (!is_nte) {
|
||||
// First, check which team has more dead SCs
|
||||
@@ -2747,8 +2746,7 @@ void Server::unknown_8023EEF4() {
|
||||
ActionState as = this->pending_attacks_with_cards[this->unknown_a14];
|
||||
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_f("as: {}", as_str);
|
||||
log.debug_f("as: {}", as.str(this->shared_from_this()));
|
||||
}
|
||||
if (is_nte) {
|
||||
this->replace_targets_due_to_destruction_nte(&as);
|
||||
@@ -2756,8 +2754,7 @@ void Server::unknown_8023EEF4() {
|
||||
this->replace_targets_due_to_destruction_or_conditions(&as);
|
||||
}
|
||||
if (log.should_log(phosg::LogLevel::L_DEBUG)) {
|
||||
string as_str = as.str(this->shared_from_this());
|
||||
log.debug_f("as after target replacement: {}", as_str);
|
||||
log.debug_f("as after target replacement: {}", as.str(this->shared_from_this()));
|
||||
}
|
||||
if (this->any_target_exists_for_attack(as)) {
|
||||
log.debug_f("as is valid");
|
||||
@@ -2837,8 +2834,8 @@ void Server::execute_bomb_assist_effect() {
|
||||
for (size_t set_index = 0; set_index < 8; set_index++) {
|
||||
auto card = ps->get_set_card(set_index);
|
||||
if (card && !(card->card_flags & 2)) {
|
||||
max_hp = max<int16_t>(max_hp, card->get_current_hp());
|
||||
min_hp = min<int16_t>(min_hp, card->get_current_hp());
|
||||
max_hp = std::max<int16_t>(max_hp, card->get_current_hp());
|
||||
min_hp = std::min<int16_t>(min_hp, card->get_current_hp());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2875,7 +2872,7 @@ void Server::replace_targets_due_to_destruction_nte(ActionState* as) {
|
||||
continue;
|
||||
}
|
||||
auto ps = target_card->player_state();
|
||||
shared_ptr<Card> found_guard_item;
|
||||
std::shared_ptr<Card> found_guard_item;
|
||||
for (size_t z = 0; z < 8; z++) {
|
||||
auto set_card = ps->get_set_card(z);
|
||||
if (set_card && (set_card != target_card) && !(set_card->card_flags & 2) && set_card->is_guard_item()) {
|
||||
@@ -2915,7 +2912,7 @@ void Server::replace_targets_due_to_destruction_or_conditions(ActionState* as) {
|
||||
return;
|
||||
}
|
||||
|
||||
vector<uint16_t> phase1_replaced_card_refs;
|
||||
std::vector<uint16_t> phase1_replaced_card_refs;
|
||||
for (size_t client_id = 0; client_id < 4; client_id++) {
|
||||
auto ps = this->get_player_state(client_id);
|
||||
if (!attacker_card->action_chain.check_flag(0x200 << client_id)) {
|
||||
@@ -3005,7 +3002,7 @@ void Server::replace_targets_due_to_destruction_or_conditions(ActionState* as) {
|
||||
}
|
||||
// as->target_card_refs[phase1_replaced_card_refs.size()] = 0xFFFF;
|
||||
|
||||
vector<uint16_t> phase2_replaced_card_refs;
|
||||
std::vector<uint16_t> phase2_replaced_card_refs;
|
||||
for (size_t z = 0; (z < 4 * 9) && (as->target_card_refs[z] != 0xFFFF); z++) {
|
||||
uint16_t target_card_ref = this->send_6xB4x06_if_card_ref_invalid(as->target_card_refs[z], 7);
|
||||
auto target_card = this->card_for_set_card_ref(target_card_ref);
|
||||
@@ -3105,13 +3102,14 @@ void Server::unknown_802402F4() {
|
||||
}
|
||||
}
|
||||
|
||||
vector<shared_ptr<Card>> Server::const_cast_set_cards_v(const vector<shared_ptr<const Card>>& cards) {
|
||||
std::vector<std::shared_ptr<Card>> Server::const_cast_set_cards_v(
|
||||
const std::vector<std::shared_ptr<const Card>>& cards) {
|
||||
// TODO: This is dumb. Figure out a not-dumb way to do this.
|
||||
vector<shared_ptr<Card>> ret;
|
||||
std::vector<std::shared_ptr<Card>> ret;
|
||||
for (auto const_card : cards) {
|
||||
auto mutable_card = this->card_for_set_card_ref(const_card->get_card_ref());
|
||||
if (mutable_card.get() != const_card.get()) {
|
||||
throw logic_error("inconsistent set cards index");
|
||||
throw std::logic_error("inconsistent set cards index");
|
||||
}
|
||||
ret.emplace_back(mutable_card);
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace Episode3 {
|
||||
// RulerServer.hh/cc
|
||||
// Server.hh/cc
|
||||
|
||||
// Class ownership levels (classes may contain weak_ptrs but not shared_ptrs to classes at the same or higher level):
|
||||
// Class ownership levels (classes may contain weak_ptrs but not std::shared_ptrs to classes at the same or higher level):
|
||||
// - Server
|
||||
// - - RulerServer
|
||||
// - - - AssistServer
|
||||
|
||||
+99
-115
@@ -7,23 +7,18 @@
|
||||
#include "../SendCommands.hh"
|
||||
#include "../ServerState.hh"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace Episode3 {
|
||||
|
||||
Tournament::PlayerEntry::PlayerEntry(uint32_t account_id, const string& player_name)
|
||||
: account_id(account_id),
|
||||
player_name(player_name) {}
|
||||
Tournament::PlayerEntry::PlayerEntry(uint32_t account_id, const std::string& player_name)
|
||||
: account_id(account_id), player_name(player_name) {}
|
||||
|
||||
Tournament::PlayerEntry::PlayerEntry(shared_ptr<Client> c)
|
||||
Tournament::PlayerEntry::PlayerEntry(std::shared_ptr<Client> c)
|
||||
: account_id(c->login->account->account_id),
|
||||
client(c),
|
||||
player_name(c->character_file()->disp.name.decode(c->language())) {}
|
||||
|
||||
Tournament::PlayerEntry::PlayerEntry(
|
||||
shared_ptr<const COMDeckDefinition> com_deck)
|
||||
: account_id(0),
|
||||
com_deck(com_deck) {}
|
||||
Tournament::PlayerEntry::PlayerEntry(std::shared_ptr<const COMDeckDefinition> com_deck)
|
||||
: account_id(0), com_deck(com_deck) {}
|
||||
|
||||
bool Tournament::PlayerEntry::is_com() const {
|
||||
return (this->com_deck != nullptr);
|
||||
@@ -33,8 +28,7 @@ bool Tournament::PlayerEntry::is_human() const {
|
||||
return (this->account_id != 0);
|
||||
}
|
||||
|
||||
Tournament::Team::Team(
|
||||
shared_ptr<Tournament> tournament, size_t index, size_t max_players)
|
||||
Tournament::Team::Team(std::shared_ptr<Tournament> tournament, size_t index, size_t max_players)
|
||||
: tournament(tournament),
|
||||
index(index),
|
||||
max_players(max_players),
|
||||
@@ -43,7 +37,7 @@ Tournament::Team::Team(
|
||||
num_rounds_cleared(0),
|
||||
is_active(true) {}
|
||||
|
||||
string Tournament::Team::str() const {
|
||||
std::string Tournament::Team::str() const {
|
||||
size_t num_human_players = 0;
|
||||
size_t num_com_players = 0;
|
||||
for (const auto& player : this->players) {
|
||||
@@ -51,7 +45,7 @@ string Tournament::Team::str() const {
|
||||
num_com_players += player.is_com();
|
||||
}
|
||||
|
||||
string ret = std::format("[Team/{} {} {}H/{}C/{}P name={} pass={} rounds={}",
|
||||
std::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,
|
||||
this->password, this->num_rounds_cleared);
|
||||
@@ -67,26 +61,27 @@ string Tournament::Team::str() const {
|
||||
return ret + "]";
|
||||
}
|
||||
|
||||
void Tournament::Team::register_player(shared_ptr<Client> c, const string& team_name, const string& password) {
|
||||
void Tournament::Team::register_player(
|
||||
std::shared_ptr<Client> c, const std::string& team_name, const std::string& password) {
|
||||
if (this->players.size() >= this->max_players) {
|
||||
throw runtime_error("team is full");
|
||||
throw std::runtime_error("team is full");
|
||||
}
|
||||
|
||||
if (!this->name.empty() && (password != this->password)) {
|
||||
throw runtime_error("incorrect password");
|
||||
throw std::runtime_error("incorrect password");
|
||||
}
|
||||
|
||||
auto tournament = this->tournament.lock();
|
||||
if (!tournament) {
|
||||
throw runtime_error("tournament has been deleted");
|
||||
throw std::runtime_error("tournament has been deleted");
|
||||
}
|
||||
if (!tournament->all_player_account_ids.emplace(c->login->account->account_id).second) {
|
||||
throw runtime_error("player already registered in same tournament");
|
||||
throw std::runtime_error("player already registered in same tournament");
|
||||
}
|
||||
|
||||
for (const auto& player : this->players) {
|
||||
if (player.is_human() && (player.account_id == c->login->account->account_id)) {
|
||||
throw logic_error("player already registered in team but not in tournament");
|
||||
throw std::logic_error("player already registered in team but not in tournament");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,7 +120,7 @@ bool Tournament::Team::unregister_player(uint32_t account_id) {
|
||||
// Look through the pending matches to see if this team is involved in any of them
|
||||
for (auto match : tournament->pending_matches) {
|
||||
if (!match->preceding_a || !match->preceding_b) {
|
||||
throw logic_error("zero-round match is pending after tournament registration phase");
|
||||
throw std::logic_error("zero-round match is pending after tournament registration phase");
|
||||
}
|
||||
if (match->preceding_a->winner_team.get() == this) {
|
||||
match->set_winner_team(match->preceding_b->winner_team);
|
||||
@@ -139,7 +134,7 @@ bool Tournament::Team::unregister_player(uint32_t account_id) {
|
||||
} else {
|
||||
// If the tournament has not started yet, just remove the player from the team
|
||||
if (!tournament->all_player_account_ids.erase(account_id)) {
|
||||
throw logic_error("player removed from team but not from tournament");
|
||||
throw std::logic_error("player removed from team but not from tournament");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,27 +171,19 @@ size_t Tournament::Team::num_com_players() const {
|
||||
}
|
||||
|
||||
Tournament::Match::Match(
|
||||
shared_ptr<Tournament> tournament, shared_ptr<Match> preceding_a, shared_ptr<Match> preceding_b)
|
||||
: tournament(tournament),
|
||||
preceding_a(preceding_a),
|
||||
preceding_b(preceding_b),
|
||||
winner_team(nullptr),
|
||||
round_num(0) {
|
||||
std::shared_ptr<Tournament> tournament, std::shared_ptr<Match> preceding_a, std::shared_ptr<Match> preceding_b)
|
||||
: tournament(tournament), preceding_a(preceding_a), preceding_b(preceding_b), winner_team(nullptr), round_num(0) {
|
||||
if (this->preceding_a->round_num != this->preceding_b->round_num) {
|
||||
throw logic_error("preceding matches have different round numbers");
|
||||
throw std::logic_error("preceding matches have different round numbers");
|
||||
}
|
||||
this->round_num = this->preceding_a->round_num + 1;
|
||||
}
|
||||
|
||||
Tournament::Match::Match(shared_ptr<Tournament> tournament, shared_ptr<Team> winner_team)
|
||||
: tournament(tournament),
|
||||
preceding_a(nullptr),
|
||||
preceding_b(nullptr),
|
||||
winner_team(winner_team),
|
||||
round_num(0) {}
|
||||
Tournament::Match::Match(std::shared_ptr<Tournament> tournament, std::shared_ptr<Team> winner_team)
|
||||
: tournament(tournament), preceding_a(nullptr), preceding_b(nullptr), winner_team(winner_team), round_num(0) {}
|
||||
|
||||
string Tournament::Match::str() const {
|
||||
string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
|
||||
std::string Tournament::Match::str() const {
|
||||
std::string winner_str = this->winner_team ? this->winner_team->str() : "(none)";
|
||||
return std::format("[Match round={} winner={}]", this->round_num, winner_str);
|
||||
}
|
||||
|
||||
@@ -262,12 +249,12 @@ void Tournament::Match::on_winner_team_set() {
|
||||
}
|
||||
}
|
||||
|
||||
void Tournament::Match::set_winner_team_without_triggers(shared_ptr<Team> team) {
|
||||
void Tournament::Match::set_winner_team_without_triggers(std::shared_ptr<Team> team) {
|
||||
if (!this->preceding_a || !this->preceding_b) {
|
||||
throw logic_error("set_winner_team called on zero-round match");
|
||||
throw std::logic_error("set_winner_team called on zero-round match");
|
||||
}
|
||||
if ((team != this->preceding_a->winner_team) && (team != this->preceding_b->winner_team)) {
|
||||
throw logic_error("winner team did not participate in match");
|
||||
throw std::logic_error("winner team did not participate in match");
|
||||
}
|
||||
|
||||
this->winner_team = team;
|
||||
@@ -280,29 +267,29 @@ void Tournament::Match::set_winner_team_without_triggers(shared_ptr<Team> team)
|
||||
}
|
||||
}
|
||||
|
||||
void Tournament::Match::set_winner_team(shared_ptr<Team> team) {
|
||||
void Tournament::Match::set_winner_team(std::shared_ptr<Team> team) {
|
||||
this->set_winner_team_without_triggers(team);
|
||||
this->on_winner_team_set();
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(shared_ptr<Team> team) const {
|
||||
std::shared_ptr<Tournament::Team> Tournament::Match::opponent_team_for_team(std::shared_ptr<Team> team) const {
|
||||
if (!this->preceding_a || !this->preceding_b) {
|
||||
throw logic_error("zero-round matches do not have opponents");
|
||||
throw std::logic_error("zero-round matches do not have opponents");
|
||||
}
|
||||
if (team == this->preceding_a->winner_team) {
|
||||
return this->preceding_b->winner_team;
|
||||
} else if (team == this->preceding_b->winner_team) {
|
||||
return this->preceding_a->winner_team;
|
||||
} else {
|
||||
throw logic_error("team is not registered for this match");
|
||||
throw std::logic_error("team is not registered for this match");
|
||||
}
|
||||
}
|
||||
|
||||
Tournament::Tournament(
|
||||
shared_ptr<const MapIndex> map_index,
|
||||
shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const string& name,
|
||||
shared_ptr<const MapIndex::Map> map,
|
||||
std::shared_ptr<const MapIndex> map_index,
|
||||
std::shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const std::string& name,
|
||||
std::shared_ptr<const MapIndex::Map> map,
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
uint8_t flags)
|
||||
@@ -317,18 +304,20 @@ Tournament::Tournament(
|
||||
current_state(State::REGISTRATION),
|
||||
menu_item_id(0xFFFFFFFF) {
|
||||
if (this->num_teams < 4) {
|
||||
throw invalid_argument("team count must be 4 or more");
|
||||
throw std::invalid_argument("team count must be 4 or more");
|
||||
}
|
||||
if (this->num_teams > 32) {
|
||||
throw invalid_argument("team count must be 32 or fewer");
|
||||
throw std::invalid_argument("team count must be 32 or fewer");
|
||||
}
|
||||
if (this->num_teams & (this->num_teams - 1)) {
|
||||
throw invalid_argument("team count must be a power of 2");
|
||||
throw std::invalid_argument("team count must be a power of 2");
|
||||
}
|
||||
}
|
||||
|
||||
Tournament::Tournament(
|
||||
shared_ptr<const MapIndex> map_index, shared_ptr<const COMDeckIndex> com_deck_index, const phosg::JSON& json)
|
||||
std::shared_ptr<const MapIndex> map_index,
|
||||
std::shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const phosg::JSON& json)
|
||||
: log(std::format("[Tournament:{}] ", json.get_string("name"))),
|
||||
map_index(map_index),
|
||||
com_deck_index(com_deck_index),
|
||||
@@ -336,7 +325,7 @@ Tournament::Tournament(
|
||||
current_state(State::REGISTRATION) {}
|
||||
|
||||
void Tournament::init() {
|
||||
vector<size_t> team_index_to_rounds_cleared;
|
||||
std::vector<size_t> team_index_to_rounds_cleared;
|
||||
|
||||
bool is_registration_complete;
|
||||
if (!this->source_json.is_null()) {
|
||||
@@ -350,7 +339,7 @@ void Tournament::init() {
|
||||
is_registration_complete = this->source_json.get_bool("is_registration_complete");
|
||||
|
||||
for (const auto& team_json : this->source_json.get_list("teams")) {
|
||||
auto& team = this->teams.emplace_back(make_shared<Team>(
|
||||
auto& team = this->teams.emplace_back(std::make_shared<Team>(
|
||||
this->shared_from_this(), this->teams.size(), team_json->get_int("max_players")));
|
||||
team->name = team_json->get_string("name");
|
||||
team->password = team_json->get_string("password");
|
||||
@@ -367,7 +356,7 @@ void Tournament::init() {
|
||||
} else if (player_json->is_string()) {
|
||||
team->players.emplace_back(this->com_deck_index->deck_for_name(player_json->as_string()));
|
||||
} else {
|
||||
throw runtime_error("invalid player spec");
|
||||
throw std::runtime_error("invalid player spec");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -378,7 +367,7 @@ void Tournament::init() {
|
||||
} else {
|
||||
// Create empty teams
|
||||
while (this->teams.size() < this->num_teams) {
|
||||
auto t = make_shared<Team>(this->shared_from_this(), this->teams.size(), (this->flags & Flag::IS_2V2) ? 2 : 1);
|
||||
auto t = std::make_shared<Team>(this->shared_from_this(), this->teams.size(), (this->flags & Flag::IS_2V2) ? 2 : 1);
|
||||
this->teams.emplace_back(t);
|
||||
}
|
||||
is_registration_complete = false;
|
||||
@@ -390,12 +379,12 @@ void Tournament::init() {
|
||||
this->create_bracket_matches();
|
||||
|
||||
// Start with all zero-round matches in the match queue
|
||||
unordered_set<shared_ptr<Match>> match_queue;
|
||||
std::unordered_set<std::shared_ptr<Match>> match_queue;
|
||||
for (auto match : this->zero_round_matches) {
|
||||
match_queue.emplace(match->following.lock());
|
||||
}
|
||||
if (match_queue.count(nullptr)) {
|
||||
throw logic_error("null match in match queue");
|
||||
throw std::logic_error("null match in match queue");
|
||||
}
|
||||
|
||||
// For each match in the queue, either resolve it from the previous state or
|
||||
@@ -406,12 +395,12 @@ void Tournament::init() {
|
||||
match_queue.erase(match_it);
|
||||
|
||||
if (!match->preceding_a->winner_team || !match->preceding_b->winner_team) {
|
||||
throw logic_error("preceding matches are not resolved");
|
||||
throw std::logic_error("preceding matches are not resolved");
|
||||
}
|
||||
size_t& a_rounds_cleared = team_index_to_rounds_cleared[match->preceding_a->winner_team->index];
|
||||
size_t& b_rounds_cleared = team_index_to_rounds_cleared[match->preceding_b->winner_team->index];
|
||||
if (a_rounds_cleared && b_rounds_cleared) {
|
||||
throw runtime_error("both teams won the same match");
|
||||
throw std::runtime_error("both teams won the same match");
|
||||
}
|
||||
if (!a_rounds_cleared && !b_rounds_cleared) {
|
||||
this->pending_matches.emplace(match); // Neither team has won yet
|
||||
@@ -434,7 +423,7 @@ void Tournament::init() {
|
||||
}
|
||||
|
||||
if (!this->final_match->winner_team == this->pending_matches.empty()) {
|
||||
throw logic_error("there must be pending matches if and only if the final match is not resolved");
|
||||
throw std::logic_error("there must be pending matches if and only if the final match is not resolved");
|
||||
}
|
||||
|
||||
// If all matches are resolved, then the tournament is complete
|
||||
@@ -449,19 +438,19 @@ void Tournament::init() {
|
||||
|
||||
void Tournament::create_bracket_matches() {
|
||||
if (this->teams.size() < 4) {
|
||||
throw logic_error("tournaments must have at least 4 teams");
|
||||
throw std::logic_error("tournaments must have at least 4 teams");
|
||||
}
|
||||
if (this->teams.size() > 32) {
|
||||
throw logic_error("tournaments must have at most 32 teams");
|
||||
throw std::logic_error("tournaments must have at most 32 teams");
|
||||
}
|
||||
if (this->teams.size() & (this->teams.size() - 1)) {
|
||||
throw logic_error("tournaments team count is not a power of 2");
|
||||
throw std::logic_error("tournaments team count is not a power of 2");
|
||||
}
|
||||
|
||||
// Create the zero-round matches, and make them all pending if registration is still open
|
||||
this->zero_round_matches.clear();
|
||||
for (const auto& team : this->teams) {
|
||||
auto m = make_shared<Match>(this->shared_from_this(), team);
|
||||
auto m = std::make_shared<Match>(this->shared_from_this(), team);
|
||||
this->zero_round_matches.emplace_back(m);
|
||||
if (this->current_state == State::REGISTRATION) {
|
||||
this->pending_matches.emplace(m);
|
||||
@@ -469,11 +458,11 @@ void Tournament::create_bracket_matches() {
|
||||
}
|
||||
|
||||
// Create the bracket matches
|
||||
vector<shared_ptr<Match>> current_round_matches = this->zero_round_matches;
|
||||
std::vector<std::shared_ptr<Match>> current_round_matches = this->zero_round_matches;
|
||||
while (current_round_matches.size() > 1) {
|
||||
vector<shared_ptr<Match>> next_round_matches;
|
||||
std::vector<std::shared_ptr<Match>> next_round_matches;
|
||||
for (size_t z = 0; z < current_round_matches.size(); z += 2) {
|
||||
auto m = make_shared<Match>(this->shared_from_this(), current_round_matches[z], current_round_matches[z + 1]);
|
||||
auto m = std::make_shared<Match>(this->shared_from_this(), current_round_matches[z], current_round_matches[z + 1]);
|
||||
current_round_matches[z]->following = m;
|
||||
current_round_matches[z + 1]->following = m;
|
||||
next_round_matches.emplace_back(std::move(m));
|
||||
@@ -516,26 +505,26 @@ phosg::JSON Tournament::json() const {
|
||||
});
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Team> Tournament::get_winner_team() const {
|
||||
std::shared_ptr<Tournament::Team> Tournament::get_winner_team() const {
|
||||
if (this->current_state != State::COMPLETE) {
|
||||
return nullptr;
|
||||
}
|
||||
if (!this->final_match) {
|
||||
throw logic_error("tournament is complete but final match is missing");
|
||||
throw std::logic_error("tournament is complete but final match is missing");
|
||||
}
|
||||
if (!this->final_match->winner_team) {
|
||||
throw logic_error("tournament is complete but winner is not set");
|
||||
throw std::logic_error("tournament is complete but winner is not set");
|
||||
}
|
||||
return this->final_match->winner_team;
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Match> Tournament::next_match_for_team(shared_ptr<Team> team) const {
|
||||
std::shared_ptr<Tournament::Match> Tournament::next_match_for_team(std::shared_ptr<Team> team) const {
|
||||
if (this->current_state == Tournament::State::REGISTRATION) {
|
||||
return nullptr;
|
||||
}
|
||||
for (auto match : this->pending_matches) {
|
||||
if (!match->preceding_a || !match->preceding_b) {
|
||||
throw logic_error("zero-round match is pending after tournament registration phase");
|
||||
throw std::logic_error("zero-round match is pending after tournament registration phase");
|
||||
}
|
||||
if ((team == match->preceding_a->winner_team) || (team == match->preceding_b->winner_team)) {
|
||||
return match;
|
||||
@@ -544,11 +533,11 @@ shared_ptr<Tournament::Match> Tournament::next_match_for_team(shared_ptr<Team> t
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Match> Tournament::get_final_match() const {
|
||||
std::shared_ptr<Tournament::Match> Tournament::get_final_match() const {
|
||||
return this->final_match;
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id) const {
|
||||
std::shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id) const {
|
||||
if (!this->all_player_account_ids.count(account_id)) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -561,16 +550,16 @@ shared_ptr<Tournament::Team> Tournament::team_for_account_id(uint32_t account_id
|
||||
}
|
||||
}
|
||||
|
||||
throw logic_error("account ID registered in tournament but not in any team");
|
||||
throw std::logic_error("account ID registered in tournament but not in any team");
|
||||
}
|
||||
|
||||
const set<uint32_t>& Tournament::get_all_player_account_ids() const {
|
||||
const std::set<uint32_t>& Tournament::get_all_player_account_ids() const {
|
||||
return this->all_player_account_ids;
|
||||
}
|
||||
|
||||
void Tournament::start() {
|
||||
if (this->current_state != State::REGISTRATION) {
|
||||
throw runtime_error("tournament has already started");
|
||||
throw std::runtime_error("tournament has already started");
|
||||
}
|
||||
|
||||
bool has_com_teams = (this->flags & Flag::HAS_COM_TEAMS);
|
||||
@@ -584,7 +573,7 @@ void Tournament::start() {
|
||||
}
|
||||
}
|
||||
if (num_human_teams < (has_com_teams ? 1 : 2)) {
|
||||
throw runtime_error("not enough registrants to start tournament");
|
||||
throw std::runtime_error("not enough registrants to start tournament");
|
||||
}
|
||||
|
||||
if ((this->flags & Flag::SHUFFLE_ENTRIES) && (this->flags & Flag::RESIZE_ON_START)) {
|
||||
@@ -642,11 +631,11 @@ void Tournament::start() {
|
||||
}
|
||||
for (const auto& player : t->players) {
|
||||
if (player.is_com()) {
|
||||
throw logic_error("non-human player on team before tournament start");
|
||||
throw std::logic_error("non-human player on team before tournament start");
|
||||
}
|
||||
}
|
||||
if (this->com_deck_index->num_decks() < t->max_players - t->players.size()) {
|
||||
throw runtime_error("not enough COM decks to complete team");
|
||||
throw std::runtime_error("not enough COM decks to complete team");
|
||||
}
|
||||
// If we allow all-COM teams, or this is a 2v2 tournament and the team has only one human on it, add a COM
|
||||
if (has_com_teams || !t->players.empty()) {
|
||||
@@ -687,10 +676,10 @@ void Tournament::send_all_state_updates_on_deletion() const {
|
||||
}
|
||||
}
|
||||
|
||||
string Tournament::bracket_str() const {
|
||||
string ret = std::format("Tournament \"{}\"\n", this->name);
|
||||
std::string Tournament::bracket_str() const {
|
||||
std::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 {
|
||||
std::function<void(std::shared_ptr<Match>, size_t)> add_match = [&](std::shared_ptr<Match> m, size_t indent_level) -> void {
|
||||
ret.append(2 * indent_level, ' ');
|
||||
ret += m->str();
|
||||
if (this->pending_matches.count(m)) {
|
||||
@@ -707,13 +696,12 @@ string Tournament::bracket_str() const {
|
||||
|
||||
auto en_vm = this->map->version(Language::ENGLISH);
|
||||
if (en_vm) {
|
||||
string map_name = en_vm->map->name.decode(en_vm->language);
|
||||
std::string map_name = en_vm->map->name.decode(en_vm->language);
|
||||
ret += std::format(" Map: {:08X} ({})\n", this->map->map_number, map_name);
|
||||
} else {
|
||||
ret += std::format(" Map: {:08X}\n", this->map->map_number);
|
||||
}
|
||||
string rules_str = this->rules.str();
|
||||
ret += std::format(" Rules: {}\n", rules_str);
|
||||
ret += std::format(" Rules: {}\n", this->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");
|
||||
@@ -739,14 +727,12 @@ string Tournament::bracket_str() const {
|
||||
if (this->current_state == State::REGISTRATION) {
|
||||
ret += " Teams:\n";
|
||||
for (const auto& team : this->teams) {
|
||||
string team_str = team->str();
|
||||
ret += std::format(" {}\n", team_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 += std::format(" {}\n", match_str);
|
||||
ret += std::format(" {}\n", match->str());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -755,13 +741,11 @@ string Tournament::bracket_str() const {
|
||||
}
|
||||
|
||||
TournamentIndex::TournamentIndex(
|
||||
shared_ptr<const MapIndex> map_index,
|
||||
shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const string& state_filename,
|
||||
std::shared_ptr<const MapIndex> map_index,
|
||||
std::shared_ptr<const COMDeckIndex> com_deck_index,
|
||||
const std::string& state_filename,
|
||||
bool skip_load_state)
|
||||
: map_index(map_index),
|
||||
com_deck_index(com_deck_index),
|
||||
state_filename(state_filename) {
|
||||
: map_index(map_index), com_deck_index(com_deck_index), state_filename(state_filename) {
|
||||
if (this->state_filename.empty() || skip_load_state) {
|
||||
return;
|
||||
}
|
||||
@@ -775,14 +759,14 @@ TournamentIndex::TournamentIndex(
|
||||
|
||||
if (json.is_list()) {
|
||||
if (json.size() > 0x20) {
|
||||
throw runtime_error("tournament phosg::JSON list length is incorrect");
|
||||
throw std::runtime_error("tournament phosg::JSON list length is incorrect");
|
||||
}
|
||||
for (size_t z = 0; z < min<size_t>(json.size(), 0x20); z++) {
|
||||
for (size_t z = 0; z < std::min<size_t>(json.size(), 0x20); z++) {
|
||||
if (!json.at(z).is_null()) {
|
||||
auto tourn = make_shared<Tournament>(this->map_index, this->com_deck_index, json.at(z));
|
||||
auto tourn = std::make_shared<Tournament>(this->map_index, this->com_deck_index, json.at(z));
|
||||
tourn->init();
|
||||
if (!this->name_to_tournament.emplace(tourn->get_name(), tourn).second) {
|
||||
throw runtime_error("multiple tournaments have the same name: " + tourn->get_name());
|
||||
throw std::runtime_error("multiple tournaments have the same name: " + tourn->get_name());
|
||||
}
|
||||
tourn->set_menu_item_id(this->menu_item_id_to_tournament.size());
|
||||
this->menu_item_id_to_tournament.emplace_back(tourn);
|
||||
@@ -790,20 +774,20 @@ TournamentIndex::TournamentIndex(
|
||||
}
|
||||
} else if (json.is_dict()) {
|
||||
if (json.size() > 0x20) {
|
||||
throw runtime_error("tournament phosg::JSON dict length is incorrect");
|
||||
throw std::runtime_error("tournament phosg::JSON dict length is incorrect");
|
||||
}
|
||||
for (const auto& it : json.as_dict()) {
|
||||
auto tourn = make_shared<Tournament>(this->map_index, this->com_deck_index, *it.second);
|
||||
auto tourn = std::make_shared<Tournament>(this->map_index, this->com_deck_index, *it.second);
|
||||
tourn->init();
|
||||
if (!this->name_to_tournament.emplace(tourn->get_name(), tourn).second) {
|
||||
// This is logic_error instead of runtime_error because phosg::JSON dicts already have unique keys
|
||||
throw logic_error("multiple tournaments have the same name: " + tourn->get_name());
|
||||
throw std::logic_error("multiple tournaments have the same name: " + tourn->get_name());
|
||||
}
|
||||
tourn->set_menu_item_id(this->menu_item_id_to_tournament.size());
|
||||
this->menu_item_id_to_tournament.emplace_back(tourn);
|
||||
}
|
||||
} else {
|
||||
throw runtime_error("tournament state root phosg::JSON is not a list or dict");
|
||||
throw std::runtime_error("tournament state root phosg::JSON is not a list or dict");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -819,20 +803,20 @@ void TournamentIndex::save() const {
|
||||
phosg::save_file(this->state_filename, json.serialize(phosg::JSON::SerializeOption::FORMAT | phosg::JSON::SerializeOption::HEX_INTEGERS | phosg::JSON::SerializeOption::ESCAPE_CONTROLS_ONLY));
|
||||
}
|
||||
|
||||
shared_ptr<Tournament> TournamentIndex::create_tournament(
|
||||
const string& name,
|
||||
shared_ptr<const MapIndex::Map> map,
|
||||
std::shared_ptr<Tournament> TournamentIndex::create_tournament(
|
||||
const std::string& name,
|
||||
std::shared_ptr<const MapIndex::Map> map,
|
||||
const Rules& rules,
|
||||
size_t num_teams,
|
||||
uint8_t flags) {
|
||||
if (this->name_to_tournament.size() >= 0x20) {
|
||||
throw runtime_error("there can be at most 32 tournaments at a time");
|
||||
throw std::runtime_error("there can be at most 32 tournaments at a time");
|
||||
}
|
||||
|
||||
auto t = make_shared<Tournament>(this->map_index, this->com_deck_index, name, map, rules, num_teams, flags);
|
||||
auto t = std::make_shared<Tournament>(this->map_index, this->com_deck_index, name, map, rules, num_teams, flags);
|
||||
t->init();
|
||||
if (!this->name_to_tournament.emplace(t->get_name(), t).second) {
|
||||
throw runtime_error("a tournament with the same name already exists");
|
||||
throw std::runtime_error("a tournament with the same name already exists");
|
||||
}
|
||||
|
||||
size_t z;
|
||||
@@ -852,7 +836,7 @@ shared_ptr<Tournament> TournamentIndex::create_tournament(
|
||||
return t;
|
||||
}
|
||||
|
||||
bool TournamentIndex::delete_tournament(const string& name) {
|
||||
bool TournamentIndex::delete_tournament(const std::string& name) {
|
||||
auto it = this->name_to_tournament.find(name);
|
||||
if (it == this->name_to_tournament.end()) {
|
||||
return false;
|
||||
@@ -869,7 +853,7 @@ bool TournamentIndex::delete_tournament(const string& name) {
|
||||
return true;
|
||||
}
|
||||
|
||||
shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t account_id) const {
|
||||
std::shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t account_id) const {
|
||||
for (const auto& it : this->name_to_tournament) {
|
||||
const auto& tourn = it.second;
|
||||
auto team = tourn->team_for_account_id(account_id);
|
||||
@@ -880,7 +864,7 @@ shared_ptr<Tournament::Team> TournamentIndex::team_for_account_id(uint32_t accou
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TournamentIndex::link_client(shared_ptr<Client> c) {
|
||||
void TournamentIndex::link_client(std::shared_ptr<Client> c) {
|
||||
if (!is_ep3(c->version())) {
|
||||
return;
|
||||
}
|
||||
@@ -898,7 +882,7 @@ void TournamentIndex::link_client(shared_ptr<Client> c) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw logic_error("tournament team found for player, but player not found on team");
|
||||
throw std::logic_error("tournament team found for player, but player not found on team");
|
||||
} else {
|
||||
c->ep3_tournament_team.reset();
|
||||
if (c->version() == Version::GC_EP3) {
|
||||
|
||||
Reference in New Issue
Block a user