forked from mirror/openmw-tes3mp
Merge remote-tracking branch 'scrawl/master'
This commit is contained in:
commit
b44fc1904b
112 changed files with 1158 additions and 469 deletions
|
@ -51,6 +51,8 @@ option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binarie
|
|||
option(BOOST_STATIC "Link static build of Boost into the binaries" FALSE)
|
||||
option(SDL2_STATIC "Link static build of SDL into the binaries" FALSE)
|
||||
|
||||
set(CUSTOM_OGRE_PLUGIN_DIR "" CACHE PATH "Specify a custom directory for Ogre plugins (autodetected by default)")
|
||||
|
||||
option(OPENMW_UNITY_BUILD "Use fewer compilation units to speed up compile time" FALSE)
|
||||
|
||||
# Apps and tools
|
||||
|
@ -323,8 +325,10 @@ if (APPLE AND OPENMW_OSX_DEPLOYMENT)
|
|||
# make it empty so plugin loading code can check this and try to find plugins inside app bundle
|
||||
add_definitions(-DOGRE_PLUGIN_DIR="")
|
||||
else()
|
||||
if (NOT DEFINED ${OGRE_PLUGIN_DIR})
|
||||
if (CUSTOM_OGRE_PLUGIN_DIR STREQUAL "")
|
||||
set(OGRE_PLUGIN_DIR ${OGRE_PLUGIN_DIR_REL})
|
||||
else()
|
||||
set(OGRE_PLUGIN_DIR ${CUSTOM_OGRE_PLUGIN_DIR})
|
||||
endif()
|
||||
|
||||
add_definitions(-DOGRE_PLUGIN_DIR="${OGRE_PLUGIN_DIR}")
|
||||
|
|
|
@ -27,8 +27,8 @@ struct Arguments
|
|||
|
||||
void replaceAll(std::string& str, const std::string& needle, const std::string& substitute)
|
||||
{
|
||||
int pos = str.find(needle);
|
||||
while(pos != -1)
|
||||
size_t pos = str.find(needle);
|
||||
while(pos != std::string::npos)
|
||||
{
|
||||
str.replace(pos, needle.size(), substitute);
|
||||
pos = str.find(needle);
|
||||
|
@ -138,8 +138,8 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||
else if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||
info.outdir = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||
|
||||
info.longformat = variables.count("long");
|
||||
info.fullpath = variables.count("full-path");
|
||||
info.longformat = variables.count("long") != 0;
|
||||
info.fullpath = variables.count("full-path") != 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ struct ESMData
|
|||
{
|
||||
std::string author;
|
||||
std::string description;
|
||||
int version;
|
||||
unsigned int version;
|
||||
std::vector<ESM::Header::MasterData> masters;
|
||||
|
||||
std::deque<EsmTool::RecordBase *> mRecords;
|
||||
|
@ -48,9 +48,9 @@ const std::set<int> ESMData::sLabeledRec =
|
|||
// Based on the legacy struct
|
||||
struct Arguments
|
||||
{
|
||||
unsigned int raw_given;
|
||||
unsigned int quiet_given;
|
||||
unsigned int loadcells_given;
|
||||
bool raw_given;
|
||||
bool quiet_given;
|
||||
bool loadcells_given;
|
||||
bool plain_given;
|
||||
|
||||
std::string mode;
|
||||
|
@ -177,10 +177,10 @@ bool parseOptions (int argc, char** argv, Arguments &info)
|
|||
if (variables["input-file"].as< std::vector<std::string> >().size() > 1)
|
||||
info.outname = variables["input-file"].as< std::vector<std::string> >()[1];
|
||||
|
||||
info.raw_given = variables.count ("raw");
|
||||
info.quiet_given = variables.count ("quiet");
|
||||
info.loadcells_given = variables.count ("loadcells");
|
||||
info.plain_given = (variables.count("plain") > 0);
|
||||
info.raw_given = variables.count ("raw") != 0;
|
||||
info.quiet_given = variables.count ("quiet") != 0;
|
||||
info.loadcells_given = variables.count ("loadcells") != 0;
|
||||
info.plain_given = variables.count("plain") != 0;
|
||||
|
||||
// Font encoding settings
|
||||
info.encoding = variables["encoding"].as<std::string>();
|
||||
|
@ -261,7 +261,7 @@ void loadCell(ESM::Cell &cell, ESM::ESMReader &esm, Arguments& info)
|
|||
std::cout << " Faction: '" << ref.mFaction << "'" << std::endl;
|
||||
std::cout << " Faction rank: '" << ref.mFactionRank << "'" << std::endl;
|
||||
std::cout << " Enchantment charge: '" << ref.mEnchantmentCharge << "'\n";
|
||||
std::cout << " Uses/health: '" << ref.mCharge << "'\n";
|
||||
std::cout << " Uses/health: '" << ref.mChargeInt << "'\n";
|
||||
std::cout << " Gold value: '" << ref.mGoldValue << "'\n";
|
||||
std::cout << " Blocked: '" << static_cast<int>(ref.mReferenceBlocked) << "'" << std::endl;
|
||||
std::cout << " Deleted: " << deleted << std::endl;
|
||||
|
@ -430,7 +430,7 @@ int clone(Arguments& info)
|
|||
return 1;
|
||||
}
|
||||
|
||||
int recordCount = info.data.mRecords.size();
|
||||
size_t recordCount = info.data.mRecords.size();
|
||||
|
||||
int digitCount = 1; // For a nicer output
|
||||
if (recordCount > 9) ++digitCount;
|
||||
|
@ -501,9 +501,9 @@ int clone(Arguments& info)
|
|||
if (!info.data.mCellRefs[ptr].empty()) {
|
||||
typedef std::deque<ESM::CellRef> RefList;
|
||||
RefList &refs = info.data.mCellRefs[ptr];
|
||||
for (RefList::iterator it = refs.begin(); it != refs.end(); ++it)
|
||||
for (RefList::iterator refIt = refs.begin(); refIt != refs.end(); ++refIt)
|
||||
{
|
||||
it->save(esm);
|
||||
refIt->save(esm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -511,7 +511,7 @@ int clone(Arguments& info)
|
|||
esm.endRecord(name.toString());
|
||||
|
||||
saved++;
|
||||
int perc = (saved / (float)recordCount)*100;
|
||||
int perc = (int)((saved / (float)recordCount)*100);
|
||||
if (perc % 10 == 0)
|
||||
{
|
||||
std::cerr << "\r" << perc << "%";
|
||||
|
|
|
@ -13,14 +13,13 @@
|
|||
#include <components/esm/loadweap.hpp>
|
||||
#include <components/esm/aipackage.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <boost/format.hpp>
|
||||
|
||||
std::string bodyPartLabel(int idx)
|
||||
{
|
||||
if (idx >= 0 && idx <= 26)
|
||||
{
|
||||
const char *bodyPartLabels[] = {
|
||||
static const char *bodyPartLabels[] = {
|
||||
"Head",
|
||||
"Hair",
|
||||
"Neck",
|
||||
|
@ -59,7 +58,7 @@ std::string meshPartLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= ESM::BodyPart::MP_Tail)
|
||||
{
|
||||
const char *meshPartLabels[] = {
|
||||
static const char *meshPartLabels[] = {
|
||||
"Head",
|
||||
"Hair",
|
||||
"Neck",
|
||||
|
@ -86,7 +85,7 @@ std::string meshTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= ESM::BodyPart::MT_Armor)
|
||||
{
|
||||
const char *meshTypeLabels[] = {
|
||||
static const char *meshTypeLabels[] = {
|
||||
"Skin",
|
||||
"Clothing",
|
||||
"Armor"
|
||||
|
@ -101,7 +100,7 @@ std::string clothingTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 9)
|
||||
{
|
||||
const char *clothingTypeLabels[] = {
|
||||
static const char *clothingTypeLabels[] = {
|
||||
"Pants",
|
||||
"Shoes",
|
||||
"Shirt",
|
||||
|
@ -123,7 +122,7 @@ std::string armorTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 10)
|
||||
{
|
||||
const char *armorTypeLabels[] = {
|
||||
static const char *armorTypeLabels[] = {
|
||||
"Helmet",
|
||||
"Cuirass",
|
||||
"Left Pauldron",
|
||||
|
@ -146,7 +145,7 @@ std::string dialogTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 4)
|
||||
{
|
||||
const char *dialogTypeLabels[] = {
|
||||
static const char *dialogTypeLabels[] = {
|
||||
"Topic",
|
||||
"Voice",
|
||||
"Greeting",
|
||||
|
@ -165,7 +164,7 @@ std::string questStatusLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 4)
|
||||
{
|
||||
const char *questStatusLabels[] = {
|
||||
static const char *questStatusLabels[] = {
|
||||
"None",
|
||||
"Name",
|
||||
"Finished",
|
||||
|
@ -182,7 +181,7 @@ std::string creatureTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 3)
|
||||
{
|
||||
const char *creatureTypeLabels[] = {
|
||||
static const char *creatureTypeLabels[] = {
|
||||
"Creature",
|
||||
"Daedra",
|
||||
"Undead",
|
||||
|
@ -198,7 +197,7 @@ std::string soundTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 7)
|
||||
{
|
||||
const char *soundTypeLabels[] = {
|
||||
static const char *soundTypeLabels[] = {
|
||||
"Left Foot",
|
||||
"Right Foot",
|
||||
"Swim Left",
|
||||
|
@ -218,7 +217,7 @@ std::string weaponTypeLabel(int idx)
|
|||
{
|
||||
if (idx >= 0 && idx <= 13)
|
||||
{
|
||||
const char *weaponTypeLabels[] = {
|
||||
static const char *weaponTypeLabels[] = {
|
||||
"Short Blade One Hand",
|
||||
"Long Blade One Hand",
|
||||
"Long Blade Two Hand",
|
||||
|
|
|
@ -25,7 +25,7 @@ void printAIPackage(ESM::AIPackage p)
|
|||
{
|
||||
std::cout << " Travel Coordinates: (" << p.mTravel.mX << ","
|
||||
<< p.mTravel.mY << "," << p.mTravel.mZ << ")" << std::endl;
|
||||
std::cout << " Travel Unknown: " << (int)p.mTravel.mUnk << std::endl;
|
||||
std::cout << " Travel Unknown: " << p.mTravel.mUnk << std::endl;
|
||||
}
|
||||
else if (p.mType == ESM::AI_Follow || p.mType == ESM::AI_Escort)
|
||||
{
|
||||
|
@ -33,12 +33,12 @@ void printAIPackage(ESM::AIPackage p)
|
|||
<< p.mTarget.mY << "," << p.mTarget.mZ << ")" << std::endl;
|
||||
std::cout << " Duration: " << p.mTarget.mDuration << std::endl;
|
||||
std::cout << " Target ID: " << p.mTarget.mId.toString() << std::endl;
|
||||
std::cout << " Unknown: " << (int)p.mTarget.mUnk << std::endl;
|
||||
std::cout << " Unknown: " << p.mTarget.mUnk << std::endl;
|
||||
}
|
||||
else if (p.mType == ESM::AI_Activate)
|
||||
{
|
||||
std::cout << " Name: " << p.mActivate.mName.toString() << std::endl;
|
||||
std::cout << " Activate Unknown: " << (int)p.mActivate.mUnk << std::endl;
|
||||
std::cout << " Activate Unknown: " << p.mActivate.mUnk << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << " BadPackage: " << boost::format("0x%08x") % p.mType << std::endl;
|
||||
|
@ -89,6 +89,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
|
|||
case 'A': if (indicator == 'R') type_str = "Not Race"; break;
|
||||
case 'B': if (indicator == 'L') type_str = "Not Cell"; break;
|
||||
case 'C': if (indicator == 's') type_str = "Not Local"; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
// Append the variable name to the function string if any.
|
||||
|
@ -110,6 +111,7 @@ std::string ruleString(ESM::DialInfo::SelectStruct ss)
|
|||
case '3': oper_str = ">="; break;
|
||||
case '4': oper_str = "< "; break;
|
||||
case '5': oper_str = "<="; break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
std::ostringstream stream;
|
||||
|
@ -430,7 +432,7 @@ void Record<ESM::Apparatus>::print()
|
|||
std::cout << " Icon: " << mData.mIcon << std::endl;
|
||||
std::cout << " Script: " << mData.mScript << std::endl;
|
||||
std::cout << " Type: " << apparatusTypeLabel(mData.mData.mType)
|
||||
<< " (" << (int)mData.mData.mType << ")" << std::endl;
|
||||
<< " (" << mData.mData.mType << ")" << std::endl;
|
||||
std::cout << " Weight: " << mData.mData.mWeight << std::endl;
|
||||
std::cout << " Value: " << mData.mData.mValue << std::endl;
|
||||
std::cout << " Quality: " << mData.mData.mQuality << std::endl;
|
||||
|
@ -816,7 +818,7 @@ void Record<ESM::Land>::print()
|
|||
// Seems like this should done with reference counting in the
|
||||
// loader to me. But I'm not really knowledgable about this
|
||||
// record type yet. --Cory
|
||||
bool wasLoaded = mData.mDataLoaded;
|
||||
bool wasLoaded = (mData.mDataLoaded != 0);
|
||||
if (mData.mDataTypes) mData.loadData(mData.mDataTypes);
|
||||
if (mData.mDataLoaded)
|
||||
{
|
||||
|
@ -999,7 +1001,7 @@ void Record<ESM::NPC>::print()
|
|||
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown2) << std::endl;
|
||||
std::cout << " Unknown3: "
|
||||
<< (unsigned int)((unsigned char)mData.mNpdt12.mUnknown3) << std::endl;
|
||||
std::cout << " Gold: " << (int)mData.mNpdt12.mGold << std::endl;
|
||||
std::cout << " Gold: " << mData.mNpdt12.mGold << std::endl;
|
||||
}
|
||||
else {
|
||||
std::cout << " Level: " << mData.mNpdt52.mLevel << std::endl;
|
||||
|
@ -1021,7 +1023,7 @@ void Record<ESM::NPC>::print()
|
|||
std::cout << " Skills:" << std::endl;
|
||||
for (int i = 0; i != ESM::Skill::Length; i++)
|
||||
std::cout << " " << skillLabel(i) << ": "
|
||||
<< (int)((unsigned char)mData.mNpdt52.mSkills[i]) << std::endl;
|
||||
<< (int)(mData.mNpdt52.mSkills[i]) << std::endl;
|
||||
|
||||
std::cout << " Health: " << mData.mNpdt52.mHealth << std::endl;
|
||||
std::cout << " Magicka: " << mData.mNpdt52.mMana << std::endl;
|
||||
|
@ -1123,9 +1125,9 @@ void Record<ESM::Race>::print()
|
|||
|
||||
std::cout << (male ? " Male:" : " Female:") << std::endl;
|
||||
|
||||
for (int i=0; i<8; ++i)
|
||||
std::cout << " " << sAttributeNames[i] << ": "
|
||||
<< mData.mData.mAttributeValues[i].getValue (male) << std::endl;
|
||||
for (int j=0; j<8; ++j)
|
||||
std::cout << " " << sAttributeNames[j] << ": "
|
||||
<< mData.mData.mAttributeValues[j].getValue (male) << std::endl;
|
||||
|
||||
std::cout << " Height: " << mData.mData.mHeight.getValue (male) << std::endl;
|
||||
std::cout << " Weight: " << mData.mData.mWeight.getValue (male) << std::endl;
|
||||
|
|
|
@ -19,7 +19,7 @@ namespace EsmTool
|
|||
{
|
||||
protected:
|
||||
std::string mId;
|
||||
int mFlags;
|
||||
uint32_t mFlags;
|
||||
ESM::NAME mType;
|
||||
bool mPrintPlain;
|
||||
|
||||
|
@ -40,11 +40,11 @@ namespace EsmTool
|
|||
mId = id;
|
||||
}
|
||||
|
||||
int getFlags() const {
|
||||
uint32_t getFlags() const {
|
||||
return mFlags;
|
||||
}
|
||||
|
||||
void setFlags(int flags) {
|
||||
void setFlags(uint32_t flags) {
|
||||
mFlags = flags;
|
||||
}
|
||||
|
||||
|
@ -52,10 +52,6 @@ namespace EsmTool
|
|||
return mType;
|
||||
}
|
||||
|
||||
bool getPrintPlain() const {
|
||||
return mPrintPlain;
|
||||
}
|
||||
|
||||
void setPrintPlain(bool plain) {
|
||||
mPrintPlain = plain;
|
||||
}
|
||||
|
|
|
@ -9,6 +9,13 @@ set(ESSIMPORTER_FILES
|
|||
importinventory.cpp
|
||||
importklst.cpp
|
||||
importcntc.cpp
|
||||
importgame.cpp
|
||||
importinfo.cpp
|
||||
importdial.cpp
|
||||
importques.cpp
|
||||
importjour.cpp
|
||||
importscri.cpp
|
||||
importscpt.cpp
|
||||
importercontext.cpp
|
||||
converter.cpp
|
||||
convertacdt.cpp
|
||||
|
@ -16,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
|
||||
{
|
||||
|
@ -27,6 +28,10 @@ namespace
|
|||
objstate.mEnabled = cellref.mEnabled;
|
||||
objstate.mPosition = cellref.mPos;
|
||||
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)
|
||||
|
@ -34,6 +39,10 @@ namespace
|
|||
if (indexedRefId.size() <= 8)
|
||||
return false;
|
||||
|
||||
if (indexedRefId.find_first_not_of("0123456789") == std::string::npos)
|
||||
return false; // entirely numeric refid, this is a reference to
|
||||
// a dynamically created record e.g. player-enchanted weapon
|
||||
|
||||
std::string index = indexedRefId.substr(indexedRefId.size()-8);
|
||||
if(index.find_first_not_of("0123456789ABCDEF") == std::string::npos )
|
||||
return true;
|
||||
|
@ -70,6 +79,12 @@ namespace ESSImport
|
|||
cell.mName = id;
|
||||
cell.load(esm, false);
|
||||
|
||||
// I wonder what 0x40 does?
|
||||
if (cell.isExterior() && cell.mData.mFlags & 0x20)
|
||||
{
|
||||
mContext->mGlobalMapState.mMarkers.insert(std::make_pair(cell.mData.mX, cell.mData.mY));
|
||||
}
|
||||
|
||||
// note if the player is in a nameless exterior cell, we will assign the cellId later based on player position
|
||||
if (id == mContext->mPlayerCellName)
|
||||
{
|
||||
|
@ -136,13 +151,6 @@ namespace ESSImport
|
|||
{
|
||||
CellRef ref;
|
||||
ref.load (esm);
|
||||
if (esm.isNextSub("DELE"))
|
||||
{
|
||||
// TODO
|
||||
// strangely this can be e.g. 52 instead of just 1,
|
||||
//std::cout << "deleted ref " << ref.mIndexedRefId << std::endl;
|
||||
esm.skipHSub();
|
||||
}
|
||||
cellrefs.push_back(ref);
|
||||
}
|
||||
|
||||
|
@ -201,8 +209,7 @@ namespace ESSImport
|
|||
for (std::vector<CellRef>::const_iterator refIt = cell.mRefs.begin(); refIt != cell.mRefs.end(); ++refIt)
|
||||
{
|
||||
const CellRef& cellref = *refIt;
|
||||
ESM::CellRef out;
|
||||
out.blank();
|
||||
ESM::CellRef out (cellref);
|
||||
|
||||
if (!isIndexedRefId(cellref.mIndexedRefId))
|
||||
{
|
||||
|
@ -241,8 +248,8 @@ namespace ESSImport
|
|||
objstate.mRef.mRefID = idLower;
|
||||
// probably need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
convertNpcData(cellref.mActorData, objstate.mNpcStats);
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
convertNpcData(cellref, objstate.mNpcStats);
|
||||
convertNPCC(npccIt->second, objstate);
|
||||
convertCellRef(cellref, objstate);
|
||||
esm.writeHNT ("OBJE", ESM::REC_NPC_);
|
||||
|
@ -273,7 +280,7 @@ namespace ESSImport
|
|||
objstate.blank();
|
||||
objstate.mRef = out;
|
||||
objstate.mRef.mRefID = idLower;
|
||||
convertACDT(cellref.mActorData.mACDT, objstate.mCreatureStats);
|
||||
convertACDT(cellref.mACDT, objstate.mCreatureStats);
|
||||
// probably need more micromanagement here so we don't overwrite values
|
||||
// from the ESM with default values
|
||||
convertCREC(crecIt->second, objstate);
|
||||
|
@ -306,6 +313,10 @@ namespace ESSImport
|
|||
it->save(esm);
|
||||
esm.endRecord(ESM::REC_MARK);
|
||||
}
|
||||
|
||||
esm.startRecord(ESM::REC_GMAP);
|
||||
mContext->mGlobalMapState.save(esm);
|
||||
esm.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include <components/esm/loadfact.hpp>
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/custommarkerstate.hpp>
|
||||
#include <components/esm/loadcrea.hpp>
|
||||
|
||||
#include "importcrec.hpp"
|
||||
#include "importcntc.hpp"
|
||||
|
@ -19,6 +20,12 @@
|
|||
#include "importercontext.hpp"
|
||||
#include "importcellref.hpp"
|
||||
#include "importklst.hpp"
|
||||
#include "importgame.hpp"
|
||||
#include "importinfo.hpp"
|
||||
#include "importdial.hpp"
|
||||
#include "importques.hpp"
|
||||
#include "importjour.hpp"
|
||||
#include "importscpt.hpp"
|
||||
|
||||
#include "convertacdt.hpp"
|
||||
#include "convertnpcc.hpp"
|
||||
|
@ -86,25 +93,53 @@ class ConvertNPC : public Converter
|
|||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
// this is always the player
|
||||
ESM::NPC npc;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
npc.load(esm);
|
||||
if (id != "player") // seems to occur sometimes, with "chargen X" names
|
||||
std::cerr << "non-player NPC record: " << id << std::endl;
|
||||
if (id != "player")
|
||||
{
|
||||
// TODO:
|
||||
// this should handle changes to the NPC struct, but since there is no index here
|
||||
// it will apply to ALL instances of the class. seems to be the reason for the
|
||||
// "feature" in MW where changing AI settings of one guard will change it for all guards of that refID.
|
||||
}
|
||||
else
|
||||
{
|
||||
mContext->mPlayer.mObject.mCreatureStats.mLevel = npc.mNpdt52.mLevel;
|
||||
mContext->mPlayerBase = npc;
|
||||
std::map<const int, float> empty;
|
||||
// FIXME: player start spells, racial spells and birthsign spells aren't listed here,
|
||||
// FIXME: player start spells and birthsign spells aren't listed here,
|
||||
// need to fix openmw to account for this
|
||||
for (std::vector<std::string>::const_iterator it = npc.mSpells.mList.begin(); it != npc.mSpells.mList.end(); ++it)
|
||||
mContext->mPlayer.mObject.mCreatureStats.mSpells.mSpells[*it] = empty;
|
||||
|
||||
// Clear the list now that we've written it, this prevents issues cropping up with
|
||||
// ensureCustomData() in OpenMW tripping over no longer existing spells, where an error would be fatal.
|
||||
mContext->mPlayerBase.mSpells.mList.clear();
|
||||
|
||||
// Same with inventory. Actually it's strange this would contain something, since there's already an
|
||||
// inventory list in NPCC. There seems to be a fair amount of redundancy in this format.
|
||||
mContext->mPlayerBase.mInventory.mList.clear();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class ConvertCREA : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
// See comment in ConvertNPC
|
||||
ESM::Creature creature;
|
||||
std::string id = esm.getHNString("NAME");
|
||||
creature.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
// Do we need ConvertCONT?
|
||||
// I've seen a CONT record in a certain save file, but the container contents in it
|
||||
// were identical to a corresponding CNTC record. See previous comment about redundancy...
|
||||
|
||||
class ConvertGlobal : public DefaultConverter<ESM::Global>
|
||||
{
|
||||
public:
|
||||
|
@ -191,7 +226,28 @@ public:
|
|||
|
||||
ESM::NpcStats& npcStats = mContext->mPlayer.mObject.mNpcStats;
|
||||
convertNpcData(refr.mActorData, npcStats);
|
||||
|
||||
mSelectedSpell = refr.mActorData.mSelectedSpell;
|
||||
if (!refr.mActorData.mSelectedEnchantItem.empty())
|
||||
{
|
||||
ESM::InventoryState& invState = mContext->mPlayer.mObject.mInventory;
|
||||
|
||||
for (unsigned int i=0; i<invState.mItems.size(); ++i)
|
||||
{
|
||||
// FIXME: in case of conflict (multiple items with this refID) use the already equipped one?
|
||||
if (Misc::StringUtils::ciEqual(invState.mItems[i].mRef.mRefID, refr.mActorData.mSelectedEnchantItem))
|
||||
invState.mSelectedEnchantItem = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
virtual void write(ESM::ESMWriter& esm)
|
||||
{
|
||||
esm.startRecord(ESM::REC_ASPL);
|
||||
esm.writeHNString("ID__", mSelectedSpell);
|
||||
esm.endRecord(ESM::REC_ASPL);
|
||||
}
|
||||
private:
|
||||
std::string mSelectedSpell;
|
||||
};
|
||||
|
||||
class ConvertPCDT : public Converter
|
||||
|
@ -329,15 +385,18 @@ public:
|
|||
{
|
||||
std::string itemid = esm.getHNString("NAME");
|
||||
|
||||
while (esm.isNextSub("ONAM"))
|
||||
while (esm.isNextSub("FNAM") || esm.isNextSub("ONAM"))
|
||||
{
|
||||
std::string ownerid = esm.getHString();
|
||||
mStolenItems.insert(std::make_pair(itemid, ownerid));
|
||||
}
|
||||
while (esm.isNextSub("FNAM"))
|
||||
{
|
||||
std::string factionid = esm.getHString();
|
||||
mFactionStolenItems.insert(std::make_pair(itemid, factionid));
|
||||
if (esm.retSubName().toString() == "FNAM")
|
||||
{
|
||||
std::string factionid = esm.getHString();
|
||||
mFactionStolenItems.insert(std::make_pair(itemid, factionid));
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string ownerid = esm.getHString();
|
||||
mStolenItems.insert(std::make_pair(itemid, ownerid));
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
@ -345,6 +404,75 @@ private:
|
|||
std::multimap<std::string, std::string> mFactionStolenItems;
|
||||
};
|
||||
|
||||
/// Seen responses for a dialogue topic?
|
||||
/// Each DIAL record is followed by a number of INFO records, I believe, just like in ESMs
|
||||
/// Dialogue conversion problems (probably have to adjust OpenMW format) -
|
||||
/// - Journal is stored in one continuous HTML markup rather than each entry separately with associated info ID.
|
||||
/// - Seen dialogue responses only store the INFO id, rather than the fulltext.
|
||||
/// - Quest stages only store the INFO id, rather than the journal entry fulltext.
|
||||
class ConvertINFO : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
INFO info;
|
||||
info.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
class ConvertDIAL : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
DIAL dial;
|
||||
dial.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
class ConvertQUES : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
std::string id = esm.getHNString("NAME");
|
||||
QUES quest;
|
||||
quest.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
class ConvertJOUR : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader& esm)
|
||||
{
|
||||
JOUR journal;
|
||||
journal.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
class ConvertGAME : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
GAME game;
|
||||
game.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
/// Running global script
|
||||
class ConvertSCPT : public Converter
|
||||
{
|
||||
public:
|
||||
virtual void read(ESM::ESMReader &esm)
|
||||
{
|
||||
SCPT script;
|
||||
script.load(esm);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -7,16 +7,23 @@ namespace ESSImport
|
|||
|
||||
void convertInventory(const Inventory &inventory, ESM::InventoryState &state)
|
||||
{
|
||||
int index = 0;
|
||||
for (std::vector<Inventory::InventoryItem>::const_iterator it = inventory.mItems.begin();
|
||||
it != inventory.mItems.end(); ++it)
|
||||
{
|
||||
ESM::ObjectState objstate;
|
||||
objstate.blank();
|
||||
objstate.mRef = *it;
|
||||
objstate.mRef.mRefID = Misc::StringUtils::lowerCase(it->mId);
|
||||
objstate.mCount = std::abs(it->mCount); // restocking items have negative count in the savefile
|
||||
// openmw handles them differently, so no need to set any flags
|
||||
objstate.mRef.mCharge = it->mCondition;
|
||||
state.mItems.push_back(std::make_pair(objstate, -1));
|
||||
state.mItems.push_back(objstate);
|
||||
if (it->mRelativeEquipmentSlot != -1)
|
||||
// Note we should really write the absolute slot here, which we do not know about
|
||||
// Not a big deal, OpenMW will auto-correct to a valid slot, the only problem is when
|
||||
// an item could be equipped in two different slots (e.g. equipped two rings)
|
||||
state.mEquipmentSlots[index] = it->mRelativeEquipmentSlot;
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
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
|
|
@ -9,18 +9,16 @@ namespace ESSImport
|
|||
|
||||
void ActorData::load(ESM::ESMReader &esm)
|
||||
{
|
||||
// unsure at which point between NAME and ESM::CellRef
|
||||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("ACTN"))
|
||||
esm.skipHSub();
|
||||
|
||||
if (esm.isNextSub("STPR"))
|
||||
esm.skipHSub();
|
||||
|
||||
ESM::CellRef bla;
|
||||
bla.ESM::CellRef::loadData(esm);
|
||||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub();
|
||||
|
||||
ESM::CellRef::loadData(esm);
|
||||
|
||||
// FIXME: not all actors have this, add flag
|
||||
esm.getHNOT(mACDT, "ACDT");
|
||||
|
@ -62,15 +60,18 @@ namespace ESSImport
|
|||
if (esm.isNextSub("PWPS"))
|
||||
esm.skipHSub();
|
||||
|
||||
// unsure at which point between LSTN and CHRD
|
||||
if (esm.isNextSub("APUD"))
|
||||
esm.skipHSub(); // 40 bytes, starts with string "ancestor guardian". maybe spellcasting in progress?
|
||||
|
||||
if (esm.isNextSub("WNAM"))
|
||||
{
|
||||
esm.skipHSub(); // seen values: "ancestor guardian", "bound dagger_en". Summoned creature / bound weapons?
|
||||
std::string id = esm.getHString();
|
||||
|
||||
if (esm.isNextSub("XNAM"))
|
||||
{
|
||||
// "demon tanto", probably the ID of spell/item that created the bound weapon/crature?
|
||||
esm.skipHSub();
|
||||
}
|
||||
mSelectedEnchantItem = esm.getHString();
|
||||
else
|
||||
mSelectedSpell = id;
|
||||
|
||||
if (esm.isNextSub("YNAM"))
|
||||
esm.skipHSub(); // 4 byte, 0
|
||||
|
@ -83,18 +84,7 @@ namespace ESSImport
|
|||
if (esm.isNextSub("CRED")) // creature only
|
||||
esm.getHExact(mCombatStats, 3*2*sizeof(int));
|
||||
|
||||
mScript = esm.getHNOString("SCRI");
|
||||
|
||||
// script variables?
|
||||
if (!mScript.empty())
|
||||
{
|
||||
if (esm.isNextSub("SLCS"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("SLSD")) // Short Data?
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("SLFD")) // Float Data?
|
||||
esm.skipHSub();
|
||||
}
|
||||
mSCRI.load(esm);
|
||||
|
||||
if (esm.isNextSub("ND3D"))
|
||||
esm.skipHSub();
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
|
||||
#include "importscri.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
|
@ -37,7 +41,7 @@ namespace ESSImport
|
|||
};
|
||||
#pragma pack(pop)
|
||||
|
||||
struct ActorData
|
||||
struct ActorData : public ESM::CellRef
|
||||
{
|
||||
ACDT mACDT;
|
||||
|
||||
|
@ -48,7 +52,10 @@ namespace ESSImport
|
|||
// to change them ingame
|
||||
int mCombatStats[3][2];
|
||||
|
||||
std::string mScript;
|
||||
std::string mSelectedSpell;
|
||||
std::string mSelectedEnchantItem;
|
||||
|
||||
SCRI mSCRI;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
|
|
@ -7,6 +7,8 @@ namespace ESSImport
|
|||
|
||||
void CellRef::load(ESM::ESMReader &esm)
|
||||
{
|
||||
blank();
|
||||
|
||||
// (FRMR subrecord name is already read by the loop in ConvertCell)
|
||||
esm.getHT(mRefNum.mIndex); // FRMR
|
||||
|
||||
|
@ -17,25 +19,32 @@ namespace ESSImport
|
|||
|
||||
mIndexedRefId = esm.getHNString("NAME");
|
||||
|
||||
ActorData::load(esm);
|
||||
if (esm.isNextSub("LVCR"))
|
||||
{
|
||||
// occurs on leveled creature spawner references
|
||||
// probably some identifier for the the creature that has been spawned?
|
||||
// probably some identifier for the creature that has been spawned?
|
||||
unsigned char lvcr;
|
||||
esm.getHT(lvcr);
|
||||
//std::cout << "LVCR: " << (int)lvcr << std::endl;
|
||||
}
|
||||
mActorData.load(esm);
|
||||
|
||||
mEnabled = true;
|
||||
esm.getHNOT(mEnabled, "ZNAM");
|
||||
|
||||
// should occur for all references but not levelled creature spawners
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
|
||||
// i've seen DATA record TWICE on a creature record - and with the exact same content too! weird
|
||||
// DATA should occur for all references, except leveled creature spawners
|
||||
// I've seen DATA *twice* on a creature record, and with the exact same content too! weird
|
||||
// alarmvoi0000.ess
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
esm.getHNOT(mPos, "DATA", 24);
|
||||
|
||||
mDeleted = 0;
|
||||
if (esm.isNextSub("DELE"))
|
||||
{
|
||||
unsigned int deleted;
|
||||
esm.getHT(deleted);
|
||||
mDeleted = (deleted >> 24) & 0x2; // the other 3 bytes seem to be uninitialized garbage
|
||||
}
|
||||
|
||||
if (esm.isNextSub("MVRF"))
|
||||
{
|
||||
|
|
|
@ -15,20 +15,16 @@ namespace ESM
|
|||
namespace ESSImport
|
||||
{
|
||||
|
||||
// Not sure if we can share any code with ESM::CellRef here
|
||||
struct CellRef
|
||||
struct CellRef : public ActorData
|
||||
{
|
||||
std::string mIndexedRefId;
|
||||
ESM::RefNum mRefNum;
|
||||
|
||||
ActorData mActorData;
|
||||
|
||||
ESM::Position mPos;
|
||||
|
||||
std::string mScript;
|
||||
|
||||
bool mEnabled;
|
||||
|
||||
bool mDeleted;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,6 +14,11 @@ namespace ESSImport
|
|||
float scale;
|
||||
esm.getHNOT(scale, "XSCL");
|
||||
|
||||
// FIXME: use AiPackageList, need to fix getSubName()
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
esm.skipHSub();
|
||||
|
||||
mInventory.load(esm);
|
||||
}
|
||||
|
||||
|
|
23
apps/essimporter/importdial.cpp
Normal file
23
apps/essimporter/importdial.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
#include "importdial.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void DIAL::load(ESM::ESMReader &esm)
|
||||
{
|
||||
// See ESM::Dialogue::Type enum, not sure why we would need this here though
|
||||
int type = 0;
|
||||
esm.getHNOT(type, "DATA");
|
||||
|
||||
// Deleted dialogue in a savefile. No clue what this means...
|
||||
int deleted = 0;
|
||||
esm.getHNOT(deleted, "DELE");
|
||||
|
||||
mIndex = 0;
|
||||
// *should* always occur except when the dialogue is deleted, but leaving it optional just in case...
|
||||
esm.getHNOT(mIndex, "XIDX");
|
||||
}
|
||||
|
||||
}
|
20
apps/essimporter/importdial.hpp
Normal file
20
apps/essimporter/importdial.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTDIAL_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTDIAL_H
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
struct DIAL
|
||||
{
|
||||
int mIndex; // Journal index
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -105,6 +105,7 @@ namespace ESSImport
|
|||
blacklist.insert(std::make_pair("REFR", "DATA")); // player position
|
||||
blacklist.insert(std::make_pair("CELL", "NAM8")); // fog of war
|
||||
blacklist.insert(std::make_pair("GAME", "GMDT")); // weather data, current time always changes
|
||||
blacklist.insert(std::make_pair("CELL", "DELE")); // first 3 bytes are uninitialized
|
||||
|
||||
// this changes way too often, name suggests some renderer internal data?
|
||||
blacklist.insert(std::make_pair("CELL", "ND3D"));
|
||||
|
@ -122,7 +123,7 @@ namespace ESSImport
|
|||
|
||||
if (i >= file2.mRecords.size())
|
||||
{
|
||||
std::cout << "Record in file1 not present in file2: (1) 0x" << std::hex << rec.mFileOffset;
|
||||
std::cout << "Record in file1 not present in file2: (1) 0x" << std::hex << rec.mFileOffset << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -141,7 +142,7 @@ namespace ESSImport
|
|||
|
||||
if (j >= rec2.mSubrecords.size())
|
||||
{
|
||||
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset;
|
||||
std::cout << "Subrecord in file1 not present in file2: (1) 0x" << std::hex << sub.mFileOffset << std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -201,11 +202,14 @@ namespace ESSImport
|
|||
const unsigned int recFMAP = ESM::FourCC<'F','M','A','P'>::value;
|
||||
const unsigned int recKLST = ESM::FourCC<'K','L','S','T'>::value;
|
||||
const unsigned int recSTLN = ESM::FourCC<'S','T','L','N'>::value;
|
||||
const unsigned int recGAME = ESM::FourCC<'G','A','M','E'>::value;
|
||||
const unsigned int recJOUR = ESM::FourCC<'J','O','U','R'>::value;
|
||||
|
||||
std::map<unsigned int, boost::shared_ptr<Converter> > converters;
|
||||
converters[ESM::REC_GLOB] = boost::shared_ptr<Converter>(new ConvertGlobal());
|
||||
converters[ESM::REC_BOOK] = boost::shared_ptr<Converter>(new ConvertBook());
|
||||
converters[ESM::REC_NPC_] = boost::shared_ptr<Converter>(new ConvertNPC());
|
||||
converters[ESM::REC_CREA] = boost::shared_ptr<Converter>(new ConvertCREA());
|
||||
converters[ESM::REC_NPCC] = boost::shared_ptr<Converter>(new ConvertNPCC());
|
||||
converters[ESM::REC_CREC] = boost::shared_ptr<Converter>(new ConvertCREC());
|
||||
converters[recREFR ] = boost::shared_ptr<Converter>(new ConvertREFR());
|
||||
|
@ -213,6 +217,7 @@ namespace ESSImport
|
|||
converters[recFMAP ] = boost::shared_ptr<Converter>(new ConvertFMAP());
|
||||
converters[recKLST ] = boost::shared_ptr<Converter>(new ConvertKLST());
|
||||
converters[recSTLN ] = boost::shared_ptr<Converter>(new ConvertSTLN());
|
||||
converters[recGAME ] = boost::shared_ptr<Converter>(new ConvertGAME());
|
||||
converters[ESM::REC_CELL] = boost::shared_ptr<Converter>(new ConvertCell());
|
||||
converters[ESM::REC_ALCH] = boost::shared_ptr<Converter>(new DefaultConverter<ESM::Potion>());
|
||||
converters[ESM::REC_CLAS] = boost::shared_ptr<Converter>(new ConvertClass());
|
||||
|
@ -226,6 +231,17 @@ namespace ESSImport
|
|||
converters[ESM::REC_LEVI] = boost::shared_ptr<Converter>(new DefaultConverter<ESM::ItemLevList>());
|
||||
converters[ESM::REC_CNTC] = boost::shared_ptr<Converter>(new ConvertCNTC());
|
||||
converters[ESM::REC_FACT] = boost::shared_ptr<Converter>(new ConvertFACT());
|
||||
converters[ESM::REC_INFO] = boost::shared_ptr<Converter>(new ConvertINFO());
|
||||
converters[ESM::REC_DIAL] = boost::shared_ptr<Converter>(new ConvertDIAL());
|
||||
converters[ESM::REC_QUES] = boost::shared_ptr<Converter>(new ConvertQUES());
|
||||
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;
|
||||
|
||||
|
@ -248,7 +264,7 @@ namespace ESSImport
|
|||
else
|
||||
{
|
||||
if (unknownRecords.insert(n.val).second)
|
||||
std::cerr << "unknown record " << n.toString() << std::endl;
|
||||
std::cerr << "unknown record " << n.toString() << " (0x" << std::hex << esm.getFileOffset() << ")" << std::endl;
|
||||
|
||||
esm.skipRecord();
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include <components/esm/loadnpc.hpp>
|
||||
#include <components/esm/player.hpp>
|
||||
#include <components/esm/dialoguestate.hpp>
|
||||
#include <components/esm/globalmap.hpp>
|
||||
|
||||
#include "importnpcc.hpp"
|
||||
#include "importcrec.hpp"
|
||||
|
@ -28,6 +29,8 @@ namespace ESSImport
|
|||
|
||||
ESM::DialogueState mDialogueState;
|
||||
|
||||
ESM::GlobalMap mGlobalMapState;
|
||||
|
||||
int mDay, mMonth, mYear;
|
||||
float mHour;
|
||||
|
||||
|
@ -48,6 +51,11 @@ namespace ESSImport
|
|||
mPlayer.mCurrentCrimeId = 0; // TODO
|
||||
mPlayer.mObject.blank();
|
||||
mPlayer.mObject.mRef.mRefID = "player"; // REFR.mRefID would be PlayerSaveGame
|
||||
|
||||
mGlobalMapState.mBounds.mMinX = 0;
|
||||
mGlobalMapState.mBounds.mMaxX = 0;
|
||||
mGlobalMapState.mBounds.mMinY = 0;
|
||||
mGlobalMapState.mBounds.mMaxY = 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
13
apps/essimporter/importgame.cpp
Normal file
13
apps/essimporter/importgame.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "importgame.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void GAME::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mGMDT, "GMDT");
|
||||
}
|
||||
|
||||
}
|
33
apps/essimporter/importgame.hpp
Normal file
33
apps/essimporter/importgame.hpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
#ifndef OPENMW_ESSIMPORT_GAME_H
|
||||
#define OPENMW_ESSIMPORT_GAME_H
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Weather data
|
||||
struct GAME
|
||||
{
|
||||
struct GMDT
|
||||
{
|
||||
char mCellName[64];
|
||||
int mFogColour;
|
||||
float mFogDensity;
|
||||
int mCurrentWeather, mNextWeather;
|
||||
int mWeatherTransition; // 0-100 transition between weathers, top 3 bytes may be garbage
|
||||
float mTimeOfNextTransition; // weather changes when gamehour == timeOfNextTransition
|
||||
int masserPhase, secundaPhase; // top 3 bytes may be garbage
|
||||
};
|
||||
|
||||
GMDT mGMDT;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
14
apps/essimporter/importinfo.cpp
Normal file
14
apps/essimporter/importinfo.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "importinfo.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void INFO::load(ESM::ESMReader &esm)
|
||||
{
|
||||
mInfo = esm.getHNString("INAM");
|
||||
mActorRefId = esm.getHNString("ACDT");
|
||||
}
|
||||
|
||||
}
|
24
apps/essimporter/importinfo.hpp
Normal file
24
apps/essimporter/importinfo.hpp
Normal file
|
@ -0,0 +1,24 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTINFO_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTINFO_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
struct INFO
|
||||
{
|
||||
std::string mInfo;
|
||||
std::string mActorRefId;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,5 +1,7 @@
|
|||
#include "importinventory.hpp"
|
||||
|
||||
#include <stdexcept>
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
#include <components/esm/loadcont.hpp>
|
||||
|
@ -17,6 +19,7 @@ namespace ESSImport
|
|||
InventoryItem item;
|
||||
item.mId = contItem.mItem.toString();
|
||||
item.mCount = contItem.mCount;
|
||||
item.mRelativeEquipmentSlot = -1;
|
||||
|
||||
// seems that a stack of items can have a set of subrecords for each item? rings0000.ess
|
||||
// doesn't make any sense to me, if the values were different then the items shouldn't stack in the first place?
|
||||
|
@ -26,25 +29,14 @@ namespace ESSImport
|
|||
if (esm.isNextSub("XIDX")) // index in the stack?
|
||||
esm.skipHSub();
|
||||
|
||||
std::string script = esm.getHNOString("SCRI");
|
||||
// script variables?
|
||||
// unsure if before or after ESM::CellRef
|
||||
if (!script.empty())
|
||||
{
|
||||
if (esm.isNextSub("SLCS"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("SLSD")) // Short Data?
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("SLFD")) // Float Data?
|
||||
esm.skipHSub();
|
||||
}
|
||||
item.mSCRI.load(esm);
|
||||
|
||||
// for XSOL and XCHG seen so far, but probably others too
|
||||
item.ESM::CellRef::loadData(esm);
|
||||
|
||||
item.mCondition = -1;
|
||||
// FIXME: for Lights, this is actually a float
|
||||
esm.getHNOT(item.mCondition, "XHLT");
|
||||
int charge=-1;
|
||||
esm.getHNOT(charge, "XHLT");
|
||||
item.mChargeInt = charge;
|
||||
}
|
||||
|
||||
mItems.push_back(item);
|
||||
|
@ -55,14 +47,21 @@ namespace ESSImport
|
|||
{
|
||||
// note: same item can be equipped 2 items (e.g. 2 rings)
|
||||
// and will be *stacked* in the NPCO list, unlike openmw!
|
||||
// this is currently not handled properly.
|
||||
|
||||
esm.getSubHeader();
|
||||
int itemIndex; // index of the item in the NPCO list
|
||||
esm.getT(itemIndex);
|
||||
|
||||
if (itemIndex < 0 || itemIndex >= int(mItems.size()))
|
||||
esm.fail("equipment item index out of range");
|
||||
|
||||
// appears to be a relative index for only the *possible* slots this item can be equipped in,
|
||||
// i.e. 0 most of the time, unlike openmw slot enum index
|
||||
// i.e. 0 most of the time
|
||||
int slotIndex;
|
||||
esm.getT(slotIndex);
|
||||
|
||||
mItems[itemIndex].mRelativeEquipmentSlot = slotIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <string>
|
||||
|
||||
#include <components/esm/cellref.hpp>
|
||||
#include "importscri.hpp"
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
|
@ -20,7 +21,8 @@ namespace ESSImport
|
|||
{
|
||||
std::string mId;
|
||||
int mCount;
|
||||
int mCondition;
|
||||
int mRelativeEquipmentSlot;
|
||||
SCRI mSCRI;
|
||||
};
|
||||
std::vector<InventoryItem> mItems;
|
||||
|
||||
|
|
13
apps/essimporter/importjour.cpp
Normal file
13
apps/essimporter/importjour.cpp
Normal file
|
@ -0,0 +1,13 @@
|
|||
#include "importjour.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void JOUR::load(ESM::ESMReader &esm)
|
||||
{
|
||||
mText = esm.getHNString("NAME");
|
||||
}
|
||||
|
||||
}
|
25
apps/essimporter/importjour.hpp
Normal file
25
apps/essimporter/importjour.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTJOUR_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTJOUR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Journal
|
||||
struct JOUR
|
||||
{
|
||||
// The entire journal, in HTML
|
||||
std::string mText;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -9,11 +9,9 @@ namespace ESSImport
|
|||
{
|
||||
esm.getHNT(mNPDT, "NPDT");
|
||||
|
||||
if (esm.isNextSub("AI_E"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("AI_T"))
|
||||
esm.skipHSub();
|
||||
if (esm.isNextSub("AI_F"))
|
||||
// FIXME: use AiPackageList, need to fix getSubName()
|
||||
while (esm.isNextSub("AI_W") || esm.isNextSub("AI_E") || esm.isNextSub("AI_T") || esm.isNextSub("AI_F")
|
||||
|| esm.isNextSub("AI_A"))
|
||||
esm.skipHSub();
|
||||
|
||||
mInventory.load(esm);
|
||||
|
|
|
@ -23,6 +23,10 @@ namespace ESSImport
|
|||
mKnownDialogueTopics.push_back(esm.getHString());
|
||||
}
|
||||
|
||||
if (esm.isNextSub("MNAM"))
|
||||
esm.skipHSub(); // If this field is here it seems to specify the interior cell the player is in,
|
||||
// but it's not always here, so it's kinda useless
|
||||
|
||||
esm.getHNT(mPNAM, "PNAM");
|
||||
|
||||
if (esm.isNextSub("SNAM"))
|
||||
|
@ -59,8 +63,11 @@ namespace ESSImport
|
|||
mFactions.push_back(fnam);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("AADT"))
|
||||
esm.skipHSub(); // 44 bytes, no clue
|
||||
|
||||
if (esm.isNextSub("KNAM"))
|
||||
esm.skipHSub();
|
||||
esm.skipHSub(); // assigned Quick Keys, I think
|
||||
|
||||
if (esm.isNextSub("WERE"))
|
||||
{
|
||||
|
@ -69,6 +76,10 @@ namespace ESSImport
|
|||
esm.getSubHeader();
|
||||
esm.skip(152);
|
||||
}
|
||||
|
||||
// unsure if before or after WERE
|
||||
if (esm.isNextSub("ANIS"))
|
||||
esm.skipHSub();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
14
apps/essimporter/importques.cpp
Normal file
14
apps/essimporter/importques.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include "importques.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void QUES::load(ESM::ESMReader &esm)
|
||||
{
|
||||
while (esm.isNextSub("DATA"))
|
||||
mInfo.push_back(esm.getHString());
|
||||
}
|
||||
|
||||
}
|
28
apps/essimporter/importques.hpp
Normal file
28
apps/essimporter/importques.hpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTQUES_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTQUES_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
struct ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// State for a quest
|
||||
/// Presumably this record only exists when Tribunal is installed,
|
||||
/// since pre-Tribunal there weren't any quest names in the data files.
|
||||
struct QUES
|
||||
{
|
||||
std::string mName; // NAME, should be assigned from outside as usual
|
||||
std::vector<std::string> mInfo; // list of journal entries for the quest
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
20
apps/essimporter/importscpt.cpp
Normal file
20
apps/essimporter/importscpt.cpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#include "importscpt.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void SCPT::load(ESM::ESMReader &esm)
|
||||
{
|
||||
esm.getHNT(mSCHD, "SCHD");
|
||||
|
||||
mSCRI.load(esm);
|
||||
|
||||
mRNAM = -1;
|
||||
esm.getHNOT(mRNAM, "RNAM");
|
||||
}
|
||||
|
||||
}
|
32
apps/essimporter/importscpt.hpp
Normal file
32
apps/essimporter/importscpt.hpp
Normal file
|
@ -0,0 +1,32 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTSCPT_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTSCPT_H
|
||||
|
||||
#include "importscri.hpp"
|
||||
|
||||
#include <components/esm/loadscpt.hpp>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
// A running global script
|
||||
// TODO: test how targeted scripts are saved
|
||||
struct SCPT
|
||||
{
|
||||
ESM::Script::SCHD mSCHD;
|
||||
|
||||
// values of local variables
|
||||
SCRI mSCRI;
|
||||
|
||||
int mRNAM; // unknown, seems to be -1 for some scripts, some huge integer for others
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
55
apps/essimporter/importscri.cpp
Normal file
55
apps/essimporter/importscri.cpp
Normal file
|
@ -0,0 +1,55 @@
|
|||
#include "importscri.hpp"
|
||||
|
||||
#include <components/esm/esmreader.hpp>
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
void SCRI::load(ESM::ESMReader &esm)
|
||||
{
|
||||
mScript = esm.getHNOString("SCRI");
|
||||
|
||||
int numShorts = 0, numLongs = 0, numFloats = 0;
|
||||
if (esm.isNextSub("SLCS"))
|
||||
{
|
||||
esm.getSubHeader();
|
||||
esm.getT(numShorts);
|
||||
esm.getT(numLongs);
|
||||
esm.getT(numFloats);
|
||||
}
|
||||
|
||||
if (esm.isNextSub("SLSD"))
|
||||
{
|
||||
esm.getSubHeader();
|
||||
for (int i=0; i<numShorts; ++i)
|
||||
{
|
||||
short val;
|
||||
esm.getT(val);
|
||||
mShorts.push_back(val);
|
||||
}
|
||||
}
|
||||
// I haven't seen Longs in a save file yet, but SLLD would make sense for the name
|
||||
// TODO: test this
|
||||
if (esm.isNextSub("SLLD"))
|
||||
{
|
||||
esm.getSubHeader();
|
||||
for (int i=0; i<numLongs; ++i)
|
||||
{
|
||||
int val;
|
||||
esm.getT(val);
|
||||
mLongs.push_back(val);
|
||||
}
|
||||
}
|
||||
if (esm.isNextSub("SLFD"))
|
||||
{
|
||||
esm.getSubHeader();
|
||||
for (int i=0; i<numFloats; ++i)
|
||||
{
|
||||
float val;
|
||||
esm.getT(val);
|
||||
mFloats.push_back(val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
30
apps/essimporter/importscri.hpp
Normal file
30
apps/essimporter/importscri.hpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
#ifndef OPENMW_ESSIMPORT_IMPORTSCRI_H
|
||||
#define OPENMW_ESSIMPORT_IMPORTSCRI_H
|
||||
|
||||
#include <components/esm/variant.hpp>
|
||||
|
||||
#include <vector>
|
||||
|
||||
namespace ESM
|
||||
{
|
||||
class ESMReader;
|
||||
}
|
||||
|
||||
namespace ESSImport
|
||||
{
|
||||
|
||||
/// Local variable assigments for a running script
|
||||
struct SCRI
|
||||
{
|
||||
std::string mScript;
|
||||
|
||||
std::vector<short> mShorts;
|
||||
std::vector<int> mLongs;
|
||||
std::vector<float> mFloats;
|
||||
|
||||
void load(ESM::ESMReader& esm);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -12,7 +12,7 @@ namespace bfs = boost::filesystem;
|
|||
|
||||
|
||||
|
||||
int main(int argc, const char** argv)
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
@ -50,7 +50,15 @@ int main(int argc, const char** argv)
|
|||
if (vm.count("compare"))
|
||||
importer.compare();
|
||||
else
|
||||
{
|
||||
const std::string& ext = ".omwsave";
|
||||
if (boost::filesystem::exists(boost::filesystem::path(outputFile))
|
||||
&& (outputFile.size() < ext.size() || outputFile.substr(outputFile.size()-ext.size()) != ext))
|
||||
{
|
||||
throw std::runtime_error("Output file already exists and does not end in .omwsave. Did you mean to use --compare?");
|
||||
}
|
||||
importer.run();
|
||||
}
|
||||
}
|
||||
catch (std::exception& e)
|
||||
{
|
||||
|
|
|
@ -1053,13 +1053,13 @@ namespace CSMWorld
|
|||
|
||||
virtual QVariant get (const Record<ESXRecordT>& record) const
|
||||
{
|
||||
return record.get().mCharge;
|
||||
return record.get().mChargeInt;
|
||||
}
|
||||
|
||||
virtual void set (Record<ESXRecordT>& record, const QVariant& data)
|
||||
{
|
||||
ESXRecordT record2 = record.get();
|
||||
record2.mCharge = data.toInt();
|
||||
record2.mChargeInt = data.toInt();
|
||||
record.setModified (record2);
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace MWBase
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type) = 0;
|
||||
|
||||
/// Changes faction1's opinion of faction2 by \a diff.
|
||||
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff) = 0;
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace MWBase
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const = 0;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -193,7 +193,7 @@ namespace MWBase
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type) = 0;
|
||||
|
||||
virtual void clear() = 0;
|
||||
|
||||
|
|
|
@ -310,7 +310,7 @@ namespace MWBase
|
|||
virtual void clear() = 0;
|
||||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) = 0;
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type) = 0;
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type) = 0;
|
||||
virtual int countSavedGameRecords() const = 0;
|
||||
|
||||
/// Does the current stack of GUI-windows permit saving?
|
||||
|
|
|
@ -108,7 +108,7 @@ namespace MWBase
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const = 0;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||
const std::map<int, int>& contentFileMap) = 0;
|
||||
|
||||
virtual MWWorld::CellStore *getExterior (int x, int y) = 0;
|
||||
|
|
|
@ -26,27 +26,6 @@
|
|||
#include "../mwrender/actors.hpp"
|
||||
#include "../mwrender/renderinginterface.hpp"
|
||||
|
||||
namespace
|
||||
{
|
||||
struct LightCustomData : public MWWorld::CustomData
|
||||
{
|
||||
float mTime;
|
||||
///< Time remaining
|
||||
|
||||
LightCustomData(MWWorld::Ptr ptr)
|
||||
{
|
||||
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
|
||||
mTime = ref->mBase->mData.mTime;
|
||||
}
|
||||
///< Constructs this CustomData from the base values for Ptr.
|
||||
|
||||
virtual MWWorld::CustomData *clone() const
|
||||
{
|
||||
return new LightCustomData (*this);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
namespace MWClass
|
||||
{
|
||||
std::string Light::getId (const MWWorld::Ptr& ptr) const
|
||||
|
@ -219,17 +198,16 @@ namespace MWClass
|
|||
|
||||
void Light::setRemainingUsageTime (const MWWorld::Ptr& ptr, float duration) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
float &timeRemaining = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
|
||||
timeRemaining = duration;
|
||||
ptr.getCellRef().setChargeFloat(duration);
|
||||
}
|
||||
|
||||
float Light::getRemainingUsageTime (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
ensureCustomData(ptr);
|
||||
|
||||
return dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
|
||||
MWWorld::LiveCellRef<ESM::Light> *ref = ptr.get<ESM::Light>();
|
||||
if (ptr.getCellRef().getCharge() == -1)
|
||||
return ref->mBase->mData.mTime;
|
||||
else
|
||||
return ptr.getCellRef().getChargeFloat();
|
||||
}
|
||||
|
||||
MWWorld::Ptr
|
||||
|
@ -241,12 +219,6 @@ namespace MWClass
|
|||
return MWWorld::Ptr(&cell.get<ESM::Light>().insert(*ref), &cell);
|
||||
}
|
||||
|
||||
void Light::ensureCustomData (const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
if (!ptr.getRefData().getCustomData())
|
||||
ptr.getRefData().setCustomData(new LightCustomData(ptr));
|
||||
}
|
||||
|
||||
bool Light::canSell (const MWWorld::Ptr& item, int npcServices) const
|
||||
{
|
||||
return npcServices & ESM::NPC::Lights;
|
||||
|
@ -282,22 +254,6 @@ namespace MWClass
|
|||
return std::make_pair(1,"");
|
||||
}
|
||||
|
||||
void Light::readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
const
|
||||
{
|
||||
ensureCustomData (ptr);
|
||||
|
||||
dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime = state.mTime;
|
||||
}
|
||||
|
||||
void Light::writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||
const
|
||||
{
|
||||
ensureCustomData (ptr);
|
||||
|
||||
state.mTime = dynamic_cast<LightCustomData&> (*ptr.getRefData().getCustomData()).mTime;
|
||||
}
|
||||
|
||||
std::string Light::getSound(const MWWorld::Ptr& ptr) const
|
||||
{
|
||||
return ptr.get<ESM::Light>()->mBase->mSound;
|
||||
|
|
|
@ -10,8 +10,6 @@ namespace MWClass
|
|||
virtual MWWorld::Ptr
|
||||
copyToCellImpl(const MWWorld::Ptr &ptr, MWWorld::CellStore &cell) const;
|
||||
|
||||
void ensureCustomData (const MWWorld::Ptr& ptr) const;
|
||||
|
||||
public:
|
||||
|
||||
/// Return ID of \a ptr
|
||||
|
@ -75,14 +73,6 @@ namespace MWClass
|
|||
|
||||
std::pair<int, std::string> canBeEquipped(const MWWorld::Ptr &ptr, const MWWorld::Ptr &npc) const;
|
||||
|
||||
virtual void readAdditionalState (const MWWorld::Ptr& ptr, const ESM::ObjectState& state)
|
||||
const;
|
||||
///< Read additional state from \a state into \a ptr.
|
||||
|
||||
virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state)
|
||||
const;
|
||||
///< Write additional state from \a ptr into \a state.
|
||||
|
||||
virtual std::string getSound(const MWWorld::Ptr& ptr) const;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -647,7 +647,7 @@ namespace MWDialogue
|
|||
writer.endRecord (ESM::REC_DIAS);
|
||||
}
|
||||
|
||||
void DialogueManager::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
void DialogueManager::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type==ESM::REC_DIAS)
|
||||
{
|
||||
|
|
|
@ -92,7 +92,7 @@ namespace MWDialogue
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
/// Changes faction1's opinion of faction2 by \a diff.
|
||||
virtual void modFactionReaction (const std::string& faction1, const std::string& faction2, int diff);
|
||||
|
|
|
@ -227,9 +227,9 @@ namespace MWDialogue
|
|||
}
|
||||
}
|
||||
|
||||
void Journal::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
void Journal::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type==ESM::REC_JOUR)
|
||||
if (type==ESM::REC_JOUR || type==ESM::REC_JOUR_LEGACY)
|
||||
{
|
||||
ESM::JournalEntry record;
|
||||
record.load (reader);
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace MWDialogue
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -886,7 +886,7 @@ namespace MWGui
|
|||
writer.endRecord(ESM::REC_GMAP);
|
||||
}
|
||||
|
||||
void MapWindow::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
void MapWindow::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
if (type == ESM::REC_GMAP)
|
||||
{
|
||||
|
|
|
@ -177,7 +177,7 @@ namespace MWGui
|
|||
void clear();
|
||||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
private:
|
||||
void onDragStart(MyGUI::Widget* _sender, int _left, int _top, MyGUI::MouseButton _id);
|
||||
|
|
|
@ -431,7 +431,7 @@ namespace MWGui
|
|||
writer.endRecord(ESM::REC_KEYS);
|
||||
}
|
||||
|
||||
void QuickKeysMenu::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
void QuickKeysMenu::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
if (type != ESM::REC_KEYS)
|
||||
return;
|
||||
|
|
|
@ -47,7 +47,7 @@ namespace MWGui
|
|||
|
||||
|
||||
void write (ESM::ESMWriter& writer);
|
||||
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
void clear();
|
||||
|
||||
|
||||
|
|
|
@ -1620,7 +1620,7 @@ namespace MWGui
|
|||
}
|
||||
}
|
||||
|
||||
void WindowManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
void WindowManager::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
if (type == ESM::REC_GMAP)
|
||||
mMap->readRecord(reader, type);
|
||||
|
|
|
@ -306,7 +306,7 @@ namespace MWGui
|
|||
virtual void clear();
|
||||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
virtual int countSavedGameRecords() const;
|
||||
|
||||
/// Does the current stack of GUI-windows permit saving?
|
||||
|
|
|
@ -1468,7 +1468,7 @@ namespace MWMechanics
|
|||
writer.endRecord(ESM::REC_DCOU);
|
||||
}
|
||||
|
||||
void Actors::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
void Actors::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type == ESM::REC_DCOU)
|
||||
{
|
||||
|
|
|
@ -128,7 +128,7 @@ namespace MWMechanics
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& listener) const;
|
||||
|
||||
void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
void clear(); // Clear death counter
|
||||
|
||||
|
|
|
@ -1360,7 +1360,7 @@ namespace MWMechanics
|
|||
mActors.write(writer, listener);
|
||||
}
|
||||
|
||||
void MechanicsManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
void MechanicsManager::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
mActors.readRecord(reader, type);
|
||||
}
|
||||
|
|
|
@ -158,7 +158,7 @@ namespace MWMechanics
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& listener) const;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
virtual void clear();
|
||||
|
||||
|
|
|
@ -472,9 +472,7 @@ namespace MWMechanics
|
|||
applyInstantEffect(target, caster, EffectKey(*effectIt), magnitude);
|
||||
|
||||
// Re-casting a summon effect will remove the creature from previous castings of that effect.
|
||||
if (effectIt->mEffectID >= ESM::MagicEffect::SummonScamp
|
||||
&& effectIt->mEffectID <= ESM::MagicEffect::SummonStormAtronach
|
||||
&& !target.isEmpty() && target.getClass().isActor())
|
||||
if (isSummoningEffect(effectIt->mEffectID) && !target.isEmpty() && target.getClass().isActor())
|
||||
{
|
||||
CreatureStats& targetStats = target.getClass().getCreatureStats(target);
|
||||
std::map<CreatureStats::SummonKey, int>::iterator found = targetStats.getSummonedCreatureMap().find(std::make_pair(effectIt->mEffectID, mId));
|
||||
|
@ -956,4 +954,13 @@ namespace MWMechanics
|
|||
|
||||
return static_cast<int>((result < 1) ? 1 : result);
|
||||
}
|
||||
|
||||
bool isSummoningEffect(int effectId)
|
||||
{
|
||||
return ((effectId >= ESM::MagicEffect::SummonScamp
|
||||
&& effectId <= ESM::MagicEffect::SummonStormAtronach)
|
||||
|| effectId == ESM::MagicEffect::SummonCenturionSphere
|
||||
|| (effectId >= ESM::MagicEffect::SummonFabricant
|
||||
&& effectId <= ESM::MagicEffect::SummonCreature05));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,8 @@ namespace MWMechanics
|
|||
|
||||
ESM::Skill::SkillEnum spellSchoolToSkill(int school);
|
||||
|
||||
bool isSummoningEffect(int effectId);
|
||||
|
||||
/**
|
||||
* @param spell spell to cast
|
||||
* @param actor calculate spell success chance for this actor (depends on actor's skills)
|
||||
|
|
|
@ -312,21 +312,17 @@ namespace MWMechanics
|
|||
|
||||
void Spells::readState(const ESM::SpellState &state)
|
||||
{
|
||||
mSpells = state.mSpells;
|
||||
mSelectedSpell = state.mSelectedSpell;
|
||||
|
||||
// Discard spells that are no longer available due to changed content files
|
||||
for (TContainer::iterator iter = mSpells.begin(); iter!=mSpells.end();)
|
||||
for (TContainer::const_iterator it = state.mSpells.begin(); it != state.mSpells.end(); ++it)
|
||||
{
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(iter->first);
|
||||
if (!spell)
|
||||
// Discard spells that are no longer available due to changed content files
|
||||
const ESM::Spell* spell = MWBase::Environment::get().getWorld()->getStore().get<ESM::Spell>().search(it->first);
|
||||
if (spell)
|
||||
{
|
||||
if (iter->first == mSelectedSpell)
|
||||
mSelectedSpell = "";
|
||||
mSpells.erase(iter++);
|
||||
mSpells[it->first] = it->second;
|
||||
|
||||
if (it->first == state.mSelectedSpell)
|
||||
mSelectedSpell = it->first;
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
}
|
||||
|
||||
// No need to discard spells here (doesn't really matter if non existent ids are kept)
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "../mwbase/environment.hpp"
|
||||
#include "../mwbase/world.hpp"
|
||||
|
||||
#include "../mwmechanics/spellcasting.hpp"
|
||||
|
||||
#include "../mwworld/esmstore.hpp"
|
||||
#include "../mwworld/class.hpp"
|
||||
#include "../mwworld/manualref.hpp"
|
||||
|
@ -51,8 +53,7 @@ namespace MWMechanics
|
|||
|
||||
void UpdateSummonedCreatures::visit(EffectKey key, const std::string &sourceName, const std::string &sourceId, int casterActorId, float magnitude, float remainingTime, float totalTime)
|
||||
{
|
||||
if (key.mId >= ESM::MagicEffect::SummonScamp
|
||||
&& key.mId <= ESM::MagicEffect::SummonStormAtronach && magnitude > 0)
|
||||
if (isSummoningEffect(key.mId) && magnitude > 0)
|
||||
{
|
||||
mActiveEffects.insert(std::make_pair(key.mId, sourceId));
|
||||
}
|
||||
|
|
|
@ -263,17 +263,27 @@ void NpcAnimation::updateNpcBase()
|
|||
}
|
||||
else
|
||||
{
|
||||
if (isVampire)
|
||||
mHeadModel = "";
|
||||
if (isVampire) // FIXME: fall back to regular head when getVampireHead fails?
|
||||
mHeadModel = getVampireHead(mNpc->mRace, mNpc->mFlags & ESM::NPC::Female);
|
||||
else if (!mNpc->mHead.empty())
|
||||
mHeadModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHead)->mModel;
|
||||
else
|
||||
mHeadModel = "";
|
||||
{
|
||||
const ESM::BodyPart* bp = store.get<ESM::BodyPart>().search(mNpc->mHead);
|
||||
if (bp)
|
||||
mHeadModel = "meshes\\" + bp->mModel;
|
||||
else
|
||||
std::cerr << "Failed to load body part '" << mNpc->mHead << "'" << std::endl;
|
||||
}
|
||||
|
||||
mHairModel = "";
|
||||
if (!mNpc->mHair.empty())
|
||||
mHairModel = "meshes\\" + store.get<ESM::BodyPart>().find(mNpc->mHair)->mModel;
|
||||
else
|
||||
mHairModel = "";
|
||||
{
|
||||
const ESM::BodyPart* bp = store.get<ESM::BodyPart>().search(mNpc->mHair);
|
||||
if (bp)
|
||||
mHairModel = "meshes\\" + bp->mModel;
|
||||
else
|
||||
std::cerr << "Failed to load body part '" << mNpc->mHair << "'" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||
|
@ -801,6 +811,8 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
|||
bodypart->mData.mPart == ESM::BodyPart::MP_Upperarm))
|
||||
bodypart = NULL;
|
||||
}
|
||||
else if (!bodypart)
|
||||
std::cerr << "Failed to find body part '" << part->mFemale << "'" << std::endl;
|
||||
}
|
||||
if(!bodypart && !part->mMale.empty())
|
||||
{
|
||||
|
@ -814,6 +826,8 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
|||
bodypart->mData.mPart == ESM::BodyPart::MP_Upperarm))
|
||||
bodypart = NULL;
|
||||
}
|
||||
else if (!bodypart)
|
||||
std::cerr << "Failed to find body part '" << part->mMale << "'" << std::endl;
|
||||
}
|
||||
|
||||
if(bodypart)
|
||||
|
|
|
@ -443,5 +443,6 @@ op 0x20002fc: RemoveFromLevCreature
|
|||
op 0x20002fd: AddToLevItem
|
||||
op 0x20002fe: RemoveFromLevItem
|
||||
op 0x20002ff: SetFactionReaction
|
||||
op 0x2000300: EnableLevelupMenu
|
||||
|
||||
opcodes 0x2000300-0x3ffffff unused
|
||||
opcodes 0x2000301-0x3ffffff unused
|
||||
|
|
|
@ -145,7 +145,7 @@ namespace MWScript
|
|||
}
|
||||
}
|
||||
|
||||
bool GlobalScripts::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
bool GlobalScripts::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type==ESM::REC_GSCR)
|
||||
{
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace MWScript
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
///< Records for variables that do not exist are dropped silently.
|
||||
///
|
||||
/// \return Known type?
|
||||
|
|
|
@ -231,6 +231,8 @@ namespace MWScript
|
|||
new OpShowDialogue (MWGui::GM_Race));
|
||||
interpreter.installSegment5 (Compiler::Gui::opcodeEnableStatsReviewMenu,
|
||||
new OpShowDialogue (MWGui::GM_Review));
|
||||
interpreter.installSegment5 (Compiler::Gui::opcodeEnableLevelupMenu,
|
||||
new OpShowDialogue (MWGui::GM_Levelup));
|
||||
|
||||
interpreter.installSegment5 (Compiler::Gui::opcodeEnableInventoryMenu,
|
||||
new OpEnableWindow (MWGui::GW_Inventory));
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -368,6 +368,7 @@ void MWState::StateManager::loadGame (const Character *character, const std::str
|
|||
break;
|
||||
|
||||
case ESM::REC_JOUR:
|
||||
case ESM::REC_JOUR_LEGACY:
|
||||
case ESM::REC_QUES:
|
||||
|
||||
MWBase::Environment::get().getJournal()->readRecord (reader, n.val);
|
||||
|
|
|
@ -81,15 +81,29 @@ namespace MWWorld
|
|||
|
||||
int CellRef::getCharge() const
|
||||
{
|
||||
return mCellRef.mCharge;
|
||||
return mCellRef.mChargeInt;
|
||||
}
|
||||
|
||||
void CellRef::setCharge(int charge)
|
||||
{
|
||||
if (charge != mCellRef.mCharge)
|
||||
if (charge != mCellRef.mChargeInt)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mCharge = charge;
|
||||
mCellRef.mChargeInt = charge;
|
||||
}
|
||||
}
|
||||
|
||||
float CellRef::getChargeFloat() const
|
||||
{
|
||||
return mCellRef.mChargeFloat;
|
||||
}
|
||||
|
||||
void CellRef::setChargeFloat(float charge)
|
||||
{
|
||||
if (charge != mCellRef.mChargeFloat)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mChargeFloat = charge;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,8 +60,11 @@ namespace MWWorld
|
|||
|
||||
// For weapon or armor, this is the remaining item health.
|
||||
// For tools (lockpicks, probes, repair hammer) it is the remaining uses.
|
||||
// If this returns int(-1) it means full health.
|
||||
int getCharge() const;
|
||||
float getChargeFloat() const; // Implemented as union with int charge
|
||||
void setCharge(int charge);
|
||||
void setChargeFloat(float charge);
|
||||
|
||||
// The NPC that owns this object (and will get angry if you steal it)
|
||||
std::string getOwner() const;
|
||||
|
|
|
@ -299,7 +299,7 @@ void MWWorld::Cells::write (ESM::ESMWriter& writer, Loading::Listener& progress)
|
|||
}
|
||||
}
|
||||
|
||||
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
bool MWWorld::Cells::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||
const std::map<int, int>& contentFileMap)
|
||||
{
|
||||
if (type==ESM::REC_CSTA)
|
||||
|
|
|
@ -76,7 +76,7 @@ namespace MWWorld
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||
const std::map<int, int>& contentFileMap);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -466,7 +466,7 @@ namespace MWWorld
|
|||
// List moved references, from separately tracked list.
|
||||
for (ESM::CellRefTracker::const_iterator it = mCell->mLeasedRefs.begin(); it != mCell->mLeasedRefs.end(); ++it)
|
||||
{
|
||||
ESM::CellRef &ref = const_cast<ESM::CellRef&>(*it);
|
||||
const ESM::CellRef &ref = *it;
|
||||
|
||||
mIds.push_back(Misc::StringUtils::lowerCase(ref.mRefID));
|
||||
}
|
||||
|
|
|
@ -79,6 +79,14 @@ MWWorld::ContainerStoreIterator MWWorld::ContainerStore::getState (CellRefList<T
|
|||
return ContainerStoreIterator (this, --collection.mList.end());
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::storeEquipmentState(const MWWorld::LiveCellRefBase &ref, int index, ESM::InventoryState &inventory) const
|
||||
{
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::readEquipmentState(const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState &inventory)
|
||||
{
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void MWWorld::ContainerStore::storeState (const LiveCellRef<T>& ref, ESM::ObjectState& state) const
|
||||
{
|
||||
|
@ -86,8 +94,8 @@ void MWWorld::ContainerStore::storeState (const LiveCellRef<T>& ref, ESM::Object
|
|||
}
|
||||
|
||||
template<typename T>
|
||||
void MWWorld::ContainerStore::storeStates (const CellRefList<T>& collection,
|
||||
std::vector<std::pair<ESM::ObjectState, int> >& states, bool equipable) const
|
||||
void MWWorld::ContainerStore::storeStates (CellRefList<T>& collection,
|
||||
ESM::InventoryState& inventory, int& index, bool equipable) const
|
||||
{
|
||||
for (typename CellRefList<T>::List::const_iterator iter (collection.mList.begin());
|
||||
iter!=collection.mList.end(); ++iter)
|
||||
|
@ -96,18 +104,13 @@ void MWWorld::ContainerStore::storeStates (const CellRefList<T>& collection,
|
|||
continue;
|
||||
ESM::ObjectState state;
|
||||
storeState (*iter, state);
|
||||
int slot = equipable ? getSlot (*iter) : -1;
|
||||
states.push_back (std::make_pair (state, slot));
|
||||
if (equipable)
|
||||
storeEquipmentState(*iter, index, inventory);
|
||||
inventory.mItems.push_back (state);
|
||||
++index;
|
||||
}
|
||||
}
|
||||
|
||||
int MWWorld::ContainerStore::getSlot (const MWWorld::LiveCellRefBase& ref) const
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::setSlot (const MWWorld::ContainerStoreIterator& iter, int slot) {}
|
||||
|
||||
const std::string MWWorld::ContainerStore::sGoldId = "gold_001";
|
||||
|
||||
MWWorld::ContainerStore::ContainerStore() : mCachedWeight (0), mWeightUpToDate (false) {}
|
||||
|
@ -641,62 +644,66 @@ MWWorld::Ptr MWWorld::ContainerStore::search (const std::string& id)
|
|||
return Ptr();
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state) const
|
||||
void MWWorld::ContainerStore::writeState (ESM::InventoryState& state)
|
||||
{
|
||||
state.mItems.clear();
|
||||
|
||||
storeStates (potions, state.mItems);
|
||||
storeStates (appas, state.mItems);
|
||||
storeStates (armors, state.mItems, true);
|
||||
storeStates (books, state.mItems);
|
||||
storeStates (clothes, state.mItems, true);
|
||||
storeStates (ingreds, state.mItems);
|
||||
storeStates (lockpicks, state.mItems, true);
|
||||
storeStates (miscItems, state.mItems);
|
||||
storeStates (probes, state.mItems, true);
|
||||
storeStates (repairs, state.mItems);
|
||||
storeStates (weapons, state.mItems, true);
|
||||
storeStates (lights, state.mItems, true);
|
||||
int index = 0;
|
||||
storeStates (potions, state, index);
|
||||
storeStates (appas, state, index);
|
||||
storeStates (armors, state, index, true);
|
||||
storeStates (books, state, index, true); // not equipable as such, but for selectedEnchantItem
|
||||
storeStates (clothes, state, index, true);
|
||||
storeStates (ingreds, state, index);
|
||||
storeStates (lockpicks, state, index, true);
|
||||
storeStates (miscItems, state, index);
|
||||
storeStates (probes, state, index, true);
|
||||
storeStates (repairs, state, index);
|
||||
storeStates (weapons, state, index, true);
|
||||
storeStates (lights, state, index, true);
|
||||
|
||||
state.mLevelledItemMap = mLevelledItemMap;
|
||||
}
|
||||
|
||||
void MWWorld::ContainerStore::readState (const ESM::InventoryState& state)
|
||||
void MWWorld::ContainerStore::readState (const ESM::InventoryState& inventory)
|
||||
{
|
||||
clear();
|
||||
|
||||
for (std::vector<std::pair<ESM::ObjectState, int> >::const_iterator
|
||||
iter (state.mItems.begin()); iter!=state.mItems.end(); ++iter)
|
||||
int index = 0;
|
||||
for (std::vector<ESM::ObjectState>::const_iterator
|
||||
iter (inventory.mItems.begin()); iter!=inventory.mItems.end(); ++iter)
|
||||
{
|
||||
int slot = iter->second;
|
||||
|
||||
const ESM::ObjectState& state = iter->first;
|
||||
const ESM::ObjectState& state = *iter;
|
||||
|
||||
int type = MWBase::Environment::get().getWorld()->getStore().find(state.mRef.mRefID);
|
||||
|
||||
int thisIndex = index++;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case ESM::REC_ALCH: getState (potions, iter->first); break;
|
||||
case ESM::REC_APPA: getState (appas, iter->first); break;
|
||||
case ESM::REC_ARMO: setSlot (getState (armors, iter->first), slot); break;
|
||||
case ESM::REC_BOOK: getState (books, iter->first); break;
|
||||
case ESM::REC_CLOT: setSlot (getState (clothes, iter->first), slot); break;
|
||||
case ESM::REC_INGR: getState (ingreds, iter->first); break;
|
||||
case ESM::REC_LOCK: setSlot (getState (lockpicks, iter->first), slot); break;
|
||||
case ESM::REC_MISC: getState (miscItems, iter->first); break;
|
||||
case ESM::REC_PROB: setSlot (getState (probes, iter->first), slot); break;
|
||||
case ESM::REC_REPA: getState (repairs, iter->first); break;
|
||||
case ESM::REC_WEAP: setSlot (getState (weapons, iter->first), slot); break;
|
||||
case ESM::REC_LIGH: setSlot (getState (lights, iter->first), slot); break;
|
||||
|
||||
case ESM::REC_ALCH: getState (potions, state); break;
|
||||
case ESM::REC_APPA: getState (appas, state); break;
|
||||
case ESM::REC_ARMO: readEquipmentState (getState (armors, state), thisIndex, inventory); break;
|
||||
case ESM::REC_BOOK: readEquipmentState (getState (books, state), thisIndex, inventory); break; // not equipable as such, but for selectedEnchantItem
|
||||
case ESM::REC_CLOT: readEquipmentState (getState (clothes, state), thisIndex, inventory); break;
|
||||
case ESM::REC_INGR: getState (ingreds, state); break;
|
||||
case ESM::REC_LOCK: readEquipmentState (getState (lockpicks, state), thisIndex, inventory); break;
|
||||
case ESM::REC_MISC: getState (miscItems, state); break;
|
||||
case ESM::REC_PROB: readEquipmentState (getState (probes, state), thisIndex, inventory); break;
|
||||
case ESM::REC_REPA: getState (repairs, state); break;
|
||||
case ESM::REC_WEAP: readEquipmentState (getState (weapons, state), thisIndex, inventory); break;
|
||||
case ESM::REC_LIGH: readEquipmentState (getState (lights, state), thisIndex, inventory); break;
|
||||
case 0:
|
||||
std::cerr << "Dropping reference to '" << state.mRef.mRefID << "' (object no longer exists)" << std::endl;
|
||||
break;
|
||||
default:
|
||||
std::cerr << "invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl;
|
||||
std::cerr << "Invalid item type in inventory state, refid " << state.mRef.mRefID << std::endl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
mLevelledItemMap = state.mLevelledItemMap;
|
||||
mLevelledItemMap = inventory.mLevelledItemMap;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -85,16 +85,13 @@ namespace MWWorld
|
|||
void storeState (const LiveCellRef<T>& ref, ESM::ObjectState& state) const;
|
||||
|
||||
template<typename T>
|
||||
void storeStates (const CellRefList<T>& collection,
|
||||
std::vector<std::pair<ESM::ObjectState, int> >& states,
|
||||
void storeStates (CellRefList<T>& collection,
|
||||
ESM::InventoryState& inventory, int& index,
|
||||
bool equipable = false) const;
|
||||
|
||||
virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const;
|
||||
///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot).
|
||||
|
||||
virtual void setSlot (const MWWorld::ContainerStoreIterator& iter, int slot);
|
||||
///< Set slot for \a iter. Ignored if \a iter is an end iterator or if slot==-1.
|
||||
virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const;
|
||||
|
||||
virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory);
|
||||
public:
|
||||
|
||||
ContainerStore();
|
||||
|
@ -171,7 +168,8 @@ namespace MWWorld
|
|||
|
||||
Ptr search (const std::string& id);
|
||||
|
||||
virtual void writeState (ESM::InventoryState& state) const;
|
||||
/// \todo make this method const once const-correct ContainerStoreIterators are available
|
||||
virtual void writeState (ESM::InventoryState& state);
|
||||
|
||||
virtual void readState (const ESM::InventoryState& state);
|
||||
|
||||
|
|
|
@ -175,7 +175,7 @@ void ESMStore::setUp()
|
|||
mCreatureLists.write (writer, progress);
|
||||
}
|
||||
|
||||
bool ESMStore::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
bool ESMStore::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
|
|
|
@ -233,7 +233,7 @@ namespace MWWorld
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
///< \return Known type?
|
||||
};
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
bool Globals::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
bool Globals::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type==ESM::REC_GLOB)
|
||||
{
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace MWWorld
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
///< Records for variables that do not exist are dropped silently.
|
||||
///
|
||||
/// \return Known type?
|
||||
|
|
|
@ -49,19 +49,47 @@ void MWWorld::InventoryStore::initSlots (TSlots& slots_)
|
|||
slots_.push_back (end());
|
||||
}
|
||||
|
||||
int MWWorld::InventoryStore::getSlot (const MWWorld::LiveCellRefBase& ref) const
|
||||
void MWWorld::InventoryStore::storeEquipmentState(const MWWorld::LiveCellRefBase &ref, int index, ESM::InventoryState &inventory) const
|
||||
{
|
||||
for (int i = 0; i<static_cast<int> (mSlots.size()); ++i)
|
||||
if (mSlots[i].getType()!=-1 && mSlots[i]->getBase()==&ref)
|
||||
return i;
|
||||
{
|
||||
inventory.mEquipmentSlots[index] = i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
if (mSelectedEnchantItem.getType()!=-1 && mSelectedEnchantItem->getBase() == &ref)
|
||||
inventory.mSelectedEnchantItem = index;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::setSlot (const MWWorld::ContainerStoreIterator& iter, int slot)
|
||||
void MWWorld::InventoryStore::readEquipmentState(const MWWorld::ContainerStoreIterator &iter, int index, const ESM::InventoryState &inventory)
|
||||
{
|
||||
if (iter!=end() && slot>=0 && slot<Slots)
|
||||
mSlots[slot] = iter;
|
||||
if (index == inventory.mSelectedEnchantItem)
|
||||
mSelectedEnchantItem = iter;
|
||||
|
||||
std::map<int, int>::const_iterator found = inventory.mEquipmentSlots.find(index);
|
||||
if (found != inventory.mEquipmentSlots.end())
|
||||
{
|
||||
if (found->second < 0 || found->second >= MWWorld::InventoryStore::Slots)
|
||||
throw std::runtime_error("Invalid slot index in inventory state");
|
||||
|
||||
// make sure the item can actually be equipped in this slot
|
||||
int slot = found->second;
|
||||
std::pair<std::vector<int>, bool> allowedSlots = iter->getClass().getEquipmentSlots(*iter);
|
||||
if (!allowedSlots.first.size())
|
||||
return;
|
||||
if (std::find(allowedSlots.first.begin(), allowedSlots.first.end(), slot) == allowedSlots.first.end())
|
||||
slot = allowedSlots.first.front();
|
||||
|
||||
// unstack if required
|
||||
if (!allowedSlots.second && iter->getRefData().getCount() > 1)
|
||||
{
|
||||
MWWorld::ContainerStoreIterator newIter = addNewStack(*iter, 1);
|
||||
iter->getRefData().setCount(iter->getRefData().getCount()-1);
|
||||
mSlots[slot] = newIter;
|
||||
}
|
||||
else
|
||||
mSlots[slot] = iter;
|
||||
}
|
||||
}
|
||||
|
||||
MWWorld::InventoryStore::InventoryStore()
|
||||
|
@ -703,7 +731,7 @@ bool MWWorld::InventoryStore::isEquipped(const MWWorld::Ptr &item)
|
|||
return false;
|
||||
}
|
||||
|
||||
void MWWorld::InventoryStore::writeState(ESM::InventoryState &state) const
|
||||
void MWWorld::InventoryStore::writeState(ESM::InventoryState &state)
|
||||
{
|
||||
MWWorld::ContainerStore::writeState(state);
|
||||
|
||||
|
|
|
@ -113,11 +113,8 @@ namespace MWWorld
|
|||
|
||||
void fireEquipmentChangedEvent();
|
||||
|
||||
virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const;
|
||||
///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot).
|
||||
|
||||
virtual void setSlot (const MWWorld::ContainerStoreIterator& iter, int slot);
|
||||
///< Set slot for \a iter. Ignored if \a iter is an end iterator or if slot==-1.
|
||||
virtual void storeEquipmentState (const MWWorld::LiveCellRefBase& ref, int index, ESM::InventoryState& inventory) const;
|
||||
virtual void readEquipmentState (const MWWorld::ContainerStoreIterator& iter, int index, const ESM::InventoryState& inventory);
|
||||
|
||||
public:
|
||||
|
||||
|
@ -209,7 +206,7 @@ namespace MWWorld
|
|||
virtual void clear();
|
||||
///< Empty container.
|
||||
|
||||
virtual void writeState (ESM::InventoryState& state) const;
|
||||
virtual void writeState (ESM::InventoryState& state);
|
||||
|
||||
virtual void readState (const ESM::InventoryState& state);
|
||||
};
|
||||
|
|
|
@ -28,7 +28,7 @@ namespace MWWorld
|
|||
cellRef.mRefID = name;
|
||||
cellRef.mScale = 1;
|
||||
cellRef.mFactionRank = 0;
|
||||
cellRef.mCharge = -1;
|
||||
cellRef.mChargeInt = -1;
|
||||
cellRef.mGoldValue = 1;
|
||||
cellRef.mEnchantmentCharge = -1;
|
||||
cellRef.mTeleport = false;
|
||||
|
|
|
@ -227,7 +227,7 @@ namespace MWWorld
|
|||
writer.endRecord (ESM::REC_PLAY);
|
||||
}
|
||||
|
||||
bool Player::readRecord (ESM::ESMReader& reader, int32_t type)
|
||||
bool Player::readRecord (ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if (type==ESM::REC_PLAY)
|
||||
{
|
||||
|
|
|
@ -102,7 +102,7 @@ namespace MWWorld
|
|||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
int getNewCrimeId(); // get new id for witnesses
|
||||
void recordCrimeId(); // record the paid crime id when bounty is 0
|
||||
|
|
|
@ -343,7 +343,7 @@ namespace MWWorld
|
|||
}
|
||||
}
|
||||
|
||||
bool ProjectileManager::readRecord(ESM::ESMReader &reader, int32_t type)
|
||||
bool ProjectileManager::readRecord(ESM::ESMReader &reader, uint32_t type)
|
||||
{
|
||||
if (type == ESM::REC_PROJ)
|
||||
{
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace MWWorld
|
|||
void clear();
|
||||
|
||||
void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
bool readRecord (ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord (ESM::ESMReader& reader, uint32_t type);
|
||||
int countSavedGameRecords() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -762,7 +762,7 @@ void WeatherManager::write(ESM::ESMWriter& writer, Loading::Listener& progress)
|
|||
writer.endRecord(ESM::REC_WTHR);
|
||||
}
|
||||
|
||||
bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type)
|
||||
bool WeatherManager::readRecord(ESM::ESMReader& reader, uint32_t type)
|
||||
{
|
||||
if(ESM::REC_WTHR == type)
|
||||
{
|
||||
|
@ -770,14 +770,6 @@ bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type)
|
|||
ESM::WeatherState state;
|
||||
state.load(reader);
|
||||
|
||||
// reset other temporary state, now that we loaded successfully
|
||||
stopSounds(); // let's hope this never throws
|
||||
mRegionOverrides.clear();
|
||||
mRegionMods.clear();
|
||||
mThunderFlash = 0.0;
|
||||
mThunderChance = 0.0;
|
||||
mThunderChanceNeeded = 50.0;
|
||||
|
||||
// swap in the loaded values now that we can't fail
|
||||
mHour = state.mHour;
|
||||
mWindSpeed = state.mWindSpeed;
|
||||
|
@ -794,6 +786,16 @@ bool WeatherManager::readRecord(ESM::ESMReader& reader, int32_t type)
|
|||
return false;
|
||||
}
|
||||
|
||||
void WeatherManager::clear()
|
||||
{
|
||||
stopSounds();
|
||||
mRegionOverrides.clear();
|
||||
mRegionMods.clear();
|
||||
mThunderFlash = 0.0;
|
||||
mThunderChance = 0.0;
|
||||
mThunderChanceNeeded = 50.0;
|
||||
}
|
||||
|
||||
void WeatherManager::switchToNextWeather(bool instantly)
|
||||
{
|
||||
MWBase::World* world = MWBase::Environment::get().getWorld();
|
||||
|
|
|
@ -199,7 +199,9 @@ namespace MWWorld
|
|||
|
||||
void write(ESM::ESMWriter& writer, Loading::Listener& progress);
|
||||
|
||||
bool readRecord(ESM::ESMReader& reader, int32_t type);
|
||||
bool readRecord(ESM::ESMReader& reader, uint32_t type);
|
||||
|
||||
void clear();
|
||||
|
||||
private:
|
||||
float mHour;
|
||||
|
|
|
@ -265,6 +265,7 @@ namespace MWWorld
|
|||
|
||||
void World::clear()
|
||||
{
|
||||
mWeatherManager->clear();
|
||||
mRendering->clear();
|
||||
|
||||
mProjectileManager->clear();
|
||||
|
@ -345,7 +346,7 @@ namespace MWWorld
|
|||
writer.endRecord(ESM::REC_CAM_);
|
||||
}
|
||||
|
||||
void World::readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
void World::readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||
const std::map<int, int>& contentFileMap)
|
||||
{
|
||||
switch (type)
|
||||
|
@ -2031,7 +2032,7 @@ namespace MWWorld
|
|||
bool World::isOnGround(const MWWorld::Ptr &ptr) const
|
||||
{
|
||||
RefData &refdata = ptr.getRefData();
|
||||
const OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
|
||||
OEngine::Physic::PhysicActor *physactor = mPhysEngine->getCharacter(refdata.getHandle());
|
||||
|
||||
if(!physactor)
|
||||
return false;
|
||||
|
@ -2049,7 +2050,7 @@ namespace MWWorld
|
|||
mPhysEngine);
|
||||
if(tracer.mFraction < 1.0f) // collision, must be close to something below
|
||||
{
|
||||
const_cast<OEngine::Physic::PhysicActor *> (physactor)->setOnGround(true);
|
||||
physactor->setOnGround(true);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace MWWorld
|
|||
|
||||
virtual void write (ESM::ESMWriter& writer, Loading::Listener& progress) const;
|
||||
|
||||
virtual void readRecord (ESM::ESMReader& reader, int32_t type,
|
||||
virtual void readRecord (ESM::ESMReader& reader, uint32_t type,
|
||||
const std::map<int, int>& contentFileMap);
|
||||
|
||||
virtual CellStore *getExterior (int x, int y);
|
||||
|
|
|
@ -215,7 +215,7 @@ namespace Compiler
|
|||
extensions.registerInstruction ("enablestatsmenu", "", opcodeEnableStatsMenu);
|
||||
|
||||
extensions.registerInstruction ("enablerest", "", opcodeEnableRest);
|
||||
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableRest);
|
||||
extensions.registerInstruction ("enablelevelupmenu", "", opcodeEnableLevelupMenu);
|
||||
|
||||
extensions.registerInstruction ("showrestmenu", "", opcodeShowRestMenu, opcodeShowRestMenuExplicit);
|
||||
|
||||
|
|
|
@ -185,6 +185,7 @@ namespace Compiler
|
|||
const int opcodeEnableMapMenu = 0x2000015;
|
||||
const int opcodeEnableStatsMenu = 0x2000016;
|
||||
const int opcodeEnableRest = 0x2000017;
|
||||
const int opcodeEnableLevelupMenu = 0x2000300;
|
||||
const int opcodeShowRestMenu = 0x2000018;
|
||||
const int opcodeShowRestMenuExplicit = 0x2000234;
|
||||
const int opcodeGetButtonPressed = 0x2000137;
|
||||
|
|
|
@ -46,12 +46,12 @@ void ESM::CellRef::loadData(ESMReader &esm)
|
|||
esm.getHNOT (mFactionRank, "INDX");
|
||||
|
||||
mGoldValue = 1;
|
||||
mCharge = -1;
|
||||
mChargeInt = -1;
|
||||
mEnchantmentCharge = -1;
|
||||
|
||||
esm.getHNOT (mEnchantmentCharge, "XCHG");
|
||||
|
||||
esm.getHNOT (mCharge, "INTV");
|
||||
esm.getHNOT (mChargeInt, "INTV");
|
||||
|
||||
esm.getHNOT (mGoldValue, "NAM9");
|
||||
|
||||
|
@ -106,8 +106,8 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory) cons
|
|||
if (mEnchantmentCharge != -1)
|
||||
esm.writeHNT("XCHG", mEnchantmentCharge);
|
||||
|
||||
if (mCharge != -1)
|
||||
esm.writeHNT("INTV", mCharge);
|
||||
if (mChargeInt != -1)
|
||||
esm.writeHNT("INTV", mChargeInt);
|
||||
|
||||
if (mGoldValue != 1) {
|
||||
esm.writeHNT("NAM9", mGoldValue);
|
||||
|
@ -146,7 +146,7 @@ void ESM::CellRef::blank()
|
|||
mSoul.clear();
|
||||
mFaction.clear();
|
||||
mFactionRank = -2;
|
||||
mCharge = -1;
|
||||
mChargeInt = -1;
|
||||
mEnchantmentCharge = -1;
|
||||
mGoldValue = 0;
|
||||
mDestCell.clear();
|
||||
|
|
|
@ -59,7 +59,11 @@ namespace ESM
|
|||
|
||||
// For weapon or armor, this is the remaining item health.
|
||||
// For tools (lockpicks, probes, repair hammer) it is the remaining uses.
|
||||
int mCharge;
|
||||
union
|
||||
{
|
||||
int mChargeInt;
|
||||
float mChargeFloat;
|
||||
};
|
||||
|
||||
// Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full).
|
||||
float mEnchantmentCharge;
|
||||
|
|
|
@ -96,15 +96,17 @@ enum RecNameInts
|
|||
REC_WEAP = 0x50414557,
|
||||
|
||||
// format 0 - saved games
|
||||
REC_SAVE = 0x45564153,
|
||||
REC_JOUR = 0x524f55a4,
|
||||
REC_QUES = 0x53455551,
|
||||
REC_GSCR = 0x52435347,
|
||||
REC_PLAY = 0x59414c50,
|
||||
REC_CSTA = 0x41545343,
|
||||
REC_GMAP = 0x50414d47,
|
||||
REC_DIAS = 0x53414944,
|
||||
REC_WTHR = 0x52485457,
|
||||
REC_SAVE = FourCC<'S','A','V','E'>::value,
|
||||
REC_JOUR_LEGACY = FourCC<0xa4,'U','O','R'>::value, // "\xa4UOR", rather than "JOUR", little oversight when magic numbers were
|
||||
// calculated by hand, needs to be supported for older files now
|
||||
REC_JOUR = FourCC<'J','O','U','R'>::value,
|
||||
REC_QUES = FourCC<'Q','U','E','S'>::value,
|
||||
REC_GSCR = FourCC<'G','S','C','R'>::value,
|
||||
REC_PLAY = FourCC<'P','L','A','Y'>::value,
|
||||
REC_CSTA = FourCC<'C','S','T','A'>::value,
|
||||
REC_GMAP = FourCC<'G','M','A','P'>::value,
|
||||
REC_DIAS = FourCC<'D','I','A','S'>::value,
|
||||
REC_WTHR = FourCC<'W','T','H','R'>::value,
|
||||
REC_KEYS = FourCC<'K','E','Y','S'>::value,
|
||||
REC_DYNA = FourCC<'D','Y','N','A'>::value,
|
||||
REC_ASPL = FourCC<'A','S','P','L'>::value,
|
||||
|
@ -117,7 +119,7 @@ enum RecNameInts
|
|||
REC_CAM_ = FourCC<'C','A','M','_'>::value,
|
||||
|
||||
// format 1
|
||||
REC_FILT = 0x544C4946,
|
||||
REC_FILT = FourCC<'F','I','L','T'>::value,
|
||||
REC_DBGP = FourCC<'D','B','G','P'>::value ///< only used in project files
|
||||
};
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ void ESM::DialogueState::load (ESMReader &esm)
|
|||
while (esm.isNextSub ("REAC"))
|
||||
{
|
||||
esm.skipHSub();
|
||||
esm.getSubHeader();
|
||||
esm.getSubName();
|
||||
esm.skipHSub();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ template <int LEN>
|
|||
union NAME_T
|
||||
{
|
||||
char name[LEN];
|
||||
int32_t val;
|
||||
uint32_t val;
|
||||
|
||||
bool operator==(const char *str) const
|
||||
{
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue