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
|
||||
importscri.cpp
|
||||
importscpt.cpp
|
||||
importproj.cpp
|
||||
importercontext.cpp
|
||||
converter.cpp
|
||||
convertacdt.cpp
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <components/esm/creaturestate.hpp>
|
||||
#include <components/esm/containerstate.hpp>
|
||||
#include <components/esm/projectilestate.hpp>
|
||||
|
||||
#include "convertcrec.hpp"
|
||||
#include "convertcntc.hpp"
|
||||
|
@ -53,6 +54,36 @@ namespace
|
|||
return true;
|
||||
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
|
||||
|
@ -322,12 +353,9 @@ namespace ESSImport
|
|||
}
|
||||
else
|
||||
{
|
||||
std::stringstream stream;
|
||||
stream << std::hex << cellref.mIndexedRefId.substr(cellref.mIndexedRefId.size()-8,8);
|
||||
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::map<std::pair<int, std::string>, NPCC>::const_iterator npccIt = mContext->mNpcChanges.find(
|
||||
|
@ -347,6 +375,10 @@ namespace ESSImport
|
|||
convertNpcData(cellref, objstate.mNpcStats);
|
||||
convertNPCC(npccIt->second, 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_);
|
||||
objstate.save(esm);
|
||||
continue;
|
||||
|
@ -383,6 +415,10 @@ namespace ESSImport
|
|||
convertACSC(cellref.mACSC, objstate.mCreatureStats);
|
||||
convertCREC(crecIt->second, 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);
|
||||
objstate.save(esm);
|
||||
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 "importjour.hpp"
|
||||
#include "importscpt.hpp"
|
||||
#include "importproj.h"
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
#include "convertnpcc.hpp"
|
||||
|
@ -593,6 +594,17 @@ private:
|
|||
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
|
||||
|
|
|
@ -303,6 +303,7 @@ namespace ESSImport
|
|||
converters[ESM::REC_QUES] = std::shared_ptr<Converter>(new ConvertQUES());
|
||||
converters[recJOUR ] = std::shared_ptr<Converter>(new ConvertJOUR());
|
||||
converters[ESM::REC_SCPT] = std::shared_ptr<Converter>(new ConvertSCPT());
|
||||
converters[ESM::REC_PROJ] = std::shared_ptr<Converter>(new ConvertPROJ());
|
||||
|
||||
// TODO:
|
||||
// - REGN (weather in certain regions?)
|
||||
|
@ -420,6 +421,19 @@ namespace ESSImport
|
|||
context.mPlayer.save(writer);
|
||||
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);
|
||||
context.mDialogueState.save(writer);
|
||||
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>, 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::NPC> mNpcs;
|
||||
|
||||
|
@ -56,6 +59,7 @@ namespace ESSImport
|
|||
, mMonth(0)
|
||||
, mYear(0)
|
||||
, mHour(0.f)
|
||||
, mNextActorId(0)
|
||||
{
|
||||
mPlayer.mAutoMove = 0;
|
||||
ESM::CellId playerCellId;
|
||||
|
@ -71,12 +75,18 @@ namespace ESSImport
|
|||
mPlayer.mObject.blank();
|
||||
mPlayer.mObject.mEnabled = true;
|
||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
||||
mPlayer.mObject.mCreatureStats.mActorId = generateActorId();
|
||||
|
||||
mGlobalMapState.mBounds.mMinX = 0;
|
||||
mGlobalMapState.mBounds.mMaxX = 0;
|
||||
mGlobalMapState.mBounds.mMinY = 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