1
0
Fork 0
mirror of https://github.com/OpenMW/openmw.git synced 2025-02-21 05:39:42 +00:00

Merge branch 'master' into 'touch_my_crank'

# Conflicts:
#   CHANGELOG.md
This commit is contained in:
psi29a 2021-07-06 09:18:12 +00:00
commit 3c0a0ba9e1
92 changed files with 341 additions and 128 deletions

View file

@ -3,6 +3,8 @@
Bug #3737: Scripts from The Underground 2 .esp do not play (all patched versions)
Bug #3846: Strings starting with "-" fail to compile if not enclosed in quotes
Bug #3905: Great House Dagoth issues
Bug #5120: Scripted object spawning updates physics system
Bug #5379: Wandering NPCs falling through cantons
Bug #5453: Magic effect VFX are offset for creatures
Bug #5483: AutoCalc flag is not used to calculate spells cost
@ -16,6 +18,7 @@
Bug #6131: Item selection in the avatar window not working correctly for large window sizes
Bug #6133: Cannot reliably sneak or steal in the sight of the NPCs siding with player
Feature #5489: MCP: Telekinesis fix for activators
Feature #6017: Separate persistent and temporary cell references when saving
0.47.0
------

View file

@ -253,10 +253,71 @@ int CSMDoc::WriteCellCollectionStage::setup()
return mDocument.getData().getCells().getSize();
}
void CSMDoc::WriteCellCollectionStage::writeReferences (const std::deque<int>& references, bool interior, unsigned int& newRefNum)
{
ESM::ESMWriter& writer = mState.getWriter();
for (std::deque<int>::const_iterator iter (references.begin());
iter!=references.end(); ++iter)
{
const CSMWorld::Record<CSMWorld::CellRef>& ref =
mDocument.getData().getReferences().getRecord (*iter);
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
{
CSMWorld::CellRef refRecord = ref.get();
// Check for uninitialized content file
if (!refRecord.mRefNum.hasContentFile())
refRecord.mRefNum.mContentFile = 0;
// recalculate the ref's cell location
std::ostringstream stream;
if (!interior)
{
std::pair<int, int> index = refRecord.getCellIndex();
stream << "#" << index.first << " " << index.second;
}
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 ||
(!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly &&
refRecord.mCell!=stream.str()))
{
refRecord.mRefNum.mIndex = newRefNum++;
}
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
!= stream.str() && !interior)
{
// An empty mOriginalCell is meant to indicate that it is the same as
// the current cell. It is possible that a moved ref is moved again.
ESM::MovedCellRef moved;
moved.mRefNum = refRecord.mRefNum;
// Need to fill mTarget with the ref's new position.
std::istringstream istream (stream.str().c_str());
char ignore;
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
refRecord.mRefNum.save (writer, false, "MVRF");
writer.writeHNT ("CNDT", moved.mTarget);
}
refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted);
}
}
}
void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
{
ESM::ESMWriter& writer = mState.getWriter();
const CSMWorld::Record<CSMWorld::Cell>& cell = mDocument.getData().getCells().getRecord (stage);
const CSMWorld::RefIdCollection& referenceables = mDocument.getData().getReferenceables();
const CSMWorld::RefIdData& refIdData = referenceables.getDataSet();
std::deque<int> tempRefs;
std::deque<int> persistentRefs;
std::map<std::string, std::deque<int> >::const_iterator references =
mState.getSubRecords().find (Misc::StringUtils::lowerCase (cell.get().mId));
@ -281,6 +342,18 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
CSMWorld::CellRef refRecord = ref.get();
CSMWorld::RefIdData::LocalIndex localIndex = refIdData.searchId(refRecord.mRefID);
unsigned int recordFlags = refIdData.getRecordFlags(refRecord.mRefID);
bool isPersistent = ((recordFlags & ESM::FLAG_Persistent) != 0)
|| refRecord.mTeleport
|| localIndex.second == CSMWorld::UniversalId::Type_Creature
|| localIndex.second == CSMWorld::UniversalId::Type_Npc;
if (isPersistent)
persistentRefs.push_back(*iter);
else
tempRefs.push_back(*iter);
if (refRecord.mNew ||
(!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly &&
/// \todo consider worldspace
@ -289,7 +362,6 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
if (refRecord.mRefNum.mIndex >= newRefNum)
newRefNum = refRecord.mRefNum.mIndex + 1;
}
}
@ -312,56 +384,9 @@ void CSMDoc::WriteCellCollectionStage::perform (int stage, Messages& messages)
// write references
if (references!=mState.getSubRecords().end())
{
for (std::deque<int>::const_iterator iter (references->second.begin());
iter!=references->second.end(); ++iter)
{
const CSMWorld::Record<CSMWorld::CellRef>& ref =
mDocument.getData().getReferences().getRecord (*iter);
if (ref.isModified() || ref.mState == CSMWorld::RecordBase::State_Deleted)
{
CSMWorld::CellRef refRecord = ref.get();
// Check for uninitialized content file
if (!refRecord.mRefNum.hasContentFile())
refRecord.mRefNum.mContentFile = 0;
// recalculate the ref's cell location
std::ostringstream stream;
if (!interior)
{
std::pair<int, int> index = refRecord.getCellIndex();
stream << "#" << index.first << " " << index.second;
}
if (refRecord.mNew || refRecord.mRefNum.mIndex == 0 ||
(!interior && ref.mState==CSMWorld::RecordBase::State_ModifiedOnly &&
refRecord.mCell!=stream.str()))
{
refRecord.mRefNum.mIndex = newRefNum++;
}
else if ((refRecord.mOriginalCell.empty() ? refRecord.mCell : refRecord.mOriginalCell)
!= stream.str() && !interior)
{
// An empty mOriginalCell is meant to indicate that it is the same as
// the current cell. It is possible that a moved ref is moved again.
ESM::MovedCellRef moved;
moved.mRefNum = refRecord.mRefNum;
// Need to fill mTarget with the ref's new position.
std::istringstream istream (stream.str().c_str());
char ignore;
istream >> ignore >> moved.mTarget[0] >> moved.mTarget[1];
refRecord.mRefNum.save (writer, false, "MVRF");
writer.writeHNT ("CNDT", moved.mTarget);
}
refRecord.save (writer, false, false, ref.mState == CSMWorld::RecordBase::State_Deleted);
}
}
writeReferences(persistentRefs, interior, newRefNum);
cellRecord.saveTempMarker(writer, int(references->second.size()) - persistentRefs.size());
writeReferences(tempRefs, interior, newRefNum);
}
writer.endRecord (cellRecord.sRecordId);

View file

@ -171,6 +171,8 @@ namespace CSMDoc
Document& mDocument;
SavingState& mState;
void writeReferences (const std::deque<int>& references, bool interior, unsigned int& newRefNum);
public:
WriteCellCollectionStage (Document& document, SavingState& state);

View file

@ -294,7 +294,6 @@ namespace CSMWorld
{ ColumnId_NpcReputation, "Reputation" },
{ ColumnId_NpcRank, "NPC Rank" },
{ ColumnId_Gold, "Gold" },
{ ColumnId_NpcPersistence, "Persistent" },
{ ColumnId_RaceAttributes, "Race Attributes" },
{ ColumnId_Male, "Male" },
@ -371,6 +370,8 @@ namespace CSMWorld
{ ColumnId_Skill6, "Skill 6" },
{ ColumnId_Skill7, "Skill 7" },
{ ColumnId_Persistent, "Persistent" },
{ -1, 0 } // end marker
};
}

View file

@ -280,7 +280,7 @@ namespace CSMWorld
ColumnId_NpcReputation = 258,
ColumnId_NpcRank = 259,
ColumnId_Gold = 260,
ColumnId_NpcPersistence = 261,
// unused
ColumnId_RaceAttributes = 262,
ColumnId_Male = 263,
@ -343,6 +343,8 @@ namespace CSMWorld
ColumnId_FactionAttrib1 = 311,
ColumnId_FactionAttrib2 = 312,
ColumnId_Persistent = 313,
// Allocated to a separate value range, so we don't get a collision should we ever need
// to extend the number of use values.
ColumnId_UseValue1 = 0x10000,

View file

@ -1108,7 +1108,6 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column
case 5: return static_cast<int>(record.get().mNpdt.mReputation);
case 6: return static_cast<int>(record.get().mNpdt.mRank);
case 7: return record.get().mNpdt.mGold;
case 8: return record.get().mPersistent == true;
default: return QVariant(); // throw an exception here?
}
else
@ -1122,7 +1121,6 @@ QVariant CSMWorld::NpcMiscRefIdAdapter::getNestedData (const RefIdColumn *column
case 5: return static_cast<int>(record.get().mNpdt.mReputation);
case 6: return static_cast<int>(record.get().mNpdt.mRank);
case 7: return record.get().mNpdt.mGold;
case 8: return record.get().mPersistent == true;
default: return QVariant(); // throw an exception here?
}
}
@ -1147,7 +1145,6 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
case 5: npc.mNpdt.mReputation = static_cast<signed char>(value.toInt()); break;
case 6: npc.mNpdt.mRank = static_cast<signed char>(value.toInt()); break;
case 7: npc.mNpdt.mGold = value.toInt(); break;
case 8: npc.mPersistent = value.toBool(); break;
default: return; // throw an exception here?
}
else
@ -1161,7 +1158,6 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
case 5: npc.mNpdt.mReputation = static_cast<signed char>(value.toInt()); break;
case 6: npc.mNpdt.mRank = static_cast<signed char>(value.toInt()); break;
case 7: npc.mNpdt.mGold = value.toInt(); break;
case 8: npc.mPersistent = value.toBool(); break;
default: return; // throw an exception here?
}
@ -1170,7 +1166,7 @@ void CSMWorld::NpcMiscRefIdAdapter::setNestedData (const RefIdColumn *column,
int CSMWorld::NpcMiscRefIdAdapter::getNestedColumnsCount(const RefIdColumn *column, const RefIdData& data) const
{
return 9; // Level, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold, Persist
return 8; // Level, Health, Mana, Fatigue, Disposition, Reputation, Rank, Gold
}
int CSMWorld::NpcMiscRefIdAdapter::getNestedRowsCount(const RefIdColumn *column, const RefIdData& data, int index) const

View file

@ -114,8 +114,9 @@ namespace CSMWorld
struct ModelColumns : public BaseColumns
{
const RefIdColumn *mModel;
const RefIdColumn *mPersistence;
ModelColumns (const BaseColumns& base) : BaseColumns (base), mModel(nullptr) {}
ModelColumns (const BaseColumns& base) : BaseColumns (base), mModel(nullptr), mPersistence(nullptr) {}
};
/// \brief Adapter for IDs with models (all but levelled lists)
@ -151,6 +152,9 @@ namespace CSMWorld
if (column==mModel.mModel)
return QString::fromUtf8 (record.get().mModel.c_str());
if (column==mModel.mPersistence)
return (record.get().mRecordFlags & ESM::FLAG_Persistent) != 0;
return BaseRefIdAdapter<RecordT>::getData (column, data, index);
}
@ -164,6 +168,13 @@ namespace CSMWorld
RecordT record2 = record.get();
if (column==mModel.mModel)
record2.mModel = value.toString().toUtf8().constData();
else if (column==mModel.mPersistence)
{
if (value.toInt() != 0)
record2.mRecordFlags |= ESM::FLAG_Persistent;
else
record2.mRecordFlags &= ~ESM::FLAG_Persistent;
}
else
{
BaseRefIdAdapter<RecordT>::setData (column, data, index, value);

View file

@ -54,6 +54,8 @@ CSMWorld::RefIdCollection::RefIdCollection()
mColumns.emplace_back(Columns::ColumnId_Model, ColumnBase::Display_Mesh);
modelColumns.mModel = &mColumns.back();
mColumns.emplace_back(Columns::ColumnId_Persistent, ColumnBase::Display_Boolean);
modelColumns.mPersistence = &mColumns.back();
NameColumns nameColumns (modelColumns);
@ -549,8 +551,6 @@ CSMWorld::RefIdCollection::RefIdCollection()
new RefIdColumn (Columns::ColumnId_NpcRank, CSMWorld::ColumnBase::Display_UnsignedInteger8));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_Gold, CSMWorld::ColumnBase::Display_Integer));
mColumns.back().addColumn(
new RefIdColumn (Columns::ColumnId_NpcPersistence, CSMWorld::ColumnBase::Display_Boolean));
WeaponColumns weaponColumns (enchantableColumns);

View file

@ -87,6 +87,39 @@ CSMWorld::RefIdData::LocalIndex CSMWorld::RefIdData::searchId (
return iter->second;
}
unsigned int CSMWorld::RefIdData::getRecordFlags (const std::string& id) const
{
LocalIndex localIndex = searchId (id);
switch (localIndex.second)
{
case UniversalId::Type_Activator: return mActivators.getRecordFlags(localIndex.first);
case UniversalId::Type_Potion: return mPotions.getRecordFlags(localIndex.first);
case UniversalId::Type_Apparatus: return mApparati.getRecordFlags(localIndex.first);
case UniversalId::Type_Armor: return mArmors.getRecordFlags(localIndex.first);
case UniversalId::Type_Book: return mBooks.getRecordFlags(localIndex.first);
case UniversalId::Type_Clothing: return mClothing.getRecordFlags(localIndex.first);
case UniversalId::Type_Container: return mContainers.getRecordFlags(localIndex.first);
case UniversalId::Type_Creature: return mCreatures.getRecordFlags(localIndex.first);
case UniversalId::Type_Door: return mDoors.getRecordFlags(localIndex.first);
case UniversalId::Type_Ingredient: return mIngredients.getRecordFlags(localIndex.first);
case UniversalId::Type_CreatureLevelledList: return mCreatureLevelledLists.getRecordFlags(localIndex.first);
case UniversalId::Type_ItemLevelledList: return mItemLevelledLists.getRecordFlags(localIndex.first);
case UniversalId::Type_Light: return mLights.getRecordFlags(localIndex.first);
case UniversalId::Type_Lockpick: return mLockpicks.getRecordFlags(localIndex.first);
case UniversalId::Type_Miscellaneous: return mMiscellaneous.getRecordFlags(localIndex.first);
case UniversalId::Type_Npc: return mNpcs.getRecordFlags(localIndex.first);
case UniversalId::Type_Probe: return mProbes.getRecordFlags(localIndex.first);
case UniversalId::Type_Repair: return mRepairs.getRecordFlags(localIndex.first);
case UniversalId::Type_Static: return mStatics.getRecordFlags(localIndex.first);
case UniversalId::Type_Weapon: return mWeapons.getRecordFlags(localIndex.first);
default:
break;
}
return 0;
}
void CSMWorld::RefIdData::erase (int index, int count)
{
LocalIndex localIndex = globalToLocalIndex (index);

View file

@ -47,6 +47,8 @@ namespace CSMWorld
virtual RecordBase& getRecord (int index)= 0;
virtual unsigned int getRecordFlags (int index) const = 0;
virtual void appendRecord (const std::string& id, bool base) = 0;
virtual void insertRecord (RecordBase& record) = 0;
@ -72,6 +74,8 @@ namespace CSMWorld
RecordBase& getRecord (int index) override;
unsigned int getRecordFlags (int index) const override;
void appendRecord (const std::string& id, bool base) override;
void insertRecord (RecordBase& record) override;
@ -111,6 +115,12 @@ namespace CSMWorld
return mContainer.at (index);
}
template<typename RecordT>
unsigned int RefIdDataContainer<RecordT>::getRecordFlags (int index) const
{
return mContainer.at (index).get().mRecordFlags;
}
template<typename RecordT>
void RefIdDataContainer<RecordT>::appendRecord (const std::string& id, bool base)
{
@ -209,7 +219,7 @@ namespace CSMWorld
if (record.isModified() || record.mState == RecordBase::State_Deleted)
{
RecordT esmRecord = record.get();
writer.startRecord(esmRecord.sRecordId);
writer.startRecord(esmRecord.sRecordId, esmRecord.mRecordFlags);
esmRecord.save(writer, record.mState == RecordBase::State_Deleted);
writer.endRecord(esmRecord.sRecordId);
}
@ -273,6 +283,8 @@ namespace CSMWorld
RecordBase& getRecord (const LocalIndex& index);
unsigned int getRecordFlags(const std::string& id) const;
void appendRecord (UniversalId::Type type, const std::string& id, bool base);
int getAppendIndex (UniversalId::Type type) const;

View file

@ -39,6 +39,11 @@ namespace MWClass
}
void Activator::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
insertObjectPhysics(ptr, model, rotation, physics, skipAnimated);
}
void Activator::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
if(!model.empty())
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);

View file

@ -19,6 +19,8 @@ namespace MWClass
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const override;
std::string getName (const MWWorld::ConstPtr& ptr) const override;
///< \return name or ID; can return an empty string.

View file

@ -107,6 +107,11 @@ namespace MWClass
}
void Container::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
insertObjectPhysics(ptr, model, rotation, physics, skipAnimated);
}
void Container::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
if(!model.empty())
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);

View file

@ -43,6 +43,7 @@ namespace MWClass
///< Add reference into a cell for rendering
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
std::string getName (const MWWorld::ConstPtr& ptr) const override;
///< \return name or ID; can return an empty string.

View file

@ -588,7 +588,7 @@ namespace MWClass
bool Creature::isPersistent(const MWWorld::ConstPtr &actor) const
{
const MWWorld::LiveCellRef<ESM::Creature>* ref = actor.get<ESM::Creature>();
return ref->mBase->mPersistent;
return (ref->mBase->mRecordFlags & ESM::FLAG_Persistent) != 0;
}
std::string Creature::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const

View file

@ -57,8 +57,7 @@ namespace MWClass
void Door::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
if(!model.empty())
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated);
insertObjectPhysics(ptr, model, rotation, physics, skipAnimated);
// Resume the door's opening/closing animation if it wasn't finished
if (ptr.getRefData().getCustomData())
@ -71,6 +70,12 @@ namespace MWClass
}
}
void Door::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
if(!model.empty())
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_Door, skipAnimated);
}
bool Door::isDoor() const
{
return true;

View file

@ -19,6 +19,7 @@ namespace MWClass
///< Add reference into a cell for rendering
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
bool isDoor() const override;

View file

@ -39,9 +39,7 @@ namespace MWClass
ptr.get<ESM::Light>();
assert (ref->mBase != nullptr);
// TODO: add option somewhere to enable collision for placeable objects
if (!model.empty() && (ref->mBase->mData.mFlags & ESM::Light::Carry) == 0)
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
insertObjectPhysics(ptr, model, rotation, physics, skipAnimated);
if (!ref->mBase->mSound.empty() && !(ref->mBase->mData.mFlags & ESM::Light::OffDefault))
MWBase::Environment::get().getSoundManager()->playSound3D(ptr, ref->mBase->mSound, 1.0, 1.0,
@ -49,6 +47,13 @@ namespace MWClass
MWSound::PlayMode::Loop);
}
void Light::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
// TODO: add option somewhere to enable collision for placeable objects
if (!model.empty() && (ptr.get<ESM::Light>()->mBase->mData.mFlags & ESM::Light::Carry) == 0)
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);
}
bool Light::useAnim() const
{
return true;

View file

@ -15,6 +15,7 @@ namespace MWClass
///< Add reference into a cell for rendering
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
bool useAnim() const override;

View file

@ -403,7 +403,7 @@ namespace MWClass
bool Npc::isPersistent(const MWWorld::ConstPtr &actor) const
{
const MWWorld::LiveCellRef<ESM::NPC>* ref = actor.get<ESM::NPC>();
return ref->mBase->mPersistent;
return (ref->mBase->mRecordFlags & ESM::FLAG_Persistent) != 0;
}
std::string Npc::getModel(const MWWorld::ConstPtr &ptr) const

View file

@ -24,6 +24,11 @@ namespace MWClass
}
void Static::insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
insertObjectPhysics(ptr, model, rotation, physics, skipAnimated);
}
void Static::insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{
if(!model.empty())
physics.addObject(ptr, model, rotation, MWPhysics::CollisionType_World, skipAnimated);

View file

@ -15,6 +15,7 @@ namespace MWClass
///< Add reference into a cell for rendering
void insertObject(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
void insertObjectPhysics(const MWWorld::Ptr& ptr, const std::string& model, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const override;
std::string getName (const MWWorld::ConstPtr& ptr) const override;
///< \return name or ID; can return an empty string.

View file

@ -463,6 +463,8 @@ namespace MWPhysics
void PhysicsSystem::addObject (const MWWorld::Ptr& ptr, const std::string& mesh, osg::Quat rotation, int collisionType, bool skipAnimated)
{
if (ptr.mRef->mData.mPhysicsPostponed)
return;
osg::ref_ptr<Resource::BulletShapeInstance> shapeInstance = mShapeManager->getInstance(mesh);
if (!shapeInstance || !shapeInstance->getCollisionShape())
return;

View file

@ -168,6 +168,8 @@ namespace MWScript
void execute (Interpreter::Runtime& runtime) override
{
MWWorld::Ptr ptr = R()(runtime);
if(!ptr.isEmpty() && !ptr.mRef->mData.isEnabled())
ptr.mRef->mData.mPhysicsPostponed = false;
MWBase::Environment::get().getWorld()->enable (ptr);
}
};

View file

@ -42,10 +42,19 @@ namespace MWScript
void execute (Interpreter::Runtime& runtime) override
{
MWWorld::Ptr from = R()(runtime);
MWWorld::Ptr from = R()(runtime, !R::implicit);
std::string name = runtime.getStringLiteral (runtime[0].mInteger);
runtime.pop();
if (from.isEmpty())
{
std::string error = "Missing implicit ref";
runtime.getContext().report(error);
Log(Debug::Error) << error;
runtime.push(0.f);
return;
}
if (from.getContainerStore()) // is the object contained?
{
MWWorld::Ptr container = MWBase::Environment::get().getWorld()->findContainer(from);
@ -501,6 +510,7 @@ namespace MWScript
pos.rot[0] = pos.rot[1] = 0;
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor();
ref.getPtr().getCellRef().setPosition(pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
placed.getClass().adjustPosition(placed, true);
@ -548,6 +558,7 @@ namespace MWScript
pos.rot[0] = pos.rot[1] = 0;
pos.rot[2] = osg::DegreesToRadians(zRotDegrees);
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(),itemID);
ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor();
ref.getPtr().getCellRef().setPosition(pos);
MWWorld::Ptr placed = MWBase::Environment::get().getWorld()->placeObject(ref.getPtr(),store,pos);
placed.getClass().adjustPosition(placed, true);
@ -588,6 +599,7 @@ namespace MWScript
{
// create item
MWWorld::ManualRef ref(MWBase::Environment::get().getWorld()->getStore(), itemID, 1);
ref.getPtr().mRef->mData.mPhysicsPostponed = !ref.getPtr().getClass().isActor();
MWWorld::Ptr ptr = MWBase::Environment::get().getWorld()->safePlaceObject(ref.getPtr(), actor, actor.getCell(), direction, distance);
MWBase::Environment::get().getWorld()->scaleObject(ptr, actor.getCellRef().getScale());

View file

@ -610,9 +610,17 @@ namespace MWWorld
ref.mRefNum.mContentFile = ESM::RefNum::RefNum_NoContentFile;
// Get each reference in turn
ESM::MovedCellRef cMRef;
cMRef.mRefNum.mIndex = 0;
bool deleted = false;
while(mCell->getNextRef(esm[index], ref, deleted))
while(mCell->getNextRef(esm[index], ref, deleted, /*ignoreMoves*/true, &cMRef))
{
if (cMRef.mRefNum.mIndex)
{
cMRef.mRefNum.mIndex = 0;
continue; // ignore refs that are moved
}
// Don't load reference if it was moved to a different cell.
ESM::MovedCellRefTracker::const_iterator iter =
std::find(mCell->mMovedRefs.begin(), mCell->mMovedRefs.end(), ref.mRefNum);

View file

@ -35,6 +35,9 @@ namespace MWWorld
}
void Class::insertObjectPhysics(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated) const
{}
bool Class::apply (const MWWorld::Ptr& ptr, const std::string& id, const MWWorld::Ptr& actor) const
{
return false;

View file

@ -80,6 +80,7 @@ namespace MWWorld
virtual void insertObjectRendering (const Ptr& ptr, const std::string& mesh, MWRender::RenderingInterface& renderingInterface) const;
virtual void insertObject(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const;
///< Add reference into a cell for rendering (default implementation: don't render anything).
virtual void insertObjectPhysics(const Ptr& ptr, const std::string& mesh, osg::Quat rotation, MWPhysics::PhysicsSystem& physics, bool skipAnimated = false) const;
virtual std::string getName (const ConstPtr& ptr) const = 0;
///< \return name or ID; can return an empty string.

View file

@ -31,6 +31,7 @@ namespace MWWorld
mChanged = refData.mChanged;
mDeletedByContentFile = refData.mDeletedByContentFile;
mFlags = refData.mFlags;
mPhysicsPostponed = refData.mPhysicsPostponed;
mAnimationState = refData.mAnimationState;
@ -44,7 +45,7 @@ namespace MWWorld
}
RefData::RefData()
: mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (nullptr), mChanged(false), mFlags(0)
: mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true), mCount (1), mCustomData (nullptr), mChanged(false), mFlags(0), mPhysicsPostponed(false)
{
for (int i=0; i<3; ++i)
{
@ -57,7 +58,7 @@ namespace MWWorld
: mBaseNode(nullptr), mDeletedByContentFile(false), mEnabled (true),
mCount (1), mPosition (cellRef.mPos),
mCustomData (nullptr),
mChanged(false), mFlags(0) // Loading from ESM/ESP files -> assume unchanged
mChanged(false), mFlags(0), mPhysicsPostponed(false) // Loading from ESM/ESP files -> assume unchanged
{
}
@ -68,7 +69,7 @@ namespace MWWorld
mPosition (objectState.mPosition),
mAnimationState(objectState.mAnimationState),
mCustomData (nullptr),
mChanged(true), mFlags(objectState.mFlags) // Loading from a savegame -> assume changed
mChanged(true), mFlags(objectState.mFlags), mPhysicsPostponed(false) // Loading from a savegame -> assume changed
{
// "Note that the ActivationFlag_UseEnabled is saved to the reference,
// which will result in permanently suppressed activation if the reference script is removed.

View file

@ -58,6 +58,8 @@ namespace MWWorld
public:
bool mPhysicsPostponed;
RefData();
/// @param cellRef Used to copy constant data such as position into this class where it can

View file

@ -343,7 +343,10 @@ namespace MWWorld
cell->forEach(visitor);
for (const auto& ptr : visitor.mObjects)
{
mPhysics->remove(ptr);
ptr.mRef->mData.mPhysicsPostponed = false;
}
if (cell->getCell()->isExterior())
{
@ -626,6 +629,24 @@ namespace MWWorld
}
return cellsPositionsToLoad;
};
for(const auto& cell : mActiveCells)
{
cell->forEach([&](const MWWorld::Ptr& ptr)
{
if(ptr.mRef->mData.mPhysicsPostponed)
{
ptr.mRef->mData.mPhysicsPostponed = false;
if(ptr.mRef->mData.isEnabled() && ptr.mRef->mData.getCount() > 0) {
std::string model = getModel(ptr, MWBase::Environment::get().getResourceSystem()->getVFS());
const auto rotation = makeNodeRotation(ptr, RotationOrder::direct);
ptr.getClass().insertObjectPhysics(ptr, model, rotation, *mPhysics);
}
}
return true;
});
}
auto cellsPositionsToLoad = cellsToLoad(mActiveCells,mHalfGridSize);
auto cellsPositionsToLoadInactive = cellsToLoad(mInactiveCells,mHalfGridSize+1);

View file

@ -118,8 +118,10 @@ void ESM::CellRef::loadData(ESMReader &esm, bool &isDeleted)
esm.getHT(mPos, 24);
break;
case ESM::FourCC<'N','A','M','0'>::value:
{
esm.skipHSub();
break;
}
case ESM::SREC_DELE:
esm.skipHSub();
isDeleted = true;
@ -145,7 +147,7 @@ void ESM::CellRef::save (ESMWriter &esm, bool wideRefNum, bool inInventory, bool
esm.writeHNCString("NAME", mRefID);
if (isDeleted) {
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -44,7 +44,7 @@ void ESM::DebugProfile::save (ESMWriter& esm, bool isDeleted) const
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -16,6 +16,11 @@ enum Version
VER_13 = 0x3fa66666
};
enum RecordFlag
{
FLAG_Persistent = 0x00000400,
FLAG_Blocked = 0x00002000
};
// CRTP for FIXED_STRING class, a structure used for holding fixed-length strings
template< template<size_t> class DERIVED, size_t SIZE>

View file

@ -42,7 +42,7 @@ void ESM::Filter::save (ESMWriter& esm, bool isDeleted) const
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Activator::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
while (esm.hasMoreSubs())
@ -50,7 +51,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -15,6 +15,7 @@ struct Activator
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Activator"; }
unsigned int mRecordFlags;
std::string mId, mName, mScript, mModel;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -11,6 +11,7 @@ namespace ESM
void Potion::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
mEffects.mList.clear();
@ -65,7 +66,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -30,6 +30,7 @@ struct Potion
};
ALDTstruct mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
EffectList mEffects;

View file

@ -11,6 +11,7 @@ namespace ESM
void Apparatus::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -61,7 +62,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -36,6 +36,7 @@ struct Apparatus
};
AADTstruct mData;
unsigned int mRecordFlags;
std::string mId, mModel, mIcon, mScript, mName;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -41,6 +41,7 @@ namespace ESM
void Armor::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
mParts.mParts.clear();
@ -99,7 +100,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -94,6 +94,7 @@ struct Armor
AODTstruct mData;
PartReferenceList mParts;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript, mEnchant;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -55,7 +55,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Book::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -66,7 +67,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -26,6 +26,7 @@ struct Book
BKDTstruct mData;
std::string mName, mModel, mIcon, mScript, mEnchant, mText;
unsigned int mRecordFlags;
std::string mId;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -56,7 +56,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}
esm.writeHNOCString("FNAM", mName);

View file

@ -146,7 +146,7 @@ namespace ESM
}
}
if (saveContext)
if (saveContext)
{
mContextList.push_back(esm.getContext());
esm.skipRecord();
@ -167,7 +167,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}
@ -197,9 +197,12 @@ namespace ESM
if (mMapColor != 0)
esm.writeHNT("NAM5", mMapColor);
}
}
if (mRefNumCounter != 0)
esm.writeHNT("NAM0", mRefNumCounter);
void Cell::saveTempMarker(ESMWriter &esm, int tempCount) const
{
if (tempCount != 0)
esm.writeHNT("NAM0", tempCount);
}
void Cell::restore(ESMReader &esm, int iCtx) const
@ -251,6 +254,8 @@ namespace ESM
{
ref.load (esm, isDeleted);
// TODO: should count the number of temp refs and validate the number
// Identify references belonging to a parent file and adapt the ID accordingly.
adjustRefNum (ref.mRefNum, esm);
return true;
@ -275,7 +280,7 @@ namespace ESM
mWater = 0;
mWaterInt = false;
mMapColor = 0;
mRefNumCounter = 0;
mRefNumCounter = -1;
mData.mFlags = 0;
mData.mX = 0;

View file

@ -94,7 +94,7 @@ struct Cell
mWater(0),
mWaterInt(false),
mMapColor(0),
mRefNumCounter(0)
mRefNumCounter(-1)
{}
// Interior cells are indexed by this (it's the 'id'), for exterior
@ -133,6 +133,7 @@ struct Cell
void loadCell(ESMReader &esm, bool saveContext = true); // Load everything, except NAME, DATAstruct and references
void save(ESMWriter &esm, bool isDeleted = false) const;
void saveTempMarker(ESMWriter &esm, int tempCount) const;
bool isExterior() const
{
@ -183,7 +184,7 @@ struct Cell
/// \param ignoreMoves ignore MVRF record and read reference like a regular CellRef.
static bool getNextRef(ESMReader &esm,
CellRef &ref,
bool &isDeleted,
bool &isDeleted,
bool ignoreMoves = false,
MovedCellRef *mref = nullptr);

View file

@ -86,7 +86,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Clothing::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
mParts.mParts.clear();
@ -69,7 +70,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -46,6 +46,7 @@ struct Clothing
PartReferenceList mParts;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mEnchant, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -32,6 +32,7 @@ namespace ESM
void Container::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
mInventory.mList.clear();
@ -95,7 +96,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -46,6 +46,7 @@ struct Container
Unknown = 8
};
unsigned int mRecordFlags;
std::string mId, mName, mModel, mScript;
float mWeight; // Not sure, might be max total weight allowed?

View file

@ -13,8 +13,7 @@ namespace ESM {
void Creature::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mPersistent = (esm.getRecordFlags() & 0x0400) != 0;
mRecordFlags = esm.getRecordFlags();
mAiPackage.mList.clear();
mInventory.mList.clear();
@ -115,7 +114,7 @@ namespace ESM {
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -76,10 +76,9 @@ struct Creature
int mBloodType;
unsigned char mFlags;
bool mPersistent;
float mScale;
unsigned int mRecordFlags;
std::string mId, mModel, mName, mScript;
std::string mOriginal; // Base creature that this is a modification of

View file

@ -61,7 +61,7 @@ namespace ESM
esm.writeHNCString("NAME", mId);
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
}
else
{

View file

@ -11,6 +11,7 @@ namespace ESM
void Door::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
while (esm.hasMoreSubs())
@ -57,7 +58,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -15,6 +15,7 @@ struct Door
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Door"; }
unsigned int mRecordFlags;
std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -53,7 +53,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -90,7 +90,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -100,7 +100,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Ingredient::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -84,7 +85,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -29,6 +29,7 @@ struct Ingredient
};
IRDTstruct mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -123,7 +123,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -9,6 +9,7 @@ namespace ESM
void LevelledListBase::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasList = false;
@ -80,7 +81,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -22,6 +22,7 @@ struct LevelledListBase
{
int mFlags;
unsigned char mChanceNone; // Chance that none are selected (0-100)
unsigned int mRecordFlags;
std::string mId;
// Record name used to read references. Must be set before load() is

View file

@ -11,6 +11,7 @@ namespace ESM
void Light::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -63,7 +64,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -45,6 +45,7 @@ struct Light
LHDTstruct mData;
unsigned int mRecordFlags;
std::string mSound, mScript, mModel, mIcon, mName, mId;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -11,6 +11,7 @@ namespace ESM
void Lockpick::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -61,7 +62,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -25,6 +25,7 @@ struct Lockpick
}; // Size = 16
Data mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -53,7 +53,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
}
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Miscellaneous::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -61,7 +62,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -30,6 +30,7 @@ struct Miscellaneous
};
MCDTstruct mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -11,8 +11,7 @@ namespace ESM
void NPC::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mPersistent = (esm.getRecordFlags() & 0x0400) != 0;
mRecordFlags = esm.getRecordFlags();
mSpells.mList.clear();
mInventory.mList.clear();
@ -135,7 +134,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -116,8 +116,6 @@ struct NPC
int mBloodType;
unsigned char mFlags;
bool mPersistent;
InventoryList mInventory;
SpellList mSpells;
@ -129,6 +127,7 @@ struct NPC
AIPackageList mAiPackage;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mRace, mClass, mFaction, mScript;
// body parts

View file

@ -156,7 +156,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Probe::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -61,7 +62,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -25,6 +25,7 @@ struct Probe
}; // Size = 16
Data mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -68,7 +68,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -89,7 +89,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -11,6 +11,7 @@ namespace ESM
void Repair::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -61,7 +62,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -25,6 +25,7 @@ struct Repair
}; // Size = 16
Data mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mScript;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -155,7 +155,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -54,7 +54,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -52,7 +52,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -59,7 +59,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -47,7 +47,7 @@ namespace ESM
esm.writeHNCString("NAME", mId);
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
}
else
{

View file

@ -11,6 +11,9 @@ namespace ESM
void Static::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
//bool isBlocked = (mRecordFlags & ESM::FLAG_Blocked) != 0;
//bool isPersistent = (mRecordFlags & ESM::FLAG_Persistent) != 0;
bool hasName = false;
while (esm.hasMoreSubs())
@ -43,7 +46,7 @@ namespace ESM
esm.writeHNCString("NAME", mId);
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
}
else
{

View file

@ -26,6 +26,7 @@ struct Static
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Static"; }
unsigned int mRecordFlags;
std::string mId, mModel;
void load(ESMReader &esm, bool &isDeleted);

View file

@ -11,6 +11,7 @@ namespace ESM
void Weapon::load(ESMReader &esm, bool &isDeleted)
{
isDeleted = false;
mRecordFlags = esm.getRecordFlags();
bool hasName = false;
bool hasData = false;
@ -62,7 +63,7 @@ namespace ESM
if (isDeleted)
{
esm.writeHNCString("DELE", "");
esm.writeHNString("DELE", "", 3);
return;
}

View file

@ -73,6 +73,7 @@ struct Weapon
WPDTstruct mData;
unsigned int mRecordFlags;
std::string mId, mName, mModel, mIcon, mEnchant, mScript;
void load(ESMReader &esm, bool &isDeleted);