Skip to content

Commit 574ecd7

Browse files
committed
feat: bo4 maptable unlinkers
1 parent 428615b commit 574ecd7

2 files changed

Lines changed: 258 additions & 10 deletions

File tree

src/core/acts/tools/fastfile/handlers/bo4/bo4_unlinker_aitype.cpp

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ namespace {
167167
static_assert(sizeof(AiType) == 0xf00);
168168
AiType& asset{ *(AiType*)ptr };
169169

170-
core::hashes::raw_file_extractor::JsonWriter json{};
170+
BO4JsonWriter json{};
171171

172172
json.BeginObject();
173173

@@ -280,15 +280,7 @@ namespace {
280280

281281
json.EndArray();
282282
}
283-
if (asset.animMappingTables[0]) {
284-
json.WriteFieldNameString("animMappingTables");
285-
json.BeginArray();
286-
for (AnimMappingTable* table : asset.animMappingTables) {
287-
json.WriteValueHash(games::bo4::pool::GetAssetName(games::bo4::pool::ASSET_TYPE_ANIMMAPPINGTABLE, table)->name);
288-
}
289-
290-
json.EndArray();
291-
}
283+
json.WriteFieldValueXAssetArray("animMappingTables", XAssetType::ASSET_TYPE_ANIMMAPPINGTABLE, ACTS_ARRAYSIZE(asset.animMappingTables), asset.animMappingTables);
292284
if (asset.secondaryWeapon) {
293285
json.WriteFieldNameString("secondaryWeapon");
294286
json.WriteValueHash(games::bo4::pool::GetAssetName(games::bo4::pool::ASSET_TYPE_WEAPON, asset.secondaryWeapon)->name);
Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
#include <includes.hpp>
2+
#include <tools/fastfile/handlers/bo4/bo4_unlinker_map.hpp>
3+
#include <tools/fastfile/handlers/bo4/bo4_unlinker_scriptbundle.hpp>
4+
#include <core/hashes/raw_file_extractor.hpp>
5+
#include <tools/utils/data_utils.hpp>
6+
7+
namespace fastfile::handlers::bo4::map {
8+
using namespace games::bo4::pool;
9+
10+
struct ScriptBundleList;
11+
struct ObjectiveList;
12+
13+
struct MapTableEntry {
14+
const char* nameStr;
15+
XHash name;
16+
int size;
17+
XHash mapName;
18+
XHash rootMapName;
19+
const char* missionName;
20+
XHash mapDescription;
21+
XHash unk58;
22+
uint64_t unk68;
23+
XHash location;
24+
XHash unk80;
25+
XHash presence;
26+
XHash unka0;
27+
XHash previewImage;
28+
XHash loadScreen;
29+
XHash unkd0;
30+
GfxImage* unke0;
31+
GfxImage* unke8;
32+
const char* loadingmovie;
33+
uint64_t unkf8;
34+
ObjectiveList* objectiveList;
35+
const char* unk108;
36+
ScriptBundleList* bundleList;
37+
XHash unk118;
38+
uint64_t unk128;
39+
uint64_t unk130;
40+
const char* unk138;
41+
GfxImage* unk140;
42+
uint32_t playerRoleTemplatesCount;
43+
PlayerRoleTemplate** playerRoleTemplates;
44+
uint64_t unk158;
45+
uint32_t unk160;
46+
uint32_t unk164;
47+
XHash unk168;
48+
scriptbundle::SB_ObjectsArray bundle;
49+
uint64_t uniqueID;
50+
};
51+
static_assert(sizeof(MapTableEntry) == 0x1A0);
52+
53+
struct MapTable {
54+
XHash name;
55+
uint32_t mapCount;
56+
MapTableEntry* maps;
57+
eModes sessionMode;
58+
uint32_t campaignMode;
59+
int32_t dlcIndex;
60+
};
61+
static_assert(sizeof(MapTable) == 0x30);
62+
63+
struct MapTableListElem {
64+
uint64_t mapsCount;
65+
XHash* maps;
66+
uint64_t devMapsCount;
67+
XHash* devMaps;
68+
};
69+
70+
struct MapTableList {
71+
XHash name;
72+
MapTableListElem cp;
73+
MapTableListElem mp;
74+
MapTableListElem zm;
75+
MapTableListElem wz;
76+
};
77+
78+
struct MapTableLoadingImages {
79+
XHash name;
80+
uint64_t imageCount;
81+
GfxImage** images;
82+
uint64_t mapCount;
83+
};
84+
static_assert(sizeof(MapTableLoadingImages) == 0x28);
85+
86+
struct MapTablePreviewImages {
87+
XHash name;
88+
uint64_t imageCount;
89+
GfxImage** images;
90+
uint64_t mapCount;
91+
};
92+
static_assert(sizeof(MapTablePreviewImages) == 0x28);
93+
94+
class MapTableWorker : public Worker {
95+
void Unlink(fastfile::FastFileOption& opt, void* ptr) override {
96+
MapTable& asset{ *(MapTable*)ptr };
97+
98+
99+
BO4JsonWriter json{};
100+
101+
json.BeginObject();
102+
json.WriteFieldValueXHash("name", asset.name);
103+
json.WriteFieldValueString("sessionMode", GetEModeName(asset.sessionMode));
104+
if (asset.dlcIndex) json.WriteFieldValueNumber("dlcIndex", asset.dlcIndex);
105+
if (asset.campaignMode) json.WriteFieldValueNumber("campaignMode", asset.campaignMode);
106+
107+
if (asset.maps) {
108+
json.WriteFieldNameString("maps");
109+
json.BeginArray();
110+
111+
for (size_t i = 0; i < asset.mapCount; i++) {
112+
MapTableEntry& e{ asset.maps[i] };
113+
114+
json.BeginObject();
115+
json.WriteFieldValueNumber("uniqueID", e.uniqueID);
116+
json.WriteFieldValueXString("name", e.nameStr);
117+
json.WriteFieldValueXHash("hashname", e.name);
118+
json.WriteFieldValueXString("missionName", e.missionName);
119+
json.WriteFieldValueXString("loadingmovie", e.loadingmovie);
120+
json.WriteFieldValueXHash("mapName", e.mapName);
121+
json.WriteFieldValueXHash("rootMapName", e.rootMapName);
122+
json.WriteFieldValueXHash("mapDescription", e.mapDescription);
123+
json.WriteFieldValueXHash("unk58", e.unk58);
124+
json.WriteFieldValueXHash("location", e.location);
125+
json.WriteFieldValueXHash("unk80", e.unk80);
126+
json.WriteFieldValueXHash("presence", e.presence);
127+
json.WriteFieldValueXHash("unka0", e.unka0);
128+
json.WriteFieldValueXHash("previewImage", e.previewImage);
129+
json.WriteFieldValueXHash("loadScreen", e.loadScreen);
130+
json.WriteFieldValueXHash("unkd0", e.unkd0);
131+
json.WriteFieldValueXHash("unk118", e.unk118);
132+
json.WriteFieldValueXHash("unk168", e.unk168);
133+
json.WriteFieldValueXAsset("e:unke0", XAssetType::ASSET_TYPE_IMAGE, e.unke0);
134+
json.WriteFieldValueXAsset("e:unke8", XAssetType::ASSET_TYPE_IMAGE, e.unke8);
135+
json.WriteFieldValueXAsset("e:unk140", XAssetType::ASSET_TYPE_IMAGE, e.unk140);
136+
if (e.unk164) json.WriteFieldValueNumber("e:unk164", e.unk164);
137+
json.WriteFieldValueXAsset("bundleList", XAssetType::ASSET_TYPE_SCRIPTBUNDLELIST, e.bundleList);
138+
json.WriteFieldValueXAsset("objectiveList", XAssetType::ASSET_TYPE_OBJECTIVE_LIST, e.objectiveList);
139+
json.WriteFieldValueXAssetArray("playerRoleTemplates", XAssetType::ASSET_TYPE_PLAYER_ROLE_TEMPLATE, e.playerRoleTemplatesCount, e.playerRoleTemplates);
140+
json.WriteFieldValueNumber("size", e.size);
141+
142+
scriptbundle::WriteObject(json, "bundle", e.bundle);
143+
144+
json.WriteFieldValueUnknown("e:unk68", e.unk68);
145+
json.WriteFieldValueUnknown("e:unkf8", e.unkf8);
146+
json.WriteFieldValueUnknown("e:unk108", e.unk108);
147+
json.WriteFieldValueUnknown("e:unk128", e.unk128);
148+
json.WriteFieldValueUnknown("e:unk130", e.unk130);
149+
json.WriteFieldValueUnknown("e:unk138", e.unk138);
150+
json.WriteFieldValueUnknown("e:unk158", e.unk158);
151+
json.WriteFieldValueUnknown("e:unk160", e.unk160);
152+
json.EndObject();
153+
}
154+
155+
json.EndArray();
156+
}
157+
158+
json.EndObject();
159+
160+
161+
std::filesystem::path outFile{ opt.m_output / "bo4" / "source" / "tables" / "map" / std::format("{}.json", hashutils::ExtractTmp("file", asset.name)) };
162+
163+
std::filesystem::create_directories(outFile.parent_path());
164+
LOG_OPT_INFO("Dump map table {}", outFile.string());
165+
166+
if (!json.WriteToFile(outFile)) {
167+
LOG_ERROR("Error when dumping {}", outFile.string());
168+
}
169+
}
170+
};
171+
class MapTablListWorker : public Worker {
172+
void Unlink(fastfile::FastFileOption& opt, void* ptr) override {
173+
MapTableList& asset{ *(MapTableList*)ptr };
174+
175+
176+
BO4JsonWriter json{};
177+
178+
json.BeginObject();
179+
json.WriteFieldValueXHash("name", asset.name);
180+
181+
auto WriteList = [&json](MapTableListElem& elem, const char* id) {
182+
if (!(elem.maps || elem.devMaps)) return;
183+
json.WriteFieldNameString(id);
184+
json.BeginObject();
185+
if (elem.maps) {
186+
json.WriteFieldNameString("maps");
187+
json.BeginArray();
188+
for (size_t i = 0; i < elem.mapsCount; i++) {
189+
json.WriteValueHash(elem.maps[i]);
190+
}
191+
json.EndArray();
192+
}
193+
if (elem.devMaps) {
194+
json.WriteFieldNameString("devMaps");
195+
json.BeginArray();
196+
for (size_t i = 0; i < elem.devMapsCount; i++) {
197+
json.WriteValueHash(elem.devMaps[i]);
198+
}
199+
json.EndArray();
200+
}
201+
json.EndObject();
202+
};
203+
204+
WriteList(asset.cp, "cp");
205+
WriteList(asset.mp, "mp");
206+
WriteList(asset.zm, "zm");
207+
WriteList(asset.wz, "wz");
208+
209+
json.EndObject();
210+
211+
212+
std::filesystem::path outFile{ opt.m_output / "bo4" / "source" / "tables" / "map" / "list" / std::format("{}.json", hashutils::ExtractTmp("file", asset.name)) };
213+
214+
std::filesystem::create_directories(outFile.parent_path());
215+
LOG_OPT_INFO("Dump map table list {}", outFile.string());
216+
217+
if (!json.WriteToFile(outFile)) {
218+
LOG_ERROR("Error when dumping {}", outFile.string());
219+
}
220+
}
221+
};
222+
223+
class MapTableImagesWorker : public Worker {
224+
const char* type;
225+
public:
226+
MapTableImagesWorker(const char* type) : type(type) {}
227+
228+
void Unlink(fastfile::FastFileOption& opt, void* ptr) override {
229+
MapTablePreviewImages& asset{ *(MapTablePreviewImages*)ptr };
230+
231+
232+
BO4JsonWriter json{};
233+
234+
json.BeginObject();
235+
json.WriteFieldValueXHash("name", asset.name);
236+
json.WriteFieldValueNumber("mapCount", asset.mapCount);
237+
json.WriteFieldValueXAssetArray("images", XAssetType::ASSET_TYPE_IMAGE, asset.imageCount, asset.images);
238+
json.EndObject();
239+
240+
241+
std::filesystem::path outFile{ opt.m_output / "bo4" / "source" / "tables" / "map" / type / std::format("{}.json", hashutils::ExtractTmp("file", asset.name)) };
242+
243+
std::filesystem::create_directories(outFile.parent_path());
244+
LOG_OPT_INFO("Dump map table {} {}", type, outFile.string());
245+
246+
if (!json.WriteToFile(outFile)) {
247+
LOG_ERROR("Error when dumping {}", outFile.string());
248+
}
249+
}
250+
};
251+
252+
utils::MapAdder<MapTableWorker, games::bo4::pool::XAssetType, Worker> impltable{ GetWorkers(), games::bo4::pool::XAssetType::ASSET_TYPE_MAPTABLE };
253+
utils::MapAdder<MapTablListWorker, games::bo4::pool::XAssetType, Worker> impltablelist{ GetWorkers(), games::bo4::pool::XAssetType::ASSET_TYPE_MAPTABLE_LIST };
254+
utils::MapAdder<MapTableImagesWorker, games::bo4::pool::XAssetType, Worker> implimgl{ GetWorkers(), games::bo4::pool::XAssetType::ASSET_TYPE_MAPTABLE_LOADING_IMAGES, "loadingimages" };
255+
utils::MapAdder<MapTableImagesWorker, games::bo4::pool::XAssetType, Worker> implimgp{ GetWorkers(), games::bo4::pool::XAssetType::ASSET_TYPE_MAPTABLE_PREVIEW_IMAGES, "previewimages" };
256+
}

0 commit comments

Comments
 (0)