void load(ESMReader &esm) { // Get the grid location esm.getSubNameIs("INTV"); esm.getT(X); esm.getT(Y); esm.getHNT(flags, "DATA"); // Store the file position context = esm.getContext(); hasData = false; int cnt = 0; // Skip these here. Load the actual data when the cell is loaded. if(esm.isNextSub("VNML")) {esm.skipHSubSize(12675);cnt++;} if(esm.isNextSub("VHGT")) {esm.skipHSubSize(4232);cnt++;} if(esm.isNextSub("WNAM")) esm.skipHSubSize(81); if(esm.isNextSub("VCLR")) esm.skipHSubSize(12675); if(esm.isNextSub("VTEX")) {esm.skipHSubSize(512);cnt++;} // We need all three of VNML, VHGT and VTEX in order to use the // landscape. hasData = (cnt == 3); }
void PathGrid::load(ESMReader &esm) { esm.getHNT(data, "DATA", 12); cell = esm.getHNString("NAME"); // Remember this file position context = esm.getContext(); // Check that the sizes match up. Size = 16 * s2 (path points?) if (esm.isNextSub("PGRP")) { esm.skipHSub(); int size = esm.getSubSize(); if (size != 16 * data.s2) esm.fail("Path grid table size mismatch"); } // Size varies. Path grid chances? Connections? Multiples of 4 // suggest either int or two shorts, or perhaps a float. Study // it later. if (esm.isNextSub("PGRC")) { esm.skipHSub(); int size = esm.getSubSize(); if (size % 4 != 0) esm.fail("PGRC size not a multiple of 4"); } }
void Land::load(ESMReader &esm) { mEsm = &esm; mPlugin = mEsm->getIndex(); // Get the grid location esm.getSubNameIs("INTV"); esm.getSubHeaderIs(8); esm.getT<int>(mX); esm.getT<int>(mY); esm.getHNT(mFlags, "DATA"); // Store the file position mContext = esm.getContext(); mHasData = false; // Skip these here. Load the actual data when the cell is loaded. if (esm.isNextSub("VNML")) { esm.skipHSubSize(12675); mDataTypes |= DATA_VNML; } if (esm.isNextSub("VHGT")) { esm.skipHSubSize(4232); mDataTypes |= DATA_VHGT; } if (esm.isNextSub("WNAM")) { esm.skipHSubSize(81); mDataTypes |= DATA_WNAM; } if (esm.isNextSub("VCLR")) { esm.skipHSubSize(12675); mDataTypes |= DATA_VCLR; } if (esm.isNextSub("VTEX")) { esm.skipHSubSize(512); mDataTypes |= DATA_VTEX; } // We need all three of VNML, VHGT and VTEX in order to use the // landscape. (Though Morrowind seems to accept terrain without VTEX/VCLR entries) mHasData = mDataTypes & (DATA_VNML|DATA_VHGT|DATA_WNAM); mDataLoaded = 0; mLandData = NULL; }
void Land::load(ESMReader &esm) { mEsm = &esm; mPlugin = mEsm->getIndex(); // Get the grid location esm.getSubNameIs("INTV"); esm.getSubHeaderIs(8); esm.getT<int>(mX); esm.getT<int>(mY); esm.getHNT(mFlags, "DATA"); // Store the file position mContext = esm.getContext(); // Skip these here. Load the actual data when the cell is loaded. if (esm.isNextSub("VNML")) { esm.skipHSubSize(12675); mDataTypes |= DATA_VNML; } if (esm.isNextSub("VHGT")) { esm.skipHSubSize(4232); mDataTypes |= DATA_VHGT; } if (esm.isNextSub("WNAM")) { esm.skipHSubSize(81); mDataTypes |= DATA_WNAM; } if (esm.isNextSub("VCLR")) { esm.skipHSubSize(12675); mDataTypes |= DATA_VCLR; } if (esm.isNextSub("VTEX")) { esm.skipHSubSize(512); mDataTypes |= DATA_VTEX; } mDataLoaded = 0; mLandData = NULL; }
void Script::loadSCVR(ESMReader &esm) { int s = mData.mStringTableSize; std::vector<char> tmp (s); // not using getHExact, vanilla doesn't seem to mind unused bytes at the end esm.getSubHeader(); int left = esm.getSubSize(); if (left < s) esm.fail("SCVR string list is smaller than specified"); esm.getExact(&tmp[0], s); if (left > s) esm.skip(left-s); // skip the leftover junk // Set up the list of variable names mVarNames.resize(mData.mNumShorts + mData.mNumLongs + mData.mNumFloats); // The tmp buffer is a null-byte separated string list, we // just have to pick out one string at a time. char* str = &tmp[0]; for (size_t i = 0; i < mVarNames.size(); i++) { // Support '\r' terminated strings like vanilla. See Bug #1324. char *termsym = strchr(str, '\r'); if(termsym) *termsym = '\0'; mVarNames[i] = std::string(str); str += mVarNames[i].size() + 1; if (str - &tmp[0] > s) { // Apparently SCVR subrecord is not used and variable names are // determined on the fly from the script text. Therefore don't throw // an exeption, just log an error and continue. std::stringstream ss; ss << "ESM Error: " << "String table overflow"; ss << "\n File: " << esm.getName(); ss << "\n Record: " << esm.getContext().recName.toString(); ss << "\n Subrecord: " << "SCVR"; ss << "\n Offset: 0x" << std::hex << esm.getFileOffset(); std::cerr << ss.str() << std::endl; break; } } }
void Cell::loadCell(ESMReader &esm, bool saveContext) { mRefNumCounter = 0; if (mData.mFlags & Interior) { // Interior cells if (esm.isNextSub("INTV")) { int waterl; esm.getHT(waterl); mWater = (float) waterl; mWaterInt = true; } else if (esm.isNextSub("WHGT")) { esm.getHT(mWater); } // Quasi-exterior cells have a region (which determines the // weather), pure interior cells have ambient lighting // instead. if (mData.mFlags & QuasiEx) mRegion = esm.getHNOString("RGNN"); else if (esm.isNextSub("AMBI")) esm.getHT(mAmbi); } else { // Exterior cells mRegion = esm.getHNOString("RGNN"); mMapColor = 0; esm.getHNOT(mMapColor, "NAM5"); } if (esm.isNextSub("NAM0")) { esm.getHT(mRefNumCounter); } if (saveContext) { mContextList.push_back(esm.getContext()); esm.skipRecord(); } }
void Cell::loadCell(ESMReader &esm, bool saveContext) { bool isLoaded = false; while (!isLoaded && esm.hasMoreSubs()) { esm.getSubName(); switch (esm.retSubName().intval) { case ESM::FourCC<'I','N','T','V'>::value: int waterl; esm.getHT(waterl); mWater = static_cast<float>(waterl); mWaterInt = true; break; case ESM::FourCC<'W','H','G','T'>::value: esm.getHT(mWater); mWaterInt = false; break; case ESM::FourCC<'A','M','B','I'>::value: esm.getHT(mAmbi); break; case ESM::FourCC<'R','G','N','N'>::value: mRegion = esm.getHString(); break; case ESM::FourCC<'N','A','M','5'>::value: esm.getHT(mMapColor); break; case ESM::FourCC<'N','A','M','0'>::value: esm.getHT(mRefNumCounter); break; default: esm.cacheSubName(); isLoaded = true; break; } } if (saveContext) { mContextList.push_back(esm.getContext()); esm.skipRecord(); } }
void Cell::load(ESMReader &esm) { // Ignore this for now, it might mean we should delete the entire // cell? if (esm.isNextSub("DELE")) esm.skipHSub(); esm.getHNT(data, "DATA", 12); // Water level water = 0; if (data.flags & Interior) { // Interior cells if (esm.isNextSub("INTV") || esm.isNextSub("WHGT")) esm.getHT(water); // Quasi-exterior cells have a region (which determines the // weather), pure interior cells have ambient lighting // instead. if (data.flags & QuasiEx) region = esm.getHNOString("RGNN"); else esm.getHNT(ambi, "AMBI", 16); } else { // Exterior cells region = esm.getHNOString("RGNN"); esm.getHNOT(mapColor, "NAM5"); } // Save position of the cell references and move on context = esm.getContext(); esm.skipRecord(); }
void Script::load(ESMReader &esm) { SCHD data; esm.getHNT(data, "SCHD", 52); mData = data.mData; mId = data.mName.toString(); // List of local variables if (esm.isNextSub("SCVR")) { int s = mData.mStringTableSize; std::vector<char> tmp (s); esm.getHExact (&tmp[0], s); // Set up the list of variable names mVarNames.resize(mData.mNumShorts + mData.mNumLongs + mData.mNumFloats); // The tmp buffer is a null-byte separated string list, we // just have to pick out one string at a time. char* str = &tmp[0]; for (size_t i = 0; i < mVarNames.size(); i++) { // Support '\r' terminated strings like vanilla. See Bug #1324. char *termsym = strchr(str, '\r'); if(termsym) *termsym = '\0'; mVarNames[i] = std::string(str); str += mVarNames[i].size() + 1; if (str - &tmp[0] > s) { // Apparently SCVR subrecord is not used and variable names are // determined on the fly from the script text. Therefore don't throw // an exeption, just log an error and continue. std::stringstream ss; ss << "ESM Error: " << "String table overflow"; ss << "\n File: " << esm.getName(); ss << "\n Record: " << esm.getContext().recName.toString(); ss << "\n Subrecord: " << "SCVR"; ss << "\n Offset: 0x" << std::hex << esm.getFileOffset(); std::cerr << ss.str() << std::endl; break; } } } // Script mData mScriptData.resize(mData.mScriptDataSize); esm.getHNExact(&mScriptData[0], mScriptData.size(), "SCDT"); // Script text mScriptText = esm.getHNOString("SCTX"); // NOTE: A minor hack/workaround... // // MAO_Containers.esp from Morrowind Acoustic Overhaul has SCVR records // at the end (see Bug #1849). Since OpenMW does not use SCVR subrecords // for variable names just skip these as a quick fix. An alternative // solution would be to decode and validate SCVR subrecords even if they // appear here. if (esm.isNextSub("SCVR")) { esm.skipHSub(); } }
void Cell::postLoad(ESMReader &esm) { // Save position of the cell references and move on mContextList.push_back(esm.getContext()); esm.skipRecord(); }
void Land::load(ESMReader &esm, bool &isDeleted) { isDeleted = false; mPlugin = esm.getIndex(); bool hasLocation = false; bool isLoaded = false; while (!isLoaded && esm.hasMoreSubs()) { esm.getSubName(); switch (esm.retSubName().val) { case ESM::FourCC<'I','N','T','V'>::value: esm.getSubHeaderIs(8); esm.getT<int>(mX); esm.getT<int>(mY); hasLocation = true; break; case ESM::FourCC<'D','A','T','A'>::value: esm.getHT(mFlags); break; case ESM::SREC_DELE: esm.skipHSub(); isDeleted = true; break; default: esm.cacheSubName(); isLoaded = true; break; } } if (!hasLocation) esm.fail("Missing INTV subrecord"); mContext = esm.getContext(); // Skip the land data here. Load it when the cell is loaded. while (esm.hasMoreSubs()) { esm.getSubName(); switch (esm.retSubName().val) { case ESM::FourCC<'V','N','M','L'>::value: esm.skipHSub(); mDataTypes |= DATA_VNML; break; case ESM::FourCC<'V','H','G','T'>::value: esm.skipHSub(); mDataTypes |= DATA_VHGT; break; case ESM::FourCC<'W','N','A','M'>::value: esm.skipHSub(); mDataTypes |= DATA_WNAM; break; case ESM::FourCC<'V','C','L','R'>::value: esm.skipHSub(); mDataTypes |= DATA_VCLR; break; case ESM::FourCC<'V','T','E','X'>::value: esm.skipHSub(); mDataTypes |= DATA_VTEX; break; default: esm.fail("Unknown subrecord"); break; } } mDataLoaded = 0; mLandData = NULL; }