forked from teamnwah/openmw-tes3coop
ESS-Importer: Convert ballistic projectiles (Feature #2320)
This commit is contained in:
parent
bd667c3847
commit
6e869c3123
7 changed files with 182 additions and 4 deletions
|
@ -16,6 +16,7 @@ set(ESSIMPORTER_FILES
|
||||||
importjour.cpp
|
importjour.cpp
|
||||||
importscri.cpp
|
importscri.cpp
|
||||||
importscpt.cpp
|
importscpt.cpp
|
||||||
|
importproj.cpp
|
||||||
importercontext.cpp
|
importercontext.cpp
|
||||||
converter.cpp
|
converter.cpp
|
||||||
convertacdt.cpp
|
convertacdt.cpp
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <components/esm/creaturestate.hpp>
|
#include <components/esm/creaturestate.hpp>
|
||||||
#include <components/esm/containerstate.hpp>
|
#include <components/esm/containerstate.hpp>
|
||||||
|
#include <components/esm/projectilestate.hpp>
|
||||||
|
|
||||||
#include "convertcrec.hpp"
|
#include "convertcrec.hpp"
|
||||||
#include "convertcntc.hpp"
|
#include "convertcntc.hpp"
|
||||||
|
@ -53,6 +54,36 @@ namespace
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void splitIndexedRefId(const std::string& indexedRefId, int& refIndex, std::string& refId)
|
||||||
|
{
|
||||||
|
std::stringstream stream;
|
||||||
|
stream << std::hex << indexedRefId.substr(indexedRefId.size()-8,8);
|
||||||
|
stream >> refIndex;
|
||||||
|
|
||||||
|
refId = indexedRefId.substr(0,indexedRefId.size()-8);
|
||||||
|
}
|
||||||
|
|
||||||
|
int convertActorId(const std::string& indexedRefId, ESSImport::Context& context)
|
||||||
|
{
|
||||||
|
if (isIndexedRefId(indexedRefId))
|
||||||
|
{
|
||||||
|
int refIndex;
|
||||||
|
std::string refId;
|
||||||
|
splitIndexedRefId(indexedRefId, refIndex, refId);
|
||||||
|
|
||||||
|
auto it = context.mActorIdMap.find(std::make_pair(refIndex, refId));
|
||||||
|
if (it == context.mActorIdMap.end())
|
||||||
|
return -1;
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
else if (indexedRefId == "PlayerSaveGame")
|
||||||
|
{
|
||||||
|
return context.mPlayer.mObject.mCreatureStats.mActorId;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ESSImport
|
namespace ESSImport
|
||||||
|
@ -322,12 +353,9 @@ namespace ESSImport
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
std::stringstream stream;
|
|
||||||
stream << std::hex << cellref.mIndexedRefId.substr(cellref.mIndexedRefId.size()-8,8);
|
|
||||||
int refIndex;
|
int refIndex;
|
||||||
stream >> refIndex;
|
splitIndexedRefId(cellref.mIndexedRefId, refIndex, out.mRefID);
|
||||||
|
|
||||||
out.mRefID = cellref.mIndexedRefId.substr(0,cellref.mIndexedRefId.size()-8);
|
|
||||||
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
std::string idLower = Misc::StringUtils::lowerCase(out.mRefID);
|
||||||
|
|
||||||
std::map<std::pair<int, std::string>, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find(
|
std::map<std::pair<int, std::string>, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find(
|
||||||
|
@ -347,6 +375,10 @@ namespace ESSImport
|
||||||
convertNpcData(cellref, objstate.mNpcStats);
|
convertNpcData(cellref, objstate.mNpcStats);
|
||||||
convertNPCC(npccIt->second, objstate);
|
convertNPCC(npccIt->second, objstate);
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
|
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||||
|
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||||
|
|
||||||
esm.writeHNT ("OBJE", ESM::REC_NPC_);
|
esm.writeHNT ("OBJE", ESM::REC_NPC_);
|
||||||
objstate.save(esm);
|
objstate.save(esm);
|
||||||
continue;
|
continue;
|
||||||
|
@ -383,6 +415,10 @@ namespace ESSImport
|
||||||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||||
convertCREC(crecIt->second, objstate);
|
convertCREC(crecIt->second, objstate);
|
||||||
convertCellRef(cellref, objstate);
|
convertCellRef(cellref, objstate);
|
||||||
|
|
||||||
|
objstate.mCreatureStats.mActorId = mContext->generateActorId();
|
||||||
|
mContext->mActorIdMap.insert(std::make_pair(std::make_pair(refIndex, out.mRefID), objstate.mCreatureStats.mActorId));
|
||||||
|
|
||||||
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
esm.writeHNT ("OBJE", ESM::REC_CREA);
|
||||||
objstate.save(esm);
|
objstate.save(esm);
|
||||||
continue;
|
continue;
|
||||||
|
@ -413,4 +449,44 @@ namespace ESSImport
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ConvertPROJ::read(ESM::ESMReader& esm)
|
||||||
|
{
|
||||||
|
mProj.load(esm);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ConvertPROJ::write(ESM::ESMWriter& esm)
|
||||||
|
{
|
||||||
|
for (const PROJ::PNAM& pnam : mProj.mProjectiles)
|
||||||
|
{
|
||||||
|
if (!pnam.isMagic())
|
||||||
|
{
|
||||||
|
ESM::ProjectileState out;
|
||||||
|
out.mId = pnam.mArrowId.toString();
|
||||||
|
out.mPosition = pnam.mPosition;
|
||||||
|
out.mOrientation.mValues[0] = out.mOrientation.mValues[1] = out.mOrientation.mValues[2] = 0.0f;
|
||||||
|
out.mOrientation.mValues[3] = 1.0f;
|
||||||
|
out.mActorId = convertActorId(pnam.mActorId.toString(), *mContext);
|
||||||
|
|
||||||
|
out.mBowId = pnam.mBowId.toString();
|
||||||
|
out.mVelocity = pnam.mVelocity;
|
||||||
|
out.mAttackStrength = pnam.mAttackStrength;
|
||||||
|
|
||||||
|
esm.startRecord(ESM::REC_PROJ);
|
||||||
|
out.save(esm);
|
||||||
|
esm.endRecord(ESM::REC_PROJ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// TODO: Implement magic projectile conversion.
|
||||||
|
|
||||||
|
/*esm.startRecord(ESM::REC_MPRJ);
|
||||||
|
out.save(esm);
|
||||||
|
esm.endRecord(ESM::REC_MPRJ);*/
|
||||||
|
|
||||||
|
std::cerr << "Warning: Skipped conversion for magic projectile \"" << pnam.mArrowId.toString() << "\" (not implemented)" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "importques.hpp"
|
#include "importques.hpp"
|
||||||
#include "importjour.hpp"
|
#include "importjour.hpp"
|
||||||
#include "importscpt.hpp"
|
#include "importscpt.hpp"
|
||||||
|
#include "importproj.h"
|
||||||
|
|
||||||
#include "convertacdt.hpp"
|
#include "convertacdt.hpp"
|
||||||
#include "convertnpcc.hpp"
|
#include "convertnpcc.hpp"
|
||||||
|
@ -593,6 +594,17 @@ private:
|
||||||
std::vector<ESM::GlobalScript> mScripts;
|
std::vector<ESM::GlobalScript> mScripts;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Projectile converter
|
||||||
|
class ConvertPROJ : public Converter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual int getStage() override { return 2; }
|
||||||
|
virtual void read(ESM::ESMReader& esm) override;
|
||||||
|
virtual void write(ESM::ESMWriter& esm) override;
|
||||||
|
private:
|
||||||
|
PROJ mProj;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -303,6 +303,7 @@ namespace ESSImport
|
||||||
converters[ESM::REC_QUES] = std::shared_ptr<Converter>(new ConvertQUES());
|
converters[ESM::REC_QUES] = std::shared_ptr<Converter>(new ConvertQUES());
|
||||||
converters[recJOUR ] = std::shared_ptr<Converter>(new ConvertJOUR());
|
converters[recJOUR ] = std::shared_ptr<Converter>(new ConvertJOUR());
|
||||||
converters[ESM::REC_SCPT] = std::shared_ptr<Converter>(new ConvertSCPT());
|
converters[ESM::REC_SCPT] = std::shared_ptr<Converter>(new ConvertSCPT());
|
||||||
|
converters[ESM::REC_PROJ] = std::shared_ptr<Converter>(new ConvertPROJ());
|
||||||
|
|
||||||
// TODO:
|
// TODO:
|
||||||
// - REGN (weather in certain regions?)
|
// - REGN (weather in certain regions?)
|
||||||
|
@ -420,6 +421,19 @@ namespace ESSImport
|
||||||
context.mPlayer.save(writer);
|
context.mPlayer.save(writer);
|
||||||
writer.endRecord(ESM::REC_PLAY);
|
writer.endRecord(ESM::REC_PLAY);
|
||||||
|
|
||||||
|
writer.startRecord(ESM::REC_ACTC);
|
||||||
|
writer.writeHNT("COUN", context.mNextActorId);
|
||||||
|
writer.endRecord(ESM::REC_ACTC);
|
||||||
|
|
||||||
|
// Stage 2 requires cell references to be written / actors IDs assigned
|
||||||
|
for (std::map<unsigned int, std::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
||||||
|
it != converters.end(); ++it)
|
||||||
|
{
|
||||||
|
if (it->second->getStage() != 2)
|
||||||
|
continue;
|
||||||
|
it->second->write(writer);
|
||||||
|
}
|
||||||
|
|
||||||
writer.startRecord (ESM::REC_DIAS);
|
writer.startRecord (ESM::REC_DIAS);
|
||||||
context.mDialogueState.save(writer);
|
context.mDialogueState.save(writer);
|
||||||
writer.endRecord(ESM::REC_DIAS);
|
writer.endRecord(ESM::REC_DIAS);
|
||||||
|
|
|
@ -48,6 +48,9 @@ namespace ESSImport
|
||||||
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
|
std::map<std::pair<int, std::string>, NPCC> mNpcChanges;
|
||||||
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
|
std::map<std::pair<int, std::string>, CNTC> mContainerChanges;
|
||||||
|
|
||||||
|
std::map<std::pair<int, std::string>, int> mActorIdMap;
|
||||||
|
int mNextActorId;
|
||||||
|
|
||||||
std::map<std::string, ESM::Creature> mCreatures;
|
std::map<std::string, ESM::Creature> mCreatures;
|
||||||
std::map<std::string, ESM::NPC> mNpcs;
|
std::map<std::string, ESM::NPC> mNpcs;
|
||||||
|
|
||||||
|
@ -56,6 +59,7 @@ namespace ESSImport
|
||||||
, mMonth(0)
|
, mMonth(0)
|
||||||
, mYear(0)
|
, mYear(0)
|
||||||
, mHour(0.f)
|
, mHour(0.f)
|
||||||
|
, mNextActorId(0)
|
||||||
{
|
{
|
||||||
mPlayer.mAutoMove = 0;
|
mPlayer.mAutoMove = 0;
|
||||||
ESM::CellId playerCellId;
|
ESM::CellId playerCellId;
|
||||||
|
@ -71,12 +75,18 @@ namespace ESSImport
|
||||||
mPlayer.mObject.blank();
|
mPlayer.mObject.blank();
|
||||||
mPlayer.mObject.mEnabled = true;
|
mPlayer.mObject.mEnabled = true;
|
||||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
||||||
|
mPlayer.mObject.mCreatureStats.mActorId = generateActorId();
|
||||||
|
|
||||||
mGlobalMapState.mBounds.mMinX = 0;
|
mGlobalMapState.mBounds.mMinX = 0;
|
||||||
mGlobalMapState.mBounds.mMaxX = 0;
|
mGlobalMapState.mBounds.mMaxX = 0;
|
||||||
mGlobalMapState.mBounds.mMinY = 0;
|
mGlobalMapState.mBounds.mMinY = 0;
|
||||||
mGlobalMapState.mBounds.mMaxY = 0;
|
mGlobalMapState.mBounds.mMaxY = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int generateActorId()
|
||||||
|
{
|
||||||
|
return mNextActorId++;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
18
apps/essimporter/importproj.cpp
Normal file
18
apps/essimporter/importproj.cpp
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
#include "importproj.h"
|
||||||
|
|
||||||
|
#include <components/esm/esmreader.hpp>
|
||||||
|
|
||||||
|
namespace ESSImport
|
||||||
|
{
|
||||||
|
|
||||||
|
void ESSImport::PROJ::load(ESM::ESMReader& esm)
|
||||||
|
{
|
||||||
|
while (esm.isNextSub("PNAM"))
|
||||||
|
{
|
||||||
|
PNAM pnam;
|
||||||
|
esm.getHT(pnam);
|
||||||
|
mProjectiles.push_back(pnam);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
47
apps/essimporter/importproj.h
Normal file
47
apps/essimporter/importproj.h
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
#ifndef OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||||
|
#define OPENMW_ESSIMPORT_IMPORTPROJ_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <components/esm/esmcommon.hpp>
|
||||||
|
#include <components/esm/util.hpp>
|
||||||
|
|
||||||
|
namespace ESM
|
||||||
|
{
|
||||||
|
class ESMReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace ESSImport
|
||||||
|
{
|
||||||
|
|
||||||
|
struct PROJ
|
||||||
|
{
|
||||||
|
|
||||||
|
#pragma pack(push)
|
||||||
|
#pragma pack(1)
|
||||||
|
struct PNAM // 184 bytes
|
||||||
|
{
|
||||||
|
float mAttackStrength;
|
||||||
|
float mSpeed;
|
||||||
|
unsigned char mUnknown[4*2];
|
||||||
|
float mFlightTime;
|
||||||
|
int mSplmIndex; // reference to a SPLM record (0 for ballistic projectiles)
|
||||||
|
unsigned char mUnknown2[4];
|
||||||
|
ESM::Vector3 mVelocity;
|
||||||
|
ESM::Vector3 mPosition;
|
||||||
|
unsigned char mUnknown3[4*9];
|
||||||
|
ESM::NAME32 mActorId; // indexed refID (with the exception of "PlayerSaveGame")
|
||||||
|
ESM::NAME32 mArrowId;
|
||||||
|
ESM::NAME32 mBowId;
|
||||||
|
|
||||||
|
bool isMagic() const { return mSplmIndex != 0; }
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
std::vector<PNAM> mProjectiles;
|
||||||
|
|
||||||
|
void load(ESM::ESMReader& esm);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in a new issue