ModelInstance::ModelInstance(MPQFile &f,const char* ModelInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) { float ff[3]; f.read(&id, 4); f.read(ff,12); pos = fixCoords(Vec3D(ff[0],ff[1],ff[2])); f.read(ff,12); rot = Vec3D(ff[0],ff[1],ff[2]); f.read(&scale,4); // scale factor - divide by 1024. blizzard devs must be on crack, why not just use a float? sc = scale / 1024.0f; char tempname[512]; sprintf(tempname, "%s/%s", szWorkDirWmo, ModelInstName); FILE *input; input = fopen(tempname, "r+b"); if(!input) { //printf("ModelInstance::ModelInstance couldn't open %s\n", tempname); return; } fseek(input, 8, SEEK_SET); // get the correct no of vertices int nVertices; fread(&nVertices, sizeof (int), 1, input); fclose(input); if(nVertices == 0) return; uint16 adtId = 0;// not used for models uint32 flags = MOD_M2; if(tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); fwrite(&tileX, sizeof(uint32), 1, pDirfile); fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&flags, sizeof(uint32), 1, pDirfile); fwrite(&adtId, sizeof(uint16), 1, pDirfile); fwrite(&id, sizeof(uint32), 1, pDirfile); fwrite(&pos, sizeof(float), 3, pDirfile); fwrite(&rot, sizeof(float), 3, pDirfile); fwrite(&sc, sizeof(float), 1, pDirfile); uint32 nlen=strlen(ModelInstName); fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(ModelInstName, sizeof(char), nlen, pDirfile); /* int realx1 = (int) ((float) pos.x / 533.333333f); int realy1 = (int) ((float) pos.z / 533.333333f); int realx2 = (int) ((float) pos.x / 533.333333f); int realy2 = (int) ((float) pos.z / 533.333333f); fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f %f %d %d %d,%d %d\n", MapName, ModelInstName, (float) pos.x, (float) pos.y, (float) pos.z, (float) rot.x, (float) rot.y, (float) rot.z, sc, nVertices, realx1, realy1, realx2, realy2 ); */ }
WMOInstance::WMOInstance(MPQFile &f,const char* WmoInstName,const char*MapName, FILE *pDirfile) { pos = Vec3D(0,0,0); float ff[3]; f.read(&id, 4); f.read(ff,12); pos = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); rot = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); pos2 = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); pos3 = Vec3D(ff[0],ff[1],ff[2]); f.read(&d2,4); f.read(&d3,4); doodadset = (d2 & 0xFFFF0000) >> 16; int realx1 = (int) ((float) pos2.x / 533.333333f); int realy1 = (int) ((float) pos2.z / 533.333333f); int realx2 = (int) ((float) pos3.x / 533.333333f); int realy2 = (int) ((float) pos3.z / 533.333333f); if(realx1 < 0) { realx1 +=20; realx2+=20; } if(realy1 < 0) { realy1 +=20; realy2+=20; } // hack to prevent neg. values //-----------add_in _dir_file---------------- char tempname[512]; // const char dirname[] = "buildings\\dir"; sprintf(tempname, "buildings\\%s", WmoInstName); FILE *input; input = fopen(tempname, "r+b"); if(!input) { return; } fseek(input, 8, SEEK_SET); // get the correct no of vertices int nVertices; fread(&nVertices, sizeof (int), 1, input); fclose(input); if(nVertices == 0) { return; } /* FILE *dirfile; dirfile = fopen(dirname, "ab"); if(!dirfile) { printf("Can't open dirfile!'%s'\n"); return; } */ float x,z; x = pos.x; z = pos.z; if(x==0 && z == 0) { x = 533.33333f*32; z = 533.33333f*32; } fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n", MapName, WmoInstName, (float) x, (float) pos.y, (float) z, (float) rot.x, (float) rot.y, (float) rot.z, nVertices, realx1, realy1, realx2, realy2 ); // fclose(dirfile); }
WMOInstance::WMOInstance(MPQFile &f,const char* WmoInstName, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) { pos = Vec3D(0,0,0); float ff[3]; f.read(&id, 4); f.read(ff,12); pos = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); rot = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); pos2 = Vec3D(ff[0],ff[1],ff[2]); f.read(ff,12); pos3 = Vec3D(ff[0],ff[1],ff[2]); f.read(&d2,4); uint16 trash,adtId; f.read(&adtId,2); f.read(&trash,2); //-----------add_in _dir_file---------------- char tempname[512]; sprintf(tempname, "%s/%s", szWorkDirWmo, WmoInstName); FILE *input; input = fopen(tempname, "r+b"); if(!input) { printf("WMOInstance::WMOInstance: couldn't open %s\n", tempname); return; } fseek(input, 8, SEEK_SET); // get the correct no of vertices int nVertices; fread(&nVertices, sizeof (int), 1, input); fclose(input); if(nVertices == 0) return; float x,z; x = pos.x; z = pos.z; if(x==0 && z == 0) { pos.x = 533.33333f*32; pos.z = 533.33333f*32; } pos = fixCoords(pos); pos2 = fixCoords(pos2); pos3 = fixCoords(pos3); float scale = 1.0f; uint32 flags = MOD_HAS_BOUND; if(tileX == 65 && tileY == 65) flags |= MOD_WORLDSPAWN; //write mapID, tileX, tileY, Flags, ID, Pos, Rot, Scale, Bound_lo, Bound_hi, name fwrite(&mapID, sizeof(uint32), 1, pDirfile); fwrite(&tileX, sizeof(uint32), 1, pDirfile); fwrite(&tileY, sizeof(uint32), 1, pDirfile); fwrite(&flags, sizeof(uint32), 1, pDirfile); fwrite(&adtId, sizeof(uint16), 1, pDirfile); fwrite(&id, sizeof(uint32), 1, pDirfile); fwrite(&pos, sizeof(float), 3, pDirfile); fwrite(&rot, sizeof(float), 3, pDirfile); fwrite(&scale, sizeof(float), 1, pDirfile); fwrite(&pos2, sizeof(float), 3, pDirfile); fwrite(&pos3, sizeof(float), 3, pDirfile); uint32 nlen=strlen(WmoInstName); fwrite(&nlen, sizeof(uint32), 1, pDirfile); fwrite(WmoInstName, sizeof(char), nlen, pDirfile); /* fprintf(pDirfile,"%s/%s %f,%f,%f_%f,%f,%f 1.0 %d %d %d,%d %d\n", MapName, WmoInstName, (float) x, (float) pos.y, (float) z, (float) rot.x, (float) rot.y, (float) rot.z, nVertices, realx1, realy1, realx2, realy2 ); */ // fclose(dirfile); }
LiquidModelInstance::LiquidModelInstance(MPQFile &f, uint32 base_pos, uint32 tileID, MH20_Header* header, uint32 mapID, uint32 tileX, uint32 tileY, FILE *pDirfile) : Info(false) { memset(&LiqHeader, 0, sizeof(LiquidHeader)); LiqHeader.layerCount = header->layerCount; if(header->ofsInformation == 0) { Info = false; return; } #ifdef _DEBUG printf("Information offset: %i\n", header->ofsInformation); #endif f.seek(header->ofsInformation+base_pos); f.read(&LiqHeader.info, sizeof(MH20_Information)); #ifdef _DEBUG if(LiqHeader.info.LiquidType != 2) // Skip oceans { printf("Liquid Data Dump:\n"); printf("Flags: %08i |\n", LiqHeader.info.flags); // printf("Height %08i |\n", LiqHeader.info.height); // printf("Level1 %08f |\n", LiqHeader.info.heightLevel1); // printf("Level2 %08f |\n", LiqHeader.info.heightLevel2); printf("LType: %08i |\n", LiqHeader.info.LiquidType); printf("Width: %08i |\n", LiqHeader.info.width); printf("xOfset %08i |\n", LiqHeader.info.xOffset); printf("yOfset %08i |\n", LiqHeader.info.yOffset); WaitForInput(); } #endif uint16* buff = new uint16[3]; buff[0] = buff[1] = buff[2] = 0; if(LiqHeader.info.ofsHeightmap > 0) { #ifdef _DEBUG printf("Height Map Offset: %i\n", LiqHeader.info.ofsHeightmap); #endif f.seek(LiqHeader.info.ofsHeightmap+base_pos); f.read(&LiqHeader.heightMap.heightMap, sizeof(float)*2); f.read(&LiqHeader.heightMap.transparency, sizeof(char)*2); buff[0] = sizeof(LiqHeader.heightMap); } if(LiqHeader.info.ofsMask2 > 0) { #ifdef _DEBUG printf("Mask Offset: %i\n", LiqHeader.info.ofsMask2); #endif f.seek(LiqHeader.info.ofsMask2+base_pos); f.read(&LiqHeader.Mask2, sizeof(uint8)); buff[1] = sizeof(uint8); } if(header->ofsRender > 0) { #ifdef _DEBUG printf("Render offset: %i\n", header->ofsRender); #endif f.seek(header->ofsRender+base_pos); f.read(&LiqHeader.Render, sizeof(uint64)); buff[2] = sizeof(uint64); } fwrite(&LiqHeader.layerCount, sizeof(uint32), 1, pDirfile); fwrite(&LiqHeader.info, sizeof(MH20_Information), 1, pDirfile); fwrite(&buff[0], sizeof(uint16), 1, pDirfile); if(buff[0]) fwrite(&LiqHeader.heightMap, sizeof(MH2O_HeightMapData), 1, pDirfile); fwrite(&buff[1], sizeof(uint16), 1, pDirfile); if(buff[1]) fwrite(&LiqHeader.Mask2, sizeof(uint8), 1, pDirfile); fwrite(&buff[2], sizeof(uint16), 1, pDirfile); if(buff[2]) fwrite(&LiqHeader.Render, sizeof(uint64), 1, pDirfile); }
Application::Application(HINSTANCE _hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { MPQInit(); instance = this; resources = NULL; imageLibrary = NULL; dotaLibrary = NULL; mainWindow = NULL; cache = NULL; hInstance = _hInstance; _loaded = false; root = String::getPath(getAppPath()); cfg.read(); warLoader = new MPQLoader("Custom_V1"); warLoader->loadArchive(String::buildFullName(cfg.warPath, "war3.mpq")); warLoader->loadArchive(String::buildFullName(cfg.warPath, "war3x.mpq")); warLoader->loadArchive(String::buildFullName(cfg.warPath, "war3xlocal.mpq")); warLoader->loadArchive(String::buildFullName(cfg.warPath, "war3patch.mpq")); if (logCommand(lpCmdLine)) return; ScriptType::initTypes(); UpdateDialog::init(hInstance); INITCOMMONCONTROLSEX iccex; iccex.dwSize = sizeof iccex; iccex.dwICC = ICC_STANDARD_CLASSES | ICC_PROGRESS_CLASS | ICC_BAR_CLASSES | ICC_TREEVIEW_CLASSES | ICC_LISTVIEW_CLASSES | ICC_TAB_CLASSES | ICC_UPDOWN_CLASS | ICC_DATE_CLASSES; InitCommonControlsEx(&iccex); LoadLibrary("Riched20.dll"); OleInitialize(NULL); String path = String::getPath(getAppPath()); String resPath = String::buildFullName(path, "resources.mpq"); String patchPath = String::buildFullName(path, "install.mpq"); File* tOpen = File::open(resPath, File::READ); if (tOpen == NULL) { tOpen = File::open(patchPath, File::READ); if (tOpen) { delete tOpen; MoveFile(patchPath, resPath); } } else delete tOpen; resources = MPQArchive::open(resPath); MPQArchive* patch = MPQArchive::open(patchPath, File::READ); if (patch) { for (uint32 i = 0; i < patch->getHashSize(); i++) { char const* name = patch->getFileName(i); if (name) { MPQFile* source = patch->openFile(i, File::READ); if (source) { MPQFile* dest = resources->openFile(name, File::REWRITE); if (dest) { static uint8 buf[1024]; while (int length = source->read(buf, sizeof buf)) dest->write(buf, length); delete dest; } delete source; } } } delete patch; DeleteFile(patchPath); } imageLibrary = new ImageLibrary(resources); cache = new CacheManager(); dotaLibrary = new DotaLibrary(); #if 0 File* dlog = File::open("diff.txt", File::REWRITE); for (int pt = 0; pt < 120; pt++) { String prev = ""; bool different = false; for (int ver = 1; ver <= 80 && !different; ver++) { Dota* dota = dotaLibrary->getDota(makeVersion(6, ver)); if (dota) { Dota::Hero* hero = dota->getHero(pt); if (hero) { if (prev == "") prev = hero->name; else if (prev.icompare(hero->name)) different = true; } } } if (different) { dlog->printf(" Pt=%d\r\n", pt); prev = ""; for (int ver = 1; ver <= 80; ver++) { Dota* dota = dotaLibrary->getDota(makeVersion(6, ver)); if (dota) { Dota::Hero* hero = dota->getHero(pt); if (hero) { if (prev.icompare(hero->name)) { dlog->printf("6.%02d = %s\r\n", ver, hero->name); prev = hero->name; } } } } } } delete dlog; #endif #if 0 dotaLibrary->getDota(parseVersion("6.79e"), "K:\\Progs\\DotAReplay\\maps\\DotA v6.79e.w3x"); WIN32_FIND_DATA data; String enumPath = "K:\\Progs\\DotAReplay\\maps"; HANDLE hFind = FindFirstFile(String::buildFullName(enumPath, "*"), &data); BOOL success = (hFind != INVALID_HANDLE_VALUE); while (success) { String file(data.cFileName); if (String::getExtension(file).icompare(".w3x") == 0) { file.toLower(); Array<String> sub; if (file.rfind("dota{{_| }allstars}?{_| }v(\\d)\\.(\\d\\d)([b-z]?)[^b-z]", 0, &sub) >= 0) { int major = sub[1].toInt(); int minor = sub[2].toInt(); int build = 0; if (!sub[3].isEmpty()) build = int(sub[3][0] - 'a'); uint32 version = makeVersion(major, minor, build); dotaLibrary->getDota(version, String::buildFullName(enumPath, file)); } } success = FindNextFile(hFind, &data); } FindClose(hFind); #endif mainWindow = new MainWnd(); mainWindow->postLoad(); _loaded = true; if (lpCmdLine[0]) { COPYDATASTRUCT cd; cd.dwData = MAINWND_OPEN_REPLAY; cd.cbData = strlen(lpCmdLine) + 1; cd.lpData = lpCmdLine; PostMessage(getMainWindow(), WM_COPYDATA_FAKE, NULL, (LPARAM) &cd); } }
inline void LoadMapChunk(MPQFile &mf, chunk *_chunk) { float h; uint32 fourcc; uint32 size; MapChunkHeader header; mf.seekRelative(4); mf.read(&size, 4); size_t lastpos = mf.getPos() + size; mf.read(&header, 0x80); // what if header size got changed? _chunk->area_id = header.areaid; float xbase = header.xpos; float ybase = header.ypos; float zbase = header.zpos; zbase = TILESIZE * 32 - zbase; xbase = TILESIZE * 32 - xbase; if(wmoc.x > xbase) wmoc.x = xbase; if(wmoc.z > zbase) wmoc.z = zbase; int chunkflags = header.flags; //printf("LMC: flags %X\n", chunkflags); float zmin = 999999999.0f; float zmax = -999999999.0f; // must be there, bl!zz uses some crazy format while (mf.getPos() < lastpos) { mf.read(&fourcc, 4); mf.read(&size, 4); size_t nextpos = mf.getPos() + size; if(fourcc == 0x4d435654) // MCVT { for (int j = 0; j < 17; ++j) { for (int i = 0; i < ((j % 2) ? 8 : 9); ++i) { mf.read(&h, 4); float z = h + ybase; if (j % 2) { if(isHole(header.holes, i, j)) _chunk->v8[i][j / 2] = -1000; else _chunk->v8[i][j / 2] = z; } else { if(isHole(header.holes, i, j)) _chunk->v9[i][j / 2] = -1000; else _chunk->v9[i][j / 2] = z; } if(z > zmax) zmax = z; //if(z < zmin) zmin = z; } } } else if(fourcc == 0x4d434e52) // MCNR { nextpos = mf.getPos() + 0x1C0; // size fix } else if(fourcc == 0x4d434c51) // MCLQ { // liquid / water level char fcc1[5]; mf.read(fcc1, 4); flipcc(fcc1); fcc1[4] = 0; float *ChunkLiqHeight = new float[81]; if (!strcmp(fcc1, "MCSE")) { for(int j = 0; j < 81; ++j) { ChunkLiqHeight[j] = -999999; // no liquid/water } } else { float maxheight; mf.read(&maxheight, 4); for(int j = 0; j < 81; ++j) { LiqData liq; mf.read(&liq, 8); if(liq.height > maxheight) ChunkLiqHeight[j] = -999999; else ChunkLiqHeight[j] = h; } if(chunkflags & 4 || chunkflags & 8) MapLiqFlag[chunk_num] |= 1; // water if(chunkflags & 16) MapLiqFlag[chunk_num] |= 2; // magma/slime } if(!(chunk_num % 16)) m = 1024 * (chunk_num / 16); k = m + (chunk_num % 16) * 8; for(int p = 0; p < 72; p += 9) { for(int s = 0; s < 8; ++s) { MapLiqHeight[k] = ChunkLiqHeight[p + s]; ++k; } k = k + 120; } delete []ChunkLiqHeight; break; } mf.seek(nextpos); } }
inline void LoadMapChunk(MPQFile & mf, chunk*_chunk) { float h; uint32 fourcc; uint32 size; MapChunkHeader header; mf.seekRelative(4); mf.read(&size, 4); size_t lastpos = mf.getPos() + size; mf.read(&header, 0x80); _chunk->area_id =header.areaid ; _chunk->flag =0; float xbase = header.xpos; float ybase = header.ypos; float zbase = header.zpos; zbase = TILESIZE*32-zbase; xbase = TILESIZE*32-xbase; if(wmoc.x >xbase)wmoc.x =xbase; if(wmoc.z >zbase)wmoc.z =zbase; int chunkflags = header.flags; float zmin=999999999.0f; float zmax=-999999999.0f; //must be there, bl!zz uses some crazy format int nTextures; while (mf.getPos() < lastpos) { mf.read(&fourcc,4); mf.read(&size, 4); //if(size!=580) // printf("\n sz=%d",size); size_t nextpos = mf.getPos() + size; if(fourcc==0x4d435654) // MCVT { for (int j=0; j<17; j++) for (int i=0; i<((j%2)?8:9); i++) { mf.read(&h,4); float z=h+ybase; if (j%2) { if(isHole(header.holes,i,j)) _chunk->v8[i][j/2] = -1000; else _chunk->v8[i][j/2] = z; } else { if(isHole(header.holes,i,j)) _chunk->v9[i][j/2] = -1000; else _chunk->v9[i][j/2] = z; } if(z>zmax)zmax=z; //if(z<zmin)zmin=z; } } else if(fourcc==0x4d434e52) // MCNR { nextpos = mf.getPos() + 0x1C0; // size fix } else if(fourcc==0x4d434c51) // MCLQ { // liquid / water level //bool haswater; char fcc1[5]; mf.read(fcc1,4); flipcc(fcc1); fcc1[4]=0; if (!strcmp(fcc1,"MCSE")) { for(int i=0;i<9;i++) for(int j=0;j<9;j++) _chunk->waterlevel[i][j]=-999999; // no liquid/water } else { float maxheight; mf.read(&maxheight, 4); for(int j=0;j<9;j++) for(int i=0;i<9;i++) { mf.read(&h, 4); mf.read(&h, 4); if(h > maxheight) _chunk->waterlevel[i][j]=-999999; else _chunk->waterlevel[i][j]=h; } if(chunkflags & 4 || chunkflags & 8) _chunk->flag |=1; if(chunkflags & 16) _chunk->flag |=2; } break; } else if (fourcc==0x4d434c59) // MCLY { // texture info nTextures = (int)size; } else if (fourcc==0x4d43414c) // MCAL { if (nTextures<=0) continue; } mf.seek(nextpos); } }
void OutdoorLightStats::init(MPQFile &f) { float h,m; f.seekRelative(4); f.read(&h,4); f.seekRelative(4); f.read(&m,4); f.seekRelative(4); f.read(&dayIntensity,4); f.seekRelative(4); f.read(&dayColor.x,4); f.seekRelative(4); f.read(&dayColor.y,4); f.seekRelative(4); f.read(&dayColor.z,4); f.seekRelative(4); f.read(&dayDir.x,4); f.seekRelative(4); f.read(&dayDir.y,4); f.seekRelative(4); f.read(&dayDir.z,4); f.seekRelative(4); f.read(&nightIntensity, 4); f.seekRelative(4); f.read(&nightColor.x,4); f.seekRelative(4); f.read(&nightColor.y,4); f.seekRelative(4); f.read(&nightColor.z,4); f.seekRelative(4); f.read(&nightDir.x,4); f.seekRelative(4); f.read(&nightDir.y,4); f.seekRelative(4); f.read(&nightDir.z,4); f.seekRelative(4); f.read(&ambientIntensity, 4); f.seekRelative(4); f.read(&ambientColor.x,4); f.seekRelative(4); f.read(&ambientColor.y,4); f.seekRelative(4); f.read(&ambientColor.z,4); f.seekRelative(4); f.read(&fogDepth, 4); f.seekRelative(4); f.read(&fogIntensity, 4); f.seekRelative(4); f.read(&fogColor.x,4); f.seekRelative(4); f.read(&fogColor.y,4); f.seekRelative(4); f.read(&fogColor.z,4); time = (int)h * 60 * 2 + (int)m * 2; // HACK: make day & night intensity exclusive; set day intensity to 1.0 if (dayIntensity > 0) { dayIntensity = 1.0f; nightIntensity = 0.0f; } }