Project SkyFire Core
SkyFire 5.4.8 server core API documentation
Loading...
Searching...
No Matches
System.cpp
Go to the documentation of this file.
1/*
2* This file is part of Project SkyFire https://www.projectskyfire.org.
3* See LICENSE.md file for Copyright information
4*/
5
6#define _CRT_SECURE_NO_DEPRECATE
7
8#include <stdio.h>
9#include <deque>
10#include <list>
11#include <cstdlib>
12#include <cstring>
13#include <vector>
14
15#ifdef _WIN64
16#include "direct.h"
17#define chdir _chdir
18#elif defined (_WIN32)
19#include "direct.h"
20#else
21#include <sys/stat.h>
22#include <unistd.h>
23#define ERROR_PATH_NOT_FOUND ERROR_FILE_NOT_FOUND
24#endif
25
26#include "StormLib.h"
27#include "dbcfile.h"
28
29#include "adt.h"
30#include "wdt.h"
31#include <fcntl.h>
32
33#if defined( __GNUC__ )
34 #define _open open
35 #define _close close
36 #ifndef O_BINARY
37 #define O_BINARY 0
38 #endif
39#else
40 #include <io.h>
41#endif
42
43#ifdef O_LARGEFILE
44 #define OPEN_FLAGS (O_RDONLY | O_BINARY | O_LARGEFILE)
45#else
46 #define OPEN_FLAGS (O_RDONLY | O_BINARY)
47#endif
48
49HANDLE WorldMpq = NULL;
50HANDLE LocaleMpq = NULL;
51
52typedef struct
53{
54 char name[64];
56} map_id;
57
61char output_path[128] = ".";
62char input_path[128] = ".";
64
65// **************************************************
66// Extractor options
67// **************************************************
74
75// Select data for extract
77
78// This option allow limit minimum height to some value (Allow save some memory)
80float CONF_use_minHeight = -500.0f;
81
82// This option allow use float to int conversion
84float CONF_float_to_int8_limit = 2.0f; // Max accuracy = val/256
85float CONF_float_to_int16_limit = 2048.0f; // Max accuracy = val/65536
86float CONF_flat_height_delta_limit = 0.005f; // If max - min less this value - surface is flat
87float CONF_flat_liquid_delta_limit = 0.001f; // If max - min less this value - liquid surface is flat
88
89uint32 CONF_TargetBuild = 18273; // 5.4.8 18273 -- current build is 18414, but Blizz didnt rename the MPQ files
90
91// List MPQ for extract maps from
92char const* CONF_mpq_list[] =
93{
94 "world.MPQ",
95 "model.MPQ",
96 "misc.MPQ",
97 "expansion1.MPQ",
98 "expansion2.MPQ",
99 "expansion3.MPQ",
100 "expansion4.MPQ"
101};
102
103uint32 const Builds[] = {16016, 16048, 16057, 16309, 16357, 16516, 16650, 16844, 16965, 17116, 17266, 17325, 17345, 17538, 17645, 17688, 17898, 18273};
104//#define LAST_DBC_IN_DATA_BUILD 13623 // after this build mpqs with dbc are back to locale folder
105#define NEW_BASE_SET_BUILD 15211
106#define LOCALES_COUNT 15
107
108char const* Locales[LOCALES_COUNT] =
109{
110 "enGB", "enUS",
111 "deDE", "esES",
112 "frFR", "koKR",
113 "zhCN", "zhTW",
114 "enCN", "enTW",
115 "esMX", "ruRU",
116 "ptBR", "ptPT",
117 "itIT",
118};
119
120TCHAR const* LocalesT[LOCALES_COUNT] =
121{
122 _T("enGB"), _T("enUS"),
123 _T("deDE"), _T("esES"),
124 _T("frFR"), _T("koKR"),
125 _T("zhCN"), _T("zhTW"),
126 _T("enCN"), _T("enTW"),
127 _T("esMX"), _T("ruRU"),
128 _T("ptBR"), _T("ptPT"),
129 _T("itIT"),
130};
131
132void CreateDir(std::string const& path)
133{
134 if (chdir(path.c_str()) == 0)
135 {
136 chdir("../");
137 return;
138 }
139
140#ifdef _WIN32
141 _mkdir(path.c_str());
142#else
143 mkdir(path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO); // 0777
144#endif
145}
146
147bool FileExists(TCHAR const* fileName)
148{
149 int fp = _open(fileName, O_RDONLY | O_BINARY);
150 if(fp != -1)
151 {
152 _close(fp);
153 return true;
154 }
155
156 return false;
157}
158
159void Usage(char const* prg)
160{
161 printf(
162 "Usage:\n"\
163 "%s -[var] [value]\n"\
164 "-i set input path\n"\
165 "-o set output path\n"\
166 "-e extract only MAP(1)/DBC(2)/Camera(4) - standard: all(7)\n"\
167 "-f height stored as int (less map size but lost some accuracy) 1 by default\n"\
168 "-b target build (default %u)\n"\
169 "Example: %s -f 0 -i \"c:\\games\\game\"", prg, CONF_TargetBuild, prg);
170 exit(1);
171}
172
173void HandleArgs(int argc, char* arg[])
174{
175 for (int c = 1; c < argc; ++c)
176 {
177 // i - input path
178 // o - output path
179 // e - extract only MAP(1)/DBC(2) - standard both(3)
180 // f - use float to int conversion
181 // h - limit minimum height
182 // b - target client build
183 if (arg[c][0] != '-')
184 Usage(arg[0]);
185
186 switch (arg[c][1])
187 {
188 case 'i':
189 if (c + 1 < argc) // all ok
190 strcpy(input_path, arg[c++ + 1]);
191 else
192 Usage(arg[0]);
193 break;
194 case 'o':
195 if (c + 1 < argc) // all ok
196 strcpy(output_path, arg[c++ + 1]);
197 else
198 Usage(arg[0]);
199 break;
200 case 'f':
201 if (c + 1 < argc) // all ok
202 CONF_allow_float_to_int = atoi(arg[c++ + 1])!=0;
203 else
204 Usage(arg[0]);
205 break;
206 case 'e':
207 if (c + 1 < argc) // all ok
208 {
209 CONF_extract = atoi(arg[c++ + 1]);
210 if (!(CONF_extract > 0 && CONF_extract < 8))
211 Usage(arg[0]);
212 }
213 else
214 Usage(arg[0]);
215 break;
216 case 'b':
217 if (c + 1 < argc) // all ok
218 CONF_TargetBuild = atoi(arg[c++ + 1]);
219 else
220 Usage(arg[0]);
221 break;
222 default:
223 break;
224 }
225 }
226}
227
228uint32 ReadBuild(int locale)
229{
230 // include build info file also
231 std::string filename = std::string("component.wow-") + Locales[locale] + ".txt";
232 //printf("Read %s file... ", filename.c_str());
233
234 HANDLE dbcFile;
235 if (!SFileOpenFileEx(LocaleMpq, filename.c_str(), SFILE_OPEN_FROM_MPQ, &dbcFile))
236 {
237 printf("Fatal error: Not found %s file!\n", filename.c_str());
238 exit(1);
239 }
240
241 char buff[512] = { 0 };
242 DWORD readBytes = 0;
243 SFileReadFile(dbcFile, buff, 512, &readBytes, NULL);
244 if (!readBytes)
245 {
246 printf("Fatal error: Not found %s file!\n", filename.c_str());
247 exit(1);
248 }
249
250 std::string text = buff;
251 SFileCloseFile(dbcFile);
252 std::string version = "version=\"";
253
254 size_t pos = text.find(version);
255 size_t pos1 = pos + version.length();
256 size_t pos2 = text.find("\"", pos1);
257 if (pos == text.npos || pos2 == text.npos || pos1 >= pos2)
258 {
259 printf("Fatal error: Invalid %s file format!\n", filename.c_str());
260 exit(1);
261 }
262
263 std::string build_str = text.substr(pos1,pos2-pos1);
264
265 int build = atoi(build_str.c_str());
266 if (build <= 0)
267 {
268 printf("Fatal error: Invalid %s file format!\n", filename.c_str());
269 exit(1);
270 }
271
272 return build;
273}
274
276{
277 printf("Read Map.dbc file... ");
278
279 HANDLE dbcFile;
280 if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\Map.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
281 {
282 printf("Fatal error: Cannot find Map.dbc in archive!\n");
283 exit(1);
284 }
285
286 DBCFile dbc(dbcFile);
287 if (!dbc.open())
288 {
289 printf("Fatal error: Invalid Map.dbc file format!\n");
290 exit(1);
291 }
292
293 size_t map_count = dbc.getRecordCount();
294 map_ids = new map_id[map_count];
295 for(uint32 x = 0; x < map_count; ++x)
296 {
297 map_ids[x].id = dbc.getRecord(x).getUInt(0);
298 strcpy(map_ids[x].name, dbc.getRecord(x).getString(1));
299 }
300
301 SFileCloseFile(dbcFile);
302 printf("Done! (%u maps loaded)\n", uint32(map_count));
303 return map_count;
304}
305
307{
308 printf("Read AreaTable.dbc file...");
309 HANDLE dbcFile;
310 if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\AreaTable.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
311 {
312 printf("Fatal error: Cannot find AreaTable.dbc in archive!\n");
313 exit(1);
314 }
315
316 DBCFile dbc(dbcFile);
317 if(!dbc.open())
318 {
319 printf("Fatal error: Invalid AreaTable.dbc file format!\n");
320 exit(1);
321 }
322
323 size_t area_count = dbc.getRecordCount();
324 maxAreaId = dbc.getMaxId();
325 areas = new uint16[maxAreaId + 1];
326
327 for (uint32 x = 0; x < area_count; ++x)
328 areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
329
330 SFileCloseFile(dbcFile);
331 printf("Done! (%u areas loaded)\n", uint32(area_count));
332}
333
335{
336 printf("Read LiquidType.dbc file...");
337 HANDLE dbcFile;
338 if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\LiquidType.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
339 {
340 printf("Fatal error: Cannot find LiquidType.dbc in archive!\n");
341 exit(1);
342 }
343
344 DBCFile dbc(dbcFile);
345 if (!dbc.open())
346 {
347 printf("Fatal error: Invalid LiquidType.dbc file format!\n");
348 exit(1);
349 }
350
351 size_t liqTypeCount = dbc.getRecordCount();
352 size_t liqTypeMaxId = dbc.getMaxId();
353 LiqType = new uint16[liqTypeMaxId + 1];
354 memset(LiqType, 0xff, (liqTypeMaxId + 1) * sizeof(uint16));
355
356 for (uint32 x = 0; x < liqTypeCount; ++x)
357 LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
358
359 SFileCloseFile(dbcFile);
360 printf("Done! (%u LiqTypes loaded)\n", (uint32)liqTypeCount);
361}
362
363//
364// Adt file convertor function and data
365//
366
367// Map file format data
368static char const* MAP_MAGIC = "MAPS";
369static char const* MAP_VERSION_MAGIC = "v1.4";
370static char const* MAP_AREA_MAGIC = "AREA";
371static char const* MAP_HEIGHT_MAGIC = "MHGT";
372static char const* MAP_LIQUID_MAGIC = "MLIQ";
373
374struct map_fileheader
375{
387};
388
389#define MAP_AREA_NO_AREA 0x0001
390
391struct map_areaHeader
392{
396};
397
398#define MAP_HEIGHT_NO_HEIGHT 0x0001
399#define MAP_HEIGHT_AS_INT16 0x0002
400#define MAP_HEIGHT_AS_INT8 0x0004
401
402struct map_heightHeader
403{
406 float gridHeight;
407 float gridMaxHeight;
408};
409
410#define MAP_LIQUID_TYPE_NO_WATER 0x00
411#define MAP_LIQUID_TYPE_WATER 0x01
412#define MAP_LIQUID_TYPE_OCEAN 0x02
413#define MAP_LIQUID_TYPE_MAGMA 0x04
414#define MAP_LIQUID_TYPE_SLIME 0x08
415
416#define MAP_LIQUID_TYPE_DARK_WATER 0x10
417#define MAP_LIQUID_TYPE_WMO_WATER 0x20
418
419#define MAP_LIQUID_NO_TYPE 0x0001
420#define MAP_LIQUID_NO_HEIGHT 0x0002
421
422struct map_liquidHeader
423{
429 uint8 width;
431 float liquidLevel;
432};
433
434float selectUInt8StepStore(float maxDiff)
435{
436 return 255 / maxDiff;
437}
438
439float selectUInt16StepStore(float maxDiff)
440{
441 return 65535 / maxDiff;
442}
443// Temporary grid data store
445
452
458
459bool ConvertADT(char *filename, char *filename2, int /*cell_y*/, int /*cell_x*/, uint32 build)
460{
461 ChunkedFile adt;
462 if (!adt.loadFile(WorldMpq, filename))
463 return false;
464
465 // Prepare map header
466 map_fileheader map;
467 map.mapMagic = *(uint32 const*)MAP_MAGIC;
469 map.buildMagic = build;
470
471 // Get area flags data
472 memset(area_flags, 0xFF, sizeof(area_flags));
473 memset(V9, 0, sizeof(V9));
474 memset(V8, 0, sizeof(V8));
475
476 memset(liquid_show, 0, sizeof(liquid_show));
477 memset(liquid_flags, 0, sizeof(liquid_flags));
478 memset(liquid_entry, 0, sizeof(liquid_entry));
479
480 memset(holes, 0, sizeof(holes));
481
482 bool hasHoles = false;
483
484 for (std::multimap<std::string, FileChunk*>::const_iterator itr = adt.chunks.lower_bound("MCNK"); itr != adt.chunks.upper_bound("MCNK"); ++itr)
485 {
486 adt_MCNK* mcnk = itr->second->As<adt_MCNK>();
487
488 // Area data
489 if (mcnk->areaid <= maxAreaId && areas[mcnk->areaid] != 0xFFFF)
490 area_flags[mcnk->iy][mcnk->ix] = areas[mcnk->areaid];
491
492 // Height
493 // Height values for triangles stored in order:
494 // 1 2 3 4 5 6 7 8 9
495 // 10 11 12 13 14 15 16 17
496 // 18 19 20 21 22 23 24 25 26
497 // 27 28 29 30 31 32 33 34
498 // . . . . . . . .
499 // For better get height values merge it to V9 and V8 map
500 // V9 height map:
501 // 1 2 3 4 5 6 7 8 9
502 // 18 19 20 21 22 23 24 25 26
503 // . . . . . . . .
504 // V8 height map:
505 // 10 11 12 13 14 15 16 17
506 // 27 28 29 30 31 32 33 34
507 // . . . . . . . .
508
509 // Set map height as grid height
510 for (int y = 0; y <= ADT_CELL_SIZE; y++)
511 {
512 int cy = mcnk->iy * ADT_CELL_SIZE + y;
513 for (int x = 0; x <= ADT_CELL_SIZE; x++)
514 {
515 int cx = mcnk->ix * ADT_CELL_SIZE + x;
516 V9[cy][cx] = mcnk->ypos;
517 }
518 }
519
520 for (int y = 0; y < ADT_CELL_SIZE; y++)
521 {
522 int cy = mcnk->iy * ADT_CELL_SIZE + y;
523 for (int x = 0; x < ADT_CELL_SIZE; x++)
524 {
525 int cx = mcnk->ix * ADT_CELL_SIZE + x;
526 V8[cy][cx] = mcnk->ypos;
527 }
528 }
529
530 // Get custom height
531 if (FileChunk* chunk = itr->second->GetSubChunk("MCVT"))
532 {
533 adt_MCVT* mcvt = chunk->As<adt_MCVT>();
534 // get V9 height map
535 for (int y = 0; y <= ADT_CELL_SIZE; y++)
536 {
537 int cy = mcnk->iy * ADT_CELL_SIZE + y;
538 for (int x = 0; x <= ADT_CELL_SIZE; x++)
539 {
540 int cx = mcnk->ix * ADT_CELL_SIZE + x;
541 V9[cy][cx] += mcvt->height_map[y*(ADT_CELL_SIZE * 2 + 1) + x];
542 }
543 }
544 // get V8 height map
545 for (int y = 0; y < ADT_CELL_SIZE; y++)
546 {
547 int cy = mcnk->iy * ADT_CELL_SIZE + y;
548 for (int x = 0; x < ADT_CELL_SIZE; x++)
549 {
550 int cx = mcnk->ix * ADT_CELL_SIZE + x;
551 V8[cy][cx] += mcvt->height_map[y*(ADT_CELL_SIZE * 2 + 1) + ADT_CELL_SIZE + 1 + x];
552 }
553 }
554 }
555
556 // Liquid data
557 if (mcnk->sizeMCLQ > 8)
558 {
559 if (FileChunk* chunk = itr->second->GetSubChunk("MCLQ"))
560 {
561 adt_MCLQ* liquid = chunk->As<adt_MCLQ>();
562 int count = 0;
563 for (int y = 0; y < ADT_CELL_SIZE; ++y)
564 {
565 int cy = mcnk->iy * ADT_CELL_SIZE + y;
566 for (int x = 0; x < ADT_CELL_SIZE; ++x)
567 {
568 int cx = mcnk->ix * ADT_CELL_SIZE + x;
569 if (liquid->flags[y][x] != 0x0F)
570 {
571 liquid_show[cy][cx] = true;
572 if (liquid->flags[y][x] & (1 << 7))
574 ++count;
575 }
576 }
577 }
578
579 uint32 c_flag = mcnk->flags;
580 if (c_flag & (1 << 2))
581 {
582 liquid_entry[mcnk->iy][mcnk->ix] = 1;
583 liquid_flags[mcnk->iy][mcnk->ix] |= MAP_LIQUID_TYPE_WATER; // water
584 }
585 if (c_flag & (1 << 3))
586 {
587 liquid_entry[mcnk->iy][mcnk->ix] = 2;
588 liquid_flags[mcnk->iy][mcnk->ix] |= MAP_LIQUID_TYPE_OCEAN; // ocean
589 }
590 if (c_flag & (1 << 4))
591 {
592 liquid_entry[mcnk->iy][mcnk->ix] = 3;
593 liquid_flags[mcnk->iy][mcnk->ix] |= MAP_LIQUID_TYPE_MAGMA; // magma/slime
594 }
595
596 if (!count && liquid_flags[mcnk->iy][mcnk->ix])
597 fprintf(stderr, "Wrong liquid detect in MCLQ chunk");
598
599 for (int y = 0; y <= ADT_CELL_SIZE; ++y)
600 {
601 int cy = mcnk->iy * ADT_CELL_SIZE + y;
602 for (int x = 0; x <= ADT_CELL_SIZE; ++x)
603 {
604 int cx = mcnk->ix * ADT_CELL_SIZE + x;
605 liquid_height[cy][cx] = liquid->liquid[y][x].height;
606 }
607 }
608 }
609 }
610
611 // Hole data
612 if (!(mcnk->flags & 0x10000))
613 {
614 if (uint16 hole = mcnk->holes)
615 {
616 holes[mcnk->iy][mcnk->ix] = mcnk->holes;
617 hasHoles = true;
618 }
619 }
620 }
621
622 // Get liquid map for grid (in WOTLK used MH2O chunk)
623 if (FileChunk* chunk = adt.GetChunk("MH2O"))
624 {
625 adt_MH2O* h2o = chunk->As<adt_MH2O>();
626 for (int i = 0; i < ADT_CELLS_PER_GRID; i++)
627 {
628 for (int j = 0; j < ADT_CELLS_PER_GRID; j++)
629 {
630 adt_liquid_header *h = h2o->getLiquidData(i, j);
631 if (!h)
632 continue;
633
634 int count = 0;
635 uint64 show = h2o->getLiquidShowMap(h);
636 for (int y = 0; y < h->height; y++)
637 {
638 int cy = i * ADT_CELL_SIZE + y + h->yOffset;
639 for (int x = 0; x < h->width; x++)
640 {
641 int cx = j * ADT_CELL_SIZE + x + h->xOffset;
642 if (show & 1)
643 {
644 liquid_show[cy][cx] = true;
645 ++count;
646 }
647 show >>= 1;
648 }
649 }
650
651 liquid_entry[i][j] = h->liquidType;
652 switch (LiqType[h->liquidType])
653 {
658 default:
659 printf("\nCan't find Liquid type %u for map %s\nchunk %d,%d\n", h->liquidType, filename, i, j);
660 break;
661 }
662 // Dark water detect
664 {
665 uint8* lm = h2o->getLiquidLightMap(h);
666 if (!lm)
668 }
669
670 if (!count && liquid_flags[i][j])
671 printf("Wrong liquid detect in MH2O chunk");
672
673 float* height = h2o->getLiquidHeightMap(h);
674 int pos = 0;
675 for (int y = 0; y <= h->height; y++)
676 {
677 int cy = i * ADT_CELL_SIZE + y + h->yOffset;
678 for (int x = 0; x <= h->width; x++)
679 {
680 int cx = j * ADT_CELL_SIZE + x + h->xOffset;
681
682 if (height)
683 liquid_height[cy][cx] = height[pos];
684 else
685 liquid_height[cy][cx] = h->heightLevel1;
686
687 pos++;
688 }
689 }
690 }
691 }
692 }
693
694 //============================================
695 // Try pack area data
696 //============================================
697 bool fullAreaData = false;
698 uint32 areaflag = area_flags[0][0];
699 for (int y=0;y<ADT_CELLS_PER_GRID;y++)
700 {
701 for(int x=0;x<ADT_CELLS_PER_GRID;x++)
702 {
703 if(area_flags[y][x]!=areaflag)
704 {
705 fullAreaData = true;
706 break;
707 }
708 }
709 }
710
711 map.areaMapOffset = sizeof(map);
712 map.areaMapSize = sizeof(map_areaHeader);
713
714 map_areaHeader areaHeader;
715 areaHeader.fourcc = *(uint32 const*)MAP_AREA_MAGIC;
716 areaHeader.flags = 0;
717 if (fullAreaData)
718 {
719 areaHeader.gridArea = 0;
720 map.areaMapSize+=sizeof(area_flags);
721 }
722 else
723 {
724 areaHeader.flags |= MAP_AREA_NO_AREA;
725 areaHeader.gridArea = (uint16)areaflag;
726 }
727
728 //============================================
729 // Try pack height data
730 //============================================
731 float maxHeight = -20000;
732 float minHeight = 20000;
733 for (int y=0; y<ADT_GRID_SIZE; y++)
734 {
735 for(int x=0;x<ADT_GRID_SIZE;x++)
736 {
737 float h = V8[y][x];
738 if (maxHeight < h) maxHeight = h;
739 if (minHeight > h) minHeight = h;
740 }
741 }
742 for (int y=0; y<=ADT_GRID_SIZE; y++)
743 {
744 for(int x=0;x<=ADT_GRID_SIZE;x++)
745 {
746 float h = V9[y][x];
747 if (maxHeight < h) maxHeight = h;
748 if (minHeight > h) minHeight = h;
749 }
750 }
751
752 // Check for allow limit minimum height (not store height in deep ochean - allow save some memory)
754 {
755 for (int y=0; y<ADT_GRID_SIZE; y++)
756 for(int x=0;x<ADT_GRID_SIZE;x++)
757 if (V8[y][x] < CONF_use_minHeight)
758 V8[y][x] = CONF_use_minHeight;
759 for (int y=0; y<=ADT_GRID_SIZE; y++)
760 for(int x=0;x<=ADT_GRID_SIZE;x++)
761 if (V9[y][x] < CONF_use_minHeight)
762 V9[y][x] = CONF_use_minHeight;
763 if (minHeight < CONF_use_minHeight)
764 minHeight = CONF_use_minHeight;
765 if (maxHeight < CONF_use_minHeight)
766 maxHeight = CONF_use_minHeight;
767 }
768
770 map.heightMapSize = sizeof(map_heightHeader);
771
772 map_heightHeader heightHeader;
773 heightHeader.fourcc = *(uint32 const*)MAP_HEIGHT_MAGIC;
774 heightHeader.flags = 0;
775 heightHeader.gridHeight = minHeight;
776 heightHeader.gridMaxHeight = maxHeight;
777
778 if (maxHeight == minHeight)
779 heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT;
780
781 // Not need store if flat surface
782 if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_height_delta_limit)
783 heightHeader.flags |= MAP_HEIGHT_NO_HEIGHT;
784
785 // Try store as packed in uint16 or uint8 values
786 if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT))
787 {
788 float step = 0;
789 // Try Store as uint values
791 {
792 float diff = maxHeight - minHeight;
793 if (diff < CONF_float_to_int8_limit) // As uint8 (max accuracy = CONF_float_to_int8_limit/256)
794 {
795 heightHeader.flags|=MAP_HEIGHT_AS_INT8;
796 step = selectUInt8StepStore(diff);
797 }
798 else if (diff<CONF_float_to_int16_limit) // As uint16 (max accuracy = CONF_float_to_int16_limit/65536)
799 {
800 heightHeader.flags|=MAP_HEIGHT_AS_INT16;
801 step = selectUInt16StepStore(diff);
802 }
803 }
804
805 // Pack it to int values if need
806 if (heightHeader.flags&MAP_HEIGHT_AS_INT8)
807 {
808 for (int y=0; y<ADT_GRID_SIZE; y++)
809 for(int x=0;x<ADT_GRID_SIZE;x++)
810 uint8_V8[y][x] = uint8((V8[y][x] - minHeight) * step + 0.5f);
811 for (int y=0; y<=ADT_GRID_SIZE; y++)
812 for(int x=0;x<=ADT_GRID_SIZE;x++)
813 uint8_V9[y][x] = uint8((V9[y][x] - minHeight) * step + 0.5f);
814 map.heightMapSize+= sizeof(uint8_V9) + sizeof(uint8_V8);
815 }
816 else if (heightHeader.flags&MAP_HEIGHT_AS_INT16)
817 {
818 for (int y=0; y<ADT_GRID_SIZE; y++)
819 for(int x=0;x<ADT_GRID_SIZE;x++)
820 uint16_V8[y][x] = uint16((V8[y][x] - minHeight) * step + 0.5f);
821 for (int y=0; y<=ADT_GRID_SIZE; y++)
822 for(int x=0;x<=ADT_GRID_SIZE;x++)
823 uint16_V9[y][x] = uint16((V9[y][x] - minHeight) * step + 0.5f);
824 map.heightMapSize+= sizeof(uint16_V9) + sizeof(uint16_V8);
825 }
826 else
827 map.heightMapSize+= sizeof(V9) + sizeof(V8);
828 }
829
830 //============================================
831 // Pack liquid data
832 //============================================
833 uint8 type = liquid_flags[0][0];
834 bool fullType = false;
835 for (int y = 0; y < ADT_CELLS_PER_GRID; y++)
836 {
837 for (int x = 0; x < ADT_CELLS_PER_GRID; x++)
838 {
839 if (liquid_flags[y][x] != type)
840 {
841 fullType = true;
843 break;
844 }
845 }
846 }
847
848 map_liquidHeader liquidHeader;
849
850 // no water data (if all grid have 0 liquid type)
851 if (type == 0 && !fullType)
852 {
853 // No liquid data
854 map.liquidMapOffset = 0;
855 map.liquidMapSize = 0;
856 }
857 else
858 {
859 int minX = 255, minY = 255;
860 int maxX = 0, maxY = 0;
861 maxHeight = -20000;
862 minHeight = 20000;
863 for (int y=0; y<ADT_GRID_SIZE; y++)
864 {
865 for(int x=0; x<ADT_GRID_SIZE; x++)
866 {
867 if (liquid_show[y][x])
868 {
869 if (minX > x) minX = x;
870 if (maxX < x) maxX = x;
871 if (minY > y) minY = y;
872 if (maxY < y) maxY = y;
873 float h = liquid_height[y][x];
874 if (maxHeight < h) maxHeight = h;
875 if (minHeight > h) minHeight = h;
876 }
877 else
879 }
880 }
882 map.liquidMapSize = sizeof(map_liquidHeader);
883 liquidHeader.fourcc = *(uint32 const*)MAP_LIQUID_MAGIC;
884 liquidHeader.flags = 0;
885 liquidHeader.liquidType = 0;
886 liquidHeader.offsetX = minX;
887 liquidHeader.offsetY = minY;
888 liquidHeader.width = maxX - minX + 1 + 1;
889 liquidHeader.height = maxY - minY + 1 + 1;
890 liquidHeader.liquidLevel = minHeight;
891
892 if (maxHeight == minHeight)
893 liquidHeader.flags |= MAP_LIQUID_NO_HEIGHT;
894
895 // Not need store if flat surface
896 if (CONF_allow_float_to_int && (maxHeight - minHeight) < CONF_flat_liquid_delta_limit)
897 liquidHeader.flags |= MAP_LIQUID_NO_HEIGHT;
898
899 if (!fullType)
900 liquidHeader.flags |= MAP_LIQUID_NO_TYPE;
901
902 if (liquidHeader.flags & MAP_LIQUID_NO_TYPE)
903 liquidHeader.liquidType = type;
904 else
905 map.liquidMapSize += sizeof(liquid_entry) + sizeof(liquid_flags);
906
907 if (!(liquidHeader.flags & MAP_LIQUID_NO_HEIGHT))
908 map.liquidMapSize += sizeof(float)*liquidHeader.width*liquidHeader.height;
909 }
910
911 if (map.liquidMapOffset)
913 else
915
916 if (hasHoles)
917 map.holesSize = sizeof(holes);
918 else
919 map.holesSize = 0;
920
921 // Ok all data prepared - store it
922 FILE* output = fopen(filename2, "wb");
923 if (!output)
924 {
925 printf("Can't create the output file '%s'\n", filename2);
926 return false;
927 }
928 fwrite(&map, sizeof(map), 1, output);
929 // Store area data
930 fwrite(&areaHeader, sizeof(areaHeader), 1, output);
931 if (!(areaHeader.flags&MAP_AREA_NO_AREA))
932 fwrite(area_flags, sizeof(area_flags), 1, output);
933
934 // Store height data
935 fwrite(&heightHeader, sizeof(heightHeader), 1, output);
936 if (!(heightHeader.flags & MAP_HEIGHT_NO_HEIGHT))
937 {
938 if (heightHeader.flags & MAP_HEIGHT_AS_INT16)
939 {
940 fwrite(uint16_V9, sizeof(uint16_V9), 1, output);
941 fwrite(uint16_V8, sizeof(uint16_V8), 1, output);
942 }
943 else if (heightHeader.flags & MAP_HEIGHT_AS_INT8)
944 {
945 fwrite(uint8_V9, sizeof(uint8_V9), 1, output);
946 fwrite(uint8_V8, sizeof(uint8_V8), 1, output);
947 }
948 else
949 {
950 fwrite(V9, sizeof(V9), 1, output);
951 fwrite(V8, sizeof(V8), 1, output);
952 }
953 }
954
955 // Store liquid data if need
956 if (map.liquidMapOffset)
957 {
958 fwrite(&liquidHeader, sizeof(liquidHeader), 1, output);
959 if (!(liquidHeader.flags & MAP_LIQUID_NO_TYPE))
960 {
961 fwrite(liquid_entry, sizeof(liquid_entry), 1, output);
962 fwrite(liquid_flags, sizeof(liquid_flags), 1, output);
963 }
964
965 if (!(liquidHeader.flags & MAP_LIQUID_NO_HEIGHT))
966 {
967 for (int y = 0; y < liquidHeader.height; y++)
968 fwrite(&liquid_height[y + liquidHeader.offsetY][liquidHeader.offsetX], sizeof(float), liquidHeader.width, output);
969 }
970 }
971
972 // store hole data
973 if (hasHoles)
974 fwrite(holes, map.holesSize, 1, output);
975
976 fclose(output);
977
978 return true;
979}
980
982{
983 char mpq_filename[1024];
984 char output_filename[1024];
985 char mpq_map_name[1024];
986
987 printf("Extracting maps...\n");
988
990
993
994 std::string path = output_path;
995 path += "/maps/";
996 CreateDir(path);
997
998 printf("Convert map files\n");
999 for (uint32 z = 0; z < map_count; ++z)
1000 {
1001 printf("Extract %s (%d/%u) \n", map_ids[z].name, z+1, map_count);
1002 // Loadup map grid data
1003 snprintf(mpq_map_name, sizeof(mpq_map_name), "World\\Maps\\%s\\%s.wdt", map_ids[z].name, map_ids[z].name);
1004 ChunkedFile wdt;
1005 if (!wdt.loadFile(WorldMpq, mpq_map_name, true))
1006 continue;
1007
1008 FileChunk* chunk = wdt.GetChunk("MAIN");
1009 for (uint32 y = 0; y < WDT_MAP_SIZE; ++y)
1010 {
1011 for (uint32 x = 0; x < WDT_MAP_SIZE; ++x)
1012 {
1013 if (!(chunk->As<wdt_MAIN>()->adt_list[y][x].flag & 0x1))
1014 continue;
1015
1016 snprintf(mpq_filename, sizeof(mpq_filename), "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
1017 snprintf(output_filename, sizeof(output_filename), "%s/maps/%04u_%02u_%02u.map", output_path, map_ids[z].id, y, x);
1018 ConvertADT(mpq_filename, output_filename, y, x, build);
1019 }
1020
1021 // draw progress bar
1022 printf("Processing........................%d%%\r", (100 * (y+1)) / WDT_MAP_SIZE);
1023 }
1024 }
1025
1026 printf("\n");
1027 delete [] areas;
1028 delete [] map_ids;
1029}
1030
1031bool ExtractFile(HANDLE fileInArchive, char const* filename)
1032{
1033 FILE* output = fopen(filename, "wb");
1034 if(!output)
1035 {
1036 printf("Can't create the output file '%s'\n", filename);
1037 return false;
1038 }
1039
1040 char buffer[0x10000];
1041 DWORD readBytes = 1;
1042
1043 while (readBytes > 0)
1044 {
1045 SFileReadFile(fileInArchive, buffer, sizeof(buffer), &readBytes, NULL);
1046 if (readBytes > 0)
1047 fwrite(buffer, 1, readBytes, output);
1048 }
1049
1050 fclose(output);
1051 return true;
1052}
1053
1054void ExtractDBCFiles(int l, bool basicLocale)
1055{
1056 printf("Extracting dbc files...\n");
1057
1058 SFILE_FIND_DATA foundFile;
1059 memset(&foundFile, 0, sizeof(foundFile));
1060 HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*dbc", &foundFile, NULL);
1061 HANDLE dbcFile = NULL;
1062 uint32 count = 0;
1063 if (listFile)
1064 {
1065 std::string outputPath = output_path;
1066 outputPath += "/dbc/";
1067
1068 CreateDir(outputPath);
1069 if (!basicLocale)
1070 {
1071 outputPath += Locales[l];
1072 outputPath += "/";
1073 CreateDir(outputPath);
1074 }
1075
1076 std::string filename;
1077
1078 do
1079 {
1080 if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_FROM_MPQ, &dbcFile))
1081 {
1082 printf("Unable to open file %s in the archive\n", foundFile.cFileName);
1083 continue;
1084 }
1085
1086 filename = foundFile.cFileName;
1087 filename = outputPath + filename.substr(filename.rfind('\\') + 1);
1088
1089 if (FileExists(filename.c_str()))
1090 continue;
1091
1092 if (ExtractFile(dbcFile, filename.c_str()))
1093 ++count;
1094
1095 SFileCloseFile(dbcFile);
1096 } while (SFileFindNextFile(listFile, &foundFile));
1097
1098 SFileFindClose(listFile);
1099 }
1100
1101 printf("Extracted %u DBC files\n\n", count);
1102}
1103
1104void ExtractCameraFiles(int locale, bool basicLocale)
1105{
1106 printf("Extracting camera files...\n");
1107 HANDLE dbcFile;
1108 if (!SFileOpenFileEx(LocaleMpq, "DBFilesClient\\CinematicCamera.dbc", SFILE_OPEN_FROM_MPQ, &dbcFile))
1109 {
1110 printf("Fatal error: Cannot find CinematicCamera.dbc in archive!\n");
1111 exit(1);
1112 }
1113
1114 DBCFile camdbc(dbcFile);
1115
1116 if (!camdbc.open())
1117 {
1118 printf("Unable to open CinematicCamera.dbc. Camera extract aborted.\n");
1119 return;
1120 }
1121
1122 // get camera file list from DBC
1123 std::vector<std::string> camerafiles;
1124 size_t cam_count = camdbc.getRecordCount();
1125
1126 for (size_t i = 0; i < cam_count; ++i)
1127 {
1128 std::string camFile(camdbc.getRecord(i).getString(1));
1129 size_t loc = camFile.find(".mdx");
1130 if (loc != std::string::npos)
1131 camFile.replace(loc, 4, ".m2");
1132 camerafiles.push_back(std::string(camFile));
1133 }
1134 SFileCloseFile(dbcFile);
1135
1136 std::string path = output_path;
1137 path += "/cameras/";
1138 CreateDir(path);
1139 if (!basicLocale)
1140 {
1141 path += Locales[locale];
1142 path += "/";
1143 CreateDir(path);
1144 }
1145
1146 // extract M2s
1147 uint32 count = 0;
1148 for (std::string thisFile : camerafiles)
1149 {
1150 std::string filename = path;
1151 std::string camerasFolder = "Cameras\\";
1152 HANDLE dbcFile = NULL;
1153 filename += (thisFile.c_str() + camerasFolder.length());
1154
1155 if (FileExists(filename.c_str()))
1156 continue;
1157
1158 if (!SFileOpenFileEx(WorldMpq, thisFile.c_str(), SFILE_OPEN_FROM_MPQ, &dbcFile))
1159 {
1160 printf("Unable to open file %s in the archive\n", thisFile.c_str());
1161 continue;
1162 }
1163
1164 if (ExtractFile(dbcFile, filename.c_str()))
1165 ++count;
1166
1167 SFileCloseFile(dbcFile);
1168 }
1169 printf("Extracted %u camera files\n", count);
1170}
1171
1172void ExtractDB2Files(int l, bool basicLocale)
1173{
1174 printf("Extracting db2 files...\n");
1175
1176 SFILE_FIND_DATA foundFile;
1177 memset(&foundFile, 0, sizeof(foundFile));
1178 HANDLE listFile = SFileFindFirstFile(LocaleMpq, "DBFilesClient\\*db2", &foundFile, NULL);
1179 HANDLE dbcFile = NULL;
1180 uint32 count = 0;
1181 if (listFile)
1182 {
1183 std::string outputPath = output_path;
1184 outputPath += "/db2/";
1185
1186 CreateDir(outputPath);
1187 if (!basicLocale)
1188 {
1189 outputPath += Locales[l];
1190 outputPath += "/";
1191 CreateDir(outputPath);
1192 }
1193
1194 std::string filename;
1195
1196 do
1197 {
1198 if (!SFileOpenFileEx(LocaleMpq, foundFile.cFileName, SFILE_OPEN_FROM_MPQ, &dbcFile))
1199 {
1200 printf("Unable to open file %s in the archive\n", foundFile.cFileName);
1201 continue;
1202 }
1203
1204 filename = foundFile.cFileName;
1205 filename = outputPath + filename.substr(filename.rfind('\\') + 1);
1206 if (ExtractFile(dbcFile, filename.c_str()))
1207 ++count;
1208
1209 SFileCloseFile(dbcFile);
1210 } while (SFileFindNextFile(listFile, &foundFile));
1211
1212 SFileFindClose(listFile);
1213 }
1214
1215 printf("Extracted %u DB2 files\n\n", count);
1216}
1217
1218bool LoadLocaleMPQFile(int locale)
1219{
1220 TCHAR buff[512];
1221 char const* prefix = "";
1222
1223 memset(buff, 0, sizeof(buff));
1224 _stprintf(buff, _T("%s/Data/misc.MPQ"), input_path);
1225 if (!SFileOpenArchive(buff, 0, MPQ_OPEN_READ_ONLY, &LocaleMpq))
1226 {
1227 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1228 {
1229 _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]);
1230 _tprintf(_T("Cannot open archive %s\n"), buff);
1231 }
1232 return false;
1233 }
1234
1235 memset(buff, 0, sizeof(buff));
1236 _stprintf(buff, _T("%s/Data/%s/locale-%s.MPQ"), input_path, LocalesT[locale], LocalesT[locale]);
1237 if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
1238 {
1239 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1240 _tprintf(_T("Cannot open patch archive %s\n"), buff);
1241 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1242 {
1243 _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]);
1244 _tprintf(_T("Cannot open archive %s\n"), buff);
1245 }
1246 return false;
1247 }
1248
1249 _tprintf(_T("\nLoading %s locale MPQs\n"), LocalesT[locale]);
1250
1251 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1252 {
1253 memset(buff, 0, sizeof(buff));
1254 prefix = "";
1255 _stprintf(buff, _T("%s/Data/wow-update-base-%u.MPQ"), input_path, Builds[i]);
1256
1257 if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
1258 {
1259 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1260 _tprintf(_T("Cannot open patch archive %s\n"), buff);
1261 else
1262 _tprintf(_T("Not found %s\n"), buff);
1263 continue;
1264 }
1265 else
1266 _tprintf(_T("Loaded %s\n"), buff);
1267 }
1268
1269 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1270 {
1271 memset(buff, 0, sizeof(buff));
1272 prefix = "";
1273 _stprintf(buff, _T("%s/Data/%s/wow-update-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]);
1274
1275 if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
1276 {
1277 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1278 _tprintf(_T("Cannot open patch archive %s\n"), buff);
1279 continue;
1280 }
1281 else
1282 _tprintf(_T("Loaded %s\n"), buff);
1283 }
1284
1285 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1286 {
1287 memset(buff, 0, sizeof(buff));
1288 prefix = "";
1289 _stprintf(buff, _T("%s/Data/Cache/patch-base-%u.MPQ"), input_path, Builds[i]);
1290
1291 if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
1292 {
1293 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1294 _tprintf(_T("Cannot open patch archive %s\n"), buff);
1295 continue;
1296 }
1297 else
1298 _tprintf(_T("Loaded %s\n"), buff);
1299 }
1300
1301 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1302 {
1303 // Load cached locales
1304 memset(buff, 0, sizeof(buff));
1305 prefix = "";
1306 _stprintf(buff, _T("%s/Data/Cache/%s/patch-%s-%u.MPQ"), input_path, LocalesT[locale], LocalesT[locale], Builds[i]);
1307
1308 if (!SFileOpenPatchArchive(LocaleMpq, buff, prefix, 0))
1309 {
1310 if (GetLastError() != ERROR_FILE_NOT_FOUND)
1311 _tprintf(_T("Cannot open patch archive %s\n"), buff);
1312 continue;
1313 }
1314 else
1315 _tprintf(_T("Loaded %s\n"), buff);
1316 }
1317
1318 printf("\n");
1319 return true;
1320}
1321
1323{
1324 TCHAR filename[512];
1325 _stprintf(filename, _T("%s/Data/world.MPQ"), input_path);
1326 _tprintf(_T("Loading common MPQ files\n"));
1327 if (!SFileOpenArchive(filename, 0, MPQ_OPEN_READ_ONLY, &WorldMpq))
1328 {
1329 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1330 _tprintf(_T("Cannot open archive %s\n"), filename);
1331 return;
1332 }
1333 else
1334 _tprintf(_T("Loaded %s\n"), filename);
1335
1336 int count = sizeof(CONF_mpq_list) / sizeof(char*);
1337 for (int i = 1; i < count; ++i)
1338 {
1339 if (build < NEW_BASE_SET_BUILD) // 4.3.2 and higher MPQ
1340 continue;
1341
1342 _stprintf(filename, _T("%s/Data/%s"), input_path, CONF_mpq_list[i]);
1343 if (!SFileOpenPatchArchive(WorldMpq, filename, "", 0))
1344 {
1345 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1346 _tprintf(_T("Cannot open archive %s\n"), filename);
1347 else
1348 _tprintf(_T("Not found %s\n"), filename);
1349 }
1350 else
1351 _tprintf(_T("Loaded %s\n"), filename);
1352 }
1353
1354 char const* prefix = NULL;
1355 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1356 {
1357 memset(filename, 0, sizeof(filename));
1358 prefix = "";
1359 _stprintf(filename, _T("%s/Data/wow-update-base-%u.MPQ"), input_path, Builds[i]);
1360
1361 if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
1362 {
1363 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1364 _tprintf(_T("Cannot open patch archive %s\n"), filename);
1365 else
1366 _tprintf(_T("Not found %s\n"), filename);
1367 continue;
1368 }
1369 else
1370 _tprintf(_T("Loaded %s\n"), filename);
1371 }
1372
1373 for (int i = 0; Builds[i] && Builds[i] <= CONF_TargetBuild; ++i)
1374 {
1375 memset(filename, 0, sizeof(filename));
1376 prefix = "";
1377 _stprintf(filename, _T("%s/Data/Cache/patch-base-%u.MPQ"), input_path, Builds[i]);
1378
1379 if (!SFileOpenPatchArchive(WorldMpq, filename, prefix, 0))
1380 {
1381 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1382 _tprintf(_T("Cannot open patch archive %s\n"), filename);
1383 else
1384 _tprintf(_T("Not found %s\n"), filename);
1385 continue;
1386 }
1387 else
1388 _tprintf(_T("Loaded %s\n"), filename);
1389 }
1390
1391 printf("\n");
1392}
1393
1394int main(int argc, char * arg[])
1395{
1396 printf("Map & DBC Extractor\n");
1397 printf("===================\n");
1398
1399 HandleArgs(argc, arg);
1400
1401 int FirstLocale = -1;
1402 uint32 build = 0;
1403
1404 for (int i = 0; i < LOCALES_COUNT; ++i)
1405 {
1406 //Open MPQs
1407 if (!LoadLocaleMPQFile(i))
1408 {
1409 if (GetLastError() != ERROR_PATH_NOT_FOUND)
1410 printf("Unable to load %s locale archives!\n", Locales[i]);
1411 continue;
1412 }
1413
1414 printf("Detected locale: %s\n", Locales[i]);
1415 if ((CONF_extract & EXTRACT_DBC) == 0)
1416 {
1417 FirstLocale = i;
1418 build = ReadBuild(i);
1419 if (build > CONF_TargetBuild)
1420 {
1421 printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], build, CONF_TargetBuild);
1422 return 0;
1423 }
1424
1425 printf("Detected client build: %u\n", build);
1426 printf("\n");
1427 break;
1428 }
1429
1430 //Extract DBC files
1431 uint32 tempBuild = ReadBuild(i);
1432 printf("Detected client build %u for locale %s\n", tempBuild, Locales[i]);
1433 if (tempBuild > CONF_TargetBuild)
1434 {
1435 SFileCloseArchive(LocaleMpq);
1436 printf("Base locale-%s.MPQ has build higher than target build (%u > %u), nothing extracted!\n", Locales[i], tempBuild, CONF_TargetBuild);
1437 continue;
1438 }
1439
1440 printf("\n");
1441 ExtractDBCFiles(i, FirstLocale < 0);
1442 ExtractDB2Files(i, FirstLocale < 0);
1443
1444 if (FirstLocale < 0)
1445 {
1446 FirstLocale = i;
1447 build = tempBuild;
1448 }
1449
1450 //Close MPQs
1451 SFileCloseArchive(LocaleMpq);
1452 }
1453
1454 if (FirstLocale < 0)
1455 {
1456 printf("No locales detected\n");
1457 return 0;
1458 }
1459
1461 {
1462 printf("Using locale: %s\n", Locales[FirstLocale]);
1463
1464 // Open MPQs
1465 LoadLocaleMPQFile(FirstLocale);
1466 LoadCommonMPQFiles(build);
1467
1468 // Extract cameras
1469 ExtractCameraFiles(FirstLocale, true);
1470
1471 // Close MPQs
1472 SFileCloseArchive(WorldMpq);
1473 SFileCloseArchive(LocaleMpq);
1474 }
1475
1477 {
1478 printf("Using locale: %s\n", Locales[FirstLocale]);
1479
1480 // Open MPQs
1481 LoadLocaleMPQFile(FirstLocale);
1482 LoadCommonMPQFiles(build);
1483
1484 // Extract maps
1485 ExtractMapsFromMpq(build);
1486
1487 // Close MPQs
1488 SFileCloseArchive(WorldMpq);
1489 SFileCloseArchive(LocaleMpq);
1490 }
1491
1492 return 0;
1493}
std::uint8_t uint8
Definition Define.h:79
std::uint32_t uint32
Definition Define.h:77
std::uint64_t uint64
Definition Define.h:76
std::uint16_t uint16
Definition Define.h:78
#define MAP_LIQUID_TYPE_MAGMA
Definition Map.h:125
#define MAP_HEIGHT_AS_INT8
Definition Map.h:88
#define MAP_AREA_NO_AREA
Definition Map.h:77
#define MAP_LIQUID_NO_TYPE
Definition Map.h:98
#define MAP_LIQUID_NO_HEIGHT
Definition Map.h:99
#define MAP_LIQUID_TYPE_WATER
Definition Map.h:123
#define MAP_LIQUID_TYPE_DARK_WATER
Definition Map.h:130
#define MAP_LIQUID_TYPE_OCEAN
Definition Map.h:124
#define MAP_LIQUID_TYPE_SLIME
Definition Map.h:126
#define MAP_HEIGHT_NO_HEIGHT
Definition Map.h:86
#define MAP_HEIGHT_AS_INT16
Definition Map.h:87
void ExtractDBCFiles(int l, bool basicLocale)
Definition System.cpp:1054
float selectUInt8StepStore(float maxDiff)
Definition System.cpp:434
float CONF_float_to_int8_limit
Definition System.cpp:84
map_id * map_ids
Definition System.cpp:58
uint16 uint16_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
Definition System.cpp:448
uint16 holes[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
Definition System.cpp:457
bool CONF_allow_height_limit
Definition System.cpp:79
uint32 maxAreaId
Definition System.cpp:63
void HandleArgs(int argc, char *arg[])
Definition System.cpp:173
bool CONF_allow_float_to_int
Definition System.cpp:83
bool ExtractFile(HANDLE fileInArchive, char const *filename)
Definition System.cpp:1031
static char const * MAP_AREA_MAGIC
Definition System.cpp:370
HANDLE WorldMpq
Definition System.cpp:49
#define ERROR_PATH_NOT_FOUND
Definition System.cpp:23
void CreateDir(std::string const &path)
Definition System.cpp:132
void LoadCommonMPQFiles(uint32 build)
Definition System.cpp:1322
bool LoadLocaleMPQFile(int locale)
Definition System.cpp:1218
uint16 uint16_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
Definition System.cpp:449
static char const * MAP_MAGIC
Definition System.cpp:368
uint32 const Builds[]
Definition System.cpp:103
float CONF_flat_liquid_delta_limit
Definition System.cpp:87
float CONF_use_minHeight
Definition System.cpp:80
uint16 * areas
Definition System.cpp:59
uint16 area_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
Definition System.cpp:444
uint32 CONF_TargetBuild
Definition System.cpp:89
#define LOCALES_COUNT
Definition System.cpp:106
#define NEW_BASE_SET_BUILD
Definition System.cpp:105
uint16 liquid_entry[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
Definition System.cpp:453
float selectUInt16StepStore(float maxDiff)
Definition System.cpp:439
Extract
Definition System.cpp:69
@ EXTRACT_CAMERA
Definition System.cpp:72
@ EXTRACT_MAP
Definition System.cpp:70
@ EXTRACT_DBC
Definition System.cpp:71
static char const * MAP_LIQUID_MAGIC
Definition System.cpp:372
float liquid_height[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
Definition System.cpp:456
static char const * MAP_VERSION_MAGIC
Definition System.cpp:369
void ExtractMapsFromMpq(uint32 build)
Definition System.cpp:981
char input_path[128]
Definition System.cpp:62
uint32 ReadMapDBC()
Definition System.cpp:275
void ExtractDB2Files(int l, bool basicLocale)
Definition System.cpp:1172
uint8 liquid_flags[ADT_CELLS_PER_GRID][ADT_CELLS_PER_GRID]
Definition System.cpp:454
float V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
Definition System.cpp:446
int CONF_extract
Definition System.cpp:76
uint8 uint8_V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
Definition System.cpp:451
uint16 * LiqType
Definition System.cpp:60
HANDLE LocaleMpq
Definition System.cpp:50
int main(int argc, char *arg[])
Definition System.cpp:1394
uint32 ReadBuild(int locale)
Definition System.cpp:228
void ReadLiquidTypeTableDBC()
Definition System.cpp:334
void Usage(char const *prg)
Definition System.cpp:159
TCHAR const * LocalesT[LOCALES_COUNT]
Definition System.cpp:120
float V9[ADT_GRID_SIZE+1][ADT_GRID_SIZE+1]
Definition System.cpp:447
static char const * MAP_HEIGHT_MAGIC
Definition System.cpp:371
float CONF_float_to_int16_limit
Definition System.cpp:85
char output_path[128]
Definition System.cpp:61
char const * CONF_mpq_list[]
Definition System.cpp:92
bool FileExists(TCHAR const *fileName)
Definition System.cpp:147
uint8 uint8_V8[ADT_GRID_SIZE][ADT_GRID_SIZE]
Definition System.cpp:450
void ReadAreaTableDBC()
Definition System.cpp:306
bool liquid_show[ADT_GRID_SIZE][ADT_GRID_SIZE]
Definition System.cpp:455
bool ConvertADT(char *filename, char *filename2, int, int, uint32 build)
Definition System.cpp:459
char const * Locales[LOCALES_COUNT]
Definition System.cpp:108
void ExtractCameraFiles(int locale, bool basicLocale)
Definition System.cpp:1104
float CONF_flat_height_delta_limit
Definition System.cpp:86
#define ADT_CELL_SIZE
Definition adt.h:27
@ LIQUID_TYPE_WATER
Definition adt.h:17
@ LIQUID_TYPE_SLIME
Definition adt.h:20
@ LIQUID_TYPE_MAGMA
Definition adt.h:19
@ LIQUID_TYPE_OCEAN
Definition adt.h:18
#define ADT_GRID_SIZE
Definition adt.h:28
#define ADT_CELLS_PER_GRID
Definition adt.h:26
bool loadFile(HANDLE mpq, char *filename, bool log=true)
Definition loadlib.cpp:24
FileChunk * GetChunk(std::string const &name)
Definition loadlib.cpp:122
std::multimap< std::string, FileChunk * > chunks
Definition loadlib.h:91
char const * getString(size_t field) const
Definition dbcfile.h:61
unsigned int getUInt(size_t field) const
Definition dbcfile.h:49
Record getRecord(size_t id)
Definition dbcfile.cpp:68
size_t getMaxId()
Definition dbcfile.cpp:74
virtual bool open()
Definition dbcfile.cpp:16
size_t getRecordCount() const
Trivial.
Definition dbcfile.h:121
Definition adt.h:50
struct adt_MCLQ::liquid_data liquid[ADT_CELL_SIZE+1][ADT_CELL_SIZE+1]
uint8 flags[ADT_CELL_SIZE][ADT_CELL_SIZE]
Definition adt.h:70
Definition adt.h:78
uint32 sizeMCLQ
Definition adt.h:117
uint32 holes
Definition adt.h:107
uint32 ix
Definition adt.h:86
uint32 iy
Definition adt.h:87
uint32 flags
Definition adt.h:85
uint32 areaid
Definition adt.h:105
float ypos
Definition adt.h:120
Definition adt.h:36
float height_map[(ADT_CELL_SIZE+1) *(ADT_CELL_SIZE+1)+ADT_CELL_SIZE *ADT_CELL_SIZE]
Definition adt.h:43
uint64 getLiquidShowMap(adt_liquid_header *h)
Definition adt.h:202
adt_liquid_header * getLiquidData(int x, int y)
Definition adt.h:160
uint8 * getLiquidLightMap(adt_liquid_header *h)
Definition adt.h:176
float * getLiquidHeightMap(adt_liquid_header *h)
Definition adt.h:167
Definition wdt.h:18
struct wdt_MAIN::adtData adt_list[64][64]
uint16 liquidType
Definition adt.h:130
uint8 width
Definition adt.h:136
float heightLevel1
Definition adt.h:132
uint8 xOffset
Definition adt.h:134
uint8 yOffset
Definition adt.h:135
uint8 height
Definition adt.h:137
uint32 fourcc
Definition Map.h:81
uint16 gridArea
Definition Map.h:83
uint16 flags
Definition Map.h:82
u_map_magic mapMagic
Definition Map.h:64
uint32 holesSize
Definition Map.h:74
uint32 liquidMapSize
Definition Map.h:72
uint32 areaMapOffset
Definition Map.h:67
uint32 heightMapSize
Definition Map.h:70
uint32 heightMapOffset
Definition Map.h:69
u_map_magic buildMagic
Definition Map.h:66
uint32 holesOffset
Definition Map.h:73
u_map_magic versionMagic
Definition Map.h:65
uint32 liquidMapOffset
Definition Map.h:71
uint32 areaMapSize
Definition Map.h:68
float gridMaxHeight
Definition Map.h:95
uint32 flags
Definition Map.h:93
float gridHeight
Definition Map.h:94
uint32 fourcc
Definition Map.h:92
uint32 id
Definition System.cpp:55
char name[64]
Definition System.cpp:54
uint8 offsetX
Definition Map.h:106
uint32 fourcc
Definition Map.h:103
uint8 width
Definition Map.h:108
uint8 height
Definition Map.h:109
uint16 liquidType
Definition Map.h:105
uint8 offsetY
Definition Map.h:107
float liquidLevel
Definition Map.h:110
uint16 flags
Definition Map.h:104
uint32 flag
Definition wdt.h:27
uint32 map_count
#define WDT_MAP_SIZE
Definition wdt.h:13