Merge branch 'master' of https://github.com/OpenMW/openmw into osg

Conflicts:
	apps/openmw/mwmechanics/aicombat.cpp
	apps/openmw/mwmechanics/aitravel.cpp
This commit is contained in:
scrawl 2015-06-14 16:14:56 +02:00
commit cad18969e3
56 changed files with 322 additions and 298 deletions

View file

@ -830,12 +830,12 @@ std::string npcFlags(int flags)
std::string properties = ""; std::string properties = "";
if (flags == 0) properties += "[None] "; if (flags == 0) properties += "[None] ";
// Mythicmods and the ESM component differ. Mythicmods says // Mythicmods and the ESM component differ. Mythicmods says
// 0x8=None and 0x10=AutoCalc, while our code defines 0x8 as // 0x8=None and 0x10=AutoCalc, while our code previously defined
// AutoCalc. The former seems to be correct. All Bethesda // 0x8 as AutoCalc. The former seems to be correct. All Bethesda
// records have bit 0x8 set. A suspiciously large portion of // records have bit 0x8 set. Previously, suspiciously large portion
// females have autocalc turned off. // of females had autocalc turned off.
if (flags & ESM::NPC::Autocalc) properties += "Unknown "; if (flags & 0x00000008) properties += "Unknown ";
if (flags & 0x00000010) properties += "Autocalc "; if (flags & ESM::NPC::Autocalc) properties += "Autocalc ";
if (flags & ESM::NPC::Female) properties += "Female "; if (flags & ESM::NPC::Female) properties += "Female ";
if (flags & ESM::NPC::Respawn) properties += "Respawn "; if (flags & ESM::NPC::Respawn) properties += "Respawn ";
if (flags & ESM::NPC::Essential) properties += "Essential "; if (flags & ESM::NPC::Essential) properties += "Essential ";
@ -847,8 +847,8 @@ std::string npcFlags(int flags)
// however the only unknown bit occurs on ALL records, and // however the only unknown bit occurs on ALL records, and
// relatively few NPCs have this bit set. // relatively few NPCs have this bit set.
int unused = (0xFFFFFFFF ^ int unused = (0xFFFFFFFF ^
(ESM::NPC::Autocalc| (0x00000008|
0x00000010| ESM::NPC::Autocalc|
ESM::NPC::Female| ESM::NPC::Female|
ESM::NPC::Respawn| ESM::NPC::Respawn|
ESM::NPC::Essential| ESM::NPC::Essential|

View file

@ -490,7 +490,7 @@ bool Launcher::MainDialog::writeSettings()
// Game settings // Game settings
QFile file(userPath + QString("openmw.cfg")); QFile file(userPath + QString("openmw.cfg"));
if (!file.open(QIODevice::ReadWrite | QIODevice::Text)) { if (!file.open(QIODevice::ReadWrite | QIODevice::Text | QIODevice::Truncate)) {
// File cannot be opened or created // File cannot be opened or created
QMessageBox msgBox; QMessageBox msgBox;
msgBox.setWindowTitle(tr("Error writing OpenMW configuration file")); msgBox.setWindowTitle(tr("Error writing OpenMW configuration file"));
@ -503,8 +503,10 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
mGameSettings.writeFileWithComments(file); mGameSettings.writeFile(stream);
file.close(); file.close();
// Graphics settings // Graphics settings
@ -523,7 +525,6 @@ bool Launcher::MainDialog::writeSettings()
return false; return false;
} }
QTextStream stream(&file);
stream.setDevice(&file); stream.setDevice(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8")); stream.setCodec(QTextCodec::codecForName("UTF-8"));

View file

@ -648,7 +648,7 @@ void CSMTools::ReferenceableCheckStage::npcCheck (
if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated if (npc.mNpdtType == ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS) //12 = autocalculated
{ {
if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0008 = autocalculated flag if ((npc.mFlags & ESM::NPC::Autocalc) == 0) //0x0010 = autocalculated flag
{ {
messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend? messages.push_back (std::make_pair (id, npc.mId + " mNpdtType or flags mismatch!")); //should not happend?
return; return;

View file

@ -37,10 +37,18 @@ void CSMWorld::PotionRefIdAdapter::setData (const RefIdColumn *column, RefIdData
Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> ( Record<ESM::Potion>& record = static_cast<Record<ESM::Potion>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Potion)));
ESM::Potion potion = record.get();
if (column==mAutoCalc) if (column==mAutoCalc)
record.get().mData.mAutoCalc = value.toInt(); potion.mData.mAutoCalc = value.toInt();
else else
{
InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value); InventoryRefIdAdapter<ESM::Potion>::setData (column, data, index, value);
return;
}
record.setModified(potion);
} }
@ -71,12 +79,19 @@ void CSMWorld::ApparatusRefIdAdapter::setData (const RefIdColumn *column, RefIdD
Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> ( Record<ESM::Apparatus>& record = static_cast<Record<ESM::Apparatus>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Apparatus)));
ESM::Apparatus apparatus = record.get();
if (column==mType) if (column==mType)
record.get().mData.mType = value.toInt(); apparatus.mData.mType = value.toInt();
else if (column==mQuality) else if (column==mQuality)
record.get().mData.mQuality = value.toFloat(); apparatus.mData.mQuality = value.toFloat();
else else
{
InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value); InventoryRefIdAdapter<ESM::Apparatus>::setData (column, data, index, value);
return;
}
record.setModified(apparatus);
} }
@ -114,14 +129,22 @@ void CSMWorld::ArmorRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> ( Record<ESM::Armor>& record = static_cast<Record<ESM::Armor>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Armor)));
ESM::Armor armor = record.get();
if (column==mType) if (column==mType)
record.get().mData.mType = value.toInt(); armor.mData.mType = value.toInt();
else if (column==mHealth) else if (column==mHealth)
record.get().mData.mHealth = value.toInt(); armor.mData.mHealth = value.toInt();
else if (column==mArmor) else if (column==mArmor)
record.get().mData.mArmor = value.toInt(); armor.mData.mArmor = value.toInt();
else else
{
EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value); EnchantableRefIdAdapter<ESM::Armor>::setData (column, data, index, value);
return;
}
record.setModified(armor);
} }
CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns, CSMWorld::BookRefIdAdapter::BookRefIdAdapter (const EnchantableColumns& columns,
@ -151,12 +174,20 @@ void CSMWorld::BookRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> ( Record<ESM::Book>& record = static_cast<Record<ESM::Book>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Book)));
ESM::Book book = record.get();
if (column==mScroll) if (column==mScroll)
record.get().mData.mIsScroll = value.toInt(); book.mData.mIsScroll = value.toInt();
else if (column==mSkill) else if (column==mSkill)
record.get().mData.mSkillID = value.toInt(); book.mData.mSkillID = value.toInt();
else else
{
EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value); EnchantableRefIdAdapter<ESM::Book>::setData (column, data, index, value);
return;
}
record.setModified(book);
} }
CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns, CSMWorld::ClothingRefIdAdapter::ClothingRefIdAdapter (const EnchantableColumns& columns,
@ -186,10 +217,18 @@ void CSMWorld::ClothingRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> ( Record<ESM::Clothing>& record = static_cast<Record<ESM::Clothing>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Clothing)));
ESM::Clothing clothing = record.get();
if (column==mType) if (column==mType)
record.get().mData.mType = value.toInt(); clothing.mData.mType = value.toInt();
else else
{
EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value); EnchantableRefIdAdapter<ESM::Clothing>::setData (column, data, index, value);
return;
}
record.setModified(clothing);
} }
CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns, CSMWorld::ContainerRefIdAdapter::ContainerRefIdAdapter (const NameColumns& columns,
@ -226,24 +265,32 @@ void CSMWorld::ContainerRefIdAdapter::setData (const RefIdColumn *column, RefIdD
Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> ( Record<ESM::Container>& record = static_cast<Record<ESM::Container>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Container)));
ESM::Container container = record.get();
if (column==mWeight) if (column==mWeight)
record.get().mWeight = value.toFloat(); container.mWeight = value.toFloat();
else if (column==mOrganic) else if (column==mOrganic)
{ {
if (value.toInt()) if (value.toInt())
record.get().mFlags |= ESM::Container::Organic; container.mFlags |= ESM::Container::Organic;
else else
record.get().mFlags &= ~ESM::Container::Organic; container.mFlags &= ~ESM::Container::Organic;
} }
else if (column==mRespawn) else if (column==mRespawn)
{ {
if (value.toInt()) if (value.toInt())
record.get().mFlags |= ESM::Container::Respawn; container.mFlags |= ESM::Container::Respawn;
else else
record.get().mFlags &= ~ESM::Container::Respawn; container.mFlags &= ~ESM::Container::Respawn;
} }
else else
{
NameRefIdAdapter<ESM::Container>::setData (column, data, index, value); NameRefIdAdapter<ESM::Container>::setData (column, data, index, value);
return;
}
record.setModified(container);
} }
CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns) CSMWorld::CreatureColumns::CreatureColumns (const ActorColumns& actorColumns)
@ -303,20 +350,22 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> ( Record<ESM::Creature>& record = static_cast<Record<ESM::Creature>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Creature)));
ESM::Creature creature = record.get();
if (column==mColumns.mType) if (column==mColumns.mType)
record.get().mData.mType = value.toInt(); creature.mData.mType = value.toInt();
else if (column==mColumns.mSoul) else if (column==mColumns.mSoul)
record.get().mData.mSoul = value.toInt(); creature.mData.mSoul = value.toInt();
else if (column==mColumns.mScale) else if (column==mColumns.mScale)
record.get().mScale = value.toFloat(); creature.mScale = value.toFloat();
else if (column==mColumns.mOriginal) else if (column==mColumns.mOriginal)
record.get().mOriginal = value.toString().toUtf8().constData(); creature.mOriginal = value.toString().toUtf8().constData();
else if (column==mColumns.mCombat) else if (column==mColumns.mCombat)
record.get().mData.mCombat = value.toInt(); creature.mData.mCombat = value.toInt();
else if (column==mColumns.mMagic) else if (column==mColumns.mMagic)
record.get().mData.mMagic = value.toInt(); creature.mData.mMagic = value.toInt();
else if (column==mColumns.mStealth) else if (column==mColumns.mStealth)
record.get().mData.mStealth = value.toInt(); creature.mData.mStealth = value.toInt();
else else
{ {
std::map<const RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -325,13 +374,19 @@ void CSMWorld::CreatureRefIdAdapter::setData (const RefIdColumn *column, RefIdDa
if (iter!=mColumns.mFlags.end()) if (iter!=mColumns.mFlags.end())
{ {
if (value.toInt()!=0) if (value.toInt()!=0)
record.get().mFlags |= iter->second; creature.mFlags |= iter->second;
else else
record.get().mFlags &= ~iter->second; creature.mFlags &= ~iter->second;
} }
else else
{
ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value); ActorRefIdAdapter<ESM::Creature>::setData (column, data, index, value);
return;
}
} }
record.setModified(creature);
} }
CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns, CSMWorld::DoorRefIdAdapter::DoorRefIdAdapter (const NameColumns& columns,
@ -361,12 +416,20 @@ void CSMWorld::DoorRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> ( Record<ESM::Door>& record = static_cast<Record<ESM::Door>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Door)));
ESM::Door door = record.get();
if (column==mOpenSound) if (column==mOpenSound)
record.get().mOpenSound = value.toString().toUtf8().constData(); door.mOpenSound = value.toString().toUtf8().constData();
else if (column==mCloseSound) else if (column==mCloseSound)
record.get().mCloseSound = value.toString().toUtf8().constData(); door.mCloseSound = value.toString().toUtf8().constData();
else else
{
NameRefIdAdapter<ESM::Door>::setData (column, data, index, value); NameRefIdAdapter<ESM::Door>::setData (column, data, index, value);
return;
}
record.setModified(door);
} }
CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns) CSMWorld::LightColumns::LightColumns (const InventoryColumns& columns)
@ -409,14 +472,16 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> ( Record<ESM::Light>& record = static_cast<Record<ESM::Light>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Light)));
ESM::Light light = record.get();
if (column==mColumns.mTime) if (column==mColumns.mTime)
record.get().mData.mTime = value.toInt(); light.mData.mTime = value.toInt();
else if (column==mColumns.mRadius) else if (column==mColumns.mRadius)
record.get().mData.mRadius = value.toInt(); light.mData.mRadius = value.toInt();
else if (column==mColumns.mColor) else if (column==mColumns.mColor)
record.get().mData.mColor = value.toInt(); light.mData.mColor = value.toInt();
else if (column==mColumns.mSound) else if (column==mColumns.mSound)
record.get().mSound = value.toString().toUtf8().constData(); light.mSound = value.toString().toUtf8().constData();
else else
{ {
std::map<const RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -425,13 +490,19 @@ void CSMWorld::LightRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
if (iter!=mColumns.mFlags.end()) if (iter!=mColumns.mFlags.end())
{ {
if (value.toInt()!=0) if (value.toInt()!=0)
record.get().mData.mFlags |= iter->second; light.mData.mFlags |= iter->second;
else else
record.get().mData.mFlags &= ~iter->second; light.mData.mFlags &= ~iter->second;
} }
else else
{
InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value); InventoryRefIdAdapter<ESM::Light>::setData (column, data, index, value);
return;
}
} }
record.setModified (light);
} }
CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key) CSMWorld::MiscRefIdAdapter::MiscRefIdAdapter (const InventoryColumns& columns, const RefIdColumn *key)
@ -456,10 +527,18 @@ void CSMWorld::MiscRefIdAdapter::setData (const RefIdColumn *column, RefIdData&
Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> ( Record<ESM::Miscellaneous>& record = static_cast<Record<ESM::Miscellaneous>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Miscellaneous)));
ESM::Miscellaneous misc = record.get();
if (column==mKey) if (column==mKey)
record.get().mData.mIsKey = value.toInt(); misc.mData.mIsKey = value.toInt();
else else
{
InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value); InventoryRefIdAdapter<ESM::Miscellaneous>::setData (column, data, index, value);
return;
}
record.setModified(misc);
} }
CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns) CSMWorld::NpcColumns::NpcColumns (const ActorColumns& actorColumns)
@ -525,16 +604,18 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> ( Record<ESM::NPC>& record = static_cast<Record<ESM::NPC>&> (
data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc))); data.getRecord (RefIdData::LocalIndex (index, UniversalId::Type_Npc)));
ESM::NPC npc = record.get();
if (column==mColumns.mRace) if (column==mColumns.mRace)
record.get().mRace = value.toString().toUtf8().constData(); npc.mRace = value.toString().toUtf8().constData();
else if (column==mColumns.mClass) else if (column==mColumns.mClass)
record.get().mClass = value.toString().toUtf8().constData(); npc.mClass = value.toString().toUtf8().constData();
else if (column==mColumns.mFaction) else if (column==mColumns.mFaction)
record.get().mFaction = value.toString().toUtf8().constData(); npc.mFaction = value.toString().toUtf8().constData();
else if (column==mColumns.mHair) else if (column==mColumns.mHair)
record.get().mHair = value.toString().toUtf8().constData(); npc.mHair = value.toString().toUtf8().constData();
else if (column==mColumns.mHead) else if (column==mColumns.mHead)
record.get().mHead = value.toString().toUtf8().constData(); npc.mHead = value.toString().toUtf8().constData();
else else
{ {
std::map<const RefIdColumn *, unsigned int>::const_iterator iter = std::map<const RefIdColumn *, unsigned int>::const_iterator iter =
@ -543,13 +624,23 @@ void CSMWorld::NpcRefIdAdapter::setData (const RefIdColumn *column, RefIdData& d
if (iter!=mColumns.mFlags.end()) if (iter!=mColumns.mFlags.end())
{ {
if (value.toInt()!=0) if (value.toInt()!=0)
record.get().mFlags |= iter->second; npc.mFlags |= iter->second;
else else
record.get().mFlags &= ~iter->second; npc.mFlags &= ~iter->second;
if (iter->second == ESM::NPC::Autocalc)
npc.mNpdtType = (value.toInt() != 0) ? ESM::NPC::NPC_WITH_AUTOCALCULATED_STATS
: ESM::NPC::NPC_DEFAULT;
} }
else else
{
ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value); ActorRefIdAdapter<ESM::NPC>::setData (column, data, index, value);
return;
}
} }
record.setModified (npc);
} }
CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter () CSMWorld::NpcAttributesRefIdAdapter::NpcAttributesRefIdAdapter ()

View file

@ -673,44 +673,32 @@ namespace MWMechanics
return false; return false;
} }
bool AiCombat::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell)
{
if (!mPathFinder.getPath().empty())
{
osg::Vec3f currPathTarget(PathFinder::MakeOsgVec3(mPathFinder.getPath().back()));
osg::Vec3f newPathTarget = PathFinder::MakeOsgVec3(dest);
float dist = (newPathTarget - currPathTarget).length();
float targetPosThreshold = (cell->isExterior()) ? 300.0f : 100.0f;
return dist > targetPosThreshold;
}
else
{
// necessarily construct a new path
return true;
}
}
void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target) void AiCombat::buildNewPath(const MWWorld::Ptr& actor, const MWWorld::Ptr& target)
{ {
osg::Vec3f newPathTarget = target.getRefData().getPosition().asVec3(); ESM::Pathgrid::Point newPathTarget = PathFinder::MakePathgridPoint(target.getRefData().getPosition());
float dist;
if(!mPathFinder.getPath().empty())
{
ESM::Pathgrid::Point lastPt = mPathFinder.getPath().back();
osg::Vec3f currPathTarget(PathFinder::MakeOsgVec3(lastPt));
dist = (newPathTarget - currPathTarget).length();
}
else dist = 1e+38F; // necessarily construct a new path
float targetPosThreshold = (actor.getCell()->getCell()->isExterior())? 300.0f : 100.0f;
//construct new path only if target has moved away more than on [targetPosThreshold] //construct new path only if target has moved away more than on [targetPosThreshold]
if(dist > targetPosThreshold) if (doesPathNeedRecalc(newPathTarget, actor.getCell()->getCell()))
{ {
ESM::Position pos = actor.getRefData().getPosition(); ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(actor.getRefData().getPosition()));
mPathFinder.buildSyncedPath(start, newPathTarget, actor.getCell(), false);
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
ESM::Pathgrid::Point dest(PathFinder::MakePathgridPoint(newPathTarget));
if(!mPathFinder.isPathConstructed())
mPathFinder.buildPath(start, dest, actor.getCell(), false);
else
{
PathFinder newPathFinder;
newPathFinder.buildPath(start, dest, actor.getCell(), false);
if(!mPathFinder.getPath().empty())
{
newPathFinder.syncStart(mPathFinder.getPath());
mPathFinder = newPathFinder;
}
}
} }
} }

View file

@ -51,6 +51,9 @@ namespace MWMechanics
virtual void writeState(ESM::AiSequence::AiSequence &sequence) const; virtual void writeState(ESM::AiSequence::AiSequence &sequence) const;
protected:
virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell);
private: private:
int mTargetActorId; int mTargetActorId;

View file

@ -28,9 +28,9 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
ESM::Position pos = actor.getRefData().getPosition(); //position of the actor ESM::Position pos = actor.getRefData().getPosition(); //position of the actor
/// Stops the actor when it gets too close to a unloaded cell /// Stops the actor when it gets too close to a unloaded cell
const ESM::Cell *cell = actor.getCell()->getCell();
{ {
MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr();
const ESM::Cell *cell = actor.getCell()->getCell();
Movement &movement = actor.getClass().getMovementSettings(actor); Movement &movement = actor.getClass().getMovementSettings(actor);
//Ensure pursuer doesn't leave loaded cells //Ensure pursuer doesn't leave loaded cells
@ -65,8 +65,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
//*********************** //***********************
if(mTimer > 0.25) if(mTimer > 0.25)
{ {
if(distance(mPrevDest, dest) > 10) { //Only rebuild path if it's moved if (doesPathNeedRecalc(dest, cell)) { //Only rebuild path if it's moved
mPathFinder.buildPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved mPathFinder.buildSyncedPath(start, dest, actor.getCell(), true); //Rebuild path, in case the target has moved
mPrevDest = dest; mPrevDest = dest;
} }
@ -121,3 +121,8 @@ bool MWMechanics::AiPackage::pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Po
return false; return false;
} }
bool MWMechanics::AiPackage::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell)
{
return distance(mPrevDest, dest) > 10;
}

View file

@ -4,6 +4,8 @@
#include "pathfinding.hpp" #include "pathfinding.hpp"
#include <components/esm/defs.hpp> #include <components/esm/defs.hpp>
#include "../mwworld/cellstore.hpp"
#include "obstacle.hpp" #include "obstacle.hpp"
#include "aistate.hpp" #include "aistate.hpp"
@ -71,6 +73,8 @@ namespace MWMechanics
/** \return If the actor has arrived at his destination **/ /** \return If the actor has arrived at his destination **/
bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration); bool pathTo(const MWWorld::Ptr& actor, ESM::Pathgrid::Point dest, float duration);
virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell);
// TODO: all this does not belong here, move into temporary storage // TODO: all this does not belong here, move into temporary storage
PathFinder mPathFinder; PathFinder mPathFinder;
ObstacleCheck mObstacleCheck; ObstacleCheck mObstacleCheck;

View file

@ -49,64 +49,31 @@ namespace MWMechanics
bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration) bool AiTravel::execute (const MWWorld::Ptr& actor, AiState& state, float duration)
{ {
MWBase::World *world = MWBase::Environment::get().getWorld();
ESM::Position pos = actor.getRefData().getPosition(); ESM::Position pos = actor.getRefData().getPosition();
Movement &movement = actor.getClass().getMovementSettings(actor);
const ESM::Cell *cell = actor.getCell()->getCell();
actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false); actor.getClass().getCreatureStats(actor).setMovementFlag(CreatureStats::Flag_Run, false);
actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing); actor.getClass().getCreatureStats(actor).setDrawState(DrawState_Nothing);
MWWorld::Ptr player = world->getPlayerPtr();
if(cell->mData.mX != player.getCell()->getCell()->mData.mX)
{
int sideX = PathFinder::sgn(cell->mData.mX - player.getCell()->getCell()->mData.mX);
//check if actor is near the border of an inactive cell. If so, stop walking.
if(sideX * (pos.pos[0] - cell->mData.mX*ESM::Land::REAL_SIZE) >
sideX * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{
movement.mPosition[1] = 0;
return false;
}
}
if(cell->mData.mY != player.getCell()->getCell()->mData.mY)
{
int sideY = PathFinder::sgn(cell->mData.mY - player.getCell()->getCell()->mData.mY);
//check if actor is near the border of an inactive cell. If so, stop walking.
if(sideY * (pos.pos[1] - cell->mData.mY*ESM::Land::REAL_SIZE) >
sideY * (ESM::Land::REAL_SIZE/2.0f - 200.0f))
{
movement.mPosition[1] = 0;
return false;
}
}
if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), pos.asVec3())) if (!isWithinMaxRange(osg::Vec3f(mX, mY, mZ), pos.asVec3()))
return false; return false;
if (pathTo(actor, ESM::Pathgrid::Point(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ)), duration))
{
actor.getClass().getMovementSettings(actor).mPosition[1] = 0;
return true;
}
return false;
}
bool AiTravel::doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell)
{
bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY; bool cellChange = cell->mData.mX != mCellX || cell->mData.mY != mCellY;
if(!mPathFinder.isPathConstructed() || cellChange) if (!mPathFinder.isPathConstructed() || cellChange)
{ {
mCellX = cell->mData.mX; mCellX = cell->mData.mX;
mCellY = cell->mData.mY; mCellY = cell->mData.mY;
ESM::Pathgrid::Point dest(static_cast<int>(mX), static_cast<int>(mY), static_cast<int>(mZ));
ESM::Pathgrid::Point start(PathFinder::MakePathgridPoint(pos));
mPathFinder.buildPath(start, dest, actor.getCell(), true);
}
if(mPathFinder.checkPathCompleted(pos.pos[0], pos.pos[1]))
{
movement.mPosition[1] = 0;
return true; return true;
} }
zTurn(actor, osg::DegreesToRadians(mPathFinder.getZAngleToNext(pos.pos[0], pos.pos[1])));
movement.mPosition[1] = 1;
return false; return false;
} }

View file

@ -34,6 +34,9 @@ namespace MWMechanics
virtual int getTypeId() const; virtual int getTypeId() const;
protected:
virtual bool doesPathNeedRecalc(ESM::Pathgrid::Point dest, const ESM::Cell *cell);
private: private:
float mX; float mX;
float mY; float mY;

View file

@ -298,23 +298,35 @@ namespace MWMechanics
return false; return false;
} }
// used by AiCombat, see header for the rationale // see header for the rationale
bool PathFinder::syncStart(const std::list<ESM::Pathgrid::Point> &path) void PathFinder::buildSyncedPath(const ESM::Pathgrid::Point &startPoint,
const ESM::Pathgrid::Point &endPoint,
const MWWorld::CellStore* cell,
bool allowShortcuts)
{ {
if (mPath.size() < 2) if (mPath.size() < 2)
return false; //nothing to pop
std::list<ESM::Pathgrid::Point>::const_iterator oldStart = path.begin();
std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin();
if( (*iter).mX == oldStart->mX
&& (*iter).mY == oldStart->mY
&& (*iter).mZ == oldStart->mZ)
{ {
mPath.pop_front(); // if path has one point, then it's the destination.
return true; // don't need to worry about bad path for this case
buildPath(startPoint, endPoint, cell, allowShortcuts);
}
else
{
const ESM::Pathgrid::Point oldStart(*getPath().begin());
buildPath(startPoint, endPoint, cell, allowShortcuts);
if (mPath.size() >= 2)
{
// if 2nd waypoint of new path == 1st waypoint of old,
// delete 1st waypoint of new path.
std::list<ESM::Pathgrid::Point>::iterator iter = ++mPath.begin();
if (iter->mX == oldStart.mX
&& iter->mY == oldStart.mY
&& iter->mZ == oldStart.mZ)
{
mPath.pop_front();
}
}
} }
return false;
} }
} }

View file

@ -61,13 +61,13 @@ namespace MWMechanics
/** Synchronize new path with old one to avoid visiting 1 waypoint 2 times /** Synchronize new path with old one to avoid visiting 1 waypoint 2 times
@note @note
If the first point is chosen as the nearest one BuildPath() takes closest PathGrid point to NPC as first point of path.
the situation can occur when the 1st point of the new path is undesirable This is undesireable if NPC has just passed a Pathgrid point, as this
(i.e. the 2nd point of new path == the 1st point of old path). makes the 2nd point of the new path == the 1st point of old path.
@param path - old path Which results in NPC "running in a circle" back to the just passed waypoint.
@return true if such point was found and deleted
*/ */
bool syncStart(const std::list<ESM::Pathgrid::Point> &path); void buildSyncedPath(const ESM::Pathgrid::Point &startPoint, const ESM::Pathgrid::Point &endPoint,
const MWWorld::CellStore* cell, bool allowShortcuts = true);
void addPointToPath(ESM::Pathgrid::Point &point) void addPointToPath(ESM::Pathgrid::Point &point)
{ {

View file

@ -188,7 +188,7 @@ namespace MWWorld
const T *ptr = search(id); const T *ptr = search(id);
if (ptr == 0) { if (ptr == 0) {
std::ostringstream msg; std::ostringstream msg;
msg << "Object '" << id << "' not found (const)"; msg << T::getRecordType() << " '" << id << "' not found";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
return ptr; return ptr;
@ -202,7 +202,7 @@ namespace MWWorld
if(ptr == 0) if(ptr == 0)
{ {
std::ostringstream msg; std::ostringstream msg;
msg << "Object starting with '"<<id<<"' not found (const)"; msg << T::getRecordType() << " starting with '"<<id<<"' not found";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
return ptr; return ptr;
@ -989,7 +989,7 @@ namespace MWWorld
const T *ptr = search(index); const T *ptr = search(index);
if (ptr == 0) { if (ptr == 0) {
std::ostringstream msg; std::ostringstream msg;
msg << "Object with index " << index << " not found"; msg << T::getRecordType() << " with index " << index << " not found";
throw std::runtime_error(msg.str()); throw std::runtime_error(msg.str());
} }
return ptr; return ptr;

View file

@ -1,7 +1,6 @@
#include "gamesettings.hpp" #include "gamesettings.hpp"
#include "launchersettings.hpp" #include "launchersettings.hpp"
#include <QTextCodec>
#include <QTextStream> #include <QTextStream>
#include <QDir> #include <QDir>
#include <QString> #include <QString>
@ -174,138 +173,6 @@ bool Config::GameSettings::writeFile(QTextStream &stream)
return true; return true;
} }
// Policy:
//
// - Always ignore a line beginning with '#' or empty lines
//
// - If a line in file exists with matching key and first part of value (before ',',
// '\n', etc) also matches, then replace the line with that of mUserSettings.
// - else remove line (TODO: maybe replace the line with '#' in front instead?)
//
// - If there is no corresponding line in file, add at the end
//
bool Config::GameSettings::writeFileWithComments(QFile &file)
{
QTextStream stream(&file);
stream.setCodec(QTextCodec::codecForName("UTF-8"));
// slurp
std::vector<QString> fileCopy;
QString line = stream.readLine();
while (!line.isNull())
{
fileCopy.push_back(line);
line = stream.readLine();
}
stream.seek(0);
// empty file, no comments to keep
if (fileCopy.empty())
return writeFile(stream);
// Temp copy of settings to save, but with the keys appended with the first part of the value
//
// ATTENTION!
//
// A hack to avoid looping through each line, makes use of the fact that fallbacks values
// are comma separated.
QMap<QString, QString> userSettingsCopy;
QRegExp settingRegex("^([^=]+)\\s*=\\s*([^,]+)(.*)$");
QString settingLine;
QMap<QString, QString>::const_iterator settingsIter = mUserSettings.begin();
for (; settingsIter != mUserSettings.end(); ++settingsIter)
{
settingLine = settingsIter.key()+"="+settingsIter.value();
if (settingRegex.indexIn(settingLine) != -1)
{
userSettingsCopy[settingRegex.cap(1)+"="+settingRegex.cap(2)] =
(settingRegex.captureCount() < 3) ? "" : settingRegex.cap(3);
}
}
QString keyVal;
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
{
// skip empty or comment lines
if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
continue;
// look for a key in the line
if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2)
{
// no key or first part of value found in line, replace with a null string which
// will be remved later
*iter = QString();
continue;
}
// look for a matching key in user settings
keyVal = settingRegex.cap(1)+"="+settingRegex.cap(2);
QMap<QString, QString>::iterator it = userSettingsCopy.find(keyVal);
if (it == userSettingsCopy.end())
{
// no such key+valStart, replace with a null string which will be remved later
*iter = QString();
}
else
{
*iter = QString(it.key()+it.value());
userSettingsCopy.erase(it);
}
}
// write the new config file
QString key;
QString value;
for (std::vector<QString>::iterator iter = fileCopy.begin(); iter != fileCopy.end(); ++iter)
{
if ((*iter).isNull())
continue;
// Below is based on readFile() code, if that changes corresponding change may be
// required (for example duplicates may be inserted if the rules don't match)
if ((*iter).isEmpty() || (*iter).contains(QRegExp("^\\s*#")))
{
stream << *iter << "\n";
continue;
}
if (settingRegex.indexIn(*iter) == -1 || settingRegex.captureCount() < 2)
continue;
// Quote paths with spaces
key = settingRegex.cap(1);
value = settingRegex.cap(2)+settingRegex.cap(3);
if (key == QLatin1String("data")
|| key == QLatin1String("data-local")
|| key == QLatin1String("resources"))
{
if (value.contains(QChar(' ')))
{
value.remove(QChar('\"')); // Remove quotes
stream << key << "=\"" << value << "\"\n";
continue;
}
}
stream << key << "=" << value << "\n";
}
// new entries
if (!userSettingsCopy.empty())
{
QMap<QString, QString>::const_iterator it = userSettingsCopy.begin();
for (; it != userSettingsCopy.end(); ++it)
{
stream << it.key() << it.value() << "\n";
}
}
file.resize(file.pos());
return true;
}
bool Config::GameSettings::hasMaster() bool Config::GameSettings::hasMaster()
{ {
bool result = false; bool result = false;

View file

@ -4,7 +4,6 @@
#include <QTextStream> #include <QTextStream>
#include <QStringList> #include <QStringList>
#include <QString> #include <QString>
#include <QFile>
#include <QMap> #include <QMap>
#include <boost/filesystem/path.hpp> #include <boost/filesystem/path.hpp>
@ -67,7 +66,6 @@ namespace Config
bool readUserFile(QTextStream &stream); bool readUserFile(QTextStream &stream);
bool writeFile(QTextStream &stream); bool writeFile(QTextStream &stream);
bool writeFileWithComments(QFile &file);
void setContentList(const QStringList& fileNames); void setContentList(const QStringList& fileNames);
QStringList getContentList() const; QStringList getContentList() const;

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct Activator struct Activator
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Activator"; }
std::string mId, mName, mScript, mModel; std::string mId, mName, mScript, mModel;

View file

@ -19,6 +19,9 @@ struct Potion
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Potion"; }
struct ALDTstruct struct ALDTstruct
{ {
float mWeight; float mWeight;

View file

@ -16,6 +16,8 @@ class ESMWriter;
struct Apparatus struct Apparatus
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Apparatus"; }
enum AppaType enum AppaType
{ {

View file

@ -66,6 +66,8 @@ struct PartReferenceList
struct Armor struct Armor
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Armor"; }
enum Type enum Type
{ {

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct BodyPart struct BodyPart
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "BodyPart"; }
enum MeshPart enum MeshPart
{ {

View file

@ -15,6 +15,8 @@ class ESMWriter;
struct Book struct Book
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Book"; }
struct BKDTstruct struct BKDTstruct
{ {

View file

@ -14,6 +14,8 @@ class ESMWriter;
struct BirthSign struct BirthSign
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "BirthSign"; }
std::string mId, mName, mDescription, mTexture; std::string mId, mName, mDescription, mTexture;

View file

@ -56,6 +56,8 @@ typedef std::list<CellRef> CellRefTracker;
struct Cell struct Cell
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Cell"; }
enum Flags enum Flags
{ {

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Class struct Class
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Class"; }
enum AutoCalc enum AutoCalc
{ {

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Clothing struct Clothing
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Clothing"; }
enum Type enum Type
{ {

View file

@ -36,6 +36,8 @@ struct InventoryList
struct Container struct Container
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Container"; }
enum Flags enum Flags
{ {

View file

@ -22,6 +22,8 @@ class ESMWriter;
struct Creature struct Creature
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Creature"; }
// Default is 0x48? // Default is 0x48?
enum Flags enum Flags

View file

@ -21,6 +21,8 @@ class ESMWriter;
struct Dialogue struct Dialogue
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Dialogue"; }
enum Type enum Type
{ {

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct Door struct Door
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Door"; }
std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound; std::string mId, mName, mModel, mScript, mOpenSound, mCloseSound;

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Enchantment struct Enchantment
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Enchantment"; }
enum Type enum Type
{ {

View file

@ -30,6 +30,8 @@ struct RankData
struct Faction struct Faction
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Faction"; }
std::string mId, mName; std::string mId, mName;

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Global struct Global
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Global"; }
std::string mId; std::string mId;
Variant mValue; Variant mValue;

View file

@ -19,6 +19,8 @@ class ESMWriter;
struct GameSetting struct GameSetting
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "GameSetting"; }
std::string mId; std::string mId;

View file

@ -21,6 +21,8 @@ class ESMWriter;
struct DialInfo struct DialInfo
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "DialInfo"; }
enum Gender enum Gender
{ {

View file

@ -16,6 +16,8 @@ class ESMWriter;
struct Ingredient struct Ingredient
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Ingredient"; }
struct IRDTstruct struct IRDTstruct
{ {

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Land struct Land
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Land"; }
Land(); Land();
~Land(); ~Land();

View file

@ -46,6 +46,8 @@ struct LevelledListBase
struct CreatureLevList: LevelledListBase struct CreatureLevList: LevelledListBase
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "CreatureLevList"; }
enum Flags enum Flags
{ {
@ -64,6 +66,8 @@ struct CreatureLevList: LevelledListBase
struct ItemLevList: LevelledListBase struct ItemLevList: LevelledListBase
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "ItemLevList"; }
enum Flags enum Flags
{ {

View file

@ -17,6 +17,8 @@ class ESMWriter;
struct Light struct Light
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Light"; }
enum Flags enum Flags
{ {

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct Lockpick struct Lockpick
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Lockpick"; }
struct Data struct Data
{ {

View file

@ -28,6 +28,8 @@ class ESMWriter;
struct LandTexture struct LandTexture
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "LandTexture"; }
std::string mId, mTexture; std::string mId, mTexture;
int mIndex; int mIndex;

View file

@ -13,6 +13,8 @@ class ESMWriter;
struct MagicEffect struct MagicEffect
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "MagicEffect"; }
std::string mId; std::string mId;

View file

@ -17,6 +17,8 @@ class ESMWriter;
struct Miscellaneous struct Miscellaneous
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Miscellaneous"; }
struct MCDTstruct struct MCDTstruct
{ {

View file

@ -23,6 +23,8 @@ class ESMWriter;
struct NPC struct NPC
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "NPC"; }
// Services // Services
enum Services enum Services
@ -52,12 +54,12 @@ struct NPC
enum Flags enum Flags
{ {
Female = 0x0001, Female = 0x0001,
Essential = 0x0002, Essential = 0x0002,
Respawn = 0x0004, Respawn = 0x0004,
Autocalc = 0x0008, Autocalc = 0x0010,
Skeleton = 0x0400, // Skeleton blood effect (white) Skeleton = 0x0400, // Skeleton blood effect (white)
Metal = 0x0800 // Metal blood effect (golden?) Metal = 0x0800 // Metal blood effect (golden?)
}; };
enum NpcType enum NpcType

View file

@ -16,6 +16,8 @@ class ESMWriter;
struct Pathgrid struct Pathgrid
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Pathgrid"; }
struct DATAstruct struct DATAstruct
{ {

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct Probe struct Probe
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Probe"; }
struct Data struct Data
{ {

View file

@ -18,6 +18,8 @@ class ESMWriter;
struct Race struct Race
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Race"; }
struct SkillBonus struct SkillBonus
{ {

View file

@ -19,6 +19,8 @@ class ESMWriter;
struct Region struct Region
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Region"; }
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)

View file

@ -12,6 +12,8 @@ class ESMWriter;
struct Repair struct Repair
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Repair"; }
struct Data struct Data
{ {

View file

@ -20,6 +20,8 @@ class Script
{ {
public: public:
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Script"; }
struct SCHDstruct struct SCHDstruct
{ {

View file

@ -20,6 +20,8 @@ class ESMWriter;
struct Skill struct Skill
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Skill"; }
std::string mId; std::string mId;

View file

@ -16,6 +16,8 @@ class ESMWriter;
struct SoundGenerator struct SoundGenerator
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "SoundGenerator"; }
enum Type enum Type
{ {

View file

@ -17,6 +17,8 @@ struct SOUNstruct
struct Sound struct Sound
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Sound"; }
SOUNstruct mData; SOUNstruct mData;
std::string mId, mSound; std::string mId, mSound;

View file

@ -14,6 +14,8 @@ class ESMWriter;
struct Spell struct Spell
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Spell"; }
enum SpellType enum SpellType
{ {

View file

@ -20,6 +20,8 @@ class ESMWriter;
struct StartScript struct StartScript
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "StartScript"; }
std::string mData; std::string mData;
std::string mId; std::string mId;

View file

@ -23,6 +23,8 @@ class ESMWriter;
struct Static struct Static
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Static"; }
std::string mId, mModel; std::string mId, mModel;

View file

@ -16,6 +16,8 @@ class ESMWriter;
struct Weapon struct Weapon
{ {
static unsigned int sRecordId; static unsigned int sRecordId;
/// Return a string descriptor for this record type. Currently used for debugging / error logs only.
static std::string getRecordType() { return "Weapon"; }
enum Type enum Type
{ {