Some more map extractor fixes. Patch provided by andstan.

Coding style fix.
Removed hack from lava detection code.
Please test water/lava detection. Should work fine now.
This commit is contained in:
tomrus88 2008-12-06 19:19:46 +03:00
parent 129c0797a7
commit bfe899b126
6 changed files with 254 additions and 250 deletions

View file

@ -17,3 +17,4 @@
debug debug
release release
*.user *.user
*.ilk

View file

@ -16,21 +16,22 @@
extern unsigned int iRes; extern unsigned int iRes;
extern ArchiveSet gOpenArchives; extern ArchiveSet gOpenArchives;
bool ConvertADT(char*,char*); bool ConvertADT(char*, char*);
typedef struct{ typedef struct{
char name[64]; char name[64];
unsigned int id; unsigned int id;
}map_id; } map_id;
typedef unsigned char uint8; typedef unsigned char uint8;
typedef unsigned short uint16; typedef unsigned short uint16;
typedef unsigned int uint32; typedef unsigned int uint32;
map_id * map_ids; map_id *map_ids;
uint16 * areas; uint16 *areas;
char output_path[128]="."; uint16 *LiqType;
char input_path[128]="."; char output_path[128] = ".";
char input_path[128] = ".";
uint32 maxAreaId = 0; uint32 maxAreaId = 0;
enum Extract enum Extract
@ -40,7 +41,7 @@ enum Extract
}; };
int extract = EXTRACT_MAP | EXTRACT_DBC; int extract = EXTRACT_MAP | EXTRACT_DBC;
static char* const langs[]={"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" }; static char* const langs[] = {"enGB", "enUS", "deDE", "esES", "frFR", "koKR", "zhCN", "zhTW", "enCN", "enTW", "esMX", "ruRU" };
#define LANG_COUNT 12 #define LANG_COUNT 12
#define ADT_RES 64 #define ADT_RES 64
@ -56,9 +57,9 @@ void CreateDir( const std::string& Path )
bool FileExists( const char* FileName ) bool FileExists( const char* FileName )
{ {
if( FILE* fp = fopen( FileName, "rb" ) ) if(FILE* fp = fopen( FileName, "rb" ))
{ {
fclose( fp ); fclose(fp);
return true; return true;
} }
@ -67,46 +68,45 @@ bool FileExists( const char* FileName )
void Usage(char* prg) void Usage(char* prg)
{ {
printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", printf("Usage:\n%s -[var] [value]\n-i set input path\n-o set output path\n-r set resolution\n-e extract only MAP(1)/DBC(2) - standard: both(3)\nExample: %s -r 256 -i \"c:\\games\\game\"", prg, prg);
prg,prg);
exit(1); exit(1);
} }
void HandleArgs(int argc, char * arg[]) void HandleArgs(int argc, char * arg[])
{ {
for(int c=1;c<argc;c++) for(int c = 1; c < argc; ++c)
{ {
//i - input path // i - input path
//o - output path // o - output path
//r - resolution, array of (r * r) heights will be created // r - resolution, array of (r * r) heights will be created
//e - extract only MAP(1)/DBC(2) - standard both(3) // e - extract only MAP(1)/DBC(2) - standard both(3)
if(arg[c][0] != '-') if(arg[c][0] != '-')
Usage(arg[0]); Usage(arg[0]);
switch(arg[c][1]) switch(arg[c][1])
{ {
case 'i': case 'i':
if(c+1<argc)//all ok if(c + 1 < argc) // all ok
strcpy(input_path,arg[(c++) +1]); strcpy(input_path, arg[(c++) + 1]);
else else
Usage(arg[0]); Usage(arg[0]);
break; break;
case 'o': case 'o':
if(c+1<argc)//all ok if(c + 1 < argc) // all ok
strcpy(output_path,arg[(c++) +1]); strcpy(output_path, arg[(c++) + 1]);
else else
Usage(arg[0]); Usage(arg[0]);
break; break;
case 'r': case 'r':
if(c+1<argc)//all ok if(c + 1 < argc) // all ok
iRes=atoi(arg[(c++) +1]); iRes=atoi(arg[(c++) + 1]);
else else
Usage(arg[0]); Usage(arg[0]);
break; break;
case 'e': case 'e':
if(c+1<argc)//all ok if(c + 1 < argc) // all ok
{ {
extract=atoi(arg[(c++) +1]); extract=atoi(arg[(c++) + 1]);
if(!(extract > 0 && extract < 4)) if(!(extract > 0 && extract < 4))
Usage(arg[0]); Usage(arg[0]);
} }
@ -123,12 +123,12 @@ uint32 ReadMapDBC()
DBCFile dbc("DBFilesClient\\Map.dbc"); DBCFile dbc("DBFilesClient\\Map.dbc");
dbc.open(); dbc.open();
uint32 map_count=dbc.getRecordCount(); size_t map_count = dbc.getRecordCount();
map_ids=new map_id[map_count]; map_ids = new map_id[map_count];
for(unsigned int x=0;x<map_count;x++) for(uint32 x = 0; x < map_count; ++x)
{ {
map_ids[x].id=dbc.getRecord(x).getUInt(0); map_ids[x].id = dbc.getRecord(x).getUInt(0);
strcpy(map_ids[x].name,dbc.getRecord(x).getString(1)); strcpy(map_ids[x].name, dbc.getRecord(x).getString(1));
} }
printf("Done! (%u maps loaded)\n", map_count); printf("Done! (%u maps loaded)\n", map_count);
return map_count; return map_count;
@ -136,15 +136,16 @@ uint32 ReadMapDBC()
void ReadAreaTableDBC() void ReadAreaTableDBC()
{ {
printf("Read AreaTable.dbc file... "); printf("Read AreaTable.dbc file...");
DBCFile dbc("DBFilesClient\\AreaTable.dbc"); DBCFile dbc("DBFilesClient\\AreaTable.dbc");
dbc.open(); dbc.open();
unsigned int area_count=dbc.getRecordCount(); size_t area_count = dbc.getRecordCount();
uint32 maxid = dbc.getMaxId(); size_t maxid = dbc.getMaxId();
areas=new uint16[maxid + 1]; areas = new uint16[maxid + 1];
memset(areas, 0xff, sizeof(areas)); memset(areas, 0xff, sizeof(areas));
for(unsigned int x=0; x<area_count;++x)
for(uint32 x = 0; x < area_count; ++x)
areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3); areas[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
maxAreaId = dbc.getMaxId(); maxAreaId = dbc.getMaxId();
@ -152,6 +153,22 @@ void ReadAreaTableDBC()
printf("Done! (%u areas loaded)\n", area_count); printf("Done! (%u areas loaded)\n", area_count);
} }
void ReadLiquidTypeTableDBC()
{
printf("Read LiquidType.dbc file...");
DBCFile dbc("DBFilesClient\\LiquidType.dbc");
dbc.open();
size_t LiqType_count = dbc.getRecordCount();
size_t LiqType_maxid = dbc.getMaxId();
LiqType = new uint16[LiqType_maxid + 1];
memset(LiqType, 0xff, (LiqType_maxid + 1) * sizeof(uint16));
for(uint32 x = 0; x < LiqType_count; ++x)
LiqType[dbc.getRecord(x).getUInt(0)] = dbc.getRecord(x).getUInt(3);
printf("Done! (%u LiqTypes loaded)\n", LiqType_count);
}
void ExtractMapsFromMpq() void ExtractMapsFromMpq()
{ {
char mpq_filename[1024]; char mpq_filename[1024];
@ -162,27 +179,28 @@ void ExtractMapsFromMpq()
uint32 map_count = ReadMapDBC(); uint32 map_count = ReadMapDBC();
ReadAreaTableDBC(); ReadAreaTableDBC();
ReadLiquidTypeTableDBC();
unsigned int total=map_count*ADT_RES*ADT_RES; unsigned int total = map_count * ADT_RES * ADT_RES;
unsigned int done=0; unsigned int done = 0;
std::string path = output_path; std::string path = output_path;
path += "/maps/"; path += "/maps/";
CreateDir(path); CreateDir(path);
for(unsigned int x = 0; x < ADT_RES; ++x) for(uint32 x = 0; x < ADT_RES; ++x)
{ {
for(unsigned int y = 0; y < ADT_RES; ++y) for(uint32 y = 0; y < ADT_RES; ++y)
{ {
for(unsigned int z = 0; z < map_count; ++z) for(uint32 z = 0; z < map_count; ++z)
{ {
sprintf(mpq_filename,"World\\Maps\\%s\\%s_%u_%u.adt",map_ids[z].name,map_ids[z].name,x,y); sprintf(mpq_filename, "World\\Maps\\%s\\%s_%u_%u.adt", map_ids[z].name, map_ids[z].name, x, y);
sprintf(output_filename,"%s/maps/%03u%02u%02u.map",output_path,map_ids[z].id,y,x); sprintf(output_filename, "%s/maps/%03u%02u%02u.map", output_path, map_ids[z].id, y, x);
ConvertADT(mpq_filename,output_filename); ConvertADT(mpq_filename, output_filename);
done++; done++;
} }
//draw progess bar // draw progess bar
printf("Processing........................%d%%\r",(100*done)/total); printf("Processing........................%d%%\r", (100 * done) / total);
} }
} }
@ -225,15 +243,15 @@ void ExtractDBCFiles(int locale, bool basicLocale)
string filename = path; string filename = path;
filename += (iter->c_str() + strlen("DBFilesClient\\")); filename += (iter->c_str() + strlen("DBFilesClient\\"));
FILE *output=fopen(filename.c_str(),"wb"); FILE *output=fopen(filename.c_str(), "wb");
if(!output) if(!output)
{ {
printf("Can't create the output file '%s'\n",filename.c_str()); printf("Can't create the output file '%s'\n", filename.c_str());
continue; continue;
} }
MPQFile m(iter->c_str()); MPQFile m(iter->c_str());
if(!m.isEof()) if(!m.isEof())
fwrite(m.getPointer(),1,m.getSize(),output); fwrite(m.getPointer(), 1, m.getSize(), output);
fclose(output); fclose(output);
++count; ++count;
@ -245,7 +263,7 @@ void LoadLocaleMPQFiles(int const locale)
{ {
char filename[512]; char filename[512];
sprintf(filename,"%s/Data/%s/locale-%s.MPQ",input_path,langs[locale],langs[locale]); sprintf(filename,"%s/Data/%s/locale-%s.MPQ", input_path, langs[locale], langs[locale]);
new MPQArchive(filename); new MPQArchive(filename);
for(int i = 1; i < 5; ++i) for(int i = 1; i < 5; ++i)
@ -254,7 +272,7 @@ void LoadLocaleMPQFiles(int const locale)
if(i > 1) if(i > 1)
sprintf(ext, "-%i", i); sprintf(ext, "-%i", i);
sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ",input_path,langs[locale],langs[locale],ext); sprintf(filename,"%s/Data/%s/patch-%s%s.MPQ", input_path, langs[locale], langs[locale], ext);
if(FileExists(filename)) if(FileExists(filename))
new MPQArchive(filename); new MPQArchive(filename);
} }
@ -264,11 +282,11 @@ void LoadCommonMPQFiles()
{ {
char filename[512]; char filename[512];
sprintf(filename,"%s/Data/common-2.MPQ",input_path); sprintf(filename,"%s/Data/common-2.MPQ", input_path);
new MPQArchive(filename); new MPQArchive(filename);
sprintf(filename,"%s/Data/lichking.MPQ",input_path); sprintf(filename,"%s/Data/lichking.MPQ", input_path);
new MPQArchive(filename); new MPQArchive(filename);
sprintf(filename,"%s/Data/expansion.MPQ",input_path); sprintf(filename,"%s/Data/expansion.MPQ", input_path);
new MPQArchive(filename); new MPQArchive(filename);
for(int i = 1; i < 5; ++i) for(int i = 1; i < 5; ++i)
@ -277,7 +295,7 @@ void LoadCommonMPQFiles()
if(i > 1) if(i > 1)
sprintf(ext, "-%i", i); sprintf(ext, "-%i", i);
sprintf(filename,"%s/Data/patch%s.MPQ",input_path,ext); sprintf(filename,"%s/Data/patch%s.MPQ", input_path, ext);
if(FileExists(filename)) if(FileExists(filename))
new MPQArchive(filename); new MPQArchive(filename);
} }
@ -311,12 +329,12 @@ int main(int argc, char * arg[])
if((extract & EXTRACT_DBC) == 0) if((extract & EXTRACT_DBC) == 0)
{ {
FirstLocale=i; FirstLocale = i;
break; break;
} }
//Extract DBC files //Extract DBC files
if(FirstLocale<0) if(FirstLocale < 0)
{ {
ExtractDBCFiles(i, true); ExtractDBCFiles(i, true);
FirstLocale = i; FirstLocale = i;
@ -329,7 +347,7 @@ int main(int argc, char * arg[])
} }
} }
if(FirstLocale<0) if(FirstLocale < 0)
{ {
printf("No locales detected\n"); printf("No locales detected\n");
return 0; return 0;

Binary file not shown.

View file

@ -15,15 +15,15 @@
#include "adt.h" #include "adt.h"
#include "mpq_libmpq.h" #include "mpq_libmpq.h"
unsigned int iRes=256; unsigned int iRes = 256;
extern uint16 *areas; extern uint16 *areas;
extern uint16 *LiqType;
extern uint32 maxAreaId; extern uint32 maxAreaId;
vec wmoc; vec wmoc;
Cell * cell; Cell *cell;
uint32 wmo_count; //uint32 wmo_count;
mcell *mcells; mcell *mcells;
int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888}; int holetab_h[4] = {0x1111, 0x2222, 0x4444, 0x8888};
int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000}; int holetab_v[4] = {0x000F, 0x00F0, 0x0F00, 0xF000};
@ -35,18 +35,27 @@ bool LoadADT(char* filename)
if(mf.isEof()) if(mf.isEof())
{ {
//printf("No such file %s\n",filename); //printf("No such file %s\n", filename);
return false; return false;
} }
MapLiqFlag = new uint8[256];
for(int j = 0; j < 256; ++j)
MapLiqFlag[j] = 0; // no water
MapLiqHeight = new float[16384];
for(int j = 0; j < 16384; ++j)
MapLiqHeight[j] = -999999; // no water
mcells=new mcell; mcells=new mcell;
wmoc.x =65*TILESIZE; wmoc.x =65 * TILESIZE;
wmoc.z =65*TILESIZE; wmoc.z =65 * TILESIZE;
size_t mcnk_offsets[256], mcnk_sizes[256]; size_t mcnk_offsets[256], mcnk_sizes[256];
wmo_count=0; //wmo_count = 0;
bool found=false; //bool found = false;
MH2O_presence = false; MH2O_presence = false;
chunk_num = 0; chunk_num = 0;
@ -54,30 +63,30 @@ bool LoadADT(char* filename)
while (!mf.isEof()) while (!mf.isEof())
{ {
uint32 fourcc; uint32 fourcc;
mf.read(&fourcc,4); mf.read(&fourcc, 4);
mf.read(&size, 4); mf.read(&size, 4);
size_t nextpos = mf.getPos() + size; size_t nextpos = mf.getPos() + size;
//if(fourcc==0x4d484452) // MHDR header //if(fourcc==0x4d484452) // MHDR header
//if(fourcc==0x4d564552) // MVER //if(fourcc==0x4d564552) // MVER
if(fourcc==0x4d43494e) // MCIN if(fourcc == 0x4d43494e) // MCIN
{ {
for (int i=0; i<256; ++i) for (int i = 0; i < 256; ++i)
{ {
mf.read(&mcnk_offsets[i],4); mf.read(&mcnk_offsets[i], 4);
mf.read(&mcnk_sizes[i],4); mf.read(&mcnk_sizes[i], 4);
mf.seekRelative(8); mf.seekRelative(8);
} }
} }
//if(fourcc==0x4d544558) // MTEX textures (strings) //if(fourcc == 0x4d544558) // MTEX textures (strings)
//if(fourcc==0x4d4d4458) // MMDX m2 models (strings) //if(fourcc == 0x4d4d4458) // MMDX m2 models (strings)
//if(fourcc==0x4d4d4944) // MMID offsets for strings in MMDX //if(fourcc == 0x4d4d4944) // MMID offsets for strings in MMDX
//if(fourcc==0x4d574d4f) // MWMO //if(fourcc == 0x4d574d4f) // MWMO
//if(fourcc==0x4d574944) // MWID offsets for strings in MWMO //if(fourcc == 0x4d574944) // MWID offsets for strings in MWMO
//if(fourcc==0x4d444446) // MDDF //if(fourcc == 0x4d444446) // MDDF
//if(fourcc==0x4d4f4446) // MODF //if(fourcc == 0x4d4f4446) // MODF
if(fourcc==0x4d48324f && size) // MH2O new in WotLK if(fourcc == 0x4d48324f && size) // MH2O new in WotLK
{ {
MH2O_presence = true; MH2O_presence = true;
// çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî // çäåñü íàäî çàïîìíèòü áàçîâóþ ïîçèöèþ â ôàéëå òê âñå ñìåùåíèÿ áóäóò îò íåãî
@ -88,29 +97,31 @@ bool LoadADT(char* filename)
ChunkLiqHeight = new float[81]; ChunkLiqHeight = new float[81];
for(;chunk_num < 256; ++chunk_num) for(;chunk_num < 256; ++chunk_num)
{ {
mf.read(LiqOffsData,12); mf.read(LiqOffsData, 12);
header_pos = mf.getPos(); header_pos = mf.getPos();
if(LiqOffsData->offsData1 !=0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü if(LiqOffsData->offsData1 != 0) // åñëè äàííûå â Data1 î âîäå åñòü, òî èõ íàäî êîíâåðòèðîâàòü
{ {
// ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà // ïåðåõîäèì ïî ñìåùåíèþ èç offsData1 ÎÒ ÍÀ×ÀËÀ êóñêà
mf.seek(base_pos + LiqOffsData->offsData1); mf.seek(base_pos + LiqOffsData->offsData1);
mf.read(LiqChunkData1,24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1 mf.read(LiqChunkData1, 24); // ñ÷èòûâàåì ñàìè äàííûå â ñòðóêòóðó òèïà MH2O_Data1
// çàíîñèì äàííûå ôëàãà äëÿ êóñêà // çàíîñèì äàííûå ôëàãà äëÿ êóñêà
if(LiqChunkData1->flags & 4 || LiqChunkData1->flags & 8) if(LiqType[LiqChunkData1->LiquidTypeId] == 0xffff)
MapLiqFlag[chunk_num] |= 1; printf("\nCan't find Liquid type for map %s\nchunk %d\n", filename, chunk_num);
if(LiqChunkData1->flags & 16) else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_WATER || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_OCEAN)
MapLiqFlag[chunk_num] |= 2; MapLiqFlag[chunk_num] |= 1; // water/ocean
else if(LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_MAGMA || LiqType[LiqChunkData1->LiquidTypeId] == LIQUID_TYPE_SLIME)
MapLiqFlag[chunk_num] |= 2; // magma/slime
// ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû // ïðåäâàðèòåëüíî çàïîëíÿåì âåñü êóñîê äàííûìè - íåò âîäû
for(int j=0;j<81;++j) for(int j = 0; j < 81; ++j)
{ {
ChunkLiqHeight[j] = -999999; // no liquid/water ChunkLiqHeight[j] = -999999; // no liquid/water
} }
// òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå // òåïåðü âû÷èñëÿåì òå ÷òî ñ âîäîé è ïåðåçàïèñûâàåì èõ â êóñêå
for(int b=0; b <= LiqChunkData1->height; ++b) for(int b = 0; b <= LiqChunkData1->height; ++b)
{ {
for(int c=LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset+LiqChunkData1->width); ++c) for(int c = LiqChunkData1->xOffset; c <= (LiqChunkData1->xOffset + LiqChunkData1->width); ++c)
{ {
int n = (9*(LiqChunkData1->yOffset + b))+c; int n = (9 * (LiqChunkData1->yOffset + b)) + c;
ChunkLiqHeight[n] = LiqChunkData1->heightLevel1; ChunkLiqHeight[n] = LiqChunkData1->heightLevel1;
} }
} }
@ -118,22 +129,22 @@ bool LoadADT(char* filename)
} }
else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû else // åñëè äàííûõ â Data1 íåò, òî íàäî çàïîëíèòü âåñü êóñîê, íî äàííûìè - íåò âîäû
{ {
for(int j=0; j<81; ++j) for(int j = 0; j < 81; ++j)
ChunkLiqHeight[j] = -999999; // no liquid/water ChunkLiqHeight[j] = -999999; // no liquid/water
} }
if(!(chunk_num%16)) if(!(chunk_num % 16))
m = 1024*(chunk_num/16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024 m = 1024 * (chunk_num / 16); // ñìåùåíèå ïî ðÿäàì êóñêîâ ñ ïåðåêðûòèåì = 1024
k = m +(chunk_num%16)*8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà k = m + (chunk_num % 16) * 8; // óñòàíàâëèâàåìñÿ íà íà÷àëüíûé èíäåêñ äëÿ çàïîëíåíèÿ ðÿäà
// çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81 // çàíîñèì äàííûå êóñêà â ìàññèâ äëÿ êàðòû, ñ ïåðåêðûòèåì è îáðåçàíèåì êóñêîâ òê äàííûõ 81
// ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ // ýòî àíàëîã ñòàðîãî îáðåçàíèÿ ãðàíè÷íûõ ïðàâûõ-áîêîâûõ è íèæíèõ äàííûõ
for(int p=0;p<72;p+=9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì for(int p = 0; p < 72; p += 9) // íèæíèå 8 íå çàíîñèì òê îíè äóáëèðóåòñÿ ñëåä êóñêîì
{ {
for(int s=0; s<8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128 for(int s = 0; s < 8; ++s) // 9 çíà÷åíèå â ñòðîêå íå çàíîñèì òê îíî äóáëèðóåòñÿ ñëåä êóñêîì, à â ïðàâûõ-áîêîâûõ îáðåçàåòñÿ äëÿ 128õ128
{ {
MapLiqHeight[k] = ChunkLiqHeight[p+s]; MapLiqHeight[k] = ChunkLiqHeight[p + s];
++k; ++k;
} }
k=k+120; k = k + 120;
} }
} }
delete LiqOffsData; delete LiqOffsData;
@ -149,12 +160,12 @@ bool LoadADT(char* filename)
//printf("Loading chunks info\n"); //printf("Loading chunks info\n");
// read individual map chunks // read individual map chunks
for (int j=0; j<16; ++j) for (int j = 0; j < 16; ++j)
{ {
for (int i=0; i<16; ++i) for (int i = 0; i < 16; ++i)
{ {
mf.seek((int)mcnk_offsets[j*16+i]); mf.seek((int)mcnk_offsets[j * 16 + i]);
LoadMapChunk(mf,&(mcells->ch[i][j])); LoadMapChunk(mf, &(mcells->ch[i][j]));
++chunk_num; ++chunk_num;
} }
} }
@ -164,14 +175,14 @@ bool LoadADT(char* filename)
bool isHole(int holes, int i, int j) bool isHole(int holes, int i, int j)
{ {
int testi = i/2; int testi = i / 2;
int testj = j/4; int testj = j / 4;
if(testi>3) testi = 3; if(testi > 3) testi = 3;
if(testj>3) testj = 3; if(testj > 3) testj = 3;
return (holes & holetab_h[testi] & holetab_v[testj])!=0; return (holes & holetab_h[testi] & holetab_v[testj]) != 0;
} }
inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) inline void LoadMapChunk(MPQFile &mf, chunk *_chunk)
{ {
float h; float h;
uint32 fourcc; uint32 fourcc;
@ -183,68 +194,69 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk)
size_t lastpos = mf.getPos() + size; size_t lastpos = mf.getPos() + size;
mf.read(&header, 0x80); // what if header size got changed? mf.read(&header, 0x80); // what if header size got changed?
_chunk->area_id =header.areaid ; _chunk->area_id = header.areaid;
float xbase = header.xpos; float xbase = header.xpos;
float ybase = header.ypos; float ybase = header.ypos;
float zbase = header.zpos; float zbase = header.zpos;
zbase = TILESIZE*32-zbase; zbase = TILESIZE * 32 - zbase;
xbase = TILESIZE*32-xbase; xbase = TILESIZE * 32 - xbase;
if(wmoc.x >xbase)wmoc.x =xbase; if(wmoc.x > xbase) wmoc.x = xbase;
if(wmoc.z >zbase)wmoc.z =zbase; if(wmoc.z > zbase) wmoc.z = zbase;
int chunkflags = header.flags; int chunkflags = header.flags;
float zmin=999999999.0f; //printf("LMC: flags %X\n", chunkflags);
float zmax=-999999999.0f; float zmin = 999999999.0f;
float zmax = -999999999.0f;
// must be there, bl!zz uses some crazy format // must be there, bl!zz uses some crazy format
while (mf.getPos() < lastpos) while (mf.getPos() < lastpos)
{ {
mf.read(&fourcc,4); mf.read(&fourcc, 4);
mf.read(&size, 4); mf.read(&size, 4);
size_t nextpos = mf.getPos() + size; size_t nextpos = mf.getPos() + size;
if(fourcc==0x4d435654) // MCVT if(fourcc == 0x4d435654) // MCVT
{ {
for (int j=0; j<17; ++j) for (int j = 0; j < 17; ++j)
{ {
for (int i=0; i<((j%2)?8:9); ++i) for (int i = 0; i < ((j % 2) ? 8 : 9); ++i)
{ {
mf.read(&h,4); mf.read(&h, 4);
float z=h+ybase; float z = h + ybase;
if (j%2) if (j % 2)
{ {
if(isHole(header.holes,i,j)) if(isHole(header.holes, i, j))
_chunk->v8[i][j/2] = -1000; _chunk->v8[i][j / 2] = -1000;
else else
_chunk->v8[i][j/2] = z; _chunk->v8[i][j / 2] = z;
} }
else else
{ {
if(isHole(header.holes,i,j)) if(isHole(header.holes, i, j))
_chunk->v9[i][j/2] = -1000; _chunk->v9[i][j / 2] = -1000;
else else
_chunk->v9[i][j/2] = z; _chunk->v9[i][j / 2] = z;
} }
if(z>zmax)zmax=z; if(z > zmax) zmax = z;
//if(z<zmin)zmin=z; //if(z < zmin) zmin = z;
} }
} }
} }
else if(fourcc==0x4d434e52) // MCNR else if(fourcc == 0x4d434e52) // MCNR
{ {
nextpos = mf.getPos() + 0x1C0; // size fix nextpos = mf.getPos() + 0x1C0; // size fix
} }
else if(fourcc==0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ else if(fourcc == 0x4d434c51 && !MH2O_presence) // íå áóäåì ó÷èòûâàòü åñëè óæå áûëè äàííûå â MH2O, ïåðåñòðàõîâêà :) // MCLQ
{ {
// liquid / water level // liquid / water level
char fcc1[5]; char fcc1[5];
mf.read(fcc1,4); mf.read(fcc1, 4);
flipcc(fcc1); flipcc(fcc1);
fcc1[4]=0; fcc1[4] = 0;
ChunkLiqHeight = new float[81]; ChunkLiqHeight = new float[81];
if (!strcmp(fcc1,"MCSE")) if (!strcmp(fcc1, "MCSE"))
{ {
for(int j=0;j<81;++j) for(int j = 0; j < 81; ++j)
{ {
ChunkLiqHeight[j] = -999999; // no liquid/water ChunkLiqHeight[j] = -999999; // no liquid/water
} }
@ -253,7 +265,7 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk)
{ {
float maxheight; float maxheight;
mf.read(&maxheight, 4); mf.read(&maxheight, 4);
for(int j=0;j<81;++j) for(int j = 0; j < 81; ++j)
{ {
mf.read(&h, 4); mf.read(&h, 4);
mf.read(&h, 4); mf.read(&h, 4);
@ -264,23 +276,23 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk)
} }
if(chunkflags & 4 || chunkflags & 8) if(chunkflags & 4 || chunkflags & 8)
MapLiqFlag[chunk_num] |= 1; MapLiqFlag[chunk_num] |= 1; // water
if(chunkflags & 16) if(chunkflags & 16)
MapLiqFlag[chunk_num] |= 2; MapLiqFlag[chunk_num] |= 2; // magma/slime
} }
// çàïîëíåì òàê æå êàê â MH2O // çàïîëíåì òàê æå êàê â MH2O
if(!(chunk_num%16)) if(!(chunk_num % 16))
m = 1024*(chunk_num/16); m = 1024 * (chunk_num / 16);
k = m +(chunk_num%16)*8; k = m +(chunk_num % 16) * 8;
for(int p=0;p<72;p+=9) for(int p = 0; p < 72; p += 9)
{ {
for(int s=0; s<8; ++s) for(int s = 0; s < 8; ++s)
{ {
MapLiqHeight[k] = ChunkLiqHeight[p+s]; MapLiqHeight[k] = ChunkLiqHeight[p + s];
++k; ++k;
} }
k=k+120; k = k + 120;
} }
delete []ChunkLiqHeight; delete []ChunkLiqHeight;
break; break;
@ -291,10 +303,10 @@ inline void LoadMapChunk(MPQFile & mf, chunk*_chunk)
double solve (vec *v,vec *p) double solve (vec *v,vec *p)
{ {
double a = v[0].y *(v[1].z - v[2].z) + v[1].y *(v[2].z - v[0].z) + v[2].y *(v[0].z - v[1].z); double a = v[0].y * (v[1].z - v[2].z) + v[1].y * (v[2].z - v[0].z) + v[2].y * (v[0].z - v[1].z);
double b = v[0].z *(v[1].x - v[2].x) + v[1].z *(v[2].x - v[0].x) + v[2].z *(v[0].x - v[1].x); double b = v[0].z * (v[1].x - v[2].x) + v[1].z * (v[2].x - v[0].x) + v[2].z * (v[0].x - v[1].x);
double c = v[0].x *(v[1].y - v[2].y) + v[1].x *(v[2].y - v[0].y) + v[2].x *(v[0].y - v[1].y); double c = v[0].x * (v[1].y - v[2].y) + v[1].x * (v[2].y - v[0].y) + v[2].x * (v[0].y - v[1].y);
double d = v[0].x *(v[1].y*v[2].z - v[2].y*v[1].z) + v[1].x* (v[2].y*v[0].z - v[0].y*v[2].z) + v[2].x* (v[0].y*v[1].z - v[1].y*v[0].z); double d = v[0].x * (v[1].y * v[2].z - v[2].y * v[1].z) + v[1].x * (v[2].y * v[0].z - v[0].y * v[2].z) + v[2].x * (v[0].y * v[1].z - v[1].y * v[0].z);
// -d // -d
// plane equation ax+by+cz+d=0 // plane equation ax+by+cz+d=0
@ -307,66 +319,66 @@ inline double GetZ(double x, double z)
vec p; vec p;
{ {
// find out quadrant // find out quadrant
int xc=(int)(x/UNITSIZE); int xc = (int)(x / UNITSIZE);
int zc=(int)(z/UNITSIZE); int zc = (int)(z / UNITSIZE);
if(xc>127)xc=127; if(xc > 127) xc = 127;
if(zc>127)zc=127; if(zc > 127) zc = 127;
double lx=x-xc*UNITSIZE; double lx = x - xc * UNITSIZE;
double lz=z-zc*UNITSIZE; double lz = z - zc * UNITSIZE;
p.x=lx; p.x = lx;
p.z=lz; p.z = lz;
v[0].x=UNITSIZE/2; v[0].x = UNITSIZE / 2;
v[0].y =cell->v8[xc][zc]; v[0].y = cell->v8[xc][zc];
v[0].z=UNITSIZE/2; v[0].z = UNITSIZE / 2;
if(lx>lz) if(lx > lz)
{ {
v[1].x=UNITSIZE; v[1].x = UNITSIZE;
v[1].y =cell->v9[xc+1][zc]; v[1].y = cell->v9[xc + 1][zc];
v[1].z=0; v[1].z = 0.0f;
} }
else else
{ {
v[1].x=0.0; v[1].x = 0.0f;
v[1].y =cell->v9[xc][zc+1]; v[1].y = cell->v9[xc][zc + 1];
v[1].z=UNITSIZE; v[1].z = UNITSIZE;
} }
if(lz>UNITSIZE-lx) if(lz > UNITSIZE - lx)
{ {
v[2].x=UNITSIZE; v[2].x = UNITSIZE;
v[2].y =cell->v9[xc+1][zc+1]; v[2].y = cell->v9[xc + 1][zc + 1];
v[2].z=UNITSIZE; v[2].z = UNITSIZE;
} }
else else
{ {
v[2].x=0; v[2].x = 0.0f;
v[2].y=cell->v9[xc][zc]; v[2].y = cell->v9[xc][zc];
v[2].z=0; v[2].z = 0.0f;
} }
return -solve(v,&p); return -solve(v, &p);
} }
} }
inline void TransformData() inline void TransformData()
{ {
cell= new Cell; cell = new Cell;
for(int x=0;x<128;++x) for(uint32 x = 0; x < 128; ++x)
{ {
for(int y=0;y<128;++y) for(uint32 y = 0; y < 128; ++y)
{ {
cell->v8[x][y] = (float)mcells->ch[x/8][y/8].v8[x%8][y%8]; cell->v8[x][y] = (float)mcells->ch[x / 8][y / 8].v8[x % 8][y % 8];
cell->v9[x][y] = (float)mcells->ch[x/8][y/8].v9[x%8][y%8]; cell->v9[x][y] = (float)mcells->ch[x / 8][y / 8].v9[x % 8][y % 8];
} }
// extra 1 point on bounds // extra 1 point on bounds
cell->v9[x][128] = (float)mcells->ch[x/8][15].v9[x%8][8]; cell->v9[x][128] = (float)mcells->ch[x / 8][15].v9[x % 8][8];
// x==y // x == y
cell->v9[128][x] = (float)mcells->ch[15][x/8].v9[8][x%8]; cell->v9[128][x] = (float)mcells->ch[15][x / 8].v9[8][x % 8];
} }
@ -378,70 +390,59 @@ inline void TransformData()
const char MAP_MAGIC[] = "MAP_2.01"; const char MAP_MAGIC[] = "MAP_2.01";
bool ConvertADT(char * filename,char * filename2) bool ConvertADT(char *filename, char *filename2)
{ {
MapLiqHeight = new float[16384];
MapLiqFlag = new char[256];
for(int j = 0; j < 256; ++j)
MapLiqFlag[j] = 0;
for(int j = 0; j < 16384; ++j)
MapLiqHeight[j] = -999999;
if(!LoadADT(filename)) if(!LoadADT(filename))
{
delete [] MapLiqHeight;
delete [] MapLiqFlag;
return false; return false;
}
FILE *output=fopen(filename2,"wb"); FILE *output=fopen(filename2, "wb");
if(!output) if(!output)
{ {
printf("Can't create the output file '%s'\n",filename2); printf("Can't create the output file '%s'\n", filename2);
delete [] MapLiqHeight; delete [] MapLiqHeight;
delete [] MapLiqFlag; delete [] MapLiqFlag;
return false; return false;
} }
// write magic header // write magic header
fwrite(MAP_MAGIC,1,8,output); fwrite(MAP_MAGIC, 1, 8, output);
for(unsigned int x=0;x<16;++x) for(uint32 x = 0; x < 16; ++x)
{ {
for(unsigned int y=0;y<16;++y) for(uint32 y = 0; y < 16; ++y)
{ {
if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId) if(mcells->ch[y][x].area_id && mcells->ch[y][x].area_id <= maxAreaId)
{ {
if(areas[mcells->ch[y][x].area_id]==0xffff) if(areas[mcells->ch[y][x].area_id] == 0xffff)
printf("\nCan't find area flag for areaid %u.\n",mcells->ch[y][x].area_id); printf("\nCan't find area flag for areaid %u.\n", mcells->ch[y][x].area_id);
fwrite(&areas[mcells->ch[y][x].area_id],1,2,output); fwrite(&areas[mcells->ch[y][x].area_id], 1, 2, output);
} }
else else
{ {
uint16 flag=0xffff; uint16 flag = 0xffff;
fwrite(&flag,1,2,output); fwrite(&flag, 1, 2, output);
} }
} }
} }
fwrite(MapLiqFlag,1,256,output); fwrite(MapLiqFlag, 1, 256, output);
delete [] MapLiqFlag; delete [] MapLiqFlag;
fwrite(MapLiqHeight,sizeof(float),16384,output); fwrite(MapLiqHeight, sizeof(float), 16384, output);
delete [] MapLiqHeight; delete [] MapLiqHeight;
TransformData(); TransformData();
for(unsigned int x=0;x<iRes;++x) for(uint32 x = 0; x < iRes; ++x)
{ {
for(unsigned int y=0;y<iRes;++y) for(uint32 y = 0; y < iRes; ++y)
{ {
float z=(float)GetZ( float z = (float)GetZ(
(((double)(y))*TILESIZE)/((double)(iRes-1)), (((double)(y)) * TILESIZE) / ((double)(iRes - 1)),
(((double)(x))*TILESIZE)/((double)(iRes-1))); (((double)(x)) * TILESIZE) / ((double)(iRes - 1)));
fwrite(&z,1,sizeof(z),output); fwrite(&z, 1, sizeof(z), output);
} }
} }

View file

@ -31,8 +31,8 @@ typedef struct{
} Cell; } Cell;
typedef struct{ typedef struct{
double v9[9][9]; double v9[9][9];
double v8[8][8]; double v8[8][8];
uint16 area_id; uint16 area_id;
} chunk; } chunk;
@ -88,7 +88,7 @@ typedef struct {
} MH2O_offsData; } MH2O_offsData;
typedef struct { typedef struct {
uint16 flags; uint16 LiquidTypeId;
uint16 type; uint16 type;
float heightLevel1; float heightLevel1;
float heightLevel2; float heightLevel2;
@ -100,13 +100,21 @@ typedef struct {
uint32 ofsData2b; uint32 ofsData2b;
} MH2O_Data1; } MH2O_Data1;
enum LiquidType
{
LIQUID_TYPE_WATER = 0,
LIQUID_TYPE_OCEAN = 1,
LIQUID_TYPE_MAGMA = 2,
LIQUID_TYPE_SLIME = 3
};
class MPQFile; class MPQFile;
bool MH2O_presence; bool MH2O_presence;
MH2O_offsData *LiqOffsData; MH2O_offsData *LiqOffsData;
MH2O_Data1 *LiqChunkData1; MH2O_Data1 *LiqChunkData1;
float *ChunkLiqHeight, *MapLiqHeight; float *ChunkLiqHeight, *MapLiqHeight;
char* MapLiqFlag; uint8* MapLiqFlag;
uint32 k, m, chunk_num; uint32 k, m, chunk_num;
void LoadMapChunk(MPQFile &, chunk*); void LoadMapChunk(MPQFile &, chunk*);
bool LoadWMO(char* filename); bool LoadWMO(char* filename);

View file

@ -907,53 +907,29 @@ void Player::HandleDrowning()
void Player::HandleLava() void Player::HandleLava()
{ {
bool ValidArea = false;
if ((m_isunderwater & 0x80) && isAlive()) if ((m_isunderwater & 0x80) && isAlive())
{ {
//Single trigger Set BreathTimer // Single trigger Set BreathTimer
if (!(m_isunderwater & 0x80)) if (!(m_isunderwater & 0x80))
{ {
m_isunderwater|= 0x04; m_isunderwater|= 0x04;
m_breathTimer = 1000; m_breathTimer = 1000;
} }
//Reset BreathTimer and still in the lava
// Reset BreathTimer and still in the lava
if (!m_breathTimer) if (!m_breathTimer)
{ {
uint64 guid = GetGUID(); uint64 guid = GetGUID();
uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage uint32 damage = urand(600, 700); // TODO: Get more detailed information about lava damage
uint32 dmgZone = GetZoneId(); // TODO: Find correct "lava dealing zone" flag in Area Table
// Deal lava damage only in lava zones. // if not gamemaster then deal damage
switch(dmgZone) if ( !isGameMaster() )
{
case 0x8D:
ValidArea = false;
break;
case 0x94:
ValidArea = false;
break;
case 0x2CE:
ValidArea = false;
break;
case 0x2CF:
ValidArea = false;
break;
default:
if (dmgZone / 5 & 0x408)
ValidArea = true;
}
// if is valid area and is not gamemaster then deal damage
if ( ValidArea && !isGameMaster() )
EnvironmentalDamage(guid, DAMAGE_LAVA, damage); EnvironmentalDamage(guid, DAMAGE_LAVA, damage);
m_breathTimer = 1000; m_breathTimer = 1000;
} }
} }
//Death timer disabled and WaterFlags reset else if (m_deathState == DEAD) // Disable breath timer and reset underwater flags
else if (m_deathState == DEAD)
{ {
m_breathTimer = 0; m_breathTimer = 0;
m_isunderwater = 0; m_isunderwater = 0;