add $setassist command
This commit is contained in:
+50
-4
@@ -1762,6 +1762,54 @@ static void server_command_ep3_set_def_dice_range(shared_ptr<Client> c, const st
|
||||
}
|
||||
}
|
||||
|
||||
static void server_command_ep3_replace_assist_card(shared_ptr<Client> c, const std::string& args) {
|
||||
auto s = c->require_server_state();
|
||||
auto l = c->require_lobby();
|
||||
check_is_game(l, true);
|
||||
check_is_ep3(c, true);
|
||||
check_cheats_enabled(l, c);
|
||||
|
||||
if (l->episode != Episode::EP3) {
|
||||
throw logic_error("non-Ep3 client in Ep3 game");
|
||||
}
|
||||
if (!l->ep3_server) {
|
||||
send_text_message(c, "$C6Episode 3 server\nis not initialized");
|
||||
return;
|
||||
}
|
||||
if (l->ep3_server->setup_phase != Episode3::SetupPhase::MAIN_BATTLE) {
|
||||
send_text_message(c, "$C6Battle has not\nyet begun");
|
||||
return;
|
||||
}
|
||||
if (args.empty()) {
|
||||
send_text_message(c, "$C6Missing arguments");
|
||||
return;
|
||||
}
|
||||
|
||||
uint8_t client_id;
|
||||
string card_name;
|
||||
if (isdigit(args[0])) {
|
||||
auto tokens = split(args, ' ', 1);
|
||||
client_id = stoul(tokens.at(0), nullptr, 0);
|
||||
card_name = tokens.at(1);
|
||||
} else {
|
||||
client_id = c->lobby_client_id;
|
||||
card_name = args;
|
||||
}
|
||||
|
||||
shared_ptr<const Episode3::CardIndex::CardEntry> ce;
|
||||
try {
|
||||
ce = l->ep3_server->options.card_index->definition_for_name_normalized(card_name);
|
||||
} catch (const out_of_range&) {
|
||||
send_text_message(c, "$C6Card not found");
|
||||
return;
|
||||
}
|
||||
if (ce->def.type != Episode3::CardType::ASSIST) {
|
||||
send_text_message(c, "$C6Card is not an\nAssist card");
|
||||
return;
|
||||
}
|
||||
l->ep3_server->force_replace_assist_card(client_id, ce->def.card_id);
|
||||
}
|
||||
|
||||
static void server_command_ep3_unset_field_character(shared_ptr<Client> c, const std::string& args) {
|
||||
auto s = c->require_server_state();
|
||||
auto l = c->require_lobby();
|
||||
@@ -1823,10 +1871,7 @@ static void server_command_get_ep3_battle_stat(shared_ptr<Client> c, const std::
|
||||
send_text_message(c, "$C6Battle has not\nyet started");
|
||||
return;
|
||||
}
|
||||
if (c->lobby_client_id >= 4) {
|
||||
throw logic_error("client ID is too large");
|
||||
}
|
||||
auto ps = l->ep3_server->player_states[c->lobby_client_id];
|
||||
auto ps = l->ep3_server->player_states.at(c->lobby_client_id);
|
||||
if (!ps) {
|
||||
send_text_message(c, "$C6Player is missing");
|
||||
return;
|
||||
@@ -1950,6 +1995,7 @@ static const unordered_map<string, ChatCommandDefinition> chat_commands({
|
||||
{"$saverec", {server_command_saverec, nullptr}},
|
||||
{"$sc", {server_command_send_client, proxy_command_send_client}},
|
||||
{"$secid", {server_command_secid, proxy_command_secid}},
|
||||
{"$setassist", {server_command_ep3_replace_assist_card, nullptr}},
|
||||
{"$si", {server_command_server_info, nullptr}},
|
||||
{"$silence", {server_command_silence, nullptr}},
|
||||
{"$song", {server_command_song, proxy_command_song}},
|
||||
|
||||
@@ -1850,7 +1850,7 @@ bool CardSpecial::execute_effect(
|
||||
if (client_id == 0xFF) {
|
||||
return false;
|
||||
}
|
||||
auto ps = this->server()->player_states[client_id];
|
||||
auto ps = this->server()->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return false;
|
||||
}
|
||||
@@ -1993,7 +1993,7 @@ bool CardSpecial::execute_effect(
|
||||
if (client_id == 0xFF) {
|
||||
return false;
|
||||
}
|
||||
auto ps = this->server()->player_states[client_id];
|
||||
auto ps = this->server()->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return false;
|
||||
}
|
||||
@@ -2034,8 +2034,8 @@ bool CardSpecial::execute_effect(
|
||||
uint8_t attacker_client_id = client_id_for_card_ref(cond.card_ref);
|
||||
uint8_t target_client_id = client_id_for_card_ref(card->get_card_ref());
|
||||
if ((attacker_client_id != 0xFF) && (target_client_id != 0xFF)) {
|
||||
auto attacker_ps = this->server()->player_states[attacker_client_id];
|
||||
auto target_ps = this->server()->player_states[target_client_id];
|
||||
auto attacker_ps = this->server()->player_states.at(attacker_client_id);
|
||||
auto target_ps = this->server()->player_states.at(target_client_id);
|
||||
if (attacker_ps && target_ps) {
|
||||
uint8_t attacker_team_id = attacker_ps->get_team_id();
|
||||
uint8_t target_team_id = target_ps->get_team_id();
|
||||
@@ -2157,8 +2157,8 @@ bool CardSpecial::execute_effect(
|
||||
case ConditionType::GIVE_OR_TAKE_EXP:
|
||||
if (unknown_p7 & 4) {
|
||||
uint8_t client_id = client_id_for_card_ref(card->get_card_ref());
|
||||
if ((client_id != 0xFF) && this->server()->player_states[client_id]) {
|
||||
uint8_t team_id = this->server()->player_states[client_id]->get_team_id();
|
||||
if ((client_id != 0xFF) && this->server()->player_states.at(client_id)) {
|
||||
uint8_t team_id = this->server()->player_states.at(client_id)->get_team_id();
|
||||
int32_t existing_exp = this->server()->team_exp[team_id];
|
||||
if ((clamped_expr_value + existing_exp) < 0) {
|
||||
clamped_expr_value = -existing_exp;
|
||||
@@ -3672,7 +3672,7 @@ void CardSpecial::evaluate_and_apply_effects(
|
||||
|
||||
DiceRoll dice_roll;
|
||||
uint8_t client_id = client_id_for_card_ref(dice_cmd.effect.target_card_ref);
|
||||
auto set_card_ps = (client_id == 0xFF) ? nullptr : this->server()->player_states[client_id];
|
||||
auto set_card_ps = (client_id == 0xFF) ? nullptr : this->server()->player_states.at(client_id);
|
||||
|
||||
dice_roll.value = 1;
|
||||
if (set_card_ps) {
|
||||
|
||||
@@ -42,7 +42,7 @@ PlayerState::PlayerState(uint8_t client_id, shared_ptr<Server> server)
|
||||
void PlayerState::init() {
|
||||
auto s = this->server();
|
||||
|
||||
if (s->player_states[this->client_id].get() != this) {
|
||||
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");
|
||||
@@ -1267,7 +1267,7 @@ bool PlayerState::set_card_from_hand(
|
||||
return false;
|
||||
}
|
||||
|
||||
auto target_ps = s->player_states[assist_target_client_id];
|
||||
auto target_ps = s->player_states.at(assist_target_client_id);
|
||||
if (target_ps) {
|
||||
uint16_t prev_assist_card_ref = target_ps->card_refs[6];
|
||||
target_ps->discard_set_assist_card();
|
||||
@@ -1752,7 +1752,7 @@ void PlayerState::unknown_8023C174() {
|
||||
this->send_set_card_updates(0);
|
||||
}
|
||||
|
||||
void PlayerState::handle_homesick_assist_effect(shared_ptr<Card> card) {
|
||||
void PlayerState::handle_homesick_assist_effect_from_bomb(shared_ptr<Card> card) {
|
||||
if (!card) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
int16_t get_assist_turns_remaining();
|
||||
bool set_action_cards_for_action_state(const ActionState& pa);
|
||||
void unknown_8023C174();
|
||||
void handle_homesick_assist_effect(std::shared_ptr<Card> card);
|
||||
void handle_homesick_assist_effect_from_bomb(std::shared_ptr<Card> card);
|
||||
void apply_main_die_assist_effects(uint8_t* die_value) const;
|
||||
void roll_main_dice();
|
||||
void unknown_8023C110();
|
||||
|
||||
+33
-21
@@ -418,7 +418,7 @@ shared_ptr<Card> Server::card_for_set_card_ref(uint16_t card_ref) {
|
||||
if (client_id == 0xFF) {
|
||||
return nullptr;
|
||||
}
|
||||
auto ps = this->player_states[client_id];
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -444,7 +444,7 @@ shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
|
||||
if (client_id == 0xFF) {
|
||||
return nullptr;
|
||||
}
|
||||
auto ps = this->player_states[client_id];
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -464,10 +464,11 @@ shared_ptr<const Card> Server::card_for_set_card_ref(uint16_t card_ref) const {
|
||||
uint16_t Server::card_id_for_card_ref(uint16_t card_ref) const {
|
||||
uint8_t client_id = client_id_for_card_ref(card_ref);
|
||||
if (client_id != 0xFF) {
|
||||
if (!this->player_states[client_id]) {
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return 0xFFFF;
|
||||
}
|
||||
auto deck = this->player_states[client_id]->get_deck();
|
||||
auto deck = ps->get_deck();
|
||||
if (deck) {
|
||||
return deck->card_id_for_card_ref(card_ref);
|
||||
}
|
||||
@@ -558,8 +559,19 @@ bool Server::check_for_battle_end() {
|
||||
return ret;
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
ps->replace_assist_card_by_id(card_id);
|
||||
}
|
||||
|
||||
void Server::force_destroy_field_character(uint8_t client_id, size_t visible_index) {
|
||||
auto ps = this->player_states[client_id];
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
throw 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
|
||||
@@ -584,7 +596,7 @@ void Server::force_destroy_field_character(uint8_t client_id, size_t visible_ind
|
||||
}
|
||||
|
||||
void Server::force_battle_result(uint8_t specified_client_id, bool set_winner) {
|
||||
auto specified_ps = this->player_states[specified_client_id];
|
||||
auto specified_ps = this->player_states.at(specified_client_id);
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
auto ps = this->player_states[z];
|
||||
if (ps) {
|
||||
@@ -824,7 +836,7 @@ void Server::end_attack_list_for_client(uint8_t client_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ps = this->player_states[client_id];
|
||||
auto ps = this->player_states.at(client_id);
|
||||
if (!ps) {
|
||||
return;
|
||||
}
|
||||
@@ -1670,10 +1682,11 @@ void Server::handle_CAx0B_mulligan_hand(shared_ptr<Client>, const string& data)
|
||||
error_code = -0x78;
|
||||
}
|
||||
if (error_code == 0) {
|
||||
if (!this->player_states[in_cmd.client_id]) {
|
||||
auto ps = this->player_states.at(in_cmd.client_id);
|
||||
if (!ps) {
|
||||
error_code = -0x72;
|
||||
} else {
|
||||
this->player_states[in_cmd.client_id]->do_mulligan();
|
||||
ps->do_mulligan();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1709,18 +1722,17 @@ void Server::handle_CAx0C_end_mulligan_phase(shared_ptr<Client>, const string& d
|
||||
this->send(out_cmd_ack);
|
||||
|
||||
if (error_code == 0) {
|
||||
if (!this->player_states[in_cmd.client_id]) {
|
||||
auto ps = this->player_states.at(in_cmd.client_id);
|
||||
if (!ps) {
|
||||
error_code = -0x72;
|
||||
} else {
|
||||
this->clients_done_in_mulligan_phase[in_cmd.client_id] = true;
|
||||
auto ps = this->player_states[in_cmd.client_id];
|
||||
ps->assist_flags |= AssistFlag::READY_TO_END_PHASE;
|
||||
ps->update_hand_and_equip_state_and_send_6xB4x02_if_needed();
|
||||
|
||||
bool all_clients_ready = true;
|
||||
for (size_t z = 0; z < 4; z++) {
|
||||
if (this->player_states[z] &&
|
||||
!this->clients_done_in_mulligan_phase[z]) {
|
||||
if (this->player_states[z] && !this->clients_done_in_mulligan_phase[z]) {
|
||||
all_clients_ready = false;
|
||||
break;
|
||||
}
|
||||
@@ -1781,7 +1793,7 @@ void Server::handle_CAx0E_discard_card_from_hand(shared_ptr<Client>, const strin
|
||||
}
|
||||
|
||||
if (error_code == 0) {
|
||||
auto ps = this->player_states[in_cmd.client_id];
|
||||
auto ps = this->player_states.at(in_cmd.client_id);
|
||||
if (!ps) {
|
||||
error_code = -0x72;
|
||||
} else if (!(ps->assist_flags & AssistFlag::IS_SKIPPING_TURN)) {
|
||||
@@ -1824,11 +1836,11 @@ void Server::handle_CAx0F_set_card_from_hand(shared_ptr<Client>, const string& d
|
||||
}
|
||||
if (error_code == 0) {
|
||||
this->ruler_server->error_code1 = 0;
|
||||
if (!this->player_states[in_cmd.client_id]) {
|
||||
auto ps = this->player_states.at(in_cmd.client_id);
|
||||
if (!ps) {
|
||||
this->ruler_server->error_code1 = -0x72;
|
||||
} else {
|
||||
this->player_states[in_cmd.client_id]->set_card_from_hand(
|
||||
in_cmd.card_ref, in_cmd.set_index, &in_cmd.loc, in_cmd.assist_target_player, 0);
|
||||
ps->set_card_from_hand(in_cmd.card_ref, in_cmd.set_index, &in_cmd.loc, in_cmd.assist_target_player, 0);
|
||||
}
|
||||
} else {
|
||||
this->ruler_server->error_code1 = error_code;
|
||||
@@ -1861,12 +1873,12 @@ void Server::handle_CAx10_move_fc_to_location(shared_ptr<Client>, const string&
|
||||
error_code = -0x78;
|
||||
}
|
||||
if (error_code == 0) {
|
||||
if (!this->player_states[in_cmd.client_id]) {
|
||||
auto ps = this->player_states.at(in_cmd.client_id);
|
||||
if (!ps) {
|
||||
this->ruler_server->error_code2 = -0x72;
|
||||
} else {
|
||||
this->ruler_server->error_code2 = 0;
|
||||
this->player_states[in_cmd.client_id]->move_card_to_location_by_card_index(
|
||||
in_cmd.set_index, in_cmd.loc);
|
||||
ps->move_card_to_location_by_card_index(in_cmd.set_index, in_cmd.loc);
|
||||
}
|
||||
} else {
|
||||
this->ruler_server->error_code2 = error_code;
|
||||
@@ -2655,7 +2667,7 @@ void Server::execute_bomb_assist_effect() {
|
||||
auto card = ps->get_set_card(set_index);
|
||||
if (card && !(card->card_flags & 2) &&
|
||||
((card->get_current_hp() == max_hp) || (card->get_current_hp() == min_hp))) {
|
||||
card->player_state()->handle_homesick_assist_effect(card);
|
||||
card->player_state()->handle_homesick_assist_effect_from_bomb(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ public:
|
||||
void send_commands_for_joining_spectator(Channel& ch) const;
|
||||
|
||||
void force_battle_result(uint8_t surrendered_client_id, bool set_winner);
|
||||
void force_replace_assist_card(uint8_t client_id, uint16_t card_id);
|
||||
void force_destroy_field_character(uint8_t client_id, size_t set_index);
|
||||
|
||||
__attribute__((format(printf, 2, 3))) void send_debug_message_printf(const char* fmt, ...) const;
|
||||
@@ -288,7 +289,7 @@ public:
|
||||
uint32_t should_copy_prev_states_to_current_states;
|
||||
std::shared_ptr<CardSpecial> card_special;
|
||||
std::shared_ptr<StateFlags> state_flags;
|
||||
std::shared_ptr<PlayerState> player_states[4];
|
||||
std::array<std::shared_ptr<PlayerState>, 4> player_states;
|
||||
parray<uint32_t, 4> clients_done_in_mulligan_phase;
|
||||
uint32_t num_pending_attacks_with_cards;
|
||||
std::shared_ptr<Card> attack_cards[0x20];
|
||||
|
||||
Reference in New Issue
Block a user