mirror of
https://github.com/OpenMW/openmw.git
synced 2025-02-06 08:45:33 +00:00
gives MWWorld::CellRef the MWWorld::Cell treatment
MWWorld::CellRef now has a variant, and datas that are part of the intersection of both ESM4::Reference and ESM::CellRef are part of MWWorld::CellRef For ESM4 most data isn't filled in, so it returns default values.
This commit is contained in:
parent
23614ae2ae
commit
e6e27413d9
3 changed files with 188 additions and 91 deletions
|
@ -7,10 +7,54 @@
|
|||
|
||||
namespace MWWorld
|
||||
{
|
||||
CellRef::CellRef(const ESM::CellRef& ref)
|
||||
: mCellRef(ESM::ReferenceVariant(ref))
|
||||
{
|
||||
mChanged = false;
|
||||
mSoul = ref.mSoul;
|
||||
mTrap = ref.mTrap;
|
||||
mKey = ref.mKey;
|
||||
mFaction = ref.mFaction;
|
||||
mOwner = ref.mOwner;
|
||||
mReferenceType = ref.mRefID;
|
||||
mPos = ref.mPos;
|
||||
mDoorDest = ref.mDoorDest;
|
||||
mRefNum = ref.mRefNum;
|
||||
mGlobalVariable = ref.mGlobalVariable;
|
||||
mDestCell = ref.mDestCell;
|
||||
|
||||
mLockLevel = ref.mLockLevel;
|
||||
mGoldValue = ref.mGoldValue;
|
||||
mFactionRank = ref.mFactionRank;
|
||||
mEnchantmentCharge = ref.mEnchantmentCharge;
|
||||
|
||||
mScale = ref.mScale;
|
||||
}
|
||||
|
||||
CellRef::CellRef(const ESM4::Reference& ref)
|
||||
: mCellRef(ESM::ReferenceVariant(ref))
|
||||
{
|
||||
|
||||
mChanged = false;
|
||||
|
||||
mReferenceType = ref.mBaseObj;
|
||||
mPos = { { ref.mPlacement.pos.x, ref.mPlacement.pos.y, ref.mPlacement.pos.z },
|
||||
{ ref.mPlacement.rot.x, ref.mPlacement.rot.y, ref.mPlacement.rot.z } };
|
||||
|
||||
mRefNum = {};
|
||||
mDoorDest = {};
|
||||
|
||||
mLockLevel = ref.mLockLevel;
|
||||
mFactionRank = ref.mFactionRank;
|
||||
mGoldValue = 0;
|
||||
mEnchantmentCharge = 0;
|
||||
|
||||
mScale = ref.mScale;
|
||||
}
|
||||
|
||||
const ESM::RefNum& CellRef::getOrAssignRefNum(ESM::RefNum& lastAssignedRefNum)
|
||||
{
|
||||
if (!mCellRef.mRefNum.isSet())
|
||||
if (!mRefNum.isSet())
|
||||
{
|
||||
// Generated RefNums have negative mContentFile
|
||||
assert(lastAssignedRefNum.mContentFile < 0);
|
||||
|
@ -22,30 +66,38 @@ namespace MWWorld
|
|||
else
|
||||
Log(Debug::Error) << "RefNum counter overflow in CellRef::getOrAssignRefNum";
|
||||
}
|
||||
mCellRef.mRefNum = lastAssignedRefNum;
|
||||
mRefNum = lastAssignedRefNum;
|
||||
mChanged = true;
|
||||
}
|
||||
return mCellRef.mRefNum;
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mRefNum = mRefNum;
|
||||
return mRefNum;
|
||||
}
|
||||
|
||||
void CellRef::unsetRefNum()
|
||||
{
|
||||
mCellRef.mRefNum = ESM::RefNum{};
|
||||
mRefNum = ESM::RefNum{};
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mRefNum = mRefNum;
|
||||
}
|
||||
|
||||
void CellRef::setScale(float scale)
|
||||
{
|
||||
if (scale != mCellRef.mScale)
|
||||
if (scale != mScale)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mScale = scale;
|
||||
mScale = scale;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mScale = Scale;
|
||||
}
|
||||
|
||||
void CellRef::setPosition(const ESM::Position& position)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mPos = position;
|
||||
mPos = position;
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mPos = position;
|
||||
}
|
||||
|
||||
float CellRef::getNormalizedEnchantmentCharge(int maxCharge) const
|
||||
|
@ -54,113 +106,140 @@ namespace MWWorld
|
|||
{
|
||||
return 0;
|
||||
}
|
||||
else if (mCellRef.mEnchantmentCharge == -1)
|
||||
else if (mEnchantmentCharge == -1)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
return mCellRef.mEnchantmentCharge / static_cast<float>(maxCharge);
|
||||
return mEnchantmentCharge / static_cast<float>(maxCharge);
|
||||
}
|
||||
}
|
||||
|
||||
void CellRef::setEnchantmentCharge(float charge)
|
||||
{
|
||||
if (charge != mCellRef.mEnchantmentCharge)
|
||||
if (charge != mEnchantmentCharge)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mEnchantmentCharge = charge;
|
||||
mEnchantmentCharge = charge;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mEnchantmentCharge = mEnchantmentCharge;
|
||||
}
|
||||
|
||||
void CellRef::setCharge(int charge)
|
||||
{
|
||||
if (charge != mCellRef.mChargeInt)
|
||||
if (mCellRef.isESM4())
|
||||
return;
|
||||
|
||||
auto& cellRef3 = mCellRef.getEsm3();
|
||||
if (charge != cellRef3.mChargeInt)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mChargeInt = charge;
|
||||
cellRef3.mChargeInt = charge;
|
||||
}
|
||||
}
|
||||
|
||||
void CellRef::applyChargeRemainderToBeSubtracted(float chargeRemainder)
|
||||
{
|
||||
mCellRef.mChargeIntRemainder += std::abs(chargeRemainder);
|
||||
if (mCellRef.mChargeIntRemainder > 1.0f)
|
||||
if (mCellRef.isESM4())
|
||||
return;
|
||||
|
||||
auto& cellRef3 = mCellRef.getEsm3();
|
||||
cellRef3.mChargeIntRemainder += std::abs(chargeRemainder);
|
||||
if (cellRef3.mChargeIntRemainder > 1.0f)
|
||||
{
|
||||
float newChargeRemainder = (mCellRef.mChargeIntRemainder - std::floor(mCellRef.mChargeIntRemainder));
|
||||
if (mCellRef.mChargeInt <= static_cast<int>(mCellRef.mChargeIntRemainder))
|
||||
float newChargeRemainder = (cellRef3.mChargeIntRemainder - std::floor(cellRef3.mChargeIntRemainder));
|
||||
if (cellRef3.mChargeInt <= static_cast<int>(cellRef3.mChargeIntRemainder))
|
||||
{
|
||||
mCellRef.mChargeInt = 0;
|
||||
cellRef3.mChargeInt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
mCellRef.mChargeInt -= static_cast<int>(mCellRef.mChargeIntRemainder);
|
||||
cellRef3.mChargeInt -= static_cast<int>(cellRef3.mChargeIntRemainder);
|
||||
}
|
||||
mCellRef.mChargeIntRemainder = newChargeRemainder;
|
||||
cellRef3.mChargeIntRemainder = newChargeRemainder;
|
||||
}
|
||||
}
|
||||
|
||||
void CellRef::setChargeFloat(float charge)
|
||||
{
|
||||
if (charge != mCellRef.mChargeFloat)
|
||||
if (mCellRef.isESM4())
|
||||
return;
|
||||
|
||||
auto& cellRef3 = mCellRef.getEsm3();
|
||||
if (charge != cellRef3.mChargeFloat)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mChargeFloat = charge;
|
||||
cellRef3.mChargeFloat = charge;
|
||||
}
|
||||
}
|
||||
|
||||
void CellRef::resetGlobalVariable()
|
||||
{
|
||||
if (!mCellRef.mGlobalVariable.empty())
|
||||
if (!mGlobalVariable.empty())
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mGlobalVariable.erase();
|
||||
mGlobalVariable.erase();
|
||||
}
|
||||
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mGlobalVariable = mGlobalVariable;
|
||||
}
|
||||
|
||||
void CellRef::setFactionRank(int factionRank)
|
||||
{
|
||||
if (factionRank != mCellRef.mFactionRank)
|
||||
if (factionRank != mFactionRank)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mFactionRank = factionRank;
|
||||
mFactionRank = factionRank;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mFactionRank = mFactionRank;
|
||||
}
|
||||
|
||||
void CellRef::setOwner(const ESM::RefId& owner)
|
||||
{
|
||||
if (owner != mCellRef.mOwner)
|
||||
if (owner != mOwner)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mOwner = owner;
|
||||
mOwner = owner;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mOwner = mOwner;
|
||||
}
|
||||
|
||||
void CellRef::setSoul(const ESM::RefId& soul)
|
||||
{
|
||||
if (soul != mCellRef.mSoul)
|
||||
if (soul != mSoul)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mSoul = soul;
|
||||
mSoul = soul;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mSoul = mSoul;
|
||||
}
|
||||
|
||||
void CellRef::setFaction(const ESM::RefId& faction)
|
||||
{
|
||||
if (faction != mCellRef.mFaction)
|
||||
if (faction != mFaction)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mFaction = faction;
|
||||
mFaction = faction;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mFaction = mFaction;
|
||||
}
|
||||
|
||||
void CellRef::setLockLevel(int lockLevel)
|
||||
{
|
||||
if (lockLevel != mCellRef.mLockLevel)
|
||||
if (lockLevel != mLockLevel)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mLockLevel = lockLevel;
|
||||
mLockLevel = lockLevel;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mLockLevel = mLockLevel;
|
||||
}
|
||||
|
||||
void CellRef::lock(int lockLevel)
|
||||
|
@ -173,30 +252,38 @@ namespace MWWorld
|
|||
|
||||
void CellRef::unlock()
|
||||
{
|
||||
setLockLevel(-abs(mCellRef.mLockLevel)); // Makes lockLevel negative
|
||||
setLockLevel(-abs(mLockLevel)); // Makes lockLevel negative
|
||||
}
|
||||
|
||||
void CellRef::setTrap(const ESM::RefId& trap)
|
||||
{
|
||||
if (trap != mCellRef.mTrap)
|
||||
if (trap != mTrap)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mTrap = trap;
|
||||
mTrap = trap;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mTrap = mTrap;
|
||||
}
|
||||
|
||||
void CellRef::setGoldValue(int value)
|
||||
{
|
||||
if (value != mCellRef.mGoldValue)
|
||||
if (value != mGoldValue)
|
||||
{
|
||||
mChanged = true;
|
||||
mCellRef.mGoldValue = value;
|
||||
mGoldValue = value;
|
||||
}
|
||||
if (!mCellRef.isESM4())
|
||||
mCellRef.getEsm3().mGoldValue = mGoldValue;
|
||||
}
|
||||
|
||||
void CellRef::writeState(ESM::ObjectState& state) const
|
||||
{
|
||||
state.mRef = mCellRef;
|
||||
if (!mCellRef.isESM4())
|
||||
{
|
||||
auto& cellRef3 = mCellRef.getEsm3();
|
||||
state.mRef = cellRef3;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -19,24 +19,12 @@ namespace MWWorld
|
|||
class CellRef
|
||||
{
|
||||
public:
|
||||
CellRef(const ESM::CellRef& ref)
|
||||
: mCellRef(ref)
|
||||
{
|
||||
mIsEsm4 = false;
|
||||
mChanged = false;
|
||||
}
|
||||
CellRef(const ESM::CellRef& ref);
|
||||
|
||||
CellRef(const ESM4::Reference& ref)
|
||||
: mCellRef4(ref)
|
||||
{
|
||||
mRefrPos = { { mCellRef4.mPlacement.pos.x, mCellRef4.mPlacement.pos.y, mCellRef4.mPlacement.pos.z },
|
||||
{ mCellRef4.mPlacement.rot.x, mCellRef4.mPlacement.rot.y, mCellRef4.mPlacement.rot.z } };
|
||||
mChanged = false;
|
||||
mIsEsm4 = true;
|
||||
}
|
||||
CellRef(const ESM4::Reference& ref);
|
||||
|
||||
// Note: Currently unused for items in containers
|
||||
const ESM::RefNum& getRefNum() const { return mCellRef.mRefNum; }
|
||||
const ESM::RefNum& getRefNum() const { return mRefNum; }
|
||||
|
||||
// Returns RefNum.
|
||||
// If RefNum is not set, assigns a generated one and changes the "lastAssignedRefNum" counter.
|
||||
|
@ -46,44 +34,32 @@ namespace MWWorld
|
|||
void unsetRefNum();
|
||||
|
||||
/// Does the RefNum have a content file?
|
||||
bool hasContentFile() const { return mCellRef.mRefNum.hasContentFile(); }
|
||||
bool hasContentFile() const { return mRefNum.hasContentFile(); }
|
||||
|
||||
// Id of object being referenced
|
||||
const ESM::RefId& getRefId() const { return mCellRef.mRefID; }
|
||||
const ESM::RefId& getRefId() const { return mReferenceType; }
|
||||
|
||||
// For doors - true if this door teleports to somewhere else, false
|
||||
// if it should open through animation.
|
||||
bool getTeleport() const { return mCellRef.mTeleport; }
|
||||
bool getTeleport() const { return mCellRef.isESM4() ? false : mCellRef.getEsm3().mTeleport; }
|
||||
|
||||
// Teleport location for the door, if this is a teleporting door.
|
||||
const ESM::Position& getDoorDest() const { return mCellRef.mDoorDest; }
|
||||
const ESM::Position& getDoorDest() const { return mDoorDest; }
|
||||
|
||||
// Destination cell for doors (optional)
|
||||
const std::string& getDestCell() const { return mCellRef.mDestCell; }
|
||||
const std::string& getDestCell() const { return mDestCell; }
|
||||
|
||||
// Scale applied to mesh
|
||||
float getScale() const
|
||||
{
|
||||
if (mIsEsm4)
|
||||
return mCellRef4.mScale;
|
||||
else
|
||||
return mCellRef.mScale;
|
||||
}
|
||||
float getScale() const { return mScale; }
|
||||
void setScale(float scale);
|
||||
|
||||
// The *original* position and rotation as it was given in the Construction Set.
|
||||
// Current position and rotation of the object is stored in RefData.
|
||||
const ESM::Position& getPosition() const
|
||||
{
|
||||
if (mIsEsm4)
|
||||
return mRefrPos;
|
||||
else
|
||||
return mCellRef.mPos;
|
||||
}
|
||||
const ESM::Position& getPosition() const { return mPos; }
|
||||
void setPosition(const ESM::Position& position);
|
||||
|
||||
// Remaining enchantment charge. This could be -1 if the charge was not touched yet (i.e. full).
|
||||
float getEnchantmentCharge() const { return mCellRef.mEnchantmentCharge; }
|
||||
float getEnchantmentCharge() const { return mEnchantmentCharge; }
|
||||
|
||||
// Remaining enchantment charge rescaled to the supplied maximum charge (such as one of the enchantment).
|
||||
float getNormalizedEnchantmentCharge(int maxCharge) const;
|
||||
|
@ -93,50 +69,53 @@ 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 { return mCellRef.mChargeInt; }
|
||||
float getChargeFloat() const { return mCellRef.mChargeFloat; } // Implemented as union with int charge
|
||||
int getCharge() const { return mCellRef.isESM4() ? 0 : mCellRef.getEsm3().mChargeInt; }
|
||||
float getChargeFloat() const
|
||||
{
|
||||
return mCellRef.isESM4() ? 0.f : mCellRef.getEsm3().mChargeFloat;
|
||||
} // Implemented as union with int charge
|
||||
void setCharge(int charge);
|
||||
void setChargeFloat(float charge);
|
||||
void applyChargeRemainderToBeSubtracted(float chargeRemainder); // Stores remainders and applies if > 1
|
||||
|
||||
// The NPC that owns this object (and will get angry if you steal it)
|
||||
const ESM::RefId& getOwner() const { return mCellRef.mOwner; }
|
||||
const ESM::RefId& getOwner() const { return mOwner; }
|
||||
void setOwner(const ESM::RefId& owner);
|
||||
|
||||
// Name of a global variable. If the global variable is set to '1', using the object is temporarily allowed
|
||||
// even if it has an Owner field.
|
||||
// Used by bed rent scripts to allow the player to use the bed for the duration of the rent.
|
||||
const std::string& getGlobalVariable() const { return mCellRef.mGlobalVariable; }
|
||||
const std::string& getGlobalVariable() const { return mGlobalVariable; }
|
||||
|
||||
void resetGlobalVariable();
|
||||
|
||||
// ID of creature trapped in this soul gem
|
||||
const ESM::RefId& getSoul() const { return mCellRef.mSoul; }
|
||||
const ESM::RefId& getSoul() const { return mSoul; }
|
||||
void setSoul(const ESM::RefId& soul);
|
||||
|
||||
// The faction that owns this object (and will get angry if
|
||||
// you take it and are not a faction member)
|
||||
const ESM::RefId& getFaction() const { return mCellRef.mFaction; }
|
||||
const ESM::RefId& getFaction() const { return mFaction; }
|
||||
void setFaction(const ESM::RefId& faction);
|
||||
|
||||
// PC faction rank required to use the item. Sometimes is -1, which means "any rank".
|
||||
void setFactionRank(int factionRank);
|
||||
int getFactionRank() const { return mCellRef.mFactionRank; }
|
||||
int getFactionRank() const { return mFactionRank; }
|
||||
|
||||
// Lock level for doors and containers
|
||||
// Positive for a locked door. 0 for a door that was never locked.
|
||||
// For an unlocked door, it is set to -(previous locklevel)
|
||||
int getLockLevel() const { return mCellRef.mLockLevel; }
|
||||
int getLockLevel() const { return mLockLevel; }
|
||||
void setLockLevel(int lockLevel);
|
||||
void lock(int lockLevel);
|
||||
void unlock();
|
||||
// Key and trap ID names, if any
|
||||
const ESM::RefId& getKey() const { return mCellRef.mKey; }
|
||||
const ESM::RefId& getTrap() const { return mCellRef.mTrap; }
|
||||
const ESM::RefId& getKey() const { return mKey; }
|
||||
const ESM::RefId& getTrap() const { return mTrap; }
|
||||
void setTrap(const ESM::RefId& trap);
|
||||
|
||||
// This is 5 for Gold_005 references, 100 for Gold_100 and so on.
|
||||
int getGoldValue() const { return mCellRef.mGoldValue; }
|
||||
int getGoldValue() const { return mGoldValue; }
|
||||
void setGoldValue(int value);
|
||||
|
||||
// Write the content of this CellRef into the given ObjectState
|
||||
|
@ -147,10 +126,15 @@ namespace MWWorld
|
|||
|
||||
private:
|
||||
bool mChanged;
|
||||
ESM::CellRef mCellRef;
|
||||
ESM4::Reference mCellRef4;
|
||||
ESM::Position mRefrPos;
|
||||
bool mIsEsm4;
|
||||
ESM::ReferenceVariant mCellRef;
|
||||
|
||||
ESM::RefId mSoul, mFaction, mKey, mTrap, mOwner, mReferenceType;
|
||||
float Scale;
|
||||
ESM::Position mPos, mDoorDest;
|
||||
ESM::RefNum mRefNum;
|
||||
std::string mGlobalVariable, mDestCell;
|
||||
int mLockLevel, mGoldValue, mFactionRank, mEnchantmentCharge;
|
||||
float mScale;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
#include <string_view>
|
||||
#include <variant>
|
||||
|
||||
#include <components/misc/notnullptr.hpp>
|
||||
#include <components/esm3/cellref.hpp>
|
||||
#include <components/esm4/loadrefr.hpp>
|
||||
|
||||
namespace ESM4
|
||||
{
|
||||
|
@ -39,6 +40,31 @@ namespace ESM
|
|||
|
||||
const ESM::Cell& getEsm3() const;
|
||||
};
|
||||
|
||||
struct ReferenceVariant
|
||||
{
|
||||
protected:
|
||||
std::variant<ESM::CellRef, ESM4::Reference> mVariant;
|
||||
|
||||
public:
|
||||
explicit ReferenceVariant(const ESM4::Reference& ref)
|
||||
: mVariant(ref)
|
||||
{
|
||||
}
|
||||
|
||||
explicit ReferenceVariant(const ESM::CellRef& ref)
|
||||
: mVariant(ref)
|
||||
{
|
||||
}
|
||||
|
||||
bool isESM4() const { return std::holds_alternative<ESM4::Reference>(mVariant); }
|
||||
|
||||
const ESM::CellRef& getEsm3() const { return std::get<ESM::CellRef>(mVariant); }
|
||||
const ESM4::Reference& getEsm4() const { return std::get<ESM4::Reference>(mVariant); }
|
||||
|
||||
ESM::CellRef& getEsm3() { return std::get<ESM::CellRef>(mVariant); }
|
||||
ESM4::Reference& getEsm4() { return std::get<ESM4::Reference>(mVariant); }
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue