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:
parent
79cdc08253
commit
9f49682d01
9 changed files with 144 additions and 189 deletions
|
@ -5,7 +5,6 @@ set(ESSIMPORTER_FILES
|
||||||
importnpcc.cpp
|
importnpcc.cpp
|
||||||
importcrec.cpp
|
importcrec.cpp
|
||||||
importcellref.cpp
|
importcellref.cpp
|
||||||
importacdt.cpp
|
|
||||||
importinventory.cpp
|
importinventory.cpp
|
||||||
importklst.cpp
|
importklst.cpp
|
||||||
importcntc.cpp
|
importcntc.cpp
|
||||||
|
|
|
@ -35,11 +35,11 @@ namespace
|
||||||
objstate.mRef.mRefNum = cellref.mRefNum;
|
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||||
if (cellref.mDeleted)
|
if (cellref.mDeleted)
|
||||||
objstate.mCount = 0;
|
objstate.mCount = 0;
|
||||||
convertSCRI(cellref.mSCRI, objstate.mLocals);
|
convertSCRI(cellref.mActorData.mSCRI, objstate.mLocals);
|
||||||
objstate.mHasLocals = !objstate.mLocals.mVariables.empty();
|
objstate.mHasLocals = !objstate.mLocals.mVariables.empty();
|
||||||
|
|
||||||
if (cellref.mHasANIS)
|
if (cellref.mActorData.mHasANIS)
|
||||||
convertANIS(cellref.mANIS, objstate.mAnimationState);
|
convertANIS(cellref.mActorData.mANIS, objstate.mAnimationState);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isIndexedRefId(const std::string& indexedRefId)
|
bool isIndexedRefId(const std::string& indexedRefId)
|
||||||
|
@ -268,7 +268,7 @@ namespace ESSImport
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CellRef> cellrefs;
|
std::vector<CellRef> cellrefs;
|
||||||
while (esm.hasMoreSubs() && esm.isNextSub("FRMR"))
|
while (esm.hasMoreSubs() && esm.peekNextSub("FRMR"))
|
||||||
{
|
{
|
||||||
CellRef ref;
|
CellRef ref;
|
||||||
ref.load (esm);
|
ref.load (esm);
|
||||||
|
@ -369,13 +369,13 @@ namespace ESSImport
|
||||||
objstate.mRef.mRefID = idLower;
|
objstate.mRef.mRefID = idLower;
|
||||||
// TODO: need more micromanagement here so we don't overwrite values
|
// TODO: need more micromanagement here so we don't overwrite values
|
||||||
// from the ESM with default values
|
// from the ESM with default values
|
||||||
if (cellref.mHasACDT)
|
if (cellref.mActorData.mHasACDT)
|
||||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||||
else
|
else
|
||||||
objstate.mCreatureStats.mMissingACDT = true;
|
objstate.mCreatureStats.mMissingACDT = true;
|
||||||
if (cellref.mHasACSC)
|
if (cellref.mActorData.mHasACSC)
|
||||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
|
||||||
convertNpcData(cellref, objstate.mNpcStats);
|
convertNpcData(cellref.mActorData, objstate.mNpcStats);
|
||||||
convertNPCC(npccIt->second, objstate);
|
convertNPCC(npccIt->second, objstate);
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
|
@ -412,12 +412,12 @@ namespace ESSImport
|
||||||
objstate.mRef.mRefID = idLower;
|
objstate.mRef.mRefID = idLower;
|
||||||
// TODO: need more micromanagement here so we don't overwrite values
|
// TODO: need more micromanagement here so we don't overwrite values
|
||||||
// from the ESM with default values
|
// from the ESM with default values
|
||||||
if (cellref.mHasACDT)
|
if (cellref.mActorData.mHasACDT)
|
||||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||||
else
|
else
|
||||||
objstate.mCreatureStats.mMissingACDT = true;
|
objstate.mCreatureStats.mMissingACDT = true;
|
||||||
if (cellref.mHasACSC)
|
if (cellref.mActorData.mHasACSC)
|
||||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
convertACSC(cellref.mActorData.mACSC, objstate.mCreatureStats);
|
||||||
convertCREC(crecIt->second, objstate);
|
convertCREC(crecIt->second, objstate);
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
|
|
|
@ -235,9 +235,9 @@ class ConvertREFR : public Converter
|
||||||
public:
|
public:
|
||||||
void read(ESM::ESMReader &esm) override
|
void read(ESM::ESMReader &esm) override
|
||||||
{
|
{
|
||||||
REFR refr;
|
CellRef refr;
|
||||||
refr.load(esm);
|
refr.load(esm);
|
||||||
assert(refr.mRefID == "PlayerSaveGame");
|
assert(refr.mIndexedRefID == "PlayerSaveGame");
|
||||||
mContext->mPlayer.mObject.mPosition = refr.mPos;
|
mContext->mPlayer.mObject.mPosition = refr.mPos;
|
||||||
|
|
||||||
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;
|
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -3,8 +3,6 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include <components/esm3/cellref.hpp>
|
|
||||||
|
|
||||||
#include "importscri.hpp"
|
#include "importscri.hpp"
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -63,7 +61,7 @@ namespace ESSImport
|
||||||
};
|
};
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct ActorData : public ESM::CellRef
|
struct ActorData
|
||||||
{
|
{
|
||||||
bool mHasACDT;
|
bool mHasACDT;
|
||||||
ACDT mACDT;
|
ACDT mACDT;
|
||||||
|
@ -85,10 +83,6 @@ namespace ESSImport
|
||||||
|
|
||||||
bool mHasANIS;
|
bool mHasANIS;
|
||||||
ANIS mANIS; // scripted animation state
|
ANIS mANIS; // scripted animation state
|
||||||
|
|
||||||
virtual void load(ESM::ESMReader& esm);
|
|
||||||
|
|
||||||
virtual ~ActorData() = default;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,7 @@ namespace ESSImport
|
||||||
{
|
{
|
||||||
blank();
|
blank();
|
||||||
|
|
||||||
// (FRMR subrecord name is already read by the loop in ConvertCell)
|
esm.getHNT(mRefNum.mIndex, "FRMR");
|
||||||
esm.getHT(mRefNum.mIndex); // FRMR
|
|
||||||
|
|
||||||
// this is required since openmw supports more than 255 content files
|
// this is required since openmw supports more than 255 content files
|
||||||
int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24;
|
int pluginIndex = (mRefNum.mIndex & 0xff000000) >> 24;
|
||||||
|
@ -19,7 +18,128 @@ namespace ESSImport
|
||||||
|
|
||||||
mIndexedRefId = esm.getHNString("NAME");
|
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"))
|
if (esm.isNextSub("LVCR"))
|
||||||
{
|
{
|
||||||
// occurs on levelled creature spawner references
|
// occurs on levelled creature spawner references
|
||||||
|
|
|
@ -15,7 +15,7 @@ namespace ESM
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
struct CellRef : public ActorData
|
struct CellRef : public ESM::CellRef
|
||||||
{
|
{
|
||||||
std::string mIndexedRefId;
|
std::string mIndexedRefId;
|
||||||
|
|
||||||
|
@ -25,9 +25,11 @@ namespace ESSImport
|
||||||
|
|
||||||
bool mDeleted;
|
bool mDeleted;
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm) override;
|
ActorData mActorData;
|
||||||
|
|
||||||
~CellRef() override = default;
|
void load(ESM::ESMReader& esm);
|
||||||
|
|
||||||
|
~CellRef() = default;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,17 +5,6 @@
|
||||||
namespace ESSImport
|
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)
|
void PCDT::load(ESM::ESMReader &esm)
|
||||||
{
|
{
|
||||||
while (esm.isNextSub("DNAM"))
|
while (esm.isNextSub("DNAM"))
|
||||||
|
|
|
@ -18,18 +18,6 @@ namespace ESM
|
||||||
namespace ESSImport
|
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
|
/// Other player data
|
||||||
struct PCDT
|
struct PCDT
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue