link map objects to constructor args instead of copying them
This commit is contained in:
+2
-8
@@ -302,13 +302,7 @@ shared_ptr<Map> Lobby::load_maps(
|
||||
shared_ptr<PSOLFGEncryption> opt_rand_crypt,
|
||||
shared_ptr<const string> quest_dat_contents_decompressed) {
|
||||
auto map = make_shared<Map>(version, lobby_id, random_seed, opt_rand_crypt);
|
||||
map->add_entities_from_quest_data(
|
||||
episode,
|
||||
difficulty,
|
||||
event,
|
||||
quest_dat_contents_decompressed->data(),
|
||||
quest_dat_contents_decompressed->size(),
|
||||
rare_rates);
|
||||
map->add_entities_from_quest_data(episode, difficulty, event, quest_dat_contents_decompressed, rare_rates);
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -396,7 +390,7 @@ shared_ptr<Map> Lobby::load_maps(
|
||||
if (!floor_object_filename.empty()) {
|
||||
auto map_data = get_file_data(version, floor_object_filename);
|
||||
if (map_data) {
|
||||
map->add_objects_from_map_data(floor, map_data->data(), map_data->size());
|
||||
map->add_objects_from_map_data(floor, map_data);
|
||||
if (log) {
|
||||
log->info("Loaded objects map %s for floor %02zX", floor_object_filename.c_str(), floor);
|
||||
}
|
||||
|
||||
+1
-1
@@ -2401,7 +2401,7 @@ Action a_load_maps_test(
|
||||
fprintf(stderr, " [%s => ", objects_filename.c_str());
|
||||
auto map_data = s->load_map_file(v, objects_filename);
|
||||
if (map_data) {
|
||||
map->add_objects_from_map_data(floor, map_data->data(), map_data->size());
|
||||
map->add_objects_from_map_data(floor, map_data);
|
||||
fprintf(stderr, "%zu objects]", map->objects.size());
|
||||
} else {
|
||||
fprintf(stderr, "__MISSING__]");
|
||||
|
||||
+31
-24
@@ -704,17 +704,25 @@ string Map::Event::str() const {
|
||||
}
|
||||
|
||||
string Map::Object::str() const {
|
||||
return phosg::string_printf("[Map::Object source %zX %04hX(%s) @%04hX p1=%g p456=[%08" PRIX32 " %08" PRIX32 " %08" PRIX32 "] floor=%02hhX item_drop_checked=%s]",
|
||||
this->source_index,
|
||||
this->base_type,
|
||||
Map::name_for_object_type(this->base_type),
|
||||
this->section,
|
||||
this->param1,
|
||||
this->param4,
|
||||
this->param5,
|
||||
this->param6,
|
||||
return phosg::string_printf("[Map::Object floor %02hhX source %zX %04hX(%s) @%04hX:(%g %g %g)/(%04" PRIX32 " %04" PRIX32 " %04" PRIX32 ") +%04hX params [%g %g %g %08" PRIX32 " %08" PRIX32 " %08" PRIX32 "]]",
|
||||
this->floor,
|
||||
this->item_drop_checked ? "true" : "false");
|
||||
this->source_index,
|
||||
this->args->base_type.load(),
|
||||
Map::name_for_object_type(this->args->base_type),
|
||||
this->args->section.load(),
|
||||
this->args->x.load(),
|
||||
this->args->y.load(),
|
||||
this->args->z.load(),
|
||||
this->args->x_angle.load(),
|
||||
this->args->y_angle.load(),
|
||||
this->args->z_angle.load(),
|
||||
this->args->group.load(),
|
||||
this->args->param1.load(),
|
||||
this->args->param2.load(),
|
||||
this->args->param3.load(),
|
||||
this->args->param4.load(),
|
||||
this->args->param5.load(),
|
||||
this->args->param6.load());
|
||||
}
|
||||
|
||||
Map::Map(Version version, uint32_t lobby_id, uint32_t rare_seed, std::shared_ptr<PSOLFGEncryption> opt_rand_crypt)
|
||||
@@ -729,7 +737,7 @@ void Map::clear() {
|
||||
this->rare_enemy_indexes.clear();
|
||||
}
|
||||
|
||||
void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size) {
|
||||
void Map::add_objects_from_owned_map_data(uint8_t floor, const void* data, size_t size) {
|
||||
size_t entry_count = size / sizeof(ObjectEntry);
|
||||
if (size != entry_count * sizeof(ObjectEntry)) {
|
||||
throw runtime_error("data size is not a multiple of entry size");
|
||||
@@ -739,17 +747,10 @@ void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size
|
||||
for (size_t z = 0; z < entry_count; z++) {
|
||||
uint16_t object_id = this->objects.size();
|
||||
this->objects.emplace_back(Object{
|
||||
.args = &objects[z],
|
||||
.source_index = z,
|
||||
.floor = floor,
|
||||
.object_id = object_id,
|
||||
.base_type = objects[z].base_type,
|
||||
.section = objects[z].section,
|
||||
.group = objects[z].group,
|
||||
.param1 = objects[z].param1,
|
||||
.param3 = objects[z].param3,
|
||||
.param4 = objects[z].param4,
|
||||
.param5 = objects[z].param5,
|
||||
.param6 = objects[z].param6,
|
||||
.game_flags = 0,
|
||||
.set_flags = 0,
|
||||
.item_drop_checked = false,
|
||||
@@ -759,6 +760,11 @@ void Map::add_objects_from_map_data(uint8_t floor, const void* data, size_t size
|
||||
}
|
||||
}
|
||||
|
||||
void Map::add_objects_from_map_data(uint8_t floor, std::shared_ptr<const string> data) {
|
||||
this->link_owned_data(data);
|
||||
this->add_objects_from_owned_map_data(floor, data->data(), data->size());
|
||||
}
|
||||
|
||||
bool Map::check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate) {
|
||||
if (default_is_rare) {
|
||||
return true;
|
||||
@@ -1597,12 +1603,13 @@ void Map::add_entities_from_quest_data(
|
||||
Episode episode,
|
||||
uint8_t difficulty,
|
||||
uint8_t event,
|
||||
const void* data,
|
||||
size_t size,
|
||||
std::shared_ptr<const string> data,
|
||||
std::shared_ptr<const RareEnemyRates> rare_rates) {
|
||||
auto all_floor_sections = this->collect_quest_map_data_sections(data, size);
|
||||
this->link_owned_data(data);
|
||||
|
||||
phosg::StringReader r(data, size);
|
||||
auto all_floor_sections = this->collect_quest_map_data_sections(data->data(), data->size());
|
||||
|
||||
phosg::StringReader r(*data);
|
||||
shared_ptr<DATParserRandomState> random_state;
|
||||
for (size_t floor = 0; floor < all_floor_sections.size(); floor++) {
|
||||
const auto& floor_sections = all_floor_sections[floor];
|
||||
@@ -1612,7 +1619,7 @@ void Map::add_entities_from_quest_data(
|
||||
if (header.data_size % sizeof(ObjectEntry)) {
|
||||
throw runtime_error("quest layout object section size is not a multiple of object entry size");
|
||||
}
|
||||
this->add_objects_from_map_data(floor, r.pgetv(floor_sections.objects + sizeof(header), header.data_size), header.data_size);
|
||||
this->add_objects_from_owned_map_data(floor, r.pgetv(floor_sections.objects + sizeof(header), header.data_size), header.data_size);
|
||||
}
|
||||
|
||||
if ((floor_sections.wave_events != 0xFFFFFFFF) &&
|
||||
|
||||
+11
-13
@@ -51,9 +51,9 @@ struct Map {
|
||||
/* 1C */ le_uint32_t x_angle;
|
||||
/* 20 */ le_uint32_t y_angle;
|
||||
/* 24 */ le_uint32_t z_angle;
|
||||
/* 28 */ le_float param1; // If <= 0, this is a specialized box, and the specialization is in param4/5/6
|
||||
/* 28 */ le_float param1; // Boxes: if <= 0, this is a specialized box, and the specialization is in param4/5/6
|
||||
/* 2C */ le_float param2;
|
||||
/* 30 */ le_float param3;
|
||||
/* 30 */ le_float param3; // Boxes: if == 0, the item should be varied by difficulty and area
|
||||
/* 34 */ le_uint32_t param4;
|
||||
/* 38 */ le_uint32_t param5;
|
||||
/* 3C */ le_uint32_t param6;
|
||||
@@ -211,17 +211,10 @@ struct Map {
|
||||
struct Object {
|
||||
// TODO: Add more fields in here if we ever care about them. Currently we
|
||||
// only care about boxes with fixed item drops.
|
||||
const ObjectEntry* args;
|
||||
size_t source_index;
|
||||
uint8_t floor;
|
||||
uint16_t object_id;
|
||||
uint16_t base_type;
|
||||
uint16_t section;
|
||||
uint16_t group;
|
||||
float param1; // If <= 0, this is a specialized box, and the specialization is in param4/5/6
|
||||
float param3; // If == 0, the item should be varied by difficulty and area
|
||||
uint32_t param4;
|
||||
uint32_t param5;
|
||||
uint32_t param6;
|
||||
uint16_t game_flags;
|
||||
// Technically set_flags shouldn't be part of the Object struct, but all
|
||||
// object entries always generate exactly one object, so we store it here.
|
||||
@@ -305,7 +298,12 @@ struct Map {
|
||||
|
||||
void clear();
|
||||
|
||||
void add_objects_from_map_data(uint8_t floor, const void* data, size_t size);
|
||||
inline void link_owned_data(std::shared_ptr<const std::string> data) {
|
||||
this->linked_data.emplace(data);
|
||||
}
|
||||
|
||||
void add_objects_from_owned_map_data(uint8_t floor, const void* data, size_t size);
|
||||
void add_objects_from_map_data(uint8_t floor, std::shared_ptr<const std::string> data);
|
||||
|
||||
bool check_and_log_rare_enemy(bool default_is_rare, uint32_t rare_rate);
|
||||
void add_enemy(
|
||||
@@ -359,8 +357,7 @@ struct Map {
|
||||
Episode episode,
|
||||
uint8_t difficulty,
|
||||
uint8_t event,
|
||||
const void* data,
|
||||
size_t size,
|
||||
std::shared_ptr<const std::string> data,
|
||||
std::shared_ptr<const RareEnemyRates> rare_rates = Map::DEFAULT_RARE_ENEMIES);
|
||||
|
||||
const Enemy& find_enemy(uint16_t enemy_id) const;
|
||||
@@ -380,6 +377,7 @@ struct Map {
|
||||
phosg::PrefixedLogger log;
|
||||
Version version;
|
||||
uint32_t rare_seed;
|
||||
std::unordered_set<std::shared_ptr<const std::string>> linked_data;
|
||||
std::shared_ptr<PSOLFGEncryption> opt_rand_crypt;
|
||||
std::vector<Object> objects;
|
||||
std::vector<Enemy> enemies;
|
||||
|
||||
@@ -2579,26 +2579,26 @@ DropReconcileResult reconcile_drop_request_with_map(
|
||||
if (map) {
|
||||
map_object = &map->objects.at(cmd.entity_id);
|
||||
log.info("Drop check for K-%hX %c %s",
|
||||
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->base_type));
|
||||
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->args->base_type));
|
||||
if (cmd.floor != map_object->floor) {
|
||||
log.warning("Floor %02hhX from command does not match object\'s expected floor %02hhX", cmd.floor, map_object->floor);
|
||||
}
|
||||
if (is_v1_or_v2(version) && (version != Version::GC_NTE)) {
|
||||
// V1 and V2 don't have 6xA2, so we can't get ignore_def or the object
|
||||
// parameters from the client on those versions
|
||||
cmd.param3 = map_object->param3;
|
||||
cmd.param4 = map_object->param4;
|
||||
cmd.param5 = map_object->param5;
|
||||
cmd.param6 = map_object->param6;
|
||||
cmd.param3 = map_object->args->param3;
|
||||
cmd.param4 = map_object->args->param4;
|
||||
cmd.param5 = map_object->args->param5;
|
||||
cmd.param6 = map_object->args->param6;
|
||||
}
|
||||
bool object_ignore_def = (map_object->param1 > 0.0);
|
||||
bool object_ignore_def = (map_object->args->param1 > 0.0);
|
||||
if (res.ignore_def != object_ignore_def) {
|
||||
log.warning("ignore_def value %s from command does not match object\'s expected ignore_def %s (from p1=%g)",
|
||||
res.ignore_def ? "true" : "false", object_ignore_def ? "true" : "false", map_object->param1);
|
||||
res.ignore_def ? "true" : "false", object_ignore_def ? "true" : "false", map_object->args->param1.load());
|
||||
}
|
||||
if (config.check_flag(Client::Flag::DEBUG_ENABLED)) {
|
||||
send_text_message_printf(client_channel, "$C5K-%hX %c %s",
|
||||
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->base_type));
|
||||
map_object->object_id, res.ignore_def ? 'G' : 'S', Map::name_for_object_type(map_object->args->base_type));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user