1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-01-30 18:45:38 +00:00

essimporter: refactor ESSImport::CellRef and fix doubled actors

This commit is contained in:
Alexei Kotov 2022-07-30 19:13:41 +03:00
parent 79cdc08253
commit 9f49682d01
9 changed files with 144 additions and 189 deletions

View file

@ -5,7 +5,6 @@ set(ESSIMPORTER_FILES
importnpcc.cpp
importcrec.cpp
importcellref.cpp
importacdt.cpp
importinventory.cpp
importklst.cpp
importcntc.cpp

View file

@ -35,11 +35,11 @@ namespace
objstate.mRef.mRefNum = cellref.mRefNum;
if (cellref.mDeleted)
objstate.mCount = 0;
convertSCRI(cellref.mSCRI, objstate.mLocals);
convertSCRI(cellref.mActorData.mSCRI, objstate.mLocals);
objstate.mHasLocals = !objstate.mLocals.mVariables.empty();
if (cellref.mHasANIS)
convertANIS(cellref.mANIS, objstate.mAnimationState);
if (cellref.mActorData.mHasANIS)
convertANIS(cellref.mActorData.mANIS, objstate.mAnimationState);
}
bool isIndexedRefId(const std::string& indexedRefId)
@ -268,7 +268,7 @@ namespace ESSImport
}
std::vector<CellRef> cellrefs;
while (esm.hasMoreSubs() && esm.isNextSub("FRMR"))
while (esm.hasMoreSubs() && esm.peekNextSub("FRMR"))
{
CellRef ref;
ref.load (esm);
@ -369,13 +369,13 @@ namespace ESSImport
objstate.mRef.mRefID = idLower;
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
if (cellref.mHasACDT)
convertACDT(cellref.mACDT, objstate.mCreatureStats);
if (cellref.mActorData.mHasACDT)
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
else
objstate.mCreatureStats.mMissingACDT = true;
if (cellref.mHasACSC)
convertACSC(cellref.mACSC, objstate.mCreatureStats);
convertNpcData(cellref, objstate.mNpcStats);
if (cellref.mActorData.mHasACSC)
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
convertNpcData(cellref.mActorData, objstate.mNpcStats);
convertNPCC(npccIt->second, objstate);
convertCellRef(cellref, objstate);
@ -412,12 +412,12 @@ namespace ESSImport
objstate.mRef.mRefID = idLower;
// TODO: need more micromanagement here so we don't overwrite values
// from the ESM with default values
if (cellref.mHasACDT)
convertACDT(cellref.mACDT, objstate.mCreatureStats);
if (cellref.mActorData.mHasACDT)
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
else
objstate.mCreatureStats.mMissingACDT = true;
if (cellref.mHasACSC)
convertACSC(cellref.mACSC, objstate.mCreatureStats);
if (cellref.mActorData.mHasACSC)
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
convertCREC(crecIt->second, objstate);
convertCellRef(cellref, objstate);

View file

@ -235,9 +235,9 @@ class ConvertREFR : public Converter
public:
void read(ESM::ESMReader &esm) override
{
REFR refr;
CellRef refr;
refr.load(esm);
assert(refr.mRefID == "PlayerSaveGame");
assert(refr.mIndexedRefID == "PlayerSaveGame");
mContext->mPlayer.mObject.mPosition = refr.mPos;
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;

View file

@ -1,137 +0,0 @@
#include "importacdt.hpp"
#include <components/esm3/esmreader.hpp>
#include <components/esm3/cellref.hpp>
namespace ESSImport
{
void ActorData::load(ESM::ESMReader &esm)
{
blank();
if (esm.isNextSub("ACTN"))
{
/*
Activation flags:
ActivationFlag_UseEnabled = 1
ActivationFlag_OnActivate = 2
ActivationFlag_OnDeath = 10h
ActivationFlag_OnKnockout = 20h
ActivationFlag_OnMurder = 40h
ActivationFlag_DoorOpening = 100h
ActivationFlag_DoorClosing = 200h
ActivationFlag_DoorJammedOpening = 400h
ActivationFlag_DoorJammedClosing = 800h
*/
esm.skipHSub();
}
if (esm.isNextSub("STPR"))
esm.skipHSub();
if (esm.isNextSub("MNAM"))
esm.skipHSub();
bool isDeleted = false;
ESM::CellRef::loadData(esm, isDeleted);
mHasACDT = false;
if (esm.isNextSub("ACDT"))
{
mHasACDT = true;
esm.getHT(mACDT);
}
mHasACSC = false;
if (esm.isNextSub("ACSC"))
{
mHasACSC = true;
esm.getHT(mACSC);
}
if (esm.isNextSub("ACSL"))
esm.skipHSubSize(112);
if (esm.isNextSub("CSTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
if (esm.isNextSub("LSTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
// unsure at which point between LSTN and TGTN
if (esm.isNextSub("CSHN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
// unsure if before or after CSTN/LSTN
if (esm.isNextSub("LSHN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
while (esm.isNextSub("TGTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
while (esm.isNextSub("FGTN"))
esm.getHString(); // fight target?
// unsure at which point between TGTN and CRED
if (esm.isNextSub("AADT"))
{
// occurred when a creature was in the middle of its attack, 44 bytes
esm.skipHSub();
}
// unsure at which point between FGTN and CHRD
if (esm.isNextSub("PWPC"))
esm.skipHSub();
if (esm.isNextSub("PWPS"))
esm.skipHSub();
if (esm.isNextSub("WNAM"))
{
std::string id = esm.getHString();
if (esm.isNextSub("XNAM"))
mSelectedEnchantItem = esm.getHString();
else
mSelectedSpell = id;
if (esm.isNextSub("YNAM"))
esm.skipHSub(); // 4 byte, 0
}
while (esm.isNextSub("APUD"))
{
// used power
esm.getSubHeader();
std::string id = esm.getString(32);
(void)id;
// timestamp can't be used: this is the total hours passed, calculated by
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
// unfortunately cumulativeDays[month] is not clearly defined,
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
double timestamp;
esm.getT(timestamp);
}
// FIXME: not all actors have this, add flag
if (esm.isNextSub("CHRD")) // npc only
esm.getHExact(mSkills, 27*2*sizeof(int));
if (esm.isNextSub("CRED")) // creature only
esm.getHExact(mCombatStats, 3*2*sizeof(int));
mSCRI.load(esm);
if (esm.isNextSub("ND3D"))
esm.skipHSub();
mHasANIS = false;
if (esm.isNextSub("ANIS"))
{
mHasANIS = true;
esm.getHT(mANIS);
}
}
}

View file

@ -3,8 +3,6 @@
#include <string>
#include <components/esm3/cellref.hpp>
#include "importscri.hpp"
namespace ESM
@ -63,7 +61,7 @@ namespace ESSImport
};
#pragma pack(pop)
struct ActorData : public ESM::CellRef
struct ActorData
{
bool mHasACDT;
ACDT mACDT;
@ -85,10 +83,6 @@ namespace ESSImport
bool mHasANIS;
ANIS mANIS; // scripted animation state
virtual void load(ESM::ESMReader& esm);
virtual ~ActorData() = default;
};
}

View file

@ -9,8 +9,7 @@ namespace ESSImport
{
blank();
// (FRMR subrecord name is already read by the loop in ConvertCell)
esm.getHT(mRefNum.mIndex); // FRMR
esm.getHNT(mRefNum.mIndex, "FRMR");
// this is required since openmw supports more than 255 content files
int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24;
@ -19,7 +18,128 @@ namespace ESSImport
mIndexedRefId = esm.getHNString("NAME");
ActorData::load(esm);
if (esm.isNextSub("ACTN"))
{
/*
Activation flags:
ActivationFlag_UseEnabled = 1
ActivationFlag_OnActivate = 2
ActivationFlag_OnDeath = 10h
ActivationFlag_OnKnockout = 20h
ActivationFlag_OnMurder = 40h
ActivationFlag_DoorOpening = 100h
ActivationFlag_DoorClosing = 200h
ActivationFlag_DoorJammedOpening = 400h
ActivationFlag_DoorJammedClosing = 800h
*/
esm.skipHSub();
}
if (esm.isNextSub("STPR"))
esm.skipHSub();
if (esm.isNextSub("MNAM"))
esm.skipHSub();
bool isDeleted = false;
ESM::CellRef::loadData(esm, isDeleted);
mActorData.mHasACDT = false;
if (esm.isNextSub("ACDT"))
{
mActorData.mHasACDT = true;
esm.getHT(mActorData.mACDT);
}
mActorData.mHasACSC = false;
if (esm.isNextSub("ACSC"))
{
mActorData.mHasACSC = true;
esm.getHT(mActorData.mACSC);
}
if (esm.isNextSub("ACSL"))
esm.skipHSubSize(112);
if (esm.isNextSub("CSTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
if (esm.isNextSub("LSTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
// unsure at which point between LSTN and TGTN
if (esm.isNextSub("CSHN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
// unsure if before or after CSTN/LSTN
if (esm.isNextSub("LSHN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
while (esm.isNextSub("TGTN"))
esm.skipHSub(); // "PlayerSaveGame", link to some object?
while (esm.isNextSub("FGTN"))
esm.getHString(); // fight target?
// unsure at which point between TGTN and CRED
if (esm.isNextSub("AADT"))
{
// occurred when a creature was in the middle of its attack, 44 bytes
esm.skipHSub();
}
// unsure at which point between FGTN and CHRD
if (esm.isNextSub("PWPC"))
esm.skipHSub();
if (esm.isNextSub("PWPS"))
esm.skipHSub();
if (esm.isNextSub("WNAM"))
{
std::string id = esm.getHString();
if (esm.isNextSub("XNAM"))
mActorData.mSelectedEnchantItem = esm.getHString();
else
mActorData.mSelectedSpell = id;
if (esm.isNextSub("YNAM"))
esm.skipHSub(); // 4 byte, 0
}
while (esm.isNextSub("APUD"))
{
// used power
esm.getSubHeader();
std::string id = esm.getString(32);
(void)id;
// timestamp can't be used: this is the total hours passed, calculated by
// timestamp = 24 * (365 * year + cumulativeDays[month] + day)
// unfortunately cumulativeDays[month] is not clearly defined,
// in the (non-MCP) vanilla version the first month was missing, but MCP added it.
double timestamp;
esm.getT(timestamp);
}
// FIXME: not all actors have this, add flag
if (esm.isNextSub("CHRD")) // npc only
esm.getHExact(mActorData.mSkills, 27*2*sizeof(int));
if (esm.isNextSub("CRED")) // creature only
esm.getHExact(mActorData.mCombatStats, 3*2*sizeof(int));
mActorData.mSCRI.load(esm);
if (esm.isNextSub("ND3D"))
esm.skipHSub();
mActorData.mHasANIS = false;
if (esm.isNextSub("ANIS"))
{
mActorData.mHasANIS = true;
esm.getHT(mActorData.mANIS);
}
if (esm.isNextSub("LVCR"))
{
// occurs on levelled creature spawner references

View file

@ -15,7 +15,7 @@ namespace ESM
namespace ESSImport
{
struct CellRef : public ActorData
struct CellRef : public ESM::CellRef
{
std::string mIndexedRefId;
@ -25,9 +25,11 @@ namespace ESSImport
bool mDeleted;
void load(ESM::ESMReader& esm) override;
ActorData mActorData;
~CellRef() override = default;
void load(ESM::ESMReader& esm);
~CellRef() = default;
};
}

View file

@ -5,17 +5,6 @@
namespace ESSImport
{
void REFR::load(ESM::ESMReader &esm)
{
esm.getHNT(mRefNum.mIndex, "FRMR");
mRefID = esm.getHNString("NAME");
mActorData.load(esm);
esm.getHNOTSized<24>(mPos, "DATA");
}
void PCDT::load(ESM::ESMReader &esm)
{
while (esm.isNextSub("DNAM"))

View file

@ -18,18 +18,6 @@ namespace ESM
namespace ESSImport
{
/// Player-agnostic player data
struct REFR
{
ActorData mActorData;
std::string mRefID;
ESM::Position mPos;
ESM::RefNum mRefNum;
void load(ESM::ESMReader& esm);
};
/// Other player data
struct PCDT
{