mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-01-16 19:19:56 +00:00
ESSImport: player is placed in correct cell, npc cellrefs work
This commit is contained in:
parent
c8ed24cc84
commit
08ad4d73bb
27 changed files with 370 additions and 110 deletions
|
@ -5,9 +5,11 @@ set(ESSIMPORTER_FILES
|
|||
importnpcc.cpp
|
||||
importcrec.cpp
|
||||
importcellref.cpp
|
||||
importacdt.hpp
|
||||
importacdt.cpp
|
||||
importercontext.cpp
|
||||
converter.cpp
|
||||
convertacdt.cpp
|
||||
convertnpcc.cpp
|
||||
)
|
||||
|
||||
add_executable(openmw-essimporter
|
||||
|
|
42
apps/essimporter/convertacdt.cpp
Normal file
42
apps/essimporter/convertacdt.cpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
#include "convertacdt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
int translateDynamicIndex(int mwIndex)
|
||||
{
|
||||
if (mwIndex == 1)
|
||||
return 2;
|
||||
else if (mwIndex == 2)
|
||||
return 1;
|
||||
return mwIndex;
|
||||
}
|
||||
|
||||
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats)
|
||||
{
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
int writeIndex = translateDynamicIndex(i);
|
||||
cStats.mDynamic[writeIndex].mBase = acdt.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mMod = acdt.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mCurrent = acdt.mDynamic[i][0];
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
cStats.mAttributes[i].mBase = acdt.mAttributes[i][1];
|
||||
cStats.mAttributes[i].mMod = acdt.mAttributes[i][0];
|
||||
cStats.mAttributes[i].mCurrent = acdt.mAttributes[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats)
|
||||
{
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
npcStats.mSkills[i].mRegular.mMod = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mCurrent = actorData.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mBase = actorData.mSkills[i][0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
apps/essimporter/convertacdt.hpp
Normal file
22
apps/essimporter/convertacdt.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTACDT_H
|
||||
|
||||
#include <components/esm/creaturestats.hpp>
|
||||
#include <components/esm/npcstats.hpp>
|
||||
#include <components/esm/loadskil.hpp>
|
||||
|
||||
#include "importacdt.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
||||
int translateDynamicIndex(int mwIndex);
|
||||
|
||||
|
||||
void convertACDT (const ACDT& acdt, ESM::CreatureStats& cStats);
|
||||
|
||||
void convertNpcData (const ActorData& actorData, ESM::NpcStats& npcStats);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -43,8 +43,15 @@ namespace ESSImport
|
|||
{
|
||||
ESM::Cell cell;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
cell.mName = id;
|
||||
cell.load(esm, false);
|
||||
|
||||
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
|
||||
if (id == mContext->mPlayerCellName)
|
||||
{
|
||||
mContext->mPlayer.mCellId = cell.getCellId();
|
||||
}
|
||||
|
||||
Cell newcell;
|
||||
newcell.mCell = cell;
|
||||
|
||||
|
@ -55,7 +62,12 @@ namespace ESSImport
|
|||
unsigned char nam8[32];
|
||||
if (esm.isNextSub("NAM8"))
|
||||
{
|
||||
esm.getHExact(nam8, 32);
|
||||
esm.getSubHeader();
|
||||
// FIXME: different size in interior cells for some reason
|
||||
if (esm.getSubSize() == 36)
|
||||
esm.skip(4);
|
||||
|
||||
esm.getExact(nam8, 32);
|
||||
|
||||
newcell.mFogOfWar.reserve(16*16);
|
||||
for (int x=0; x<16; ++x)
|
||||
|
@ -87,6 +99,8 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
newcell.mRefs = cellrefs;
|
||||
|
||||
// FIXME: map by ID for exterior cells
|
||||
mCells[id] = newcell;
|
||||
}
|
||||
|
||||
|
@ -127,20 +141,36 @@ namespace ESSImport
|
|||
std::make_pair(refIndex, out.mRefID));
|
||||
if (crecIt != mContext->mCreatureChanges.end())
|
||||
{
|
||||
std::cerr << "Can't' find CREC for " << refIndex << " " << out.mRefID << std::endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
ESM::CreatureState objstate;
|
||||
objstate.mCount = 1;
|
||||
objstate.blank();
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
objstate.mEnabled = cellref.mEnabled;
|
||||
objstate.mHasLocals = 0;
|
||||
objstate.mLocalRotation[0] = objstate.mLocalRotation[1] = objstate.mLocalRotation[2] = 0;
|
||||
objstate.mPosition = cellref.mPos;
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::map<std::pair<int, std::string>, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find(
|
||||
std::make_pair(refIndex, out.mRefID));
|
||||
if (npccIt != mContext->mNpcChanges.end())
|
||||
{
|
||||
ESM::NpcState objstate;
|
||||
objstate.blank();
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
convertNpcData(cellref.mActorData, objstate.mNpcStats);
|
||||
objstate.mEnabled = cellref.mEnabled;
|
||||
objstate.mPosition = cellref.mPos;
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||
esm.writeHNT ("OBJE", ESM::REC_NPC_);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
}
|
||||
|
||||
std::cerr << "Can't find type for " << refIndex << " " << out.mRefID << std::endl;
|
||||
}
|
||||
|
||||
esm.endRecord(ESM::REC_CSTA);
|
||||
|
|
|
@ -14,6 +14,9 @@
|
|||
#include "importercontext.hpp"
|
||||
#include "importcellref.hpp"
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
#include "convertnpcc.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
|
@ -151,9 +154,10 @@ public:
|
|||
npcc.load(esm);
|
||||
if (id == "PlayerSaveGame")
|
||||
{
|
||||
mContext->mPlayer.mObject.mNpcStats.mReputation = npcc.mNPDT.mReputation;
|
||||
convertNPCC(npcc, mContext->mPlayer.mObject);
|
||||
}
|
||||
//mContext->mNpcChanges.insert(std::make_pair(std::make_pair(npcc.mIndex,id), crec));
|
||||
else
|
||||
mContext->mNpcChanges.insert(std::make_pair(std::make_pair(npcc.mIndex,id), npcc));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -168,36 +172,10 @@ public:
|
|||
mContext->mPlayer.mObject.mPosition = refr.mPos;
|
||||
|
||||
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;
|
||||
for (int i=0; i<3; ++i)
|
||||
{
|
||||
int writeIndex = translateDynamicIndex(i);
|
||||
cStats.mDynamic[writeIndex].mBase = refr.mACDT.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mMod = refr.mACDT.mDynamic[i][1];
|
||||
cStats.mDynamic[writeIndex].mCurrent = refr.mACDT.mDynamic[i][0];
|
||||
}
|
||||
for (int i=0; i<8; ++i)
|
||||
{
|
||||
cStats.mAttributes[i].mBase = refr.mACDT.mAttributes[i][1];
|
||||
cStats.mAttributes[i].mMod = refr.mACDT.mAttributes[i][0];
|
||||
cStats.mAttributes[i].mCurrent = refr.mACDT.mAttributes[i][0];
|
||||
}
|
||||
ESM::NpcStats& npcStats = mContext->mPlayer.mObject.mNpcStats;
|
||||
for (int i=0; i<ESM::Skill::Length; ++i)
|
||||
{
|
||||
npcStats.mSkills[i].mRegular.mMod = refr.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mCurrent = refr.mSkills[i][1];
|
||||
npcStats.mSkills[i].mRegular.mBase = refr.mSkills[i][0];
|
||||
}
|
||||
}
|
||||
convertACDT(refr.mActorData.mACDT, cStats);
|
||||
|
||||
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
||||
int translateDynamicIndex(int mwIndex)
|
||||
{
|
||||
if (mwIndex == 1)
|
||||
return 2;
|
||||
else if (mwIndex == 2)
|
||||
return 1;
|
||||
return mwIndex;
|
||||
ESM::NpcStats& npcStats = mContext->mPlayer.mObject.mNpcStats;
|
||||
convertNpcData(refr.mActorData, npcStats);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
22
apps/essimporter/convertnpcc.cpp
Normal file
22
apps/essimporter/convertnpcc.cpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#include "convertnpcc.hpp"
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertNPCC(const NPCC &npcc, ESM::NpcState &npcState)
|
||||
{
|
||||
npcState.mNpcStats.mReputation = npcc.mNPDT.mReputation;
|
||||
|
||||
for (std::vector<NPCC::InventoryItem>::const_iterator it = npcc.mInventory.begin();
|
||||
it != npcc.mInventory.end(); ++it)
|
||||
{
|
||||
ESM::ObjectState obj;
|
||||
obj.blank();
|
||||
obj.mRef.mRefID = it->mId;
|
||||
obj.mRef.mCharge = it->mCondition;
|
||||
|
||||
// Don't know type of object :( change save format?
|
||||
// npcState.mInventory.mItems.push_back(std::make_pair(obj, std::make_pair(0,0)));
|
||||
}
|
||||
}
|
||||
}
|
15
apps/essimporter/convertnpcc.hpp
Normal file
15
apps/essimporter/convertnpcc.hpp
Normal file
|
@ -0,0 +1,15 @@
|
|||
#ifndef OPENMW_ESSIMPORT_CONVERTNPCC_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTNPCC_H
|
||||
|
||||
#include "importnpcc.hpp"
|
||||
|
||||
#include <components/esm/npcstate.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertNPCC (const NPCC& npcc, ESM::NpcState& npcState);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
28
apps/essimporter/importacdt.cpp
Normal file
28
apps/essimporter/importacdt.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#include "importacdt.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void ActorData::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mACDT, "ACDT");
|
||||
|
||||
ACSC acsc;
|
||||
esm.getHNOT(acsc, "ACSC");
|
||||
esm.getHNOT(acsc, "ACSL");
|
||||
|
||||
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));
|
||||
|
||||
mScript = esm.getHNOString("SCRI");
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +1,17 @@
|
|||
#ifndef OPENMW_ESSIMPORT_ACDT_H
|
||||
#define OPENMW_ESSIMPORT_ACDT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
|
||||
/// Actor data, shared by (at least) REFR and CellRef
|
||||
struct ACDT
|
||||
{
|
||||
|
@ -14,6 +22,22 @@ namespace ESSImport
|
|||
unsigned char mUnknown3[120];
|
||||
};
|
||||
|
||||
struct ActorData
|
||||
{
|
||||
ACDT mACDT;
|
||||
|
||||
int mSkills[27][2];
|
||||
|
||||
// creature combat stats, base and modified
|
||||
// I think these can be ignored in the conversion, because it is not possible
|
||||
// to change them ingame
|
||||
int mCombatStats[3][2];
|
||||
|
||||
std::string mScript;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
/// Unknown, shared by (at least) REFR and CellRef
|
||||
struct ACSC
|
||||
{
|
||||
|
|
|
@ -16,22 +16,19 @@ namespace ESSImport
|
|||
|
||||
mIndexedRefId = esm.getHNString("NAME");
|
||||
|
||||
esm.getHNT(mACDT, "ACDT");
|
||||
// the following two occur in ESM::CellRef too (Charge and Gold),
|
||||
// but may have entirely different meanings here
|
||||
int intv;
|
||||
esm.getHNOT(intv, "INTV");
|
||||
int nam9;
|
||||
esm.getHNOT(nam9, "NAM9");
|
||||
|
||||
ACSC acsc;
|
||||
esm.getHNOT(acsc, "ACSC");
|
||||
esm.getHNOT(acsc, "ACSL");
|
||||
|
||||
if (esm.isNextSub("CRED"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
mActorData.load(esm);
|
||||
|
||||
mEnabled = true;
|
||||
esm.getHNOT(mEnabled, "ZNAM");
|
||||
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
esm.getHNT(mPos, "DATA", 24);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@ namespace ESSImport
|
|||
std::string mIndexedRefId;
|
||||
ESM::RefNum mRefNum;
|
||||
|
||||
ACDT mACDT;
|
||||
ActorData mActorData;
|
||||
|
||||
ESM::Position mPos;
|
||||
|
||||
std::string mScript;
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
|
|
|
@ -185,6 +185,9 @@ namespace ESSImport
|
|||
|
||||
Context context;
|
||||
|
||||
const ESM::Header& header = esm.getHeader();
|
||||
context.mPlayerCellName = header.mGameData.mCurrentCell.toString();
|
||||
|
||||
const unsigned int recREFR = ESM::FourCC<'R','E','F','R'>::value;
|
||||
const unsigned int recPCDT = ESM::FourCC<'P','C','D','T'>::value;
|
||||
const unsigned int recFMAP = ESM::FourCC<'F','M','A','P'>::value;
|
||||
|
@ -234,8 +237,6 @@ namespace ESSImport
|
|||
}
|
||||
}
|
||||
|
||||
const ESM::Header& header = esm.getHeader();
|
||||
|
||||
ESM::ESMWriter writer;
|
||||
|
||||
writer.setFormat (ESM::Header::CurrentFormat);
|
||||
|
@ -247,6 +248,11 @@ namespace ESSImport
|
|||
writer.setAuthor("");
|
||||
writer.setDescription("");
|
||||
writer.setRecordCount (0);
|
||||
|
||||
for (std::vector<ESM::Header::MasterData>::const_iterator it = header.mMaster.begin();
|
||||
it != header.mMaster.end(); ++it)
|
||||
writer.addMaster (it->name, 0); // not using the size information anyway -> use value of 0
|
||||
|
||||
writer.save (stream);
|
||||
|
||||
ESM::SavedGame profile;
|
||||
|
@ -298,6 +304,15 @@ namespace ESSImport
|
|||
}
|
||||
|
||||
writer.startRecord(ESM::REC_PLAY);
|
||||
if (context.mPlayer.mCellId.mPaged)
|
||||
{
|
||||
// exterior cell -> determine cell coordinates based on position
|
||||
const int cellSize = 8192;
|
||||
int cellX = std::floor(context.mPlayer.mObject.mPosition.pos[0]/cellSize);
|
||||
int cellY = std::floor(context.mPlayer.mObject.mPosition.pos[1]/cellSize);
|
||||
context.mPlayer.mCellId.mIndex.mX = cellX;
|
||||
context.mPlayer.mCellId.mIndex.mY = cellY;
|
||||
}
|
||||
context.mPlayer.save(writer);
|
||||
writer.endRecord(ESM::REC_PLAY);
|
||||
}
|
||||
|
|
|
@ -17,6 +17,9 @@ namespace ESSImport
|
|||
|
||||
struct Context
|
||||
{
|
||||
// set from the TES3 header
|
||||
std::string mPlayerCellName;
|
||||
|
||||
ESM::Player mPlayer;
|
||||
ESM::NPC mPlayerBase;
|
||||
std::string mCustomPlayerClassName;
|
||||
|
@ -38,33 +41,8 @@ namespace ESSImport
|
|||
//mPlayer.mLastKnownExteriorPosition
|
||||
mPlayer.mHasMark = 0; // TODO
|
||||
mPlayer.mCurrentCrimeId = 0; // TODO
|
||||
mPlayer.mObject.mCount = 1;
|
||||
mPlayer.mObject.mEnabled = 1;
|
||||
mPlayer.mObject.mHasLocals = false;
|
||||
mPlayer.mObject.blank();
|
||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
||||
mPlayer.mObject.mCreatureStats.mHasAiSettings = true;
|
||||
mPlayer.mObject.mCreatureStats.mDead = false;
|
||||
mPlayer.mObject.mCreatureStats.mDied = false;
|
||||
mPlayer.mObject.mCreatureStats.mKnockdown = false;
|
||||
mPlayer.mObject.mCreatureStats.mKnockdownOneFrame = false;
|
||||
mPlayer.mObject.mCreatureStats.mKnockdownOverOneFrame = false;
|
||||
mPlayer.mObject.mCreatureStats.mHitRecovery = false;
|
||||
mPlayer.mObject.mCreatureStats.mBlock = false;
|
||||
mPlayer.mObject.mCreatureStats.mMovementFlags = 0;
|
||||
mPlayer.mObject.mCreatureStats.mAttackStrength = 0.f;
|
||||
mPlayer.mObject.mCreatureStats.mFallHeight = 0.f;
|
||||
mPlayer.mObject.mCreatureStats.mRecalcDynamicStats = false;
|
||||
mPlayer.mObject.mCreatureStats.mDrawState = 0;
|
||||
mPlayer.mObject.mCreatureStats.mDeathAnimation = 0;
|
||||
mPlayer.mObject.mNpcStats.mIsWerewolf = false;
|
||||
mPlayer.mObject.mNpcStats.mTimeToStartDrowning = 20;
|
||||
mPlayer.mObject.mNpcStats.mLevelProgress = 0;
|
||||
mPlayer.mObject.mNpcStats.mDisposition = 0;
|
||||
mPlayer.mObject.mNpcStats.mTimeToStartDrowning = 20;
|
||||
mPlayer.mObject.mNpcStats.mReputation = 0;
|
||||
mPlayer.mObject.mNpcStats.mCrimeId = -1;
|
||||
mPlayer.mObject.mNpcStats.mWerewolfKills = 0;
|
||||
mPlayer.mObject.mNpcStats.mProfit = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -7,12 +7,29 @@ namespace ESSImport
|
|||
|
||||
void NPCC::load(ESM::ESMReader &esm)
|
||||
{
|
||||
mIndex = 0;
|
||||
esm.getHNOT(mIndex, "INDX");
|
||||
|
||||
esm.getHNT(mNPDT, "NPDT");
|
||||
|
||||
// container:
|
||||
// XIDX
|
||||
// XHLT - condition
|
||||
// WIDX - equipping?
|
||||
while (esm.isNextSub("NPCO"))
|
||||
{
|
||||
InventoryItem item;
|
||||
item.mId = esm.getHString();
|
||||
|
||||
if (esm.isNextSub("XIDX"))
|
||||
esm.skipHSub();
|
||||
|
||||
item.mCondition = -1;
|
||||
esm.getHNOT(item.mCondition, "XHLT");
|
||||
mInventory.push_back(item);
|
||||
}
|
||||
|
||||
while (esm.isNextSub("WIDX"))
|
||||
{
|
||||
// equipping?
|
||||
esm.skipHSub();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
#ifndef OPENMW_ESSIMPORT_NPCC_H
|
||||
#define OPENMW_ESSIMPORT_NPCC_H
|
||||
|
||||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/loadcont.hpp>
|
||||
|
||||
namespace ESM
|
||||
|
@ -12,7 +11,7 @@ namespace ESM
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
struct NPCC : public ESM::NPC
|
||||
struct NPCC
|
||||
{
|
||||
struct NPDT
|
||||
{
|
||||
|
@ -21,6 +20,15 @@ namespace ESSImport
|
|||
unsigned char unknown2[5];
|
||||
} mNPDT;
|
||||
|
||||
struct InventoryItem
|
||||
{
|
||||
std::string mId;
|
||||
int mCondition;
|
||||
};
|
||||
std::vector<InventoryItem> mInventory;
|
||||
|
||||
int mIndex;
|
||||
|
||||
void load(ESM::ESMReader &esm);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,16 +14,7 @@ namespace ESSImport
|
|||
if (esm.isNextSub("STPR"))
|
||||
esm.skipHSub(); // ESS TODO
|
||||
|
||||
esm.getHNT(mACDT, "ACDT");
|
||||
|
||||
ACSC acsc;
|
||||
esm.getHNOT(acsc, "ACSC");
|
||||
esm.getHNOT(acsc, "ACSL");
|
||||
|
||||
esm.getHNExact(mSkills, 27*2*sizeof(int), "CHRD");
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub(); // ESS TODO (1 byte)
|
||||
mActorData.load(esm);
|
||||
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
}
|
||||
|
@ -45,6 +36,9 @@ namespace ESSImport
|
|||
if (esm.isNextSub("ENAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("LNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
while (esm.isNextSub("FNAM"))
|
||||
{
|
||||
FNAM fnam;
|
||||
|
|
|
@ -21,15 +21,12 @@ namespace ESSImport
|
|||
/// Player-agnostic player data
|
||||
struct REFR
|
||||
{
|
||||
ACDT mACDT;
|
||||
ActorData mActorData;
|
||||
|
||||
std::string mRefID;
|
||||
ESM::Position mPos;
|
||||
ESM::RefNum mRefNum;
|
||||
|
||||
int mSkills[27][2];
|
||||
float mAttributes[8][2];
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
|
|
|
@ -18,3 +18,9 @@ void ESM::CreatureState::save (ESMWriter &esm, bool inInventory) const
|
|||
|
||||
mCreatureStats.save (esm);
|
||||
}
|
||||
|
||||
void ESM::CreatureState::blank()
|
||||
{
|
||||
ObjectState::blank();
|
||||
mCreatureStats.blank();
|
||||
}
|
||||
|
|
|
@ -14,6 +14,9 @@ namespace ESM
|
|||
InventoryState mInventory;
|
||||
CreatureStats mCreatureStats;
|
||||
|
||||
/// Initialize to default state
|
||||
void blank();
|
||||
|
||||
virtual void load (ESMReader &esm);
|
||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||
};
|
||||
|
|
|
@ -218,6 +218,38 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
|
|||
}
|
||||
|
||||
esm.writeHNT("AISE", mHasAiSettings);
|
||||
if (mHasAiSettings)
|
||||
{
|
||||
for (int i=0; i<4; ++i)
|
||||
mAiSettings[i].save(esm);
|
||||
}
|
||||
}
|
||||
|
||||
void ESM::CreatureStats::blank()
|
||||
{
|
||||
mTradeTime.mHour = 0;
|
||||
mTradeTime.mDay = 0;
|
||||
mGoldPool = 0;
|
||||
mActorId = 0;
|
||||
mHasAiSettings = false;
|
||||
mDead = false;
|
||||
mDied = false;
|
||||
mMurdered = false;
|
||||
mFriendlyHits = 0;
|
||||
mTalkedTo = false;
|
||||
mAlarmed = false;
|
||||
mAttacked = false;
|
||||
mAttackingOrSpell = false;
|
||||
mKnockdown = false;
|
||||
mKnockdownOneFrame = false;
|
||||
mKnockdownOverOneFrame = false;
|
||||
mHitRecovery = false;
|
||||
mBlock = false;
|
||||
mMovementFlags = 0;
|
||||
mAttackStrength = 0.f;
|
||||
mFallHeight = 0.f;
|
||||
mRecalcDynamicStats = false;
|
||||
mDrawState = 0;
|
||||
mDeathAnimation = 0;
|
||||
mLevel = 1;
|
||||
}
|
||||
|
|
|
@ -66,6 +66,9 @@ namespace ESM
|
|||
SpellState mSpells;
|
||||
ActiveSpells mActiveSpells;
|
||||
|
||||
/// Initialize to default state
|
||||
void blank();
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
|
|
@ -22,3 +22,10 @@ void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const
|
|||
|
||||
mCreatureStats.save (esm);
|
||||
}
|
||||
|
||||
void ESM::NpcState::blank()
|
||||
{
|
||||
ObjectState::blank();
|
||||
mNpcStats.blank();
|
||||
mCreatureStats.blank();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,9 @@ namespace ESM
|
|||
NpcStats mNpcStats;
|
||||
CreatureStats mCreatureStats;
|
||||
|
||||
/// Initialize to default state
|
||||
void blank();
|
||||
|
||||
virtual void load (ESMReader &esm);
|
||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||
};
|
||||
|
|
|
@ -150,3 +150,18 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
|||
if (mCrimeId != -1)
|
||||
esm.writeHNT ("CRID", mCrimeId);
|
||||
}
|
||||
|
||||
void ESM::NpcStats::blank()
|
||||
{
|
||||
mIsWerewolf = false;
|
||||
mDisposition = 0;
|
||||
mBounty = 0;
|
||||
mReputation = 0;
|
||||
mWerewolfKills = 0;
|
||||
mProfit = 0;
|
||||
mLevelProgress = 0;
|
||||
for (int i=0; i<8; ++i)
|
||||
mSkillIncrease[i] = 0;
|
||||
mTimeToStartDrowning = 20;
|
||||
mCrimeId = -1;
|
||||
}
|
||||
|
|
|
@ -47,6 +47,9 @@ namespace ESM
|
|||
float mTimeToStartDrowning;
|
||||
int mCrimeId;
|
||||
|
||||
/// Initialize to default state
|
||||
void blank();
|
||||
|
||||
void load (ESMReader &esm);
|
||||
void save (ESMWriter &esm) const;
|
||||
};
|
||||
|
|
|
@ -48,4 +48,18 @@ void ESM::ObjectState::save (ESMWriter &esm, bool inInventory) const
|
|||
}
|
||||
}
|
||||
|
||||
void ESM::ObjectState::blank()
|
||||
{
|
||||
mRef.blank();
|
||||
mHasLocals = 0;
|
||||
mEnabled = false;
|
||||
mCount = 1;
|
||||
for (int i=0;i<3;++i)
|
||||
{
|
||||
mPosition.pos[i] = 0;
|
||||
mPosition.rot[i] = 0;
|
||||
mLocalRotation[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
ESM::ObjectState::~ObjectState() {}
|
|
@ -29,6 +29,9 @@ namespace ESM
|
|||
virtual void load (ESMReader &esm);
|
||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||
|
||||
/// Initialize to default state
|
||||
void blank();
|
||||
|
||||
virtual ~ObjectState();
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue