forked from teamnwah/openmw-tes3coop
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
|
importnpcc.cpp
|
||||||
importcrec.cpp
|
importcrec.cpp
|
||||||
importcellref.cpp
|
importcellref.cpp
|
||||||
importacdt.hpp
|
importacdt.cpp
|
||||||
importercontext.cpp
|
importercontext.cpp
|
||||||
converter.cpp
|
converter.cpp
|
||||||
|
convertacdt.cpp
|
||||||
|
convertnpcc.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(openmw-essimporter
|
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;
|
ESM::Cell cell;
|
||||||
std::string id = esm.getHNString("NAME");
|
std::string id = esm.getHNString("NAME");
|
||||||
|
cell.mName = id;
|
||||||
cell.load(esm, false);
|
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;
|
Cell newcell;
|
||||||
newcell.mCell = cell;
|
newcell.mCell = cell;
|
||||||
|
|
||||||
|
@ -55,7 +62,12 @@ namespace ESSImport
|
||||||
unsigned char nam8[32];
|
unsigned char nam8[32];
|
||||||
if (esm.isNextSub("NAM8"))
|
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);
|
newcell.mFogOfWar.reserve(16*16);
|
||||||
for (int x=0; x<16; ++x)
|
for (int x=0; x<16; ++x)
|
||||||
|
@ -87,6 +99,8 @@ namespace ESSImport
|
||||||
}
|
}
|
||||||
|
|
||||||
newcell.mRefs = cellrefs;
|
newcell.mRefs = cellrefs;
|
||||||
|
|
||||||
|
// FIXME: map by ID for exterior cells
|
||||||
mCells[id] = newcell;
|
mCells[id] = newcell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,20 +141,36 @@ namespace ESSImport
|
||||||
std::make_pair(refIndex, out.mRefID));
|
std::make_pair(refIndex, out.mRefID));
|
||||||
if (crecIt != mContext->mCreatureChanges.end())
|
if (crecIt != mContext->mCreatureChanges.end())
|
||||||
{
|
{
|
||||||
std::cerr << "Can't' find CREC for " << refIndex << " " << out.mRefID << std::endl;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
ESM::CreatureState objstate;
|
ESM::CreatureState objstate;
|
||||||
objstate.mCount = 1;
|
objstate.blank();
|
||||||
|
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||||
objstate.mEnabled = cellref.mEnabled;
|
objstate.mEnabled = cellref.mEnabled;
|
||||||
objstate.mHasLocals = 0;
|
|
||||||
objstate.mLocalRotation[0] = objstate.mLocalRotation[1] = objstate.mLocalRotation[2] = 0;
|
|
||||||
objstate.mPosition = cellref.mPos;
|
objstate.mPosition = cellref.mPos;
|
||||||
objstate.mRef = out;
|
objstate.mRef = out;
|
||||||
objstate.mRef.mRefNum = cellref.mRefNum;
|
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||||
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
||||||
objstate.save(esm);
|
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);
|
esm.endRecord(ESM::REC_CSTA);
|
||||||
|
|
|
@ -14,6 +14,9 @@
|
||||||
#include "importercontext.hpp"
|
#include "importercontext.hpp"
|
||||||
#include "importcellref.hpp"
|
#include "importcellref.hpp"
|
||||||
|
|
||||||
|
#include "convertacdt.hpp"
|
||||||
|
#include "convertnpcc.hpp"
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -151,9 +154,10 @@ public:
|
||||||
npcc.load(esm);
|
npcc.load(esm);
|
||||||
if (id == "PlayerSaveGame")
|
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;
|
mContext->mPlayer.mObject.mPosition = refr.mPos;
|
||||||
|
|
||||||
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;
|
ESM::CreatureStats& cStats = mContext->mPlayer.mObject.mCreatureStats;
|
||||||
for (int i=0; i<3; ++i)
|
convertACDT(refr.mActorData.mACDT, cStats);
|
||||||
{
|
|
||||||
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];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// OpenMW uses Health,Magicka,Fatigue, MW uses Health,Fatigue,Magicka
|
ESM::NpcStats& npcStats = mContext->mPlayer.mObject.mNpcStats;
|
||||||
int translateDynamicIndex(int mwIndex)
|
convertNpcData(refr.mActorData, npcStats);
|
||||||
{
|
|
||||||
if (mwIndex == 1)
|
|
||||||
return 2;
|
|
||||||
else if (mwIndex == 2)
|
|
||||||
return 1;
|
|
||||||
return mwIndex;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
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
|
#ifndef OPENMW_ESSIMPORT_ACDT_H
|
||||||
#define OPENMW_ESSIMPORT_ACDT_H
|
#define OPENMW_ESSIMPORT_ACDT_H
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
struct ESMReader;
|
||||||
|
}
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/// Actor data, shared by (at least) REFR and CellRef
|
/// Actor data, shared by (at least) REFR and CellRef
|
||||||
struct ACDT
|
struct ACDT
|
||||||
{
|
{
|
||||||
|
@ -14,6 +22,22 @@ namespace ESSImport
|
||||||
unsigned char mUnknown3[120];
|
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
|
/// Unknown, shared by (at least) REFR and CellRef
|
||||||
struct ACSC
|
struct ACSC
|
||||||
{
|
{
|
||||||
|
|
|
@ -16,22 +16,19 @@ namespace ESSImport
|
||||||
|
|
||||||
mIndexedRefId = esm.getHNString("NAME");
|
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;
|
mActorData.load(esm);
|
||||||
esm.getHNOT(acsc, "ACSC");
|
|
||||||
esm.getHNOT(acsc, "ACSL");
|
|
||||||
|
|
||||||
if (esm.isNextSub("CRED"))
|
|
||||||
esm.skipHSub();
|
|
||||||
|
|
||||||
if (esm.isNextSub("ND3D"))
|
|
||||||
esm.skipHSub();
|
|
||||||
|
|
||||||
mEnabled = true;
|
mEnabled = true;
|
||||||
esm.getHNOT(mEnabled, "ZNAM");
|
esm.getHNOT(mEnabled, "ZNAM");
|
||||||
|
|
||||||
esm.getHNOT(mPos, "DATA", 24);
|
esm.getHNT(mPos, "DATA", 24);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,10 +21,12 @@ namespace ESSImport
|
||||||
std::string mIndexedRefId;
|
std::string mIndexedRefId;
|
||||||
ESM::RefNum mRefNum;
|
ESM::RefNum mRefNum;
|
||||||
|
|
||||||
ACDT mACDT;
|
ActorData mActorData;
|
||||||
|
|
||||||
ESM::Position mPos;
|
ESM::Position mPos;
|
||||||
|
|
||||||
|
std::string mScript;
|
||||||
|
|
||||||
bool mEnabled;
|
bool mEnabled;
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm);
|
void load(ESM::ESMReader& esm);
|
||||||
|
|
|
@ -185,6 +185,9 @@ namespace ESSImport
|
||||||
|
|
||||||
Context context;
|
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 recREFR = ESM::FourCC<'R','E','F','R'>::value;
|
||||||
const unsigned int recPCDT = ESM::FourCC<'P','C','D','T'>::value;
|
const unsigned int recPCDT = ESM::FourCC<'P','C','D','T'>::value;
|
||||||
const unsigned int recFMAP = ESM::FourCC<'F','M','A','P'>::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;
|
ESM::ESMWriter writer;
|
||||||
|
|
||||||
writer.setFormat (ESM::Header::CurrentFormat);
|
writer.setFormat (ESM::Header::CurrentFormat);
|
||||||
|
@ -247,6 +248,11 @@ namespace ESSImport
|
||||||
writer.setAuthor("");
|
writer.setAuthor("");
|
||||||
writer.setDescription("");
|
writer.setDescription("");
|
||||||
writer.setRecordCount (0);
|
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);
|
writer.save (stream);
|
||||||
|
|
||||||
ESM::SavedGame profile;
|
ESM::SavedGame profile;
|
||||||
|
@ -298,6 +304,15 @@ namespace ESSImport
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.startRecord(ESM::REC_PLAY);
|
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);
|
context.mPlayer.save(writer);
|
||||||
writer.endRecord(ESM::REC_PLAY);
|
writer.endRecord(ESM::REC_PLAY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,9 @@ namespace ESSImport
|
||||||
|
|
||||||
struct Context
|
struct Context
|
||||||
{
|
{
|
||||||
|
// set from the TES3 header
|
||||||
|
std::string mPlayerCellName;
|
||||||
|
|
||||||
ESM::Player mPlayer;
|
ESM::Player mPlayer;
|
||||||
ESM::NPC mPlayerBase;
|
ESM::NPC mPlayerBase;
|
||||||
std::string mCustomPlayerClassName;
|
std::string mCustomPlayerClassName;
|
||||||
|
@ -38,33 +41,8 @@ namespace ESSImport
|
||||||
//mPlayer.mLastKnownExteriorPosition
|
//mPlayer.mLastKnownExteriorPosition
|
||||||
mPlayer.mHasMark = 0; // TODO
|
mPlayer.mHasMark = 0; // TODO
|
||||||
mPlayer.mCurrentCrimeId = 0; // TODO
|
mPlayer.mCurrentCrimeId = 0; // TODO
|
||||||
mPlayer.mObject.mCount = 1;
|
mPlayer.mObject.blank();
|
||||||
mPlayer.mObject.mEnabled = 1;
|
|
||||||
mPlayer.mObject.mHasLocals = false;
|
|
||||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
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)
|
void NPCC::load(ESM::ESMReader &esm)
|
||||||
{
|
{
|
||||||
|
mIndex = 0;
|
||||||
|
esm.getHNOT(mIndex, "INDX");
|
||||||
|
|
||||||
esm.getHNT(mNPDT, "NPDT");
|
esm.getHNT(mNPDT, "NPDT");
|
||||||
|
|
||||||
// container:
|
while (esm.isNextSub("NPCO"))
|
||||||
// XIDX
|
{
|
||||||
// XHLT - condition
|
InventoryItem item;
|
||||||
// WIDX - equipping?
|
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
|
#ifndef OPENMW_ESSIMPORT_NPCC_H
|
||||||
#define OPENMW_ESSIMPORT_NPCC_H
|
#define OPENMW_ESSIMPORT_NPCC_H
|
||||||
|
|
||||||
#include <components/esm/loadnpc.hpp>
|
|
||||||
#include <components/esm/loadcont.hpp>
|
#include <components/esm/loadcont.hpp>
|
||||||
|
|
||||||
namespace ESM
|
namespace ESM
|
||||||
|
@ -12,7 +11,7 @@ namespace ESM
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
{
|
{
|
||||||
|
|
||||||
struct NPCC : public ESM::NPC
|
struct NPCC
|
||||||
{
|
{
|
||||||
struct NPDT
|
struct NPDT
|
||||||
{
|
{
|
||||||
|
@ -21,6 +20,15 @@ namespace ESSImport
|
||||||
unsigned char unknown2[5];
|
unsigned char unknown2[5];
|
||||||
} mNPDT;
|
} mNPDT;
|
||||||
|
|
||||||
|
struct InventoryItem
|
||||||
|
{
|
||||||
|
std::string mId;
|
||||||
|
int mCondition;
|
||||||
|
};
|
||||||
|
std::vector<InventoryItem> mInventory;
|
||||||
|
|
||||||
|
int mIndex;
|
||||||
|
|
||||||
void load(ESM::ESMReader &esm);
|
void load(ESM::ESMReader &esm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,7 @@ namespace ESSImport
|
||||||
if (esm.isNextSub("STPR"))
|
if (esm.isNextSub("STPR"))
|
||||||
esm.skipHSub(); // ESS TODO
|
esm.skipHSub(); // ESS TODO
|
||||||
|
|
||||||
esm.getHNT(mACDT, "ACDT");
|
mActorData.load(esm);
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
esm.getHNOT(mPos, "DATA", 24);
|
esm.getHNOT(mPos, "DATA", 24);
|
||||||
}
|
}
|
||||||
|
@ -45,6 +36,9 @@ namespace ESSImport
|
||||||
if (esm.isNextSub("ENAM"))
|
if (esm.isNextSub("ENAM"))
|
||||||
esm.skipHSub();
|
esm.skipHSub();
|
||||||
|
|
||||||
|
if (esm.isNextSub("LNAM"))
|
||||||
|
esm.skipHSub();
|
||||||
|
|
||||||
while (esm.isNextSub("FNAM"))
|
while (esm.isNextSub("FNAM"))
|
||||||
{
|
{
|
||||||
FNAM fnam;
|
FNAM fnam;
|
||||||
|
|
|
@ -21,15 +21,12 @@ namespace ESSImport
|
||||||
/// Player-agnostic player data
|
/// Player-agnostic player data
|
||||||
struct REFR
|
struct REFR
|
||||||
{
|
{
|
||||||
ACDT mACDT;
|
ActorData mActorData;
|
||||||
|
|
||||||
std::string mRefID;
|
std::string mRefID;
|
||||||
ESM::Position mPos;
|
ESM::Position mPos;
|
||||||
ESM::RefNum mRefNum;
|
ESM::RefNum mRefNum;
|
||||||
|
|
||||||
int mSkills[27][2];
|
|
||||||
float mAttributes[8][2];
|
|
||||||
|
|
||||||
void load(ESM::ESMReader& esm);
|
void load(ESM::ESMReader& esm);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -18,3 +18,9 @@ void ESM::CreatureState::save (ESMWriter &esm, bool inInventory) const
|
||||||
|
|
||||||
mCreatureStats.save (esm);
|
mCreatureStats.save (esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ESM::CreatureState::blank()
|
||||||
|
{
|
||||||
|
ObjectState::blank();
|
||||||
|
mCreatureStats.blank();
|
||||||
|
}
|
||||||
|
|
|
@ -14,6 +14,9 @@ namespace ESM
|
||||||
InventoryState mInventory;
|
InventoryState mInventory;
|
||||||
CreatureStats mCreatureStats;
|
CreatureStats mCreatureStats;
|
||||||
|
|
||||||
|
/// Initialize to default state
|
||||||
|
void blank();
|
||||||
|
|
||||||
virtual void load (ESMReader &esm);
|
virtual void load (ESMReader &esm);
|
||||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -218,6 +218,38 @@ void ESM::CreatureStats::save (ESMWriter &esm) const
|
||||||
}
|
}
|
||||||
|
|
||||||
esm.writeHNT("AISE", mHasAiSettings);
|
esm.writeHNT("AISE", mHasAiSettings);
|
||||||
|
if (mHasAiSettings)
|
||||||
|
{
|
||||||
for (int i=0; i<4; ++i)
|
for (int i=0; i<4; ++i)
|
||||||
mAiSettings[i].save(esm);
|
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;
|
SpellState mSpells;
|
||||||
ActiveSpells mActiveSpells;
|
ActiveSpells mActiveSpells;
|
||||||
|
|
||||||
|
/// Initialize to default state
|
||||||
|
void blank();
|
||||||
|
|
||||||
void load (ESMReader &esm);
|
void load (ESMReader &esm);
|
||||||
void save (ESMWriter &esm) const;
|
void save (ESMWriter &esm) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -22,3 +22,10 @@ void ESM::NpcState::save (ESMWriter &esm, bool inInventory) const
|
||||||
|
|
||||||
mCreatureStats.save (esm);
|
mCreatureStats.save (esm);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ESM::NpcState::blank()
|
||||||
|
{
|
||||||
|
ObjectState::blank();
|
||||||
|
mNpcStats.blank();
|
||||||
|
mCreatureStats.blank();
|
||||||
|
}
|
||||||
|
|
|
@ -16,6 +16,9 @@ namespace ESM
|
||||||
NpcStats mNpcStats;
|
NpcStats mNpcStats;
|
||||||
CreatureStats mCreatureStats;
|
CreatureStats mCreatureStats;
|
||||||
|
|
||||||
|
/// Initialize to default state
|
||||||
|
void blank();
|
||||||
|
|
||||||
virtual void load (ESMReader &esm);
|
virtual void load (ESMReader &esm);
|
||||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -150,3 +150,18 @@ void ESM::NpcStats::save (ESMWriter &esm) const
|
||||||
if (mCrimeId != -1)
|
if (mCrimeId != -1)
|
||||||
esm.writeHNT ("CRID", mCrimeId);
|
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;
|
float mTimeToStartDrowning;
|
||||||
int mCrimeId;
|
int mCrimeId;
|
||||||
|
|
||||||
|
/// Initialize to default state
|
||||||
|
void blank();
|
||||||
|
|
||||||
void load (ESMReader &esm);
|
void load (ESMReader &esm);
|
||||||
void save (ESMWriter &esm) const;
|
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() {}
|
ESM::ObjectState::~ObjectState() {}
|
|
@ -29,6 +29,9 @@ namespace ESM
|
||||||
virtual void load (ESMReader &esm);
|
virtual void load (ESMReader &esm);
|
||||||
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
virtual void save (ESMWriter &esm, bool inInventory = false) const;
|
||||||
|
|
||||||
|
/// Initialize to default state
|
||||||
|
void blank();
|
||||||
|
|
||||||
virtual ~ObjectState();
|
virtual ~ObjectState();
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue