fix various battle mode behaviors
This commit is contained in:
@@ -5510,9 +5510,9 @@ struct G_ExchangeItemForTeamPoints_BB_6xCC {
|
||||
// 6xCE: Accept master transfer (BB)
|
||||
// Same format as 6xC1
|
||||
|
||||
// 6xCF: Restart battle (BB)
|
||||
// 6xCF: Start battle (BB)
|
||||
|
||||
struct G_RestartBattle_BB_6xCF {
|
||||
struct G_StartBattle_BB_6xCF {
|
||||
G_UnusedHeader header;
|
||||
BattleRules rules;
|
||||
} __packed__;
|
||||
|
||||
@@ -10,6 +10,7 @@ using namespace std;
|
||||
|
||||
void PlayerStats::reset_to_base(uint8_t char_class, shared_ptr<const LevelTable> level_table) {
|
||||
this->level = 0;
|
||||
this->experience = 0;
|
||||
this->char_stats = level_table->base_stats_for_class(char_class);
|
||||
}
|
||||
|
||||
|
||||
@@ -372,6 +372,15 @@ void Lobby::on_item_id_generated_externally(uint32_t item_id) {
|
||||
}
|
||||
}
|
||||
|
||||
void Lobby::assign_inventory_item_ids(shared_ptr<Client> c) {
|
||||
auto p = c->game_data.character();
|
||||
for (size_t z = 0; z < p->inventory.num_items; z++) {
|
||||
p->inventory.items[z].data.id = this->generate_item_id(c->lobby_client_id);
|
||||
}
|
||||
c->log.info("Assigned item IDs");
|
||||
p->print_inventory(stderr, c->version(), c->require_server_state()->item_name_index);
|
||||
}
|
||||
|
||||
unordered_map<uint32_t, shared_ptr<Client>> Lobby::clients_by_serial_number() const {
|
||||
unordered_map<uint32_t, shared_ptr<Client>> ret;
|
||||
for (auto c : this->clients) {
|
||||
|
||||
@@ -191,6 +191,7 @@ struct Lobby : public std::enable_shared_from_this<Lobby> {
|
||||
ItemData remove_item(uint32_t item_id);
|
||||
uint32_t generate_item_id(uint8_t client_id);
|
||||
void on_item_id_generated_externally(uint32_t item_id);
|
||||
void assign_inventory_item_ids(std::shared_ptr<Client> c);
|
||||
|
||||
static uint8_t game_event_for_lobby_event(uint8_t lobby_event);
|
||||
|
||||
|
||||
+30
-26
@@ -1848,24 +1848,6 @@ void set_lobby_quest(shared_ptr<Lobby> l, shared_ptr<const Quest> q) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (vq->battle_rules) {
|
||||
lc->game_data.create_battle_overlay(vq->battle_rules, s->level_table);
|
||||
lc->log.info("Created battle overlay");
|
||||
} else if (vq->challenge_template_index >= 0) {
|
||||
lc->game_data.create_challenge_overlay(lc->version(), vq->challenge_template_index, s->level_table);
|
||||
lc->log.info("Created challenge overlay");
|
||||
}
|
||||
|
||||
// If an overlay was created, item IDs need to be assigned
|
||||
if (lc->game_data.has_overlay()) {
|
||||
auto overlay = lc->game_data.character();
|
||||
for (size_t z = 0; z < overlay->inventory.num_items; z++) {
|
||||
overlay->inventory.items[z].data.id = l->generate_item_id(client_id);
|
||||
}
|
||||
lc->log.info("Assigned overlay item IDs");
|
||||
overlay->print_inventory(stderr, lc->version(), s->item_name_index);
|
||||
}
|
||||
|
||||
string bin_filename = vq->bin_filename();
|
||||
string dat_filename = vq->dat_filename();
|
||||
string xb_filename = vq->xb_filename();
|
||||
@@ -2626,7 +2608,9 @@ static void on_AC_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data)
|
||||
(l->base_version == GameVersion::BB) &&
|
||||
l->map &&
|
||||
l->quest) {
|
||||
|
||||
auto vq = l->quest->version(QuestScriptVersion::BB_V4, c->language());
|
||||
|
||||
auto dat_contents = prs_decompress(*vq->dat_contents);
|
||||
l->map->clear();
|
||||
l->map->add_enemies_and_objects_from_quest_data(
|
||||
@@ -2637,15 +2621,36 @@ static void on_AC_V3_BB(shared_ptr<Client> c, uint16_t, uint32_t, string& data)
|
||||
dat_contents.size(),
|
||||
l->random_seed,
|
||||
(l->mode == GameMode::CHALLENGE) ? Map::NO_RARE_ENEMIES : Map::DEFAULT_RARE_ENEMIES);
|
||||
l->log.info("Replaced enemies list with quest layout (%zu entries)",
|
||||
l->map->enemies.size());
|
||||
l->item_creator->clear_destroyed_entities();
|
||||
|
||||
l->log.info("Replaced enemies list with quest layout (%zu entries)", l->map->enemies.size());
|
||||
for (size_t z = 0; z < l->map->enemies.size(); z++) {
|
||||
string e_str = l->map->enemies[z].str();
|
||||
l->log.info("(Entry %zX) %s", z, e_str.c_str());
|
||||
}
|
||||
|
||||
auto s = l->require_server_state();
|
||||
for (auto& lc : l->clients) {
|
||||
if (lc) {
|
||||
send_rare_enemy_index_list(c, l->map->rare_enemy_indexes);
|
||||
if (!lc) {
|
||||
continue;
|
||||
}
|
||||
|
||||
send_rare_enemy_index_list(c, l->map->rare_enemy_indexes);
|
||||
|
||||
// On non-BB versions, overlays are created when the quest starts because
|
||||
// the server is not informed when the clients have replaced their player
|
||||
// data. On BB, this is instead done in the 6xCF handler (for battle) or
|
||||
// the 02DF handler (for challenge).
|
||||
if (l->base_version != GameVersion::BB) {
|
||||
lc->game_data.delete_overlay();
|
||||
if (vq->battle_rules) {
|
||||
lc->game_data.create_battle_overlay(vq->battle_rules, s->level_table);
|
||||
lc->log.info("Created battle overlay");
|
||||
} else if (vq->challenge_template_index >= 0) {
|
||||
lc->game_data.create_challenge_overlay(lc->version(), vq->challenge_template_index, s->level_table);
|
||||
lc->log.info("Created challenge overlay");
|
||||
l->assign_inventory_item_ids(lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3319,10 +3324,9 @@ static void on_DF_BB(shared_ptr<Client> c, uint16_t command, uint32_t, string& d
|
||||
if (l->quest->challenge_template_index != static_cast<ssize_t>(cmd.template_index)) {
|
||||
throw runtime_error("challenge template index in quest metadata does not match index sent by client");
|
||||
}
|
||||
// Do nothing: we've already created the player overlay by the time this
|
||||
// opcode is run on the client. We can't easily move the overlay creation
|
||||
// here, since non-BB versions do not send anything when they create the
|
||||
// overlay, so we have to do it when the quest loads instead.
|
||||
c->game_data.create_challenge_overlay(c->version(), l->quest->challenge_template_index, s->level_table);
|
||||
c->log.info("Created challenge overlay");
|
||||
l->assign_inventory_item_ids(c);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -2057,8 +2057,9 @@ static void on_battle_restart_bb(shared_ptr<Client> c, uint8_t, uint8_t, const v
|
||||
if (l->is_game() &&
|
||||
(l->base_version == GameVersion::BB) &&
|
||||
(l->mode == GameMode::BATTLE) &&
|
||||
l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS)) {
|
||||
const auto& cmd = check_size_t<G_RestartBattle_BB_6xCF>(data, size);
|
||||
l->check_flag(Lobby::Flag::QUEST_IN_PROGRESS) &&
|
||||
l->leader_id == c->lobby_client_id) {
|
||||
const auto& cmd = check_size_t<G_StartBattle_BB_6xCF>(data, size);
|
||||
|
||||
shared_ptr<BattleRules> new_rules(new BattleRules(cmd.rules));
|
||||
if (l->item_creator) {
|
||||
@@ -2430,7 +2431,7 @@ subcommand_handler_t subcommand_handlers[0x100] = {
|
||||
/* 6x98 */ nullptr,
|
||||
/* 6x99 */ nullptr,
|
||||
/* 6x9A */ on_forward_check_size_game,
|
||||
/* 6x9B */ nullptr,
|
||||
/* 6x9B */ on_forward_check_size_game,
|
||||
/* 6x9C */ on_forward_check_size_game,
|
||||
/* 6x9D */ nullptr,
|
||||
/* 6x9E */ nullptr,
|
||||
|
||||
Reference in New Issue
Block a user