forked from mirror/openmw-tes3mp
ESSImport: convert script local variables
Had to add special reading code to openmw, because the variable names are not stored.
This commit is contained in:
parent
7d76213374
commit
b1bd236345
10 changed files with 167 additions and 22 deletions
|
@ -23,6 +23,7 @@ set(ESSIMPORTER_FILES
|
|||
convertinventory.cpp
|
||||
convertcrec.cpp
|
||||
convertcntc.cpp
|
||||
convertscri.cpp
|
||||
)
|
||||
|
||||
add_executable(openmw-essimporter
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
|
||||
#include "convertcrec.hpp"
|
||||
#include "convertcntc.hpp"
|
||||
#include "convertscri.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
|
@ -29,6 +30,8 @@ namespace
|
|||
objstate.mRef.mRefNum = cellref.mRefNum;
|
||||
if (cellref.mDeleted)
|
||||
objstate.mCount = 0;
|
||||
convertSCRI(cellref.mSCRI, objstate.mLocals);
|
||||
objstate.mHasLocals = !objstate.mLocals.mVariables.empty();
|
||||
}
|
||||
|
||||
bool isIndexedRefId(const std::string& indexedRefId)
|
||||
|
|
32
apps/essimporter/convertscri.cpp
Normal file
32
apps/essimporter/convertscri.cpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#include "convertscri.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T, ESM::VarType VariantType>
|
||||
void storeVariables(const std::vector<T>& variables, ESM::Locals& locals, const std::string& scriptname)
|
||||
{
|
||||
for (typename std::vector<T>::const_iterator it = variables.begin(); it != variables.end(); ++it)
|
||||
{
|
||||
ESM::Variant val(*it);
|
||||
val.setType(VariantType);
|
||||
locals.mVariables.push_back(std::make_pair(std::string(), val));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void convertSCRI(const SCRI &scri, ESM::Locals &locals)
|
||||
{
|
||||
// order *is* important, as we do not have variable names available in this format
|
||||
storeVariables<short, ESM::VT_Short> (scri.mShorts, locals, scri.mScript);
|
||||
storeVariables<int, ESM::VT_Int> (scri.mLongs, locals, scri.mScript);
|
||||
storeVariables<float, ESM::VT_Float> (scri.mFloats, locals, scri.mScript);
|
||||
}
|
||||
|
||||
}
|
16
apps/essimporter/convertscri.hpp
Normal file
16
apps/essimporter/convertscri.hpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#ifndef OPENMW_ESSIMPORT_CONVERTSCRI_H
|
||||
#define OPENMW_ESSIMPORT_CONVERTSCRI_H
|
||||
|
||||
#include "importscri.hpp"
|
||||
|
||||
#include <components/esm/locals.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Convert script variable assignments
|
||||
void convertSCRI (const SCRI& scri, ESM::Locals& locals);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -237,6 +237,12 @@ namespace ESSImport
|
|||
converters[recJOUR ] = boost::shared_ptr<Converter>(new ConvertJOUR());
|
||||
converters[ESM::REC_SCPT] = boost::shared_ptr<Converter>(new ConvertSCPT());
|
||||
|
||||
// TODO:
|
||||
// - REGN (weather in certain regions?)
|
||||
// - VFXM
|
||||
// - SPLM (active spell effects)
|
||||
// - PROJ (magic projectiles in air)
|
||||
|
||||
std::set<unsigned int> unknownRecords;
|
||||
|
||||
for (std::map<unsigned int, boost::shared_ptr<Converter> >::const_iterator it = converters.begin();
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/scriptmanager.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace MWScript
|
||||
{
|
||||
void Locals::configure (const ESM::Script& script)
|
||||
|
@ -124,27 +126,60 @@ namespace MWScript
|
|||
const Compiler::Locals& declarations =
|
||||
MWBase::Environment::get().getScriptManager()->getLocals(script);
|
||||
|
||||
for (std::vector<std::pair<std::string, ESM::Variant> >::const_iterator iter
|
||||
= locals.mVariables.begin(); iter!=locals.mVariables.end(); ++iter)
|
||||
int index = 0, numshorts = 0, numlongs = 0;
|
||||
for (unsigned int v=0; v<locals.mVariables.size();++v)
|
||||
{
|
||||
char type = declarations.getType (iter->first);
|
||||
char index = declarations.getIndex (iter->first);
|
||||
ESM::VarType type = locals.mVariables[v].second.getType();
|
||||
if (type == ESM::VT_Short)
|
||||
++numshorts;
|
||||
else if (type == ESM::VT_Int)
|
||||
++numlongs;
|
||||
}
|
||||
|
||||
try
|
||||
for (std::vector<std::pair<std::string, ESM::Variant> >::const_iterator iter
|
||||
= locals.mVariables.begin(); iter!=locals.mVariables.end(); ++iter,++index)
|
||||
{
|
||||
if (iter->first.empty())
|
||||
{
|
||||
switch (type)
|
||||
// no variable names available (this will happen for legacy, i.e. ESS-imported savegames only)
|
||||
try
|
||||
{
|
||||
case 's': mShorts.at (index) = iter->second.getInteger(); break;
|
||||
case 'l': mLongs.at (index) = iter->second.getInteger(); break;
|
||||
case 'f': mFloats.at (index) = iter->second.getFloat(); break;
|
||||
|
||||
// silently ignore locals that don't exist anymore
|
||||
if (index >= numshorts+numlongs)
|
||||
mFloats.at(index - (numshorts+numlongs)) = iter->second.getFloat();
|
||||
else if (index >= numshorts)
|
||||
mLongs.at(index - numshorts) = iter->second.getInteger();
|
||||
else
|
||||
mShorts.at(index) = iter->second.getInteger();
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
std::cerr << "Failed to read local variable state for script '"
|
||||
<< script << "' (legacy format): " << e.what()
|
||||
<< "\nNum shorts: " << numshorts << " / " << mShorts.size()
|
||||
<< " Num longs: " << numlongs << " / " << mLongs.size() << std::endl;
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
else
|
||||
{
|
||||
// ignore type changes
|
||||
/// \todo write to log
|
||||
char type = declarations.getType (iter->first);
|
||||
char index = declarations.getIndex (iter->first);
|
||||
|
||||
try
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case 's': mShorts.at (index) = iter->second.getInteger(); break;
|
||||
case 'l': mLongs.at (index) = iter->second.getInteger(); break;
|
||||
case 'f': mFloats.at (index) = iter->second.getFloat(); break;
|
||||
|
||||
// silently ignore locals that don't exist anymore
|
||||
}
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
// ignore type changes
|
||||
/// \todo write to log
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ void ESM::Locals::load (ESMReader &esm)
|
|||
std::string id = esm.getHString();
|
||||
|
||||
Variant value;
|
||||
value.read (esm, Variant::Format_Info);
|
||||
value.read (esm, Variant::Format_Local);
|
||||
|
||||
mVariables.push_back (std::make_pair (id, value));
|
||||
}
|
||||
|
@ -23,6 +23,6 @@ void ESM::Locals::save (ESMWriter &esm) const
|
|||
iter!=mVariables.end(); ++iter)
|
||||
{
|
||||
esm.writeHNString ("LOCA", iter->first);
|
||||
iter->second.write (esm, Variant::Format_Info);
|
||||
iter->second.write (esm, Variant::Format_Local);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ namespace
|
|||
const uint32_t STRV = ESM::FourCC<'S','T','R','V'>::value;
|
||||
const uint32_t INTV = ESM::FourCC<'I','N','T','V'>::value;
|
||||
const uint32_t FLTV = ESM::FourCC<'F','L','T','V'>::value;
|
||||
const uint32_t STTV = ESM::FourCC<'S','T','T','V'>::value;
|
||||
}
|
||||
|
||||
ESM::Variant::Variant() : mType (VT_None), mData (0) {}
|
||||
|
@ -141,7 +142,7 @@ void ESM::Variant::read (ESMReader& esm, Format format)
|
|||
esm.fail ("invalid subrecord: " + name.toString());
|
||||
}
|
||||
}
|
||||
else // info
|
||||
else if (format == Format_Info)
|
||||
{
|
||||
esm.getSubName();
|
||||
NAME name = esm.retSubName();
|
||||
|
@ -157,6 +158,26 @@ void ESM::Variant::read (ESMReader& esm, Format format)
|
|||
else
|
||||
esm.fail ("invalid subrecord: " + name.toString());
|
||||
}
|
||||
else if (format == Format_Local)
|
||||
{
|
||||
esm.getSubName();
|
||||
NAME name = esm.retSubName();
|
||||
|
||||
if (name==INTV)
|
||||
{
|
||||
type = VT_Int;
|
||||
}
|
||||
else if (name==FLTV)
|
||||
{
|
||||
type = VT_Float;
|
||||
}
|
||||
else if (name==STTV)
|
||||
{
|
||||
type = VT_Short;
|
||||
}
|
||||
else
|
||||
esm.fail ("invalid subrecord: " + name.toString());
|
||||
}
|
||||
|
||||
setType (type);
|
||||
|
||||
|
@ -179,6 +200,9 @@ void ESM::Variant::write (ESMWriter& esm, Format format) const
|
|||
if (format==Format_Info)
|
||||
throw std::runtime_error ("can not serialise variant of type none to info format");
|
||||
|
||||
if (format==Format_Local)
|
||||
throw std::runtime_error ("can not serialise variant of type none to local format");
|
||||
|
||||
// nothing to do here for GMST format
|
||||
}
|
||||
else
|
||||
|
|
|
@ -33,7 +33,8 @@ namespace ESM
|
|||
{
|
||||
Format_Global,
|
||||
Format_Gmst,
|
||||
Format_Info // also used for local variables in saved game files
|
||||
Format_Info,
|
||||
Format_Local // local script variables in save game files
|
||||
};
|
||||
|
||||
Variant();
|
||||
|
|
|
@ -81,6 +81,9 @@ void ESM::VariantStringData::read (ESMReader& esm, Variant::Format format, VarTy
|
|||
if (format==Variant::Format_Info)
|
||||
esm.fail ("info variables of type string not supported");
|
||||
|
||||
if (format==Variant::Format_Local)
|
||||
esm.fail ("local variables of type string not supported");
|
||||
|
||||
// GMST
|
||||
mValue = esm.getHString();
|
||||
}
|
||||
|
@ -173,6 +176,21 @@ void ESM::VariantIntegerData::read (ESMReader& esm, Variant::Format format, VarT
|
|||
|
||||
esm.getHT (mValue);
|
||||
}
|
||||
else if (format==Variant::Format_Local)
|
||||
{
|
||||
if (type==VT_Short)
|
||||
{
|
||||
short value;
|
||||
esm.getHT(value);
|
||||
mValue = value;
|
||||
}
|
||||
else if (type==VT_Int)
|
||||
{
|
||||
esm.getHT(mValue);
|
||||
}
|
||||
else
|
||||
esm.fail("unsupported local variable integer type");
|
||||
}
|
||||
}
|
||||
|
||||
void ESM::VariantIntegerData::write (ESMWriter& esm, Variant::Format format, VarType type) const
|
||||
|
@ -204,6 +222,15 @@ void ESM::VariantIntegerData::write (ESMWriter& esm, Variant::Format format, Var
|
|||
|
||||
esm.writeHNT ("INTV", mValue);
|
||||
}
|
||||
else if (format==Variant::Format_Local)
|
||||
{
|
||||
if (type==VT_Short)
|
||||
esm.writeHNT ("STTV", (short)mValue);
|
||||
else if (type == VT_Int)
|
||||
esm.writeHNT ("INTV", mValue);
|
||||
else
|
||||
throw std::runtime_error("unsupported local variable integer type");
|
||||
}
|
||||
}
|
||||
|
||||
bool ESM::VariantIntegerData::isEqual (const VariantDataBase& value) const
|
||||
|
@ -252,7 +279,7 @@ void ESM::VariantFloatData::read (ESMReader& esm, Variant::Format format, VarTyp
|
|||
{
|
||||
esm.getHNT (mValue, "FLTV");
|
||||
}
|
||||
else if (format==Variant::Format_Gmst || format==Variant::Format_Info)
|
||||
else if (format==Variant::Format_Gmst || format==Variant::Format_Info || format==Variant::Format_Local)
|
||||
{
|
||||
esm.getHT (mValue);
|
||||
}
|
||||
|
@ -268,7 +295,7 @@ void ESM::VariantFloatData::write (ESMWriter& esm, Variant::Format format, VarTy
|
|||
esm.writeHNString ("FNAM", "f");
|
||||
esm.writeHNT ("FLTV", mValue);
|
||||
}
|
||||
else if (format==Variant::Format_Gmst || format==Variant::Format_Info)
|
||||
else if (format==Variant::Format_Gmst || format==Variant::Format_Info || format==Variant::Format_Local)
|
||||
{
|
||||
esm.writeHNT ("FLTV", mValue);
|
||||
}
|
||||
|
@ -277,4 +304,4 @@ void ESM::VariantFloatData::write (ESMWriter& esm, Variant::Format format, VarTy
|
|||
bool ESM::VariantFloatData::isEqual (const VariantDataBase& value) const
|
||||
{
|
||||
return dynamic_cast<const VariantFloatData&> (value).mValue==mValue;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue