mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 17:11:33 +00:00
Merge branch 'thedichotomyof4' into 'master'
ESM4 upd8s: Fours and Worlds Closes #7445 See merge request OpenMW/openmw!3454
This commit is contained in:
commit
df1063be5d
12 changed files with 48 additions and 28 deletions
|
@ -562,7 +562,7 @@ namespace EsmTool
|
|||
{
|
||||
std::cout << "Author: " << reader.getAuthor() << '\n'
|
||||
<< "Description: " << reader.getDesc() << '\n'
|
||||
<< "File format version: " << reader.esmVersion() << '\n';
|
||||
<< "File format version: " << reader.esmVersionF() << '\n';
|
||||
|
||||
if (const std::vector<ESM::MasterData>& masterData = reader.getGameFiles(); !masterData.empty())
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
#include <osg/Stats>
|
||||
|
||||
#include <components/esm4/loadwrld.hpp>
|
||||
#include <components/resource/objectcache.hpp>
|
||||
#include <components/settings/values.hpp>
|
||||
|
||||
|
@ -20,10 +21,17 @@ namespace MWRender
|
|||
|
||||
osg::ref_ptr<ESMTerrain::LandObject> LandManager::getLand(ESM::ExteriorCellLocation cellIndex)
|
||||
{
|
||||
const MWBase::World& world = *MWBase::Environment::get().getWorld();
|
||||
if (ESM::isEsm4Ext(cellIndex.mWorldspace))
|
||||
{
|
||||
const ESM4::World* worldspace = world.getStore().get<ESM4::World>().find(cellIndex.mWorldspace);
|
||||
if (!worldspace->mParent.isZeroOrUnset() && worldspace->mParentUseFlags & ESM4::World::UseFlag_Land)
|
||||
cellIndex.mWorldspace = worldspace->mParent;
|
||||
}
|
||||
|
||||
if (const std::optional<osg::ref_ptr<osg::Object>> obj = mCache->getRefFromObjectCacheOrNone(cellIndex))
|
||||
return static_cast<ESMTerrain::LandObject*>(obj->get());
|
||||
|
||||
const MWBase::World& world = *MWBase::Environment::get().getWorld();
|
||||
osg::ref_ptr<ESMTerrain::LandObject> landObj = nullptr;
|
||||
|
||||
if (ESM::isEsm4Ext(cellIndex.mWorldspace))
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "terrainstorage.hpp"
|
||||
|
||||
#include <components/esm3/loadland.hpp>
|
||||
#include <components/esm4/loadwrld.hpp>
|
||||
|
||||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
|
@ -33,6 +34,10 @@ namespace MWRender
|
|||
|
||||
if (ESM::isEsm4Ext(cellLocation.mWorldspace))
|
||||
{
|
||||
const ESM4::World* worldspace = esmStore.get<ESM4::World>().find(cellLocation.mWorldspace);
|
||||
if (!worldspace->mParent.isZeroOrUnset() && worldspace->mParentUseFlags & ESM4::World::UseFlag_Land)
|
||||
cellLocation.mWorldspace = worldspace->mParent;
|
||||
|
||||
return esmStore.get<ESM4::Land>().search(cellLocation) != nullptr;
|
||||
}
|
||||
else
|
||||
|
@ -64,6 +69,10 @@ namespace MWRender
|
|||
|
||||
if (ESM::isEsm4Ext(worldspace))
|
||||
{
|
||||
const ESM4::World* worldRec = esmStore.get<ESM4::World>().find(worldspace);
|
||||
if (!worldRec->mParent.isZeroOrUnset() && worldRec->mParentUseFlags & ESM4::World::UseFlag_Land)
|
||||
worldspace = worldRec->mParent;
|
||||
|
||||
const auto& lands = esmStore.get<ESM4::Land>().getLands();
|
||||
for (const auto& [landPos, _] : lands)
|
||||
{
|
||||
|
|
|
@ -25,12 +25,13 @@ namespace ESM
|
|||
VER_120 = 0x3f99999a, // TES3
|
||||
VER_130 = 0x3fa66666, // TES3
|
||||
VER_080 = 0x3f4ccccd, // TES4
|
||||
VER_100 = 0x3f800000, // TES4
|
||||
VER_100 = 0x3f800000, // TES4, FO4
|
||||
VER_132 = 0x3fa8f5c3, // FONV Courier's Stash, DeadMoney
|
||||
VER_133 = 0x3faa3d71, // FONV HonestHearts
|
||||
VER_134 = 0x3fab851f, // FONV, GunRunnersArsenal, LonesomeRoad, OldWorldBlues
|
||||
VER_094 = 0x3f70a3d7, // TES5/FO3
|
||||
VER_170 = 0x3fd9999a // TES5
|
||||
VER_170 = 0x3fd9999a, // TES5
|
||||
VER_095 = 0x3f733333, // FO4
|
||||
};
|
||||
|
||||
// Defines another files (esm or esp) that this file depends upon.
|
||||
|
|
|
@ -249,9 +249,8 @@ void ESM4::Navigation::load(ESM4::Reader& reader)
|
|||
}
|
||||
case ESM4::SUB_NVPP:
|
||||
{
|
||||
// FIXME: this is both the version for FO4 and for some TES4 files
|
||||
// How to distinguish?
|
||||
if (esmVer == ESM::VER_100)
|
||||
// FIXME: FO4 updates the format
|
||||
if (reader.hasFormVersion() && (esmVer == ESM::VER_095 || esmVer == ESM::VER_100))
|
||||
{
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
|
|
|
@ -213,7 +213,7 @@ void ESM4::NavMesh::load(ESM4::Reader& reader)
|
|||
{
|
||||
// See FIXME in ESM4::Navigation::load.
|
||||
// FO4 updates the format
|
||||
if (esmVer == ESM::VER_100)
|
||||
if (reader.hasFormVersion() && (esmVer == ESM::VER_095 || esmVer == ESM::VER_100))
|
||||
{
|
||||
reader.skipSubRecordData();
|
||||
break;
|
||||
|
|
|
@ -39,7 +39,7 @@ void ESM4::Npc::load(ESM4::Reader& reader)
|
|||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
std::uint32_t esmVer = reader.esmVersion();
|
||||
mIsTES4 = esmVer == ESM::VER_080 || esmVer == ESM::VER_100;
|
||||
mIsTES4 = (esmVer == ESM::VER_080 || esmVer == ESM::VER_100) && !reader.hasFormVersion();
|
||||
mIsFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134;
|
||||
// mIsTES5 = esmVer == ESM::VER_094 || esmVer == ESM::VER_170; // WARN: FO3 is also VER_094
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ void ESM4::Race::load(ESM4::Reader& reader)
|
|||
mFlags = reader.hdr().record.flags;
|
||||
|
||||
std::uint32_t esmVer = reader.esmVersion();
|
||||
bool isTES4 = esmVer == ESM::VER_080 || esmVer == ESM::VER_100;
|
||||
bool isTES4 = (esmVer == ESM::VER_080 || esmVer == ESM::VER_100) && !reader.hasFormVersion();
|
||||
bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134;
|
||||
bool isFO3 = false;
|
||||
|
||||
|
|
|
@ -185,6 +185,10 @@ void ESM4::World::load(ESM4::Reader& reader)
|
|||
mWaterLevel = 0.f;
|
||||
}
|
||||
}
|
||||
|
||||
// TES4 doesn't define PNAM. Exact parent worldspace behavior needs research
|
||||
if (!reader.hasFormVersion())
|
||||
mParentUseFlags = 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,18 @@ namespace ESM4
|
|||
WLD_NoGrass = 0x80 // No Grass
|
||||
};
|
||||
|
||||
enum UseFlags
|
||||
{
|
||||
UseFlag_Land = 0x01,
|
||||
UseFlag_LOD = 0x02,
|
||||
UseFlag_Map = 0x04,
|
||||
UseFlag_Water = 0x08,
|
||||
UseFlag_Climate = 0x10,
|
||||
UseFlag_Imagespace = 0x20, // Unused in TES5
|
||||
UseFlag_SkyCell = 0x40,
|
||||
// cc9cii: 0x80 == needs water adjustment? Set for WastelandNV
|
||||
};
|
||||
|
||||
struct REFRcoord
|
||||
{
|
||||
ESM::FormId formId;
|
||||
|
@ -115,15 +127,7 @@ namespace ESM4
|
|||
// ----------------------
|
||||
ESM::FormId mMusic;
|
||||
|
||||
// 0x01 use Land data
|
||||
// 0x02 use LOD data
|
||||
// 0x04 use Map data
|
||||
// 0x08 use Water data
|
||||
// 0x10 use Climate data
|
||||
// 0x20 use Image Space data (Climate for TES5)
|
||||
// 0x40 use SkyCell (TES5)
|
||||
// 0x80 needs water adjustment (this isn't for parent I think? FONV only set for wastelandnv)
|
||||
std::uint16_t mParentUseFlags; // FO3/FONV
|
||||
std::uint16_t mParentUseFlags{ 0 };
|
||||
|
||||
// cache formId's of children (e.g. CELL, ROAD)
|
||||
std::vector<ESM::FormId> mCells;
|
||||
|
|
|
@ -201,15 +201,6 @@ namespace ESM4
|
|||
|
||||
// restart from the beginning (i.e. "TES4" record header)
|
||||
mStream->seekg(0, mStream->beg);
|
||||
#if 0
|
||||
unsigned int esmVer = mHeader.mData.version.ui;
|
||||
bool isTes4 = esmVer == ESM::VER_080 || esmVer == ESM::VER_100;
|
||||
//bool isTes5 = esmVer == ESM::VER_094 || esmVer == ESM::VER_170;
|
||||
//bool isFONV = esmVer == ESM::VER_132 || esmVer == ESM::VER_133 || esmVer == ESM::VER_134;
|
||||
|
||||
// TES4 header size is 4 bytes smaller than TES5 header
|
||||
mCtx.recHeaderSize = isTes4 ? sizeof(ESM4::RecordHeader) - 4 : sizeof(ESM4::RecordHeader);
|
||||
#endif
|
||||
getRecordHeader();
|
||||
if (mCtx.recordHeader.record.typeId == REC_TES4)
|
||||
{
|
||||
|
|
|
@ -247,8 +247,12 @@ namespace ESM4
|
|||
void setRecHeaderSize(const std::size_t size);
|
||||
|
||||
inline unsigned int esmVersion() const { return mHeader.mData.version.ui; }
|
||||
inline float esmVersionF() const { return mHeader.mData.version.f; }
|
||||
inline unsigned int numRecords() const { return mHeader.mData.records; }
|
||||
|
||||
inline bool hasFormVersion() const { return mCtx.recHeaderSize == sizeof(RecordHeader); }
|
||||
inline unsigned int formVersion() const { return mCtx.recordHeader.record.version; }
|
||||
|
||||
void buildLStringIndex();
|
||||
void getLocalizedString(std::string& str);
|
||||
|
||||
|
|
Loading…
Reference in a new issue