Merge pull request #1453 from MiroslavR/convertproj

ESS-Importer: Convert ballistic projectiles
This commit is contained in:
scrawl 2017-09-15 20:53:08 +00:00 committed by GitHub
commit 820e0e9195
7 changed files with 184 additions and 5 deletions

View file

@ -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

View file

@ -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;
}
}
}
} }

View file

@ -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

View file

@ -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);

View file

@ -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;
@ -67,16 +71,23 @@ namespace ESSImport
= mPlayer.mLastKnownExteriorPosition[2] = mPlayer.mLastKnownExteriorPosition[2]
= 0.0f; = 0.0f;
mPlayer.mHasMark = 0; mPlayer.mHasMark = 0;
mPlayer.mCurrentCrimeId = 0; // TODO mPlayer.mCurrentCrimeId = -1; // TODO
mPlayer.mPaidCrimeId = -1;
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++;
}
}; };
} }

View 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);
}
}
}

View 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