diff --git a/apps/esmtool/labels.cpp b/apps/esmtool/labels.cpp index f08c31003..3fb1166e8 100644 --- a/apps/esmtool/labels.cpp +++ b/apps/esmtool/labels.cpp @@ -627,10 +627,10 @@ std::string bodyPartFlags(int flags) std::string properties = ""; if (flags == 0) properties += "[None] "; if (flags & ESM::BodyPart::BPF_Female) properties += "Female "; - if (flags & ESM::BodyPart::BPF_Playable) properties += "Playable "; + if (flags & ESM::BodyPart::BPF_NotPlayable) properties += "NotPlayable "; int unused = (0xFFFFFFFF ^ (ESM::BodyPart::BPF_Female| - ESM::BodyPart::BPF_Playable)); + ESM::BodyPart::BPF_NotPlayable)); if (flags & unused) properties += "Invalid "; properties += str(boost::format("(0x%08X)") % flags); return properties; diff --git a/apps/opencs/model/doc/document.cpp b/apps/opencs/model/doc/document.cpp index d1462d6a3..acca877f0 100644 --- a/apps/opencs/model/doc/document.cpp +++ b/apps/opencs/model/doc/document.cpp @@ -207,7 +207,7 @@ void CSMDoc::Document::createBase() { ESM::Skill record; record.mIndex = i; - record.mId = ESM::Skill::getIndexToId (record.mIndex); + record.mId = ESM::Skill::indexToId (record.mIndex); record.blank(); getData().getSkills().add (record); diff --git a/apps/opencs/model/world/columnbase.hpp b/apps/opencs/model/world/columnbase.hpp index b5863f8e4..5c2ce8a67 100644 --- a/apps/opencs/model/world/columnbase.hpp +++ b/apps/opencs/model/world/columnbase.hpp @@ -33,7 +33,8 @@ namespace CSMWorld Display_GmstVarType, Display_GlobalVarType, Display_Specialisation, - Display_Attribute + Display_Attribute, + Display_Boolean }; std::string mTitle; diff --git a/apps/opencs/model/world/columns.hpp b/apps/opencs/model/world/columns.hpp index 7764f5870..cbcddd972 100644 --- a/apps/opencs/model/world/columns.hpp +++ b/apps/opencs/model/world/columns.hpp @@ -1,6 +1,8 @@ #ifndef CSM_WOLRD_COLUMNS_H #define CSM_WOLRD_COLUMNS_H +#include + #include #include "columnbase.hpp" @@ -285,6 +287,128 @@ namespace CSMWorld } }; + template + struct NameColumn : public Column + { + NameColumn() : Column ("Name", ColumnBase::Display_String) {} + + virtual QVariant get (const Record& record) const + { + return QString::fromUtf8 (record.get().mName.c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mName = data.toString().toUtf8().constData(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct AttributesColumn : public Column + { + int mIndex; + + AttributesColumn (int index) + : Column ("Attribute #" + boost::lexical_cast (index), + ColumnBase::Display_Attribute), mIndex (index) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mAttribute[mIndex]; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mAttribute[mIndex] = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct SkillsColumn : public Column + { + int mIndex; + bool mMajor; + + SkillsColumn (int index, bool major) + : Column ((major ? "Major Skill #" : "Minor Skill #")+ + boost::lexical_cast (index), ColumnBase::Display_String), + mIndex (index), mMajor (major) + {} + + virtual QVariant get (const Record& record) const + { + int skill = record.get().mData.mSkills[mIndex][mMajor ? 1 : 0]; + + return QString::fromUtf8 (ESM::Skill::indexToId (skill).c_str()); + } + + virtual void set (Record& record, const QVariant& data) + { + std::istringstream stream (data.toString().toUtf8().constData()); + + int index = -1; + char c; + + stream >> c >> index; + + if (index!=-1) + { + ESXRecordT record2 = record.get(); + + record2.mData.mSkills[mIndex][mMajor ? 1 : 0] = index; + + record.setModified (record2); + } + } + + virtual bool isEditable() const + { + return true; + } + }; + + template + struct PlayableColumn : public Column + { + PlayableColumn() : Column ("Playable", ColumnBase::Display_Boolean) {} + + virtual QVariant get (const Record& record) const + { + return record.get().mData.mIsPlayable!=0; + } + + virtual void set (Record& record, const QVariant& data) + { + ESXRecordT record2 = record.get(); + + record2.mData.mIsPlayable = data.toInt(); + + record.setModified (record2); + } + + virtual bool isEditable() const + { + return true; + } + }; } #endif \ No newline at end of file diff --git a/apps/opencs/model/world/data.cpp b/apps/opencs/model/world/data.cpp index 4b10a6683..7b3e66771 100644 --- a/apps/opencs/model/world/data.cpp +++ b/apps/opencs/model/world/data.cpp @@ -44,9 +44,23 @@ CSMWorld::Data::Data() mSkills.addColumn (new UseValueColumn (i)); mSkills.addColumn (new DescriptionColumn); + mClasses.addColumn (new StringIdColumn); + mClasses.addColumn (new RecordStateColumn); + mClasses.addColumn (new NameColumn); + mClasses.addColumn (new AttributesColumn (0)); + mClasses.addColumn (new AttributesColumn (1)); + mClasses.addColumn (new SpecialisationColumn); + for (int i=0; i<5; ++i) + mClasses.addColumn (new SkillsColumn (i, true)); + for (int i=0; i<5; ++i) + mClasses.addColumn (new SkillsColumn (i, false)); + mClasses.addColumn (new PlayableColumn); + mClasses.addColumn (new DescriptionColumn); + addModel (new IdTable (&mGlobals), UniversalId::Type_Globals, UniversalId::Type_Global); addModel (new IdTable (&mGmsts), UniversalId::Type_Gmsts, UniversalId::Type_Gmst); addModel (new IdTable (&mSkills), UniversalId::Type_Skills, UniversalId::Type_Skill); + addModel (new IdTable (&mClasses), UniversalId::Type_Classes, UniversalId::Type_Class); } CSMWorld::Data::~Data() @@ -122,6 +136,7 @@ void CSMWorld::Data::loadFile (const boost::filesystem::path& path, bool base) case ESM::REC_GLOB: mGlobals.load (reader, base); break; case ESM::REC_GMST: mGmsts.load (reader, base); break; case ESM::REC_SKIL: mSkills.load (reader, base); break; + case ESM::REC_CLAS: mClasses.load (reader, base); break; default: diff --git a/apps/opencs/model/world/data.hpp b/apps/opencs/model/world/data.hpp index ac953dbec..7baf03259 100644 --- a/apps/opencs/model/world/data.hpp +++ b/apps/opencs/model/world/data.hpp @@ -9,6 +9,7 @@ #include #include #include +#include #include "idcollection.hpp" #include "universalid.hpp" @@ -22,6 +23,7 @@ namespace CSMWorld IdCollection mGlobals; IdCollection mGmsts; IdCollection mSkills; + IdCollection mClasses; std::vector mModels; std::map mModelIndex; diff --git a/apps/opencs/model/world/universalid.cpp b/apps/opencs/model/world/universalid.cpp index 57c276a6d..a85b30c2a 100644 --- a/apps/opencs/model/world/universalid.cpp +++ b/apps/opencs/model/world/universalid.cpp @@ -20,6 +20,7 @@ namespace { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Globals, "Global Variables" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Gmsts, "Game Settings" }, { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Skills, "Skills" }, + { CSMWorld::UniversalId::Class_RecordList, CSMWorld::UniversalId::Type_Classes, "Classes" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; @@ -29,6 +30,7 @@ namespace { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Global, "Global Variable" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Gmst, "Game Setting" }, { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Skill, "Skill" }, + { CSMWorld::UniversalId::Class_Record, CSMWorld::UniversalId::Type_Class, "Class" }, { CSMWorld::UniversalId::Class_None, CSMWorld::UniversalId::Type_None, 0 } // end marker }; diff --git a/apps/opencs/model/world/universalid.hpp b/apps/opencs/model/world/universalid.hpp index a412cb6b1..4c4d95654 100644 --- a/apps/opencs/model/world/universalid.hpp +++ b/apps/opencs/model/world/universalid.hpp @@ -39,7 +39,9 @@ namespace CSMWorld Type_Gmsts, Type_Gmst, Type_Skills, - Type_Skill + Type_Skill, + Type_Classes, + Type_Class }; private: diff --git a/apps/opencs/view/doc/view.cpp b/apps/opencs/view/doc/view.cpp index 267ddf26c..2ef66593f 100644 --- a/apps/opencs/view/doc/view.cpp +++ b/apps/opencs/view/doc/view.cpp @@ -90,6 +90,10 @@ void CSVDoc::View::setupWorldMenu() connect (skills, SIGNAL (triggered()), this, SLOT (addSkillsSubView())); world->addAction (skills); + QAction *classes = new QAction (tr ("Classes"), this); + connect (classes, SIGNAL (triggered()), this, SLOT (addClassesSubView())); + world->addAction (classes); + mVerify = new QAction (tr ("&Verify"), this); connect (mVerify, SIGNAL (triggered()), this, SLOT (verify())); world->addAction (mVerify); @@ -253,6 +257,11 @@ void CSVDoc::View::addSkillsSubView() addSubView (CSMWorld::UniversalId::Type_Skills); } +void CSVDoc::View::addClassesSubView() +{ + addSubView (CSMWorld::UniversalId::Type_Classes); +} + void CSVDoc::View::abortOperation (int type) { mDocument->abortOperation (type); diff --git a/apps/opencs/view/doc/view.hpp b/apps/opencs/view/doc/view.hpp index 4c5aa4078..bc8e8fc26 100644 --- a/apps/opencs/view/doc/view.hpp +++ b/apps/opencs/view/doc/view.hpp @@ -117,6 +117,8 @@ namespace CSVDoc void addGmstsSubView(); void addSkillsSubView(); + + void addClassesSubView(); }; } diff --git a/apps/opencs/view/world/subviews.cpp b/apps/opencs/view/world/subviews.cpp index bdff0017b..5d715ea21 100644 --- a/apps/opencs/view/world/subviews.cpp +++ b/apps/opencs/view/world/subviews.cpp @@ -17,6 +17,9 @@ void CSVWorld::addSubViewFactories (CSVDoc::SubViewFactoryManager& manager) manager.add (CSMWorld::UniversalId::Type_Skills, new CSVDoc::SubViewFactoryWithCreateFlag (false)); - manager.add (CSMWorld::UniversalId::Type_Global, - new CSVDoc::SubViewFactoryWithCreateFlag (true)); + manager.add (CSMWorld::UniversalId::Type_Classes, + new CSVDoc::SubViewFactoryWithCreateFlag (true)); + +// manager.add (CSMWorld::UniversalId::Type_Global, +// new CSVDoc::SubViewFactoryWithCreateFlag (true)); } \ No newline at end of file diff --git a/apps/openmw/mwbase/world.hpp b/apps/openmw/mwbase/world.hpp index 67d7dda6a..8eea383eb 100644 --- a/apps/openmw/mwbase/world.hpp +++ b/apps/openmw/mwbase/world.hpp @@ -44,6 +44,11 @@ namespace MWRender class Animation; } +namespace MWMechanics +{ + class Movement; +} + namespace MWWorld { class Fallback; @@ -54,7 +59,7 @@ namespace MWWorld class ESMStore; class RefData; - typedef std::vector > PtrMovementList; + typedef std::vector > PtrMovementList; } namespace MWBase diff --git a/apps/openmw/mwclass/misc.cpp b/apps/openmw/mwclass/misc.cpp index 6b51559eb..8cfac1a68 100644 --- a/apps/openmw/mwclass/misc.cpp +++ b/apps/openmw/mwclass/misc.cpp @@ -24,6 +24,18 @@ #include +namespace +{ +bool isGold (const MWWorld::Ptr& ptr) +{ + return Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") + || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); +} +} + namespace MWClass { void Miscellaneous::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const @@ -110,25 +122,15 @@ namespace MWClass std::string Miscellaneous::getUpSoundId (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) - { + if (isGold(ptr)) return std::string("Item Gold Up"); - } return std::string("Item Misc Up"); } std::string Miscellaneous::getDownSoundId (const MWWorld::Ptr& ptr) const { - MWWorld::LiveCellRef *ref = - ptr.get(); - - if (ref->mBase->mName == MWBase::Environment::get().getWorld()->getStore().get().find("sGold")->getString()) - { + if (isGold(ptr)) return std::string("Item Gold Down"); - } return std::string("Item Misc Down"); } @@ -159,19 +161,15 @@ namespace MWClass int count = ptr.getRefData().getCount(); - bool isGold = Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_001") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_005") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_010") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_025") - || Misc::StringUtils::ciEqual(ptr.getCellRef().mRefID, "gold_100"); + bool gold = isGold(ptr); - if (isGold && ptr.getCellRef().mGoldValue != 1) + if (gold && ptr.getCellRef().mGoldValue != 1) count = ptr.getCellRef().mGoldValue; - else if (isGold) + else if (gold) count *= ref->mBase->mData.mValue; std::string countString; - if (!isGold) + if (!gold) countString = MWGui::ToolTips::getCountString(count); else // gold displays its count also if it's 1. countString = " (" + boost::lexical_cast(count) + ")"; @@ -187,7 +185,7 @@ namespace MWClass std::string text; - if (!isGold) + if (!gold) { text += "\n#{sWeight}: " + MWGui::ToolTips::toString(ref->mBase->mData.mWeight); text += MWGui::ToolTips::getValueString(getValue(ptr), "#{sValue}"); @@ -211,7 +209,7 @@ namespace MWClass const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); - if (MWWorld::Class::get(ptr).getName(ptr) == store.get().find("sGold")->getString()) { + if (isGold(ptr)) { int goldAmount = ptr.getRefData().getCount(); std::string base = "Gold_001"; diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index a5319ada0..cd6b0def1 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -368,7 +368,7 @@ namespace MWClass moveSpeed = runSpeed; else moveSpeed = walkSpeed; - if(getMovementSettings(ptr).mLeftRight != 0 && getMovementSettings(ptr).mForwardBackward == 0) + if(getMovementSettings(ptr).mPosition[0] != 0 && getMovementSettings(ptr).mPosition[1] == 0) moveSpeed *= 0.75f; return moveSpeed; @@ -414,14 +414,24 @@ namespace MWClass Ogre::Vector3 Npc::getMovementVector (const MWWorld::Ptr& ptr) const { - Ogre::Vector3 vector; - vector.x = getMovementSettings(ptr).mLeftRight; - vector.y = getMovementSettings(ptr).mForwardBackward; - vector.z = getMovementSettings(ptr).mUpDown; - - return vector; + MWMechanics::Movement &movement = getMovementSettings(ptr); + Ogre::Vector3 vec(movement.mPosition); + movement.mPosition[0] = 0.0f; + movement.mPosition[1] = 0.0f; + movement.mPosition[2] = 0.0f; + return vec; } - + + Ogre::Vector3 Npc::getRotationVector (const MWWorld::Ptr& ptr) const + { + MWMechanics::Movement &movement = getMovementSettings(ptr); + Ogre::Vector3 vec(movement.mRotation); + movement.mRotation[0] = 0.0f; + movement.mRotation[1] = 0.0f; + movement.mRotation[2] = 0.0f; + return vec; + } + bool Npc::isEssential (const MWWorld::Ptr& ptr) const { MWWorld::LiveCellRef *ref = diff --git a/apps/openmw/mwclass/npc.hpp b/apps/openmw/mwclass/npc.hpp index 0f61fc8c9..1a10bce6c 100644 --- a/apps/openmw/mwclass/npc.hpp +++ b/apps/openmw/mwclass/npc.hpp @@ -96,6 +96,9 @@ namespace MWClass ///< Return desired movement vector (determined based on movement settings, /// stance and stats). + virtual Ogre::Vector3 getRotationVector (const MWWorld::Ptr& ptr) const; + ///< Return desired rotations, as euler angles. + virtual float getCapacity (const MWWorld::Ptr& ptr) const; ///< Return total weight that fits into the object. Throws an exception, if the object can't /// hold other objects. diff --git a/apps/openmw/mwgui/container.cpp b/apps/openmw/mwgui/container.cpp index 837766953..7e6a0b088 100644 --- a/apps/openmw/mwgui/container.cpp +++ b/apps/openmw/mwgui/container.cpp @@ -140,13 +140,8 @@ void ContainerBase::onSelectedItem(MyGUI::Widget* _sender) if (isInventory()) { - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - // the player is trying to sell an item, check if the merchant accepts it - // also, don't allow selling gold (let's be better than Morrowind at this, can we?) - if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object) || - MWWorld::Class::get(object).getName(object) == gmst.find("sGold")->getString()) + if (!MWBase::Environment::get().getWindowManager()->getTradeWindow()->npcAcceptsItem(object)) { // user notification "i don't buy this item" MWBase::Environment::get().getWindowManager()-> diff --git a/apps/openmw/mwgui/race.cpp b/apps/openmw/mwgui/race.cpp index 1436995c5..be693eb2b 100644 --- a/apps/openmw/mwgui/race.cpp +++ b/apps/openmw/mwgui/race.cpp @@ -19,6 +19,49 @@ using namespace MWGui; using namespace Widgets; +namespace +{ +int wrap(int index, int max) +{ + if (index < 0) + return max - 1; + else if (index >= max) + return 0; + else + return index; +} + +int countParts(const std::string &part, const std::string &race, bool male) +{ + /// \todo loop through the whole store for appropriate bodyparts instead of looking for fixed IDs + const MWWorld::Store &store = + MWBase::Environment::get().getWorld()->getStore().get(); + + std::string prefix = + "b_n_" + race + ((male) ? "_m_" : "_f_") + part; + + std::string suffix; + suffix.reserve(prefix.size() + 3); + + int count = -1; + do { + ++count; + suffix = "_" + (boost::format("%02d") % (count + 1)).str(); + } + while (store.search(prefix + suffix) != 0); + + if (count == 0 && part == "hair") { + count = -1; + do { + ++count; + suffix = (boost::format("%02d") % (count + 1)).str(); + } + while (store.search(prefix + suffix) != 0); + } + return count; +} +} + RaceDialog::RaceDialog(MWBase::WindowManager& parWindowManager) : WindowModal("openmw_chargen_race.layout", parWindowManager) , mGenderIndex(0) @@ -144,45 +187,6 @@ void RaceDialog::setRaceId(const std::string &raceId) updateSpellPowers(); } -int wrap(int index, int max) -{ - if (index < 0) - return max - 1; - else if (index >= max) - return 0; - else - return index; -} - -int countParts(const std::string &part, const std::string &race, bool male) -{ - const MWWorld::Store &store = - MWBase::Environment::get().getWorld()->getStore().get(); - - std::string prefix = - "b_n_" + race + ((male) ? "_m_" : "_f_") + part; - - std::string suffix; - suffix.reserve(prefix.size() + 3); - - int count = -1; - do { - ++count; - suffix = "_" + (boost::format("%02d") % (count + 1)).str(); - } - while (store.search(prefix + suffix) != 0); - - if (count == 0 && part == "hair") { - count = -1; - do { - ++count; - suffix = (boost::format("%02d") % (count + 1)).str(); - } - while (store.search(prefix + suffix) != 0); - } - return count; -} - void RaceDialog::close() { delete mPreview; @@ -229,28 +233,67 @@ void RaceDialog::onSelectNextGender(MyGUI::Widget*) void RaceDialog::onSelectPreviousFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex - 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectNextFace(MyGUI::Widget*) { - mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + do + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); + while (!isFacePlayable()); updatePreview(); } void RaceDialog::onSelectPreviousHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex - 1, mHairCount); + do + mHairIndex = wrap(mHairIndex - 1, mHairCount); + while (!isHairPlayable()); updatePreview(); } void RaceDialog::onSelectNextHair(MyGUI::Widget*) { - mHairIndex = wrap(mHairIndex + 1, mHairCount); + do + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isHairPlayable()); updatePreview(); } +bool RaceDialog::isFacePlayable() +{ + std::string prefix = + "b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_"); + + std::string headIndex = (boost::format("%02d") % (mFaceIndex + 1)).str(); + + const MWWorld::Store &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + + if (parts.search(prefix + "head_" + headIndex) == 0) + return !(parts.find(prefix + "head" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); + else + return !(parts.find(prefix + "head_" + headIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); +} + +bool RaceDialog::isHairPlayable() +{ + std::string prefix = + "b_n_" + mCurrentRaceId + ((mGenderIndex == 0) ? "_m_" : "_f_"); + + std::string hairIndex = (boost::format("%02d") % (mHairIndex + 1)).str(); + + const MWWorld::Store &parts = + MWBase::Environment::get().getWorld()->getStore().get(); + if (parts.search(prefix + "hair_" + hairIndex) == 0) + return !(parts.find(prefix + "hair" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); + else + return !(parts.find(prefix + "hair_" + hairIndex)->mData.mFlags & ESM::BodyPart::BPF_NotPlayable); +} + void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) { if (_index == MyGUI::ITEM_NONE) @@ -273,11 +316,16 @@ void RaceDialog::onSelectRace(MyGUI::ListBox* _sender, size_t _index) void RaceDialog::recountParts() { + mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); + mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + mFaceIndex = 0; mHairIndex = 0; - mFaceCount = countParts("head", mCurrentRaceId, mGenderIndex == 0); - mHairCount = countParts("hair", mCurrentRaceId, mGenderIndex == 0); + while (!isHairPlayable()) + mHairIndex = wrap(mHairIndex + 1, mHairCount); + while (!isFacePlayable()) + mFaceIndex = wrap(mFaceIndex + 1, mFaceCount); } // update widget content diff --git a/apps/openmw/mwgui/race.hpp b/apps/openmw/mwgui/race.hpp index efd08f439..0ca440ad5 100644 --- a/apps/openmw/mwgui/race.hpp +++ b/apps/openmw/mwgui/race.hpp @@ -81,6 +81,9 @@ namespace MWGui void updatePreview(); void recountParts(); + bool isHairPlayable(); + bool isFacePlayable(); + MyGUI::ImageBox* mPreviewImage; MyGUI::ListBox* mRaceList; MyGUI::ScrollBar* mHeadRotate; diff --git a/apps/openmw/mwgui/tradewindow.cpp b/apps/openmw/mwgui/tradewindow.cpp index 307533d91..81a29e69b 100644 --- a/apps/openmw/mwgui/tradewindow.cpp +++ b/apps/openmw/mwgui/tradewindow.cpp @@ -129,13 +129,10 @@ namespace MWGui MWWorld::Ptr gold; MWWorld::ContainerStore& playerStore = mWindowManager.getInventoryWindow()->getContainerStore(); - const MWWorld::Store &gmst = - MWBase::Environment::get().getWorld()->getStore().get(); - for (MWWorld::ContainerStoreIterator it = playerStore.begin(); it != playerStore.end(); ++it) { - if (MWWorld::Class::get(*it).getName(*it) == gmst.find("sGold")->getString()) + if (Misc::StringUtils::ciEqual(it->getCellRef().mRefID, "gold_001")) { goldFound = true; gold = *it; @@ -342,6 +339,9 @@ namespace MWGui bool TradeWindow::npcAcceptsItem(MWWorld::Ptr item) { + if (Misc::StringUtils::ciEqual(item.getCellRef().mRefID, "gold_001")) + return false; + int services = 0; if (mPtr.getTypeName() == typeid(ESM::NPC).name()) { diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index d2a0af2cd..33ab9b1b4 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -287,8 +287,6 @@ namespace MWInput triedToMove = true; mPlayer.setLeftRight (1); } - else - mPlayer.setLeftRight (0); if (actionIsActive(A_MoveForward)) { @@ -302,8 +300,6 @@ namespace MWInput mPlayer.setAutoMove (false); mPlayer.setForwardBackward (-1); } - else - mPlayer.setForwardBackward (0); mPlayer.setSneak(actionIsActive(A_Sneak)); @@ -312,8 +308,6 @@ namespace MWInput mPlayer.setUpDown (1); triedToMove = true; } - else - mPlayer.setUpDown (0); if (mAlwaysRunActive) mPlayer.setRunState(!actionIsActive(A_Run)); @@ -542,11 +536,11 @@ namespace MWInput { resetIdleTime(); - float x = arg.state.X.rel * mCameraSensitivity * 0.2; - float y = arg.state.Y.rel * mCameraSensitivity * 0.2 * (mInvertY ? -1 : 1) * mUIYMultiplier; + float x = arg.state.X.rel * mCameraSensitivity * 0.2f; + float y = arg.state.Y.rel * mCameraSensitivity * 0.2f * (mInvertY ? -1 : 1) * mUIYMultiplier; - MWBase::World *world = MWBase::Environment::get().getWorld(); - world->rotateObject(world->getPlayer().getPlayer(), -y, 0.f, x, true); + mPlayer.setYaw(x); + mPlayer.setPitch(-y); if (arg.state.Z.rel) MWBase::Environment::get().getWorld()->changeVanityModeScale(arg.state.Z.rel); diff --git a/apps/openmw/mwmechanics/activators.cpp b/apps/openmw/mwmechanics/activators.cpp index b67fcb216..cbc380299 100644 --- a/apps/openmw/mwmechanics/activators.cpp +++ b/apps/openmw/mwmechanics/activators.cpp @@ -2,6 +2,8 @@ #include +#include "movement.hpp" + #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" @@ -56,7 +58,10 @@ void Activators::update(float duration, bool paused) if(!paused) { for(PtrControllerMap::iterator iter(mActivators.begin());iter != mActivators.end();++iter) - iter->second.update(duration); + { + Movement movement; + iter->second.update(duration, movement); + } } } diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index c8d87b425..f60567c6c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -17,6 +17,7 @@ #include "../mwbase/windowmanager.hpp" #include "creaturestats.hpp" +#include "movement.hpp" namespace MWMechanics { @@ -266,7 +267,8 @@ namespace MWMechanics for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();++iter) { - Ogre::Vector3 movement = iter->second.update(duration); + Movement movement; + iter->second.update(duration, movement); mMovement.push_back(std::make_pair(iter->first, movement)); } MWBase::Environment::get().getWorld()->doPhysics(mMovement, duration); diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index fc4af8dd6..aabd86dc7 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -7,6 +7,7 @@ #include #include "character.hpp" +#include "movement.hpp" #include "../mwbase/world.hpp" namespace Ogre diff --git a/apps/openmw/mwmechanics/character.cpp b/apps/openmw/mwmechanics/character.cpp index 62958db8d..7aff2e1d0 100644 --- a/apps/openmw/mwmechanics/character.cpp +++ b/apps/openmw/mwmechanics/character.cpp @@ -21,6 +21,8 @@ #include +#include "movement.hpp" + #include "../mwrender/animation.hpp" #include "../mwbase/environment.hpp" @@ -73,6 +75,9 @@ static const struct { { CharState_SneakLeft, "sneakleft" }, { CharState_SneakRight, "sneakright" }, + { CharState_TurnLeft, "turnleft" }, + { CharState_TurnRight, "turnright" }, + { CharState_Jump, "jump" }, { CharState_Death1, "death1" }, @@ -168,21 +173,20 @@ void CharacterController::markerEvent(float time, const std::string &evt) } -Ogre::Vector3 CharacterController::update(float duration) +void CharacterController::update(float duration, Movement &movement) { - Ogre::Vector3 movement(0.0f); - float speed = 0.0f; if(!(getState() >= CharState_Death1)) { const MWBase::World *world = MWBase::Environment::get().getWorld(); const MWWorld::Class &cls = MWWorld::Class::get(mPtr); - const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); bool onground = world->isOnGround(mPtr); bool inwater = world->isSwimming(mPtr); bool isrunning = cls.getStance(mPtr, MWWorld::Class::Run); bool sneak = cls.getStance(mPtr, MWWorld::Class::Sneak); + const Ogre::Vector3 &vec = cls.getMovementVector(mPtr); + const Ogre::Vector3 &rot = cls.getRotationVector(mPtr); speed = cls.getSpeed(mPtr); /* FIXME: The state should be set to Jump, and X/Y movement should be disallowed except @@ -192,14 +196,14 @@ Ogre::Vector3 CharacterController::update(float duration) float x = cls.getJump(mPtr); if(vec.x == 0 && vec.y == 0) - movement.z += x*duration; + movement.mPosition[2] += x*duration; else { /* FIXME: this would be more correct if we were going into a jumping state, * rather than normal walking/idle states. */ //Ogre::Vector3 lat = Ogre::Vector3(vec.x, vec.y, 0.0f).normalisedCopy(); //movement += Ogre::Vector3(lat.x, lat.y, 1.0f) * x * 0.707f * duration; - movement.z += x * 0.707f * duration; + movement.mPosition[2] += x * 0.707f * duration; } //decrease fatigue by fFatigueJumpBase + (1 - normalizedEncumbrance) * fFatigueJumpMult; @@ -216,7 +220,7 @@ Ogre::Vector3 CharacterController::update(float duration) : (sneak ? CharState_SneakLeft : (isrunning ? CharState_RunLeft : CharState_WalkLeft)), true); // Apply any forward/backward movement manually - movement.y += vec.y * (speed*duration); + movement.mPosition[1] += vec.y * (speed*duration); } else if(vec.y != 0.0f && speed > 0.0f) { @@ -228,20 +232,32 @@ Ogre::Vector3 CharacterController::update(float duration) setState(inwater ? (isrunning ? CharState_SwimRunBack : CharState_SwimWalkBack) : (sneak ? CharState_SneakBack : (isrunning ? CharState_RunBack : CharState_WalkBack)), true); // Apply any sideways movement manually - movement.x += vec.x * (speed*duration); + movement.mPosition[0] += vec.x * (speed*duration); + } + else if(rot.z != 0.0f && !inwater && !sneak) + { + if(rot.z > 0.0f) + setState(CharState_TurnRight, true); + else if(rot.z < 0.0f) + setState(CharState_TurnLeft, true); } else if(mAnimQueue.size() == 0) setState((inwater ? CharState_IdleSwim : (sneak ? CharState_IdleSneak : CharState_Idle)), true); + + movement.mRotation[0] += rot.x * duration; + movement.mRotation[1] += rot.y * duration; + movement.mRotation[2] += rot.z * duration; } if(mAnimation && !mSkipAnim) { mAnimation->setSpeed(speed); - movement += mAnimation->runAnimation(duration); + Ogre::Vector3 moved = mAnimation->runAnimation(duration); + movement.mPosition[0] += moved.x; + movement.mPosition[1] += moved.y; + movement.mPosition[2] += moved.z; } mSkipAnim = false; - - return movement; } diff --git a/apps/openmw/mwmechanics/character.hpp b/apps/openmw/mwmechanics/character.hpp index 46f0690e7..5b5a65f79 100644 --- a/apps/openmw/mwmechanics/character.hpp +++ b/apps/openmw/mwmechanics/character.hpp @@ -13,6 +13,8 @@ namespace MWRender namespace MWMechanics { +class Movement; + enum CharacterState { CharState_SpecialIdle, CharState_Idle, @@ -52,6 +54,9 @@ enum CharacterState { CharState_SneakLeft, CharState_SneakRight, + CharState_TurnLeft, + CharState_TurnRight, + CharState_Jump, /* Death states must be last! */ @@ -87,7 +92,7 @@ public: void updatePtr(const MWWorld::Ptr &ptr); - Ogre::Vector3 update(float duration); + void update(float duration, Movement &movement); void playGroup(const std::string &groupname, int mode, int count); void skipAnim(); diff --git a/apps/openmw/mwmechanics/movement.hpp b/apps/openmw/mwmechanics/movement.hpp index 11eb83151..6c9a4b758 100644 --- a/apps/openmw/mwmechanics/movement.hpp +++ b/apps/openmw/mwmechanics/movement.hpp @@ -6,11 +6,14 @@ namespace MWMechanics /// Desired movement for an actor struct Movement { - signed char mLeftRight; // 1: wants to move left, -1: wants to move right - signed char mForwardBackward; // 1:wants to move forward, -1: wants to move backward - signed char mUpDown; + float mPosition[3]; + float mRotation[3]; - Movement() : mLeftRight (0), mForwardBackward (0), mUpDown(0) {} + Movement() + { + mPosition[0] = mPosition[1] = mPosition[2] = 0.0f; + mRotation[0] = mRotation[1] = mRotation[2] = 0.0f; + } }; } diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 1bab676c3..7c442c686 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -262,37 +262,29 @@ void RenderingManager::scaleObject (const MWWorld::Ptr& ptr, const Ogre::Vector3 ptr.getRefData().getBaseNode()->setScale(scale); } -bool RenderingManager::rotateObject( const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust) +bool RenderingManager::rotateObject(const MWWorld::Ptr &ptr, Ogre::Vector3 &rot, bool adjust) { bool isActive = ptr.getRefData().getBaseNode() != 0; bool isPlayer = isActive && ptr.getRefData().getHandle() == "player"; bool force = true; - + if (isPlayer) force = mPlayer->rotate(rot, adjust); - - MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); + MWWorld::Class::get(ptr).adjustRotation(ptr, rot.x, rot.y, rot.z); if (!isPlayer && isActive) { - Ogre::Quaternion xr(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yr(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zr(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); - - Ogre::Quaternion xref(Ogre::Radian(-ptr.getRefData().getPosition().rot[0]), Ogre::Vector3::UNIT_X); - Ogre::Quaternion yref(Ogre::Radian(-ptr.getRefData().getPosition().rot[1]), Ogre::Vector3::UNIT_Y); - Ogre::Quaternion zref(Ogre::Radian(-ptr.getRefData().getPosition().rot[2]), Ogre::Vector3::UNIT_Z); - - Ogre::Quaternion newo = adjust ? (xr * yr * zr) * (xref*yref*zref) : xr * yr * zr; - - Ogre::Matrix3 mat; - newo.ToRotationMatrix(mat); - Ogre::Radian ax,ay,az; - mat.ToEulerAnglesXYZ(ax,ay,az); - rot.x = -ax.valueRadians(); - rot.y = -ay.valueRadians(); - rot.z = -az.valueRadians(); + if(adjust) + { + const float *objRot = ptr.getRefData().getPosition().rot; + rot.x += objRot[0]; + rot.y += objRot[1]; + rot.z += objRot[2]; + } + Ogre::Quaternion newo = Ogre::Quaternion(Ogre::Radian(-rot.x), Ogre::Vector3::UNIT_X) * + Ogre::Quaternion(Ogre::Radian(-rot.y), Ogre::Vector3::UNIT_Y) * + Ogre::Quaternion(Ogre::Radian(-rot.z), Ogre::Vector3::UNIT_Z); ptr.getRefData().getBaseNode()->setOrientation(newo); } else if(isPlayer) diff --git a/apps/openmw/mwscript/docs/vmformat.txt b/apps/openmw/mwscript/docs/vmformat.txt index 0f07b4d2e..7e9827062 100644 --- a/apps/openmw/mwscript/docs/vmformat.txt +++ b/apps/openmw/mwscript/docs/vmformat.txt @@ -316,5 +316,7 @@ op 0x20001f9: Drop, explicit reference op 0x20001fa: DropSoulGem op 0x20001fb: DropSoulGem, explicit reference op 0x20001fc: OnDeath +op 0x20001fd: IsWerewolf +op 0x20001fe: IsWerewolf, explicit reference -opcodes 0x20001fd-0x3ffffff unused +opcodes 0x20001ff-0x3ffffff unused diff --git a/apps/openmw/mwscript/statsextensions.cpp b/apps/openmw/mwscript/statsextensions.cpp index c5fc9436b..1d321fbbb 100644 --- a/apps/openmw/mwscript/statsextensions.cpp +++ b/apps/openmw/mwscript/statsextensions.cpp @@ -1046,6 +1046,18 @@ namespace MWScript } }; + template + class OpIsWerewolf : public Interpreter::Opcode0 + { + public: + + virtual void execute (Interpreter::Runtime& runtime) + { + MWWorld::Ptr ptr = R()(runtime); + runtime.push(MWWorld::Class::get(ptr).getNpcStats(ptr).isWerewolf()); + } + }; + const int numberOfAttributes = 8; const int opcodeGetAttribute = 0x2000027; @@ -1137,6 +1149,9 @@ namespace MWScript const int opcodeOnDeath = 0x20001fc; + const int opcodeIsWerewolf = 0x20001fd; + const int opcodeIsWerewolfExplicit = 0x20001fe; + void registerExtensions (Compiler::Extensions& extensions) { static const char *attributes[numberOfAttributes] = @@ -1252,6 +1267,8 @@ namespace MWScript extensions.registerInstruction ("lowerrank", "", opcodeLowerRank, opcodeLowerRankExplicit); extensions.registerFunction ("ondeath", 'l', "", opcodeOnDeath); + + extensions.registerFunction ("iswerewolf", 'l', "", opcodeIsWerewolf, opcodeIsWerewolfExplicit); } void installOpcodes (Interpreter::Interpreter& interpreter) @@ -1368,6 +1385,9 @@ namespace MWScript interpreter.installSegment5 (opcodeLowerRankExplicit, new OpLowerRank); interpreter.installSegment5 (opcodeOnDeath, new OpOnDeath); + + interpreter.installSegment5 (opcodeIsWerewolf, new OpIsWerewolf); + interpreter.installSegment5 (opcodeIsWerewolfExplicit, new OpIsWerewolf); } } } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 1eb2f35bd..f6357f7e9 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -142,6 +142,11 @@ namespace MWWorld return Ogre::Vector3 (0, 0, 0); } + Ogre::Vector3 Class::getRotationVector (const Ptr& ptr) const + { + return Ogre::Vector3 (0, 0, 0); + } + std::pair, bool> Class::getEquipmentSlots (const Ptr& ptr) const { return std::make_pair (std::vector(), false); diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 012a03bf6..36d7e97db 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -150,6 +150,9 @@ namespace MWWorld ///< Return desired movement vector (determined based on movement settings, /// stance and stats). + virtual Ogre::Vector3 getRotationVector (const Ptr& ptr) const; + ///< Return desired rotations, as euler angles. + virtual std::pair, bool> getEquipmentSlots (const Ptr& ptr) const; ///< \return first: Return IDs of the slot this object can be equipped in; second: can object /// stay stacked when equipped? diff --git a/apps/openmw/mwworld/player.cpp b/apps/openmw/mwworld/player.cpp index 0dc8b37ef..ea8a02dee 100644 --- a/apps/openmw/mwworld/player.cpp +++ b/apps/openmw/mwworld/player.cpp @@ -42,14 +42,14 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; } void Player::setLeftRight (int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mLeftRight = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[0] = value; } void Player::setForwardBackward (int value) @@ -61,14 +61,14 @@ namespace MWWorld if (mAutoMove) value = 1; - MWWorld::Class::get (ptr).getMovementSettings (ptr).mForwardBackward = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[1] = value; } void Player::setUpDown(int value) { MWWorld::Ptr ptr = getPlayer(); - MWWorld::Class::get (ptr).getMovementSettings (ptr).mUpDown = value; + MWWorld::Class::get (ptr).getMovementSettings (ptr).mPosition[2] = value; } void Player::setRunState(bool run) @@ -84,6 +84,22 @@ namespace MWWorld MWWorld::Class::get (ptr).setStance (ptr, MWWorld::Class::Sneak, sneak); } + void Player::setYaw(float yaw) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[2] = yaw; + } + void Player::setPitch(float pitch) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[0] = pitch; + } + void Player::setRoll(float roll) + { + MWWorld::Ptr ptr = getPlayer(); + MWWorld::Class::get(ptr).getMovementSettings(ptr).mRotation[1] = roll; + } + MWMechanics::DrawState_ Player::getDrawState() { MWWorld::Ptr ptr = getPlayer(); diff --git a/apps/openmw/mwworld/player.hpp b/apps/openmw/mwworld/player.hpp index d82d3fc32..c98551091 100644 --- a/apps/openmw/mwworld/player.hpp +++ b/apps/openmw/mwworld/player.hpp @@ -67,6 +67,10 @@ namespace MWWorld void setRunState(bool run); void setSneak(bool sneak); + + void setYaw(float yaw); + void setPitch(float pitch); + void setRoll(float roll); }; } #endif diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 75ff6ec83..ae0e02c8c 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -13,6 +13,7 @@ #include "../mwbase/scriptmanager.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/movement.hpp" #include "../mwrender/sky.hpp" #include "../mwrender/player.hpp" @@ -805,18 +806,15 @@ namespace MWWorld mPhysics->scaleObject(ptr); } - void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) + void World::rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust) { - Ogre::Vector3 rot; - rot.x = Ogre::Degree(x).valueRadians(); - rot.y = Ogre::Degree(y).valueRadians(); - rot.z = Ogre::Degree(z).valueRadians(); - if (mRendering->rotateObject(ptr, rot, adjust)) { // rotate physically iff renderer confirm so float *objRot = ptr.getRefData().getPosition().rot; - objRot[0] = rot.x, objRot[1] = rot.y, objRot[2] = rot.z; + objRot[0] = rot.x; + objRot[1] = rot.y; + objRot[2] = rot.z; if (ptr.getRefData().getBaseNode() != 0) { mPhysics->rotateObject(ptr); @@ -824,6 +822,14 @@ namespace MWWorld } } + void World::rotateObject (const Ptr& ptr,float x,float y,float z, bool adjust) + { + rotateObjectImp(ptr, Ogre::Vector3(Ogre::Degree(x).valueRadians(), + Ogre::Degree(y).valueRadians(), + Ogre::Degree(z).valueRadians()), + adjust); + } + void World::safePlaceObject(const MWWorld::Ptr& ptr,MWWorld::CellStore &Cell,ESM::Position pos) { copyObjectToCell(ptr,Cell,pos); @@ -873,13 +879,18 @@ namespace MWWorld player = iter; continue; } - Ogre::Vector3 vec = mPhysics->move(iter->first, iter->second, duration, + + rotateObjectImp(iter->first, Ogre::Vector3(iter->second.mRotation), true); + + Ogre::Vector3 vec = mPhysics->move(iter->first, Ogre::Vector3(iter->second.mPosition), duration, !isSwimming(iter->first) && !isFlying(iter->first)); moveObjectImp(iter->first, vec.x, vec.y, vec.z); } if(player != actors.end()) { - Ogre::Vector3 vec = mPhysics->move(player->first, player->second, duration, + rotateObjectImp(player->first, Ogre::Vector3(player->second.mRotation), true); + + Ogre::Vector3 vec = mPhysics->move(player->first, Ogre::Vector3(player->second.mPosition), duration, !isSwimming(player->first) && !isFlying(player->first)); moveObjectImp(player->first, vec.x, vec.y, vec.z); } diff --git a/apps/openmw/mwworld/worldimp.hpp b/apps/openmw/mwworld/worldimp.hpp index 8554d904a..8cff50bd1 100644 --- a/apps/openmw/mwworld/worldimp.hpp +++ b/apps/openmw/mwworld/worldimp.hpp @@ -90,6 +90,8 @@ namespace MWWorld int getDaysPerMonth (int month) const; + void rotateObjectImp (const Ptr& ptr, Ogre::Vector3 rot, bool adjust); + bool moveObjectImp (const Ptr& ptr, float x, float y, float z); ///< @return true if the active cell (cell player is in) changed diff --git a/components/compiler/scanner.cpp b/components/compiler/scanner.cpp index 7f43c36a5..420fd8f7f 100644 --- a/components/compiler/scanner.cpp +++ b/components/compiler/scanner.cpp @@ -106,6 +106,12 @@ namespace Compiler mLoc.mLiteral.clear(); return true; } + else if (c==':') + { + // treat : as a whitespace :( + mLoc.mLiteral.clear(); + return true; + } else if (std::isdigit (c)) { bool cont = false; diff --git a/components/esm/loadbody.hpp b/components/esm/loadbody.hpp index c91bb40bf..c467b3625 100644 --- a/components/esm/loadbody.hpp +++ b/components/esm/loadbody.hpp @@ -33,7 +33,7 @@ struct BodyPart enum Flags { BPF_Female = 1, - BPF_Playable = 2 + BPF_NotPlayable = 2 }; enum MeshType diff --git a/components/esm/loadclas.cpp b/components/esm/loadclas.cpp index a62668950..d9f367fd6 100644 --- a/components/esm/loadclas.cpp +++ b/components/esm/loadclas.cpp @@ -35,4 +35,18 @@ void Class::save(ESMWriter &esm) esm.writeHNOString("DESC", mDescription); } + void Class::blank() + { + mName.clear(); + mDescription.clear(); + + mData.mAttribute[0] = mData.mAttribute[1] = 0; + mData.mSpecialization = 0; + mData.mIsPlayable = 0; + mData.mCalc = 0; + + for (int i=0; i<5; ++i) + for (int i2=0; i2<2; ++i2) + mData.mSkills[i][i2] = 0; + } } diff --git a/components/esm/loadclas.hpp b/components/esm/loadclas.hpp index 264e342e6..ac596af32 100644 --- a/components/esm/loadclas.hpp +++ b/components/esm/loadclas.hpp @@ -65,6 +65,10 @@ struct Class void load(ESMReader &esm); void save(ESMWriter &esm); + + void blank(); + ///< Set record to default state (does not touch the ID/index). + }; } #endif diff --git a/components/esm/loadskil.cpp b/components/esm/loadskil.cpp index b9d588eef..b7259db94 100644 --- a/components/esm/loadskil.cpp +++ b/components/esm/loadskil.cpp @@ -2,6 +2,8 @@ #include +#include + #include "esmreader.hpp" #include "esmwriter.hpp" @@ -103,8 +105,9 @@ void Skill::load(ESMReader &esm) // create an ID from the index and the name (only used in the editor and likely to change in the // future) - mId = getIndexToId (mIndex); + mId = indexToId (mIndex); } + void Skill::save(ESMWriter &esm) { esm.writeHNT("INDX", mIndex); @@ -120,7 +123,7 @@ void Skill::save(ESMWriter &esm) mDescription.clear(); } - std::string Skill::getIndexToId (int index) + std::string Skill::indexToId (int index) { std::ostringstream stream; diff --git a/components/esm/loadskil.hpp b/components/esm/loadskil.hpp index 83a4d8bfd..43f4fc45e 100644 --- a/components/esm/loadskil.hpp +++ b/components/esm/loadskil.hpp @@ -79,7 +79,7 @@ struct Skill void blank(); ///< Set record to default state (does not touch the ID/index). - static std::string getIndexToId (int index); + static std::string indexToId (int index); }; } #endif