From b30cd3bb8ee454d404d69494db1fb17cae41d63e Mon Sep 17 00:00:00 2001 From: Martin Michelsen Date: Mon, 24 Mar 2025 18:29:09 -0700 Subject: [PATCH] load Ep3 Morgue map --- src/ChatCommands.cc | 30 ++++++++++++------ src/Lobby.cc | 4 +-- src/Main.cc | 6 ++-- src/Map.cc | 76 ++++++++++++++++++++++----------------------- src/Quest.cc | 2 +- src/ServerState.cc | 7 +++-- 6 files changed, 69 insertions(+), 56 deletions(-) diff --git a/src/ChatCommands.cc b/src/ChatCommands.cc index da82a879..6ac69c3d 100644 --- a/src/ChatCommands.cc +++ b/src/ChatCommands.cc @@ -2784,9 +2784,15 @@ ChatCommandDefinition cc_whatobj( // TODO: We should use the actual area if a loaded quest has reassigned // them; it's likely that the variations will be wrong if we don't - auto sdt = s->set_data_table(a.c->version(), l->episode, l->mode, l->difficulty); - uint8_t area = sdt->default_area_for_floor(l->episode, a.c->floor); - uint8_t layout_var = (a.c->floor < 0x10) ? l->variations.entries[a.c->floor].layout.load() : 0x00; + uint8_t area, layout_var; + if (l->episode != Episode::EP3) { + auto sdt = s->set_data_table(a.c->version(), l->episode, l->mode, l->difficulty); + area = sdt->default_area_for_floor(l->episode, a.c->floor); + layout_var = (a.c->floor < 0x10) ? l->variations.entries[a.c->floor].layout.load() : 0x00; + } else { + area = a.c->floor; + layout_var = 0; + } float min_dist2 = 0.0f; VectorXYZF nearest_worldspace_pos; @@ -2799,15 +2805,21 @@ ChatCommandDefinition cc_whatobj( if (!def.set_entry) { continue; } + VectorXYZF worldspace_pos; - try { - const auto& room = s->room_layout_index->get_room(area, layout_var, def.set_entry->room); - // This is the order in which the game does the rotations; not sure why - worldspace_pos = def.set_entry->pos.rotate_x(room.angle.x).rotate_z(room.angle.z).rotate_y(room.angle.y) + room.position; - } catch (const out_of_range&) { - a.c->log.warning("Can't find definition for room %02hhX:%02hhX:%08hX", area, layout_var, def.set_entry->room.load()); + if (l->episode != Episode::EP3) { + try { + const auto& room = s->room_layout_index->get_room(area, layout_var, def.set_entry->room); + // This is the order in which the game does the rotations; not sure why + worldspace_pos = def.set_entry->pos.rotate_x(room.angle.x).rotate_z(room.angle.z).rotate_y(room.angle.y) + room.position; + } catch (const out_of_range&) { + a.c->log.warning("Can't find definition for room %02hhX:%02hhX:%08hX", area, layout_var, def.set_entry->room.load()); + worldspace_pos = def.set_entry->pos; + } + } else { worldspace_pos = def.set_entry->pos; } + float dist2 = (VectorXZF(worldspace_pos) - a.c->pos).norm2(); if (!nearest_obj || (dist2 < min_dist2)) { nearest_obj = it; diff --git a/src/Lobby.cc b/src/Lobby.cc index d90b2c6e..db8eb8a3 100644 --- a/src/Lobby.cc +++ b/src/Lobby.cc @@ -293,9 +293,7 @@ uint16_t Lobby::quest_version_flags() const { void Lobby::load_maps() { auto rare_rates = this->rare_enemy_rates ? this->rare_enemy_rates : MapState::DEFAULT_RARE_ENEMIES; - if (this->episode == Episode::EP3) { - this->map_state = make_shared(); - } else if (this->quest) { + if (this->quest) { this->map_state = make_shared( this->lobby_id, this->difficulty, diff --git a/src/Main.cc b/src/Main.cc index 8358d571..faca929b 100644 --- a/src/Main.cc +++ b/src/Main.cc @@ -2849,7 +2849,7 @@ Action a_check_supermaps( } if (generate_enemy_stats) { array, NUM_VERSIONS> counts_for_version; - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { counts_for_version[static_cast(v)] = supermap->count_enemy_sets_for_version(v); } string filename = phosg::string_printf("supermap_quest_%" PRIu32 "_%08" PRIX32 "_enemy_counts.txt", it.first, random_seed); @@ -2860,7 +2860,7 @@ Action a_check_supermaps( EnemyType type = static_cast(type_ss); bool any_count_nonzero = false; array counts; - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { size_t& count = counts[static_cast(v)]; try { count = counts_for_version[static_cast(v)].at(type); @@ -2873,7 +2873,7 @@ Action a_check_supermaps( } if (any_count_nonzero) { fprintf(f.get(), "%20s", phosg::name_for_enum(type)); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { size_t count = counts[static_cast(v)]; if (count > 0) { fprintf(f.get(), " %5zu", count); diff --git a/src/Map.cc b/src/Map.cc index 53421509..cb1cc9e2 100644 --- a/src/Map.cc +++ b/src/Map.cc @@ -3303,7 +3303,7 @@ string SuperMap::Object::id_str() const { string SuperMap::Object::str() const { string ret = "[Object " + this->id_str(); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& def = this->version(v); if (def.relative_object_index != 0xFFFF) { string args_str = def.set_entry->str(); @@ -3329,7 +3329,7 @@ string SuperMap::Enemy::str() const { this->alias_enemy_index_delta, this->is_default_rare_v123 ? "true" : "false", this->is_default_rare_bb ? "true" : "false"); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& def = this->version(v); if (def.relative_enemy_index != 0xFFFF) { string args_str = def.set_entry->str(); @@ -3351,7 +3351,7 @@ string SuperMap::Event::id_str() const { string SuperMap::Event::str() const { string ret = "[Event " + this->id_str(); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& def = this->version(v); if (def.relative_event_index != 0xFFFF) { string action_stream_str = phosg::format_data_string(def.action_stream, def.action_stream_size); @@ -3388,7 +3388,7 @@ SuperMap::SuperMap(Episode episode, const std::array(v)); if (map_file) { this->add_map_file(v, map_file); @@ -4591,34 +4591,34 @@ SuperMap::EfficiencyStats SuperMap::efficiency() const { EfficiencyStats ret; for (const auto& obj : this->objects) { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& obj_ver = obj->version(v); if (obj_ver.relative_object_index != 0xFFFF) { ret.filled_object_slots++; } } } - ret.total_object_slots = this->objects.size() * ALL_ARPG_SEMANTIC_VERSIONS.size(); + ret.total_object_slots = this->objects.size() * ALL_NON_PATCH_VERSIONS.size(); for (const auto& ene : this->enemy_sets) { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ene_ver = ene->version(v); if (ene_ver.relative_enemy_index != 0xFFFF) { ret.filled_enemy_set_slots++; } } } - ret.total_enemy_set_slots = this->enemy_sets.size() * ALL_ARPG_SEMANTIC_VERSIONS.size(); + ret.total_enemy_set_slots = this->enemy_sets.size() * ALL_NON_PATCH_VERSIONS.size(); for (const auto& ev : this->events) { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ev_ver = ev->version(v); if (ev_ver.relative_event_index != 0xFFFF) { ret.filled_event_slots++; } } } - ret.total_event_slots = this->events.size() * ALL_ARPG_SEMANTIC_VERSIONS.size(); + ret.total_event_slots = this->events.size() * ALL_NON_PATCH_VERSIONS.size(); return ret; } @@ -4664,7 +4664,7 @@ void SuperMap::verify() const { } } - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); if (entities.object_floor_start_indexes.at(0) != 0) { @@ -4787,16 +4787,16 @@ void SuperMap::verify() const { void SuperMap::print(FILE* stream) const { fprintf(stream, "SuperMap %s random=%08" PRIX64 "\n", name_for_episode(this->episode), this->random_seed); - fprintf(stream, " DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 XBV3 BBV4\n"); + fprintf(stream, " DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 E3TE GCE3 XBV3 BBV4\n"); fprintf(stream, " MAP "); - for (const auto& v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (const auto& v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); fprintf(stream, " %s", entities.map_file ? "++++" : "----"); } fputc('\n', stream); for (uint8_t floor = 0; floor < 0x12; floor++) { fprintf(stream, " KS START %02hhX", floor); - for (const auto& v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (const auto& v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); fprintf(stream, " %04zX", entities.object_floor_start_indexes[floor]); } @@ -4804,7 +4804,7 @@ void SuperMap::print(FILE* stream) const { } for (uint8_t floor = 0; floor < 0x12; floor++) { fprintf(stream, " ES START %02hhX", floor); - for (const auto& v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (const auto& v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); fprintf(stream, " %04zX", entities.enemy_floor_start_indexes[floor]); } @@ -4812,7 +4812,7 @@ void SuperMap::print(FILE* stream) const { } for (uint8_t floor = 0; floor < 0x12; floor++) { fprintf(stream, " ESS START %02hhX", floor); - for (const auto& v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (const auto& v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); fprintf(stream, " %04zX", entities.enemy_set_floor_start_indexes[floor]); } @@ -4820,17 +4820,17 @@ void SuperMap::print(FILE* stream) const { } for (uint8_t floor = 0; floor < 0x12; floor++) { fprintf(stream, " WS START %02hhX", floor); - for (const auto& v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (const auto& v : ALL_NON_PATCH_VERSIONS) { const auto& entities = this->version(v); fprintf(stream, " %04zX", entities.event_floor_start_indexes[floor]); } fputc('\n', stream); } - fprintf(stream, " KS-FL-ID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 XBV3 BBV4 DEFINITION\n"); + fprintf(stream, " KS-FL-ID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 E3TE GCE3 XBV3 BBV4 DEFINITION\n"); for (const auto& obj : this->objects) { fprintf(stream, " KS-%02hhX-%03zX", obj->floor, obj->super_id); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& obj_ver = obj->version(v); if (obj_ver.relative_object_index == 0xFFFF) { fprintf(stream, " ----"); @@ -4842,10 +4842,10 @@ void SuperMap::print(FILE* stream) const { fprintf(stream, " %s\n", obj_str.c_str()); } - fprintf(stream, " ES-FL-ID DCTE----- DCPR----- DCV1----- DCV2----- PCTE----- PCV2----- GCTE----- GCV3----- XBV3----- BBV4----- DEFINITION\n"); + fprintf(stream, " ES-FL-ID DCTE----- DCPR----- DCV1----- DCV2----- PCTE----- PCV2----- GCTE----- GCV3----- EP3TE---- GCEP3---- XBV3----- BBV4----- DEFINITION\n"); for (const auto& ene : this->enemies) { fprintf(stream, " ES-%02hhX-%03zX", ene->floor, ene->super_id); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ene_ver = ene->version(v); if (ene_ver.relative_enemy_index == 0xFFFF) { fprintf(stream, " ----:----"); @@ -4858,10 +4858,10 @@ void SuperMap::print(FILE* stream) const { fprintf(stream, " %s\n", ene_str.c_str()); } - fprintf(stream, " WS-FL-ID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 XBV3 BBV4 DEFINITION\n"); + fprintf(stream, " WS-FL-ID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 E3TE GCE3 XBV3 BBV4 DEFINITION\n"); for (const auto& ev : this->events) { fprintf(stream, " WS-%02hhX-%03zX", ev->floor, ev->super_id); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ev_ver = ev->version(v); if (ev_ver.relative_event_index == 0xFFFF) { fprintf(stream, " ----"); @@ -5093,7 +5093,7 @@ MapState::MapState( if (floor < this->floor_config_entries.size() - 1) { auto& next_fc = this->floor_config_entries[floor + 1]; if (this_fc.super_map) { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& this_indexes = this_fc.base_indexes_for_version(v); auto& next_indexes = next_fc.base_indexes_for_version(v); auto& entities = this_fc.super_map->version(v); @@ -5107,7 +5107,7 @@ MapState::MapState( next_fc.base_super_ids.base_enemy_set_index = this->enemy_set_states.size(); next_fc.base_super_ids.base_event_index = this->event_states.size(); } else { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { next_fc.base_indexes_for_version(v) = this_fc.base_indexes_for_version(v); } } @@ -5193,7 +5193,7 @@ void MapState::index_super_map(const FloorConfig& fc, shared_ptr det_cache; uint32_t bb_rare_rate = this->bb_rare_rates->for_enemy_type(type); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { // Skip this version if the enemy doesn't exist there uint16_t relative_enemy_index = ene->version(v).relative_enemy_index; if (relative_enemy_index == 0xFFFF) { @@ -5274,7 +5274,7 @@ void MapState::compute_dynamic_object_base_indexes() { // versions. this->dynamic_obj_base_index_for_version.fill(0); for (const auto& fc : this->floor_config_entries) { - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { if (fc.super_map) { auto& last_obj_index = this->dynamic_obj_base_index_for_version[static_cast(v)]; size_t base_index = fc.base_indexes_for_version(v).base_object_index; @@ -5749,7 +5749,7 @@ void MapState::verify() const { } } - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { FloorConfig::EntityBaseIndexes base_indexes; for (size_t floor = 0; floor < this->floor_config_entries.size(); floor++) { const auto& fc = this->floor_config_entries[floor]; @@ -5814,28 +5814,28 @@ void MapState::print(FILE* stream) const { fprintf(stream, "BB rare rates: %s\n", rare_rates_str.c_str()); fprintf(stream, "Base indexes:\n"); - fprintf(stream, " FL DCTE----------- DCPR----------- DCV1----------- DCV2----------- PCTE----------- PCV2----------- GCTE----------- GCV3----------- XBV3----------- BBV4-----------\n"); - fprintf(stream, " FL KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT\n"); + fprintf(stream, " FL DCTE----------- DCPR----------- DCV1----------- DCV2----------- PCTE----------- PCV2----------- GCTE----------- GCV3----------- GCEP3TE-------- GCEP3---------- XBV3----------- BBV4-----------\n"); + fprintf(stream, " FL KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT KST EST ESS EVT\n"); for (size_t floor = 0; floor < this->floor_config_entries.size(); floor++) { auto fc = this->floor_config_entries[floor]; if (fc.super_map) { fprintf(stream, " %02zX", floor); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& indexes = fc.base_indexes_for_version(v); fprintf(stream, " %03zX %03zX %03zX %03zX", indexes.base_object_index, indexes.base_enemy_index, indexes.base_enemy_set_index, indexes.base_event_index); } fputc('\n', stream); } else { - fprintf(stream, " %02zX --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- ---------------\n", floor); + fprintf(stream, " %02zX --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- --------------- ---------------\n", floor); } } fprintf(stream, "Objects:\n"); - fprintf(stream, " FL OBJID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 XBV3 BBV4 OBJECT\n"); + fprintf(stream, " FL OBJID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 E3TE GCE3 XBV3 BBV4 OBJECT\n"); for (const auto& obj_st : this->object_states) { fprintf(stream, " %02hhX K-%03zX", obj_st->super_obj->floor, obj_st->k_id); const auto& fc = this->floor_config(obj_st->super_obj->floor); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& obj_v = obj_st->super_obj->version(v); if (obj_v.relative_object_index == 0xFFFF) { fputs(" ----", stream); @@ -5850,11 +5850,11 @@ void MapState::print(FILE* stream) const { } fprintf(stream, "Enemies:\n"); - fprintf(stream, " FL ENEID DCTE----- DCPR----- DCV1----- DCV2----- PCTE----- PCV2----- GCTE----- GCV3----- XBV3----- BBV4----- ENEMY\n"); + fprintf(stream, " FL ENEID DCTE----- DCPR----- DCV1----- DCV2----- PCTE----- PCV2----- GCTE----- GCV3----- EP3TE---- GCEP3---- XBV3----- BBV4----- ENEMY\n"); for (const auto& ene_st : this->enemy_states) { fprintf(stream, " %02hhX E-%03zX", ene_st->super_ene->floor, ene_st->e_id); const auto& fc = this->floor_config(ene_st->super_ene->floor); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ene_v = ene_st->super_ene->version(v); if (ene_v.relative_enemy_index == 0xFFFF) { fputs(" ---------", stream); @@ -5886,11 +5886,11 @@ void MapState::print(FILE* stream) const { } fprintf(stream, "Events:\n"); - fprintf(stream, " FL EVTID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 XBV3 BBV4 EVENT\n"); + fprintf(stream, " FL EVTID DCTE DCPR DCV1 DCV2 PCTE PCV2 GCTE GCV3 E3TE GCE3 XBV3 BBV4 EVENT\n"); for (const auto& ev_st : this->event_states) { fprintf(stream, " %02hhX W-%03zX", ev_st->super_ev->floor, ev_st->w_id); const auto& fc = this->floor_config(ev_st->super_ev->floor); - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { const auto& ev_v = ev_st->super_ev->version(v); if (ev_v.relative_event_index == 0xFFFF) { fputs(" ----", stream); diff --git a/src/Quest.cc b/src/Quest.cc index 3dffc64f..34cdfb60 100644 --- a/src/Quest.cc +++ b/src/Quest.cc @@ -417,7 +417,7 @@ std::shared_ptr Quest::get_supermap(int64_t random_seed) const { bool save_to_cache = true; bool any_map_file_present = false; array, NUM_VERSIONS> map_files; - for (Version v : ALL_ARPG_SEMANTIC_VERSIONS) { + for (Version v : ALL_NON_PATCH_VERSIONS) { auto vq = this->version(v, 1); if (vq && vq->map_file) { auto map_file = vq->map_file; diff --git a/src/ServerState.cc b/src/ServerState.cc index 80f57ab9..30f7cae1 100644 --- a/src/ServerState.cc +++ b/src/ServerState.cc @@ -1578,13 +1578,16 @@ void ServerState::load_maps(bool from_non_event_thread) { { // TODO: Ep3 NTE loads map_city00_on, but it appears there are some // variants. Figure this out and load those maps too. - auto objects_data = this->load_map_file(Version::GC_EP3, "system/maps/gc-ep3/map_city_on_battle_o.dat"); - auto enemies_data = this->load_map_file(Version::GC_EP3, "system/maps/gc-ep3/map_city_on_battle_e.dat"); + auto objects_data = this->load_map_file(Version::GC_EP3, "map_city_on_battle_o.dat"); + auto enemies_data = this->load_map_file(Version::GC_EP3, "map_city_on_battle_e.dat"); if (objects_data || enemies_data) { uint32_t free_play_key = this->free_play_key(Episode::EP3, GameMode::NORMAL, 0, 0, 0, 0); auto map_file = make_shared(0, objects_data, enemies_data, nullptr); new_map_file_for_source_hash.emplace(map_file->source_hash(), map_file); new_map_files_for_free_play_key[free_play_key].at(static_cast(Version::GC_EP3)) = map_file; + config_log.info("Episode 3 map files loaded with free play key %08" PRIX32, free_play_key); + } else { + config_log.info("Episode 3 map files not found; skipping"); } }