示例#1
0
void MapChunk::save(sExtendableArray &lADTFile, int &lCurrentPosition, int &lMCIN_Position, std::map<std::string, int> &lTextures, std::map<int, WMOInstance> &lObjectInstances, std::map<int, ModelInstance> &lModelInstances)
{
	int lID;
	int lMCNK_Size = 0x80;
	int lMCNK_Position = lCurrentPosition;
	lADTFile.Extend(8 + 0x80);  // This is only the size of the header. More chunks will increase the size.
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCNK', lMCNK_Size);
	lADTFile.GetPointer<MCIN>(lMCIN_Position + 8)->mEntries[py * 16 + px].offset = lCurrentPosition; // check this

	// MCNK data
	lADTFile.Insert(lCurrentPosition + 8, 0x80, reinterpret_cast<char*>(&(header)));
	MapChunkHeader *lMCNK_header = lADTFile.GetPointer<MapChunkHeader>(lCurrentPosition + 8);

	lMCNK_header->flags = Flags;
	lMCNK_header->holes = holes;
	lMCNK_header->areaid = areaID;

	lMCNK_header->nLayers = -1;
	lMCNK_header->nDoodadRefs = -1;
	lMCNK_header->ofsHeight = -1;
	lMCNK_header->ofsNormal = -1;
	lMCNK_header->ofsLayer = -1;
	lMCNK_header->ofsRefs = -1;
	lMCNK_header->ofsAlpha = -1;
	lMCNK_header->sizeAlpha = -1;
	lMCNK_header->ofsShadow = -1;
	lMCNK_header->sizeShadow = -1;
	lMCNK_header->nMapObjRefs = -1;
	lMCNK_header->ofsMCCV = -1;

	//! \todo  Implement sound emitter support. Or not.
	lMCNK_header->ofsSndEmitters = 0;
	lMCNK_header->nSndEmitters = 0;

	lMCNK_header->ofsLiquid = 0;
	//! \todo Is this still 8 if no chunk is present? Or did they correct that?
	lMCNK_header->sizeLiquid = 8;

	memset(lMCNK_header->low_quality_texture_map, 0, 0x10);

	static const size_t minimum_value_to_overwrite(128);

	for (size_t layer(1); layer < textureSet->num(); ++layer)
	{
		for (size_t y(0); y < 8; ++y)
		{
			for (size_t x(0); x < 8; ++x)
			{
				size_t sum(0);

				for (size_t j(0); j < 8; ++j)
				{
					for (size_t i(0); i < 8; ++i)
					{
						sum += textureSet->getAlpha(layer - 1, (y * 8 + j) * 64 + (x * 8 + i));
					}
				}

				if (sum  > minimum_value_to_overwrite * 8 * 8)
				{
					const size_t array_index((y * 8 + x) / 4);
					const size_t bit_index(((y * 8 + x) % 4) * 2);

					lMCNK_header->low_quality_texture_map[array_index] |= ((layer & 3) << bit_index);
				}
			}
		}
	}
	lCurrentPosition += 8 + 0x80;

	// MCVT
	int lMCVT_Size = mapbufsize * 4;

	lADTFile.Extend(8 + lMCVT_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCVT', lMCVT_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsHeight = lCurrentPosition - lMCNK_Position;

	float* lHeightmap = lADTFile.GetPointer<float>(lCurrentPosition + 8);

	float lMedian = 0.0f;
	for (int i = 0; i < mapbufsize; ++i)
		lMedian += mVertices[i].y;

	lMedian = lMedian / mapbufsize;
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ypos = lMedian;

	for (int i = 0; i < mapbufsize; ++i)
		lHeightmap[i] = mVertices[i].y - lMedian;

	lCurrentPosition += 8 + lMCVT_Size;
	lMCNK_Size += 8 + lMCVT_Size;
	
	// MCCV
	int lMCCV_Size = mapbufsize * sizeof(unsigned int);
	lADTFile.Extend(8 + lMCCV_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCCV', lMCCV_Size);
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsMCCV = lCurrentPosition - lMCNK_Position;

	unsigned int *lmccv = lADTFile.GetPointer<unsigned int>(lCurrentPosition + 8);
	memcpy(lmccv, mccv.data(), lMCCV_Size);

	for (int i = 0; i < mapbufsize; ++i)
		lmccv[i] = Reverse(lmccv[i], false);

	lCurrentPosition += 8 + lMCCV_Size;
	lMCNK_Size += 8 + lMCCV_Size;

	// MCNR
	int lMCNR_Size = mapbufsize * 3;

	lADTFile.Extend(8 + lMCNR_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCNR', lMCNR_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsNormal = lCurrentPosition - lMCNK_Position;

	char * lNormals = lADTFile.GetPointer<char>(lCurrentPosition + 8);

	// recalculate the normals
	recalcNorms();
	for (int i = 0; i < mapbufsize; ++i)
	{
		lNormals[i * 3 + 0] = misc::roundc(-mNormals[i].z * 127);
		lNormals[i * 3 + 1] = misc::roundc(-mNormals[i].x * 127);
		lNormals[i * 3 + 2] = misc::roundc(mNormals[i].y * 127);
	}

	lCurrentPosition += 8 + lMCNR_Size;
	lMCNK_Size += 8 + lMCNR_Size;
	//        }

	// Unknown MCNR bytes
	// These are not in as we have data or something but just to make the files more blizzlike.
	//        {
	lADTFile.Extend(13);
	lCurrentPosition += 13;
	lMCNK_Size += 13;
	//        }

	// MCLY
	//        {
	size_t lMCLY_Size = textureSet->num() * 0x10;

	lADTFile.Extend(8 + lMCLY_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCLY', lMCLY_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsLayer = lCurrentPosition - lMCNK_Position;
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nLayers = textureSet->num();

	// MCLY data
	for (size_t j = 0; j < textureSet->num(); ++j)
	{
		ENTRY_MCLY * lLayer = lADTFile.GetPointer<ENTRY_MCLY>(lCurrentPosition + 8 + 0x10 * j);

		lLayer->textureID = lTextures.find(textureSet->filename(j))->second;

		lLayer->flags = textureSet->flag(j);

		// if not first, have alpha layer, if first, have not. never have compression.
		lLayer->flags = (j > 0 ? lLayer->flags | FLAG_USE_ALPHA : lLayer->flags & (~FLAG_USE_ALPHA)) & (~FLAG_ALPHA_COMPRESSED);

		lLayer->ofsAlpha = (j == 0 ? 0 : (mBigAlpha ? 64 * 64 * (j - 1) : 32 * 64 * (j - 1)));
		lLayer->effectID = textureSet->effect(j);
	}

	lCurrentPosition += 8 + lMCLY_Size;
	lMCNK_Size += 8 + lMCLY_Size;
	//        }

	// MCRF
	//        {
	std::list<int> lDoodadIDs;
	std::list<int> lObjectIDs;

	Vec3D lChunkExtents[2];
	lChunkExtents[0] = Vec3D(xbase, 0.0f, zbase);
	lChunkExtents[1] = Vec3D(xbase + CHUNKSIZE, 0.0f, zbase + CHUNKSIZE);

	// search all wmos that are inside this chunk
	lID = 0;
	for (std::map<int, WMOInstance>::iterator it = lObjectInstances.begin(); it != lObjectInstances.end(); ++it)
	{
		if (it->second.isInsideChunk(lChunkExtents))
			lObjectIDs.push_back(lID);

		lID++;
	}

	// search all models that are inside this chunk
	lID = 0;
	for (std::map<int, ModelInstance>::iterator it = lModelInstances.begin(); it != lModelInstances.end(); ++it)
	{
		if (it->second.isInsideChunk(lChunkExtents))
			lDoodadIDs.push_back(lID);

		lID++;
	}

	int lMCRF_Size = 4 * (lDoodadIDs.size() + lObjectIDs.size());
	lADTFile.Extend(8 + lMCRF_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCRF', lMCRF_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsRefs = lCurrentPosition - lMCNK_Position;
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nDoodadRefs = lDoodadIDs.size();
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nMapObjRefs = lObjectIDs.size();

	// MCRF data
	int *lReferences = lADTFile.GetPointer<int>(lCurrentPosition + 8);

	lID = 0;
	for (std::list<int>::iterator it = lDoodadIDs.begin(); it != lDoodadIDs.end(); ++it)
	{
		lReferences[lID] = *it;
		lID++;
	}

	for (std::list<int>::iterator it = lObjectIDs.begin(); it != lObjectIDs.end(); ++it)
	{
		lReferences[lID] = *it;
		lID++;
	}

	lCurrentPosition += 8 + lMCRF_Size;
	lMCNK_Size += 8 + lMCRF_Size;
	//        }

	// MCSH
	//        {
	//! \todo  Somehow determine if we need to write this or not?
	//! \todo  This sometime gets all shadows black.
	if (Flags & 1)
	{
		int lMCSH_Size = 0x200;
		lADTFile.Extend(8 + lMCSH_Size);
		SetChunkHeader(lADTFile, lCurrentPosition, 'MCSH', lMCSH_Size);

		lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsShadow = lCurrentPosition - lMCNK_Position;
		lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeShadow = 0x200;

		char * lLayer = lADTFile.GetPointer<char>(lCurrentPosition + 8);

		memcpy(lLayer, mShadowMap, 0x200);

		lCurrentPosition += 8 + lMCSH_Size;
		lMCNK_Size += 8 + lMCSH_Size;
	}
	else
	{
		lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsShadow = 0;
		lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeShadow = 0;
	}

	// MCAL
	int lDimensions = 64 * (mBigAlpha ? 64 : 32);

	size_t lMaps = textureSet->num() ? textureSet->num() - 1U : 0U;

	int lMCAL_Size = lDimensions * lMaps;

	lADTFile.Extend(8 + lMCAL_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCAL', lMCAL_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsAlpha = lCurrentPosition - lMCNK_Position;
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->sizeAlpha = 8 + lMCAL_Size;

	char * lAlphaMaps = lADTFile.GetPointer<char>(lCurrentPosition + 8);

	for (size_t j = 0; j < lMaps; j++)
	{
		//First thing we have to do is downsample the alpha maps before we can write them
		if (mBigAlpha)
			for (int k = 0; k < lDimensions; k++)
				lAlphaMaps[lDimensions * j + k] = textureSet->getAlpha(j, k);
		else
		{
			unsigned char upperNibble, lowerNibble;
			for (int k = 0; k < lDimensions; k++)
			{
				lowerNibble = static_cast<unsigned char>(std::max(std::min((static_cast<float>(textureSet->getAlpha(j, k * 2 + 0))) * 0.05882f + 0.5f, 15.0f), 0.0f));
				upperNibble = static_cast<unsigned char>(std::max(std::min((static_cast<float>(textureSet->getAlpha(j, k * 2 + 1))) * 0.05882f + 0.5f, 15.0f), 0.0f));
				lAlphaMaps[lDimensions * j + k] = (upperNibble << 4) + lowerNibble;
			}
		}
	}

	lCurrentPosition += 8 + lMCAL_Size;
	lMCNK_Size += 8 + lMCAL_Size;
	//        }

	//! Don't write anything MCLQ related anymore...

	// MCSE
	int lMCSE_Size = 0;
	lADTFile.Extend(8 + lMCSE_Size);
	SetChunkHeader(lADTFile, lCurrentPosition, 'MCSE', lMCSE_Size);

	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->ofsSndEmitters = lCurrentPosition - lMCNK_Position;
	lADTFile.GetPointer<MapChunkHeader>(lMCNK_Position + 8)->nSndEmitters = lMCSE_Size / 0x1C;

	lCurrentPosition += 8 + lMCSE_Size;
	lMCNK_Size += 8 + lMCSE_Size;

	lADTFile.GetPointer<sChunkHeader>(lMCNK_Position)->mSize = lMCNK_Size;
	lADTFile.GetPointer<MCIN>(lMCIN_Position + 8)->mEntries[py * 16 + px].size = lMCNK_Size;
}
示例#2
0
void MapTile::saveTile()
{
	Log << "Saving ADT \"" << mFilename << "\"." << std::endl;
	LogDebug << "CHANGED FLAG " << changed << std::endl;
	int lID;  // This is a global counting variable. Do not store something in here you need later.

	// Collect some information we need later.

	// Check which doodads and WMOs are on this ADT.
	Vec3D lTileExtents[2];
	unsigned int UID(0);
	std::map<int, WMOInstance> lObjectInstances;
	std::map<int, ModelInstance> lModelInstances;

	lTileExtents[0] = Vec3D(this->xbase, 0.0f, this->zbase);
	lTileExtents[1] = Vec3D(this->xbase + TILESIZE, 0.0f, this->zbase + TILESIZE);

	UID += mPositionX * 10000000;
	UID += mPositionZ *   100000;

	for (std::map<int, WMOInstance>::iterator it = gWorld->mWMOInstances.begin(); it != gWorld->mWMOInstances.end(); ++it)
	{
		if (!it->second.isInsideTile(lTileExtents)) continue;
		if (!it->second.hasUIDLock())
		{
			it->second.mUniqueID = UID++;
			it->second.lockUID();
		}
		lObjectInstances[it->second.mUniqueID] = it->second;
	}

	for (std::map<int, ModelInstance>::iterator it = gWorld->mModelInstances.begin(); it != gWorld->mModelInstances.end(); ++it)
	{
		if (!it->second.isInsideTile(lTileExtents)) continue;
		if (!it->second.hasUIDLock())
		{
			it->second.d1 = UID++;
			it->second.lockUID();
		}
		lModelInstances[it->second.d1] = it->second;
	}

	filenameOffsetThing nullyThing = { 0, 0 };

	std::map<std::string, filenameOffsetThing> lModels;

	for (std::map<int, ModelInstance>::iterator it = lModelInstances.begin(); it != lModelInstances.end(); ++it)
		if (lModels.find(it->second.model->_filename) == lModels.end())
			lModels.insert(std::pair<std::string, filenameOffsetThing>(it->second.model->_filename, nullyThing));

	lID = 0;
	for (std::map<std::string, filenameOffsetThing>::iterator it = lModels.begin(); it != lModels.end(); ++it)
		it->second.nameID = lID++;

	std::map<std::string, filenameOffsetThing> lObjects;

	for (std::map<int, WMOInstance>::iterator it = lObjectInstances.begin(); it != lObjectInstances.end(); ++it)
		if (lObjects.find(it->second.wmo->_filename) == lObjects.end())
			lObjects.insert(std::pair<std::string, filenameOffsetThing>((it->second.wmo->_filename), nullyThing));

	lID = 0;
	for (std::map<std::string, filenameOffsetThing>::iterator it = lObjects.begin(); it != lObjects.end(); ++it)
		it->second.nameID = lID++;

	// Check which textures are on this ADT.
	std::map<std::string, int> lTextures;

	for (int i = 0; i < 16; ++i)
		for (int j = 0; j < 16; ++j)
			for (size_t tex = 0; tex < mChunks[i][j]->textureSet->num(); tex++)
				if (lTextures.find(mChunks[i][j]->textureSet->filename(tex)) == lTextures.end())
					lTextures.insert(std::pair<std::string, int>(mChunks[i][j]->textureSet->filename(tex), -1));

	lID = 0;
	for (std::map<std::string, int>::iterator it = lTextures.begin(); it != lTextures.end(); ++it)
		it->second = lID++;

	// Now write the file.

	sExtendableArray *lADTFile = new sExtendableArray();

	int lCurrentPosition = 0;

	// MVER
	lADTFile->Extend(8 + 0x4);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MVER', 4);

	// MVER data
	*(lADTFile->GetPointer<int>(8)) = 18;

	lCurrentPosition += 8 + 0x4;

	// MHDR
	int lMHDR_Position = lCurrentPosition;
	lADTFile->Extend(8 + 0x40);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MHDR', 0x40);

	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->flags = mFlags;

	lCurrentPosition += 8 + 0x40;

	// MCIN
	int lMCIN_Position = lCurrentPosition;

	lADTFile->Extend(8 + 256 * 0x10);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MCIN', 256 * 0x10);
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mcin = lCurrentPosition - 0x14;

	lCurrentPosition += 8 + 256 * 0x10;

	// MTEX
	int lMTEX_Position = lCurrentPosition;
	lADTFile->Extend(8 + 0);  // We don't yet know how big this will be.
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MTEX');
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mtex = lCurrentPosition - 0x14;

	lCurrentPosition += 8 + 0;

	// MTEX data
	for (std::map<std::string, int>::iterator it = lTextures.begin(); it != lTextures.end(); ++it)
	{
		lADTFile->Insert(lCurrentPosition, it->first.size() + 1, it->first.c_str());
		lCurrentPosition += it->first.size() + 1;
		lADTFile->GetPointer<sChunkHeader>(lMTEX_Position)->mSize += it->first.size() + 1;
		LogDebug << "Added texture \"" << it->first << "\"." << std::endl;
	}

	// MMDX
	int lMMDX_Position = lCurrentPosition;
	lADTFile->Extend(8 + 0);  // We don't yet know how big this will be.
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MMDX');
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mmdx = lCurrentPosition - 0x14;

	lCurrentPosition += 8 + 0;

	// MMDX data
	for (std::map<std::string, filenameOffsetThing>::iterator it = lModels.begin(); it != lModels.end(); ++it)
	{
		it->second.filenamePosition = lADTFile->GetPointer<sChunkHeader>(lMMDX_Position)->mSize;
		lADTFile->Insert(lCurrentPosition, it->first.size() + 1, it->first.c_str());
		lCurrentPosition += it->first.size() + 1;
		lADTFile->GetPointer<sChunkHeader>(lMMDX_Position)->mSize += it->first.size() + 1;
		LogDebug << "Added model \"" << it->first << "\"." << std::endl;
	}

	// MMID
	int lMMID_Size = 4 * lModels.size();
	lADTFile->Extend(8 + lMMID_Size);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MMID', lMMID_Size);
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mmid = lCurrentPosition - 0x14;

	// MMID data
	int * lMMID_Data = lADTFile->GetPointer<int>(lCurrentPosition + 8);

	lID = 0;
	for (std::map<std::string, filenameOffsetThing>::iterator it = lModels.begin(); it != lModels.end(); ++it)
		lMMID_Data[lID++] = it->second.filenamePosition;

	lCurrentPosition += 8 + lMMID_Size;

	// MWMO
	int lMWMO_Position = lCurrentPosition;
	lADTFile->Extend(8 + 0);  // We don't yet know how big this will be.
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MWMO');
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mwmo = lCurrentPosition - 0x14;

	lCurrentPosition += 8 + 0;

	// MWMO data
	for (std::map<std::string, filenameOffsetThing>::iterator it = lObjects.begin(); it != lObjects.end(); ++it)
	{
		it->second.filenamePosition = lADTFile->GetPointer<sChunkHeader>(lMWMO_Position)->mSize;
		lADTFile->Insert(lCurrentPosition, it->first.size() + 1, it->first.c_str());
		lCurrentPosition += it->first.size() + 1;
		lADTFile->GetPointer<sChunkHeader>(lMWMO_Position)->mSize += it->first.size() + 1;
		LogDebug << "Added object \"" << it->first << "\"." << std::endl;
	}

	// MWID
	int lMWID_Size = 4 * lObjects.size();
	lADTFile->Extend(8 + lMWID_Size);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MWID', lMWID_Size);
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mwid = lCurrentPosition - 0x14;

	// MWID data
	int * lMWID_Data = lADTFile->GetPointer<int>(lCurrentPosition + 8);

	lID = 0;
	for (std::map<std::string, filenameOffsetThing>::iterator it = lObjects.begin(); it != lObjects.end(); ++it)
		lMWID_Data[lID++] = it->second.filenamePosition;

	lCurrentPosition += 8 + lMWID_Size;

	// MDDF
	int lMDDF_Size = 0x24 * lModelInstances.size();
	lADTFile->Extend(8 + lMDDF_Size);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MDDF', lMDDF_Size);
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mddf = lCurrentPosition - 0x14;

	// MDDF data
	ENTRY_MDDF* lMDDF_Data = lADTFile->GetPointer<ENTRY_MDDF>(lCurrentPosition + 8);

	lID = 0;
	for (std::map<int, ModelInstance>::iterator it = lModelInstances.begin(); it != lModelInstances.end(); ++it)
	{
		std::map<std::string, filenameOffsetThing>::iterator lMyFilenameThingey = lModels.find(it->second.model->_filename);
		if (lMyFilenameThingey == lModels.end())
		{
			LogError << "There is a problem with saving the doodads. We have a doodad that somehow changed the name during the saving function. However this got produced, you can get a reward from schlumpf by pasting him this line." << std::endl;
			return;
		}

		lMDDF_Data[lID].nameID = lMyFilenameThingey->second.nameID;
		lMDDF_Data[lID].uniqueID = it->second.d1;
		lMDDF_Data[lID].pos[0] = it->second.pos.x;
		lMDDF_Data[lID].pos[1] = it->second.pos.y;
		lMDDF_Data[lID].pos[2] = it->second.pos.z;
		lMDDF_Data[lID].rot[0] = it->second.dir.x;
		lMDDF_Data[lID].rot[1] = it->second.dir.y;
		lMDDF_Data[lID].rot[2] = it->second.dir.z;
		lMDDF_Data[lID].scale = (uint16_t)(it->second.sc * 1024);
		lMDDF_Data[lID].flags = 0;
		lID++;
	}

	lCurrentPosition += 8 + lMDDF_Size;

	LogDebug << "Added " << lID << " doodads to MDDF" << std::endl;

	// MODF
	int lMODF_Size = 0x40 * lObjectInstances.size();
	lADTFile->Extend(8 + lMODF_Size);
	SetChunkHeader(*lADTFile, lCurrentPosition, 'MODF', lMODF_Size);
	lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->modf = lCurrentPosition - 0x14;

	// MODF data
	ENTRY_MODF *lMODF_Data = lADTFile->GetPointer<ENTRY_MODF>(lCurrentPosition + 8);

	lID = 0;
	for (std::map<int, WMOInstance>::iterator it = lObjectInstances.begin(); it != lObjectInstances.end(); ++it)
	{
		std::map<std::string, filenameOffsetThing>::iterator lMyFilenameThingey = lObjects.find(it->second.wmo->_filename);
		if (lMyFilenameThingey == lObjects.end())
		{
			LogError << "There is a problem with saving the objects. We have an object that somehow changed the name during the saving function. However this got produced, you can get a reward from schlumpf by pasting him this line." << std::endl;
			return;
		}

		lMODF_Data[lID].nameID = lMyFilenameThingey->second.nameID;
		lMODF_Data[lID].uniqueID = it->second.mUniqueID;
		lMODF_Data[lID].pos[0] = it->second.pos.x;
		lMODF_Data[lID].pos[1] = it->second.pos.y;
		lMODF_Data[lID].pos[2] = it->second.pos.z;
		lMODF_Data[lID].rot[0] = it->second.dir.x;
		lMODF_Data[lID].rot[1] = it->second.dir.y;
		lMODF_Data[lID].rot[2] = it->second.dir.z;

		lMODF_Data[lID].extents[0][0] = it->second.extents[0].x;
		lMODF_Data[lID].extents[0][1] = it->second.extents[0].y;
		lMODF_Data[lID].extents[0][2] = it->second.extents[0].z;

		lMODF_Data[lID].extents[1][0] = it->second.extents[1].x;
		lMODF_Data[lID].extents[1][1] = it->second.extents[1].y;
		lMODF_Data[lID].extents[1][2] = it->second.extents[1].z;

		lMODF_Data[lID].flags = it->second.mFlags;
		lMODF_Data[lID].doodadSet = it->second.doodadset;
		lMODF_Data[lID].nameSet = it->second.mNameset;
		lMODF_Data[lID].unknown = it->second.mUnknown;
		lID++;
	}

	LogDebug << "Added " << lID << " wmos to MODF" << std::endl;

	lCurrentPosition += 8 + lMODF_Size;

	//MH2O
	Water->saveToFile(*lADTFile, lMHDR_Position, lCurrentPosition);

	// MCNK
	for (int y = 0; y < 16; ++y)
	{
		for (int x = 0; x < 16; ++x)
		{
			mChunks[y][x]->save(*lADTFile, lCurrentPosition, lMCIN_Position, lTextures, lObjectInstances, lModelInstances);
		}
	}

	// MFBO
	if (mFlags & 1)
	{
		size_t chunkSize = sizeof(int16_t) * 9 * 2;
		lADTFile->Extend(8 + chunkSize);
		SetChunkHeader(*lADTFile, lCurrentPosition, 'MFBO', chunkSize);
		lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mfbo = lCurrentPosition - 0x14;

		int16_t *lMFBO_Data = lADTFile->GetPointer<int16_t>(lCurrentPosition + 8);

		lID = 0;
		for (int i = 0; i < 9; ++i)
			lMFBO_Data[lID++] = (int16_t)mMinimumValues[i * 3 + 1];

		for (int i = 0; i < 9; ++i)
			lMFBO_Data[lID++] = (int16_t)mMaximumValues[i * 3 + 1];

		lCurrentPosition += 8 + chunkSize;
	}

	//! \todo Do not do bullshit here in MTFX.
#if 0
	if (!mTextureEffects.empty()) {
		//! \todo check if nTexEffects == nTextures, correct order etc.
		lADTFile->Extend(8 + 4 * mTextureEffects.size());
		SetChunkHeader(*lADTFile, lCurrentPosition, 'MTFX', 4 * mTextureEffects.size());
		lADTFile->GetPointer<MHDR>(lMHDR_Position + 8)->mtfx = lCurrentPosition - 0x14;

		uint32_t* lMTFX_Data = lADTFile->GetPointer<uint32_t>(lCurrentPosition + 8);

		lID = 0;
		//they should be in the correct order...
		for (std::vector<int>::iterator it = mTextureEffects.begin(); it != mTextureEffects.end(); ++it) {
			lMTFX_Data[lID] = *it;
			++lID;
		}
		lCurrentPosition += 8 + sizeof(uint32_t) * mTextureEffects.size();
	}
#endif

	lADTFile->Extend(lCurrentPosition - lADTFile->mSize); // cleaning unused nulls at the end of file
	MPQFile *f = new MPQFile(mFilename);
	f->setBuffer(lADTFile->GetPointer<char>(), lADTFile->mSize);
	f->SaveFile();
	f->close();
	
	gWorld->mapIndex->markOnDisc(this->mPositionX, this->mPositionZ, true);

	lObjectInstances.clear();
	lModelInstances.clear();
	lModels.clear();

	delete f;
}
示例#3
0
文件: MapIndex.cpp 项目: Hlkz/noggit
void MapIndex::save()
{
  std::stringstream filename;
  filename << "World\\Maps\\" << basename << "\\" << basename << ".wdt";

  Log << "Saving WDT \"" << filename << "\"." << std::endl;

  sExtendableArray wdtFile = sExtendableArray();
  int curPos = 0;

  // MVER
  //  {
  wdtFile.Extend(8 + 0x4);
  SetChunkHeader(wdtFile, curPos, 'MVER', 4);

  // MVER data
  *( wdtFile.GetPointer<int>( 8 ) ) = 18;

  curPos += 8 + 0x4;
  //  }

  // MPHD
  //  {
  wdtFile.Extend(8);
  SetChunkHeader(wdtFile, curPos, 'MPHD', sizeof(MPHD));
  curPos += 8;

  wdtFile.Insert(curPos, sizeof(MPHD), (char*)&mphd);
  curPos += sizeof(MPHD);
  //  }

  // MAIN
  //  {
  wdtFile.Extend(8);
  SetChunkHeader(wdtFile, curPos, 'MAIN', 64*64*8);
  curPos += 8;

  for( int j = 0; j < 64; ++j )
  {
    for( int i = 0; i < 64; ++i )
    {
      wdtFile.Insert(curPos, 4, (char*)&mTiles[j][i].flags);
      wdtFile.Extend(4);
      curPos += 8;
    }
  }
  //  }

  if(mHasAGlobalWMO)
  {
    // MWMO
    //  {
    wdtFile.Extend(8);
    SetChunkHeader(wdtFile, curPos, 'MWMO', globalWMOName.size());
    curPos += 8;

    wdtFile.Insert(curPos, globalWMOName.size(), globalWMOName.data());
    curPos += globalWMOName.size();
    //  }

    // MODF
    //  {
    wdtFile.Extend(8);
    SetChunkHeader(wdtFile, curPos, 'MODF', sizeof(ENTRY_MODF));
    curPos += 8;

    wdtFile.Insert(curPos, sizeof(ENTRY_MODF), (char*)&wmoEntry);
    curPos += sizeof(ENTRY_MODF);
    //  }
  }

  MPQFile f(filename.str());
  f.setBuffer(wdtFile.GetPointer<char>(), wdtFile.mSize);
  f.SaveFile();
  f.close();

  changed = false;
}