diff --git a/dep/dbmgr b/dep/dbmgr index 8a5126c..8fbdd4a 160000 --- a/dep/dbmgr +++ b/dep/dbmgr @@ -1 +1 @@ -Subproject commit 8a5126cd1a2769780bd4e05c18d553f2bcb60f56 +Subproject commit 8fbdd4aba7438c7d3eace1308476597460d0aeed diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 9d6edf4..8b20433 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -10,3 +10,6 @@ target_link_libraries(obj_extractor DatabaseManager) file(GLOB script2txt_src "script2txt/*") add_executable(script2txt ${script2txt_src}) + +file(GLOB mmp_extractor_src "mmp_extractor/*") +add_executable(mmp_extractor ${mmp_extractor_src}) diff --git a/src/mmp_extractor/mmp.cpp b/src/mmp_extractor/mmp.cpp new file mode 100644 index 0000000..4e74e84 --- /dev/null +++ b/src/mmp_extractor/mmp.cpp @@ -0,0 +1,57 @@ +/* + * AIM mmp_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "mmp.h" + +#define FREAD(var) fread(&var, 1, sizeof(var), f) +#define FREAD_N(var, n) fread(&var, 1, n, f) + +size_t file_size(FILE *f) +{ + auto old = ftell(f); + fseek(f, 0, SEEK_END); + auto sz = ftell(f); + fseek(f, old, SEEK_SET); + return sz; +} + +void mmp::load(FILE *f) +{ + FREAD(unk1); + FREAD(unk2); + FREAD(width); + FREAD(height); + FREAD(unk3); + FREAD(unk4); + FREAD(unk5); + FREAD(unk6); + FREAD(unk7); + FREAD(unk8); + + int n_seg = width / 64 * height / 64; + int sz = n_seg * sizeof(segment); + int fsz = file_size(f); + int off = fsz - sz; + fseek(f, off, SEEK_SET); + + segments = vector(n_seg); + for (int i = 0; i < n_seg; i++) + FREAD(segments[i]); + + assert(ftell(f) == fsz); +} \ No newline at end of file diff --git a/src/mmp_extractor/mmp.h b/src/mmp_extractor/mmp.h new file mode 100644 index 0000000..4650a5f --- /dev/null +++ b/src/mmp_extractor/mmp.h @@ -0,0 +1,60 @@ +/* + * AIM mmp_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +using namespace std; + +struct mmp +{ + struct segment + { + uint32_t MagicNumber; + uint32_t MiniLayer1[1089]; + uint32_t MiniLayer2[1089]; + uint32_t MiniLayer3[1089]; + uint32_t MiniLayer4[1089]; + float Heightmap[4225]; + uint32_t Infomap[4225]; + uint32_t Colormap[4225]; + uint32_t Shadowmap[4225]; + uint32_t Normalmap[4225]; + }; + + uint32_t unk1; + char unk2[0x80]; + uint32_t width; + uint32_t height; + uint32_t unk3; + char unk4[0xA0]; + uint32_t unk5[7]; + char unk6[0xA0]; + char unk7[0x1AC]; + char unk8[0x1AC]; + uint32_t offset; // the beginning of segments + + vector segments; + + void load(FILE *f); +}; \ No newline at end of file diff --git a/src/mmp_extractor/mmp_extractor.cpp b/src/mmp_extractor/mmp_extractor.cpp new file mode 100644 index 0000000..267d1ea --- /dev/null +++ b/src/mmp_extractor/mmp_extractor.cpp @@ -0,0 +1,57 @@ +/* + * AIM mmp_extractor + * Copyright (C) 2015 lzwdgc + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mmp.h" + +using namespace std; + +mmp read_mmp(string fn) +{ + mmp m; + FILE *f = fopen(fn.c_str(), "rb"); + if (!f) + return m; + m.load(f); + fclose(f); + return m; +} + +int main(int argc, char *argv[]) +{ +#ifdef NDEBUG + if (argc != 2) + { + cout << "Usage:\n" << argv[0] << " file.mmp" << "\n"; + return 1; + } + read_mmp(argv[1]); +#else + auto arena = read_mmp("h:\\Games\\Механоиды\\data\\maps.pak.dir\\arena.mmp"); + auto loc1 = read_mmp("h:\\Games\\Механоиды\\data\\maps.pak.dir\\location1.mmp"); +#endif + return 0; +} \ No newline at end of file diff --git a/src/obj_extractor/obj_extractor.cpp b/src/obj_extractor/obj_extractor.cpp index 4870b2a..0300427 100644 --- a/src/obj_extractor/obj_extractor.cpp +++ b/src/obj_extractor/obj_extractor.cpp @@ -33,6 +33,7 @@ using namespace std; struct storage { + string name; Objects objects; MechGroups mgs; MapGoods mg; @@ -43,6 +44,7 @@ struct storage storage read_mmo(string fn) { storage s; + s.name = fn; FILE *f = fopen(fn.c_str(), "rb"); if (!f) return s; @@ -69,7 +71,30 @@ void write_mmo(string db, const storage &s) auto storage = initStorage(db); storage->load(); - int map_id = 1; + auto p1 = s.name.rfind('\\'); + if (p1 == -1) + p1 = 0; + auto p2 = s.name.rfind('/'); + if (p2 == -1) + p2 = 0; + int p = max(p1, p2); + string map_name = s.name.substr(p + 1); + map_name = map_name.substr(0, map_name.find('.')); + + int map_id = 0; + for (auto &m : storage->maps) + { + if (m.second->text_id == map_name) + { + map_id = m.first; + break; + } + } + + if (map_id == 0) + return; + + auto this_map = storage->maps[map_id]; for (auto &seg : s.objects.segments) { @@ -78,7 +103,6 @@ void write_mmo(string db, const storage &s) SegmentObjects *segment = (SegmentObjects *)seg; set objs; std::map bld_ids; - std::map coord_ids; for (auto &object : segment->objects) objs.insert(object.name1); for (auto &o : objs) @@ -101,24 +125,13 @@ void write_mmo(string db, const storage &s) MapBuilding mb; mb.text_id = object.name2; mb.building = storage->buildings[bld_ids[object.name1]]; - auto iter = find_if(storage->coordinates.begin(), storage->coordinates.end(), [&](const decltype(Storage::coordinates)::value_type &p) - { - Coordinate c; - c.x = object.position.x; - c.y = object.position.y; - c.z = object.position.z; - return *p.second.get() == c; - }); - if (iter == storage->coordinates.end()) - { - auto c = storage->addCoordinate(); - c->x = object.position.x; - c->y = object.position.y; - c->z = object.position.z; - mb.coordinate = c; - } - else - mb.coordinate = iter->second; + mb.map = this_map; + mb.x = object.position.x * 100.0; + mb.y = object.position.y * 100.0; + mb.z = object.position.z * 100.0; + mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x); + mb.pitch = atan2(-object.m_rotate_z[2].x, sqrt(object.m_rotate_z[2].y * object.m_rotate_z[2].y + object.m_rotate_z[2].z * object.m_rotate_z[2].z)); + mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].z); auto i = find_if(storage->mapBuildings.begin(), storage->mapBuildings.end(), [&](const decltype(Storage::mapBuildings)::value_type &p) { return *p.second.get() == mb; @@ -138,7 +151,6 @@ void write_mmo(string db, const storage &s) SegmentObjects *segment = (SegmentObjects *)seg; set objs; std::map bld_ids; - std::map coord_ids; for (auto &object : segment->objects) objs.insert(object.name1); for (auto &o : objs) @@ -160,25 +172,14 @@ void write_mmo(string db, const storage &s) { detail::MapObject mb; //mb.text_id = object.name2; + mb.map = this_map; mb.object = storage->objects[bld_ids[object.name1]]; - auto iter = find_if(storage->coordinates.begin(), storage->coordinates.end(), [&](const decltype(Storage::coordinates)::value_type &p) - { - Coordinate c; - c.x = object.position.x; - c.y = object.position.y; - c.z = object.position.z; - return *p.second.get() == c; - }); - if (iter == storage->coordinates.end()) - { - auto c = storage->addCoordinate(); - c->x = object.position.x; - c->y = object.position.y; - c->z = object.position.z; - mb.coordinate = c; - } - else - mb.coordinate = iter->second; + mb.x = object.position.x * 100.0; + mb.y = object.position.y * 100.0; + mb.z = object.position.z * 100.0; + mb.yaw = atan2(object.m_rotate_z[1].x, object.m_rotate_z[0].x); + mb.pitch = atan2(-object.m_rotate_z[2].x, sqrt(object.m_rotate_z[2].y * object.m_rotate_z[2].y + object.m_rotate_z[2].z * object.m_rotate_z[2].z)); + mb.roll = atan2(object.m_rotate_z[2].y, object.m_rotate_z[2].z); auto i = find_if(storage->mapObjects.begin(), storage->mapObjects.end(), [&](const decltype(Storage::mapObjects)::value_type &p) { return *p.second.get() == mb;